SyntaxHighlighter

---SyntaxHighlighter ウィジェット---

2015年3月7日土曜日

マイコン(Arduino等)とMindstorms NXT/EV3をI2Cで繋ぐ(プログラム)

デバイスに依存する一部の記述を書き換えれば、
たいていの環境で利用できるよう、1から書き直しました。
松原拓也様のNicosensorを参考にさせて頂いています。
#define scl0     10
#define sda0      9
#define ACK       0
#define NAK       1
#define WRITE     0
#define READ      1

#define SDA_OPEN  1
#define SDA_LOW   0
#define SCL_OPEN  1
#define SCL_LOW   0


void setup()
{
    main0();
}
void loop()
{}


//---デバイス依存部---
void iic_ports_low()
{
    digitalWrite(scl0,LOW);
    digitalWrite(sda0,LOW);
}

void set_scl(char t)
{
    if(t==SCL_LOW)
        pinMode(scl0,OUTPUT);//Low
    else
        pinMode(scl0,INPUT);//Hi-Z

    return;
}
void set_sda(char t)
{
    if(t==SDA_LOW)
        pinMode(sda0,OUTPUT);//Low
    else
        pinMode(sda0,INPUT);//Hi-Z

    return;
}
char get_scl()
{
  return digitalRead(scl0);
}
char get_sda()
{
  return digitalRead(sda0);
}
//--------------------------

void iic_bus_open()
{
    iic_ports_low();
    set_scl(SCL_OPEN);set_sda(SDA_OPEN);    
}
void iic_wait_scl(unsigned char b_scl)
{
    while(!(get_scl() == b_scl));    
}

void iic_wait_bus(unsigned char b_sda,unsigned char b_scl)
{
    while(!(get_sda() == b_dsa && get_scl() == b_scl));
}


void iic_start()
{
    iic_bus_open();    
    iic_wait_bus(SDA_OPEN,SCL_OPEN);
    iic_wait_bus(SDA_LOW ,SCL_OPEN);
    iic_wait_bus(SDA_LOW ,SCL_LOW);
}

void iic_stop()
{
    iic_bus_open();    
    iic_wait_bus(SDA_OPEN,SCL_OPEN);
}

void iic_set_ack(char ack_or_nak)
{
    //0=ack, 1=nak
    set_sda(ack_or_nak);
    iic_wait_scl(SCL_OPEN);    
    iic_wait_scl(SCL_LOW);
}

unsigned char iic_write(unsigned char d)
{
    int i;
    int ack = 0;
    for(i=0;i<8;i++)
    {
        if((d & 0x80) != 0)
            set_sda(SDA_OPEN);
        else
            set_sda(SDA_LOW);
            
        d<<=1;
        iic_wait_scl(SCL_OPEN);    
        iic_wait_scl(SCL_LOW);
    }
//--
//0=ack, 1=nak

    set_sda(SDA_OPEN);
    iic_wait_scl(SCL_OPEN);        

    if(get_sda() != 0)
        ack = 1;

    iic_wait_scl(SCL_LOW);    

    return ack;
}
unsigned char iic_read()
{
    int i;
    unsigned char d = 0;

    for(i=0;i<8;i++)
    {
        d<<=1;

        iic_wait_scl(SCL_OPEN);    

        if(get_sda() != 0)
            d |= 1;            

        iic_wait_scl(SCL_LOW);
    }
    return d;
}

//アドレスだけほしい時
unsigned char iic_start_and_wait()
{
        iic_start();
        return iic_read();    
}

//1つのアドレスのみ反応したいとき
void iic_start_and_wait_for_me(unsigned char adr,char mode)
{
    //0=write 1=read
    unsigned char radr = 0;
    unsigned char cadr = ((adr << 1) & 0xFE)|mode;
    while(1){
        radr = iic_start_and_wait();
        
        if(radr == cadr)
            break;

        iic_set_ack(NAK);        
    }
    
    iic_set_ack(ACK);
    return;
}


#define MODE_NXT_READ_NON_REG    0
#define MODE_NXT_READ_REG        1

#define MODE_NXT_WRITE_NON_REG   2
#define MODE_NXT_WRITE_REG       3

#define MODE_EV3_1_BYTE_WRITE    4
#define MODE_EV3_1_BYTE_READ     5

#define MODE_EV3_8_BYTE_WRITE    6
#define MODE_EV3_8_BYTE_READ     7

void main0()
{
    int c,ack;
    unsigned char reg=0,reg_ary[8]={0},val=0,val_ary[8]={0};
    iic_bus_open();    
    delay(100);
    
    
    mode = x;
    
    while(1)
    {
        switch(mode)
            case MODE_NXT_READ_NON_REG:
                iic_start_and_wait_for_me(0x01,WRITE);

                iic_start_and_wait(0x01,READ);
                ack = iic_write(val);

                iic_stop();
                break;
            case MODE_NXT_READ_REG:
                iic_start_and_wait_for_me(0x01,WRITE);

                reg=iic_read();
                iic_set_ack(ACK);

                iic_start_and_wait(0x01,READ);
                ack = iic_write(val);            

                iic_stop();
                break;
            case MODE_NXT_WRITE_NON_REG:
                iic_start_and_wait_for_me(0x01,WRITE);

                val=iic_read();
                iic_set_ack(ACK);

                iic_stop();
                            break;
            case MODE_NXT_WRITE_REG:
                iic_start_and_wait_for_me(0x01,WRITE);

                reg=iic_read();
                iic_set_ack(ACK);
                val=iic_read();
                iic_set_ack(ACK);

                iic_stop();            
                break;

            case MODE_EV3_1_BYTE_READ:
                iic_start_and_wait(0x01,READ);
                ack = iic_write(val);            

                iic_stop();            
                break;
            case MODE_EV3_1_BYTE_WRITE:
                iic_start_and_wait_for_me(0x01,WRITE);

                val=iic_read();
                iic_set_ack(ACK);

                iic_stop();
                break;
            case MODE_EV3_8_BYTE_READ:
                iic_start_and_wait(0x01,READ);
                for(i=0;i<8;i++)
                    ack = iic_write(val[i]);
                iic_stop();            
                break;
            case MODE_EV3_8_BYTE_WRITE:
                iic_start_and_wait(0x01,READ);
                for(i=0;i<8;i++)
                {
                    reg[i]=iic_read();
                    iic_set_ack(ACK);
                }
                iic_stop();            
                break;
        
            iic_start_and_wait_for_me(0x01,WRITE);
            c=iic_read();
            iic_set_ack(ACK);
//            iic_set_ack(NAK);
            
//            iic_start_and_wait(0x01,READ);
                        iic_start();
            iic_read();
            iic_set_ack(ACK);
            ack = iic_write(5);
            iic_stop();
    }
    
}


void NXT_EV3_1BYTE_READ() //NXT=RegありREAD,EV3=1byteREAD
{
    int c,ack,adr;
    unsigned char val=0;
    iic_bus_open();    
    delay(100);
    
    while(1)
    {
        adr = iic_start_and_wait();

        if(adr == 0x01|READ)
        {
            iic_set_ack(ACK);

            ack = iic_write(val);            
            iic_stop();
        }else if(adr == 0x01|WRITE)
        {
            iic_set_ack(ACK);

            iic_read();
            iic_set_ack(ACK);
        }else{
            iic_set_ack(NAK);            
        }
    }    
}

0 件のコメント:

コメントを投稿