模拟I2C主机的比较多,但是从机相对主机而言要难很多,这个供大家借鉴。
这个从机程序支持主机对它的随机写和随机读,连续读和连续写没做,有兴趣的可以完善下,呵呵。
//Microcontrol CODE #include <msp430x22x4.h> #define SDA BIT1 #define SCL BIT2 #define SEG_A 0xA0 //0x0200---0x027F #define SEG_B 0xB0 //0x0280---0x02FF #define SEG_C 0xC0 //0x0300---0x037F //0x0380---0x0400 __no_init char wokao@0x243; //============================= char *send_ptr; ; ; ; ; ; ; ; //*********************函数声明************************************* void ACK(void); //**************************************************************** void main( void ) { // Stop watchdog timer to prevent time out reset WDTCTL = WDTPW + WDTHOLD; //======================MCLK=16MHz===================================== DCOCTL = CALDCO_16MHZ; BCSCTL1 = CALBC1_16MHZ; //MCLK=DCO=16MHz P3DIR &= ~(SDA+SCL); ) { NN=; PreState = READ_SDA; while(READ_SCL && NN--) { NowState = READ_SDA; if(PreState && !NowState) { START_flag = ; _DINT(); } if(!PreState && NowState) { STOP_flag = ; _EINT(); } PreState = NowState; if(START_flag) { START_flag=; while(READ_SCL); //START时的SCL高电平状态就等待 ;gg>;gg--) //接收器件地址 { while(!READ_SCL); //SCL低电平状态就等待 DEVICE_ADR<<=; if(READ_SDA) //数据的第一个CLK高电平来临 DEVICE_ADR |= 0x01; while(READ_SCL); //SCL高电平状态就等待 } ACK(); //对设备地址ACK应答信 //-----------以上收到了设备地址,并知晓主机要对从机进行读还是写操作--- ;gg>;gg--) //接收内存单元地址 { while(!READ_SCL); WORD_ADR<<=; if(READ_SDA) WORD_ADR |= 0x01; while(READ_SCL); } //-----------以上就已经接收到内存单元地址------------ ACK(); //对内存单元ACK应答信号 if(DEVICE_ADR & 0x01) //从机发数据给主机 R/W=1 { if(DEVICE_ADR==SEG_A+0x01) { send_ptr =(char*)(0x0200 + WORD_ADR); } else if(DEVICE_ADR==SEG_B+0x01) { send_ptr =(char*)(0x0280 + WORD_ADR); } else if(DEVICE_ADR==SEG_C+0x01) { send_ptr =(char*)(0x0300 + WORD_ADR); } //--------以上是判断出为主机读从机,要把要读的地址单元赋给指针--- ;gg>;gg--) { while(!READ_SCL); if( *send_ptr & 0x80) _NOP(); else { P3DIR |= SDA; //输出0 } while(READ_SCL); //SCL为1,就保持SDA输出不变 P3DIR &= ~SDA; //SCL为0,就把SDA从新切换到接收状态 *send_ptr <<=; } ACK(); //从机数据发送完毕,应答信号 _NOP(); //------------------以上是从机发数据给主机----------------- } else //主机写从机 R/W=0 { ;gg>;gg--) //接收主机要写到该器件内存单元的数据 { while(!READ_SCL); REC_DATA <<=; if(READ_SDA) REC_DATA |= 0x01; while(READ_SCL); } if(DEVICE_ADR==SEG_A) { send_ptr =(char*)(0x0200 + WORD_ADR); *send_ptr = REC_DATA; } else if(DEVICE_ADR==SEG_B) { send_ptr =(char*)(0x0280 + WORD_ADR); *send_ptr = REC_DATA; } else if(DEVICE_ADR==SEG_C) { send_ptr =(char*)(0x0300 + WORD_ADR); *send_ptr = REC_DATA; } ACK(); _NOP(); while(!READ_SCL); } }// if(START_flag) }//while(NN--) _EINT(); _NOP(); }//while(1) } //**************************************************** void ACK(void) { // while(READ_SCL); while(!READ_SCL); P3DIR |= SDA; //第9个CLK变高的情况下,SDA输出0 while(READ_SCL); P3DIR &= ~SDA; //第9个CLK变低的情况下,SDA输出1 }