LPC1768有三路IIC,其中IIC0支持高速模式和plus模式,另外兩路是普通IIC,使用IIC的過程如下
首先依然是打開IIC時鐘,同時打開GPIO時鐘
然后配置引腳為IIC功能
另外,因為iic0支持plus結(jié)構(gòu),所以gpio控制的時候還有這個寄存器需要設置
接下來設置IIC的高低電平占空比
最后使能接口就可以使用了
初始化示例代碼如下
void IIC0Init(u32 baud)
{
u32 t=(SystemCoreClock/4)/baud;
//打開IIC時鐘
LPC_SC->PCONP"=(1<<7);
LPC_SC->PCONP|=(1<<15);//gpio 時鐘
//配置IIC引腳 sda
LPC_PINCON->PINSEL1&=~(0x03<<22);
LPC_PINCON->PINSEL1|=(0x01<<22);
LPC_PINCON->PINMODE1&=~(0x03<<22);
LPC_PINCON->PINMODE1|=(0x01<<22);
LPC_PINCON->PINMODE_OD0|=0x01<<27;
//scl
LPC_PINCON->PINSEL1&=~(0x03<<24);
LPC_PINCON->PINSEL1|=(0x01<<24);
LPC_PINCON->PINMODE1&=~(0x03<<24);
LPC_PINCON->PINMODE1|=(0x01<<24);
LPC_PINCON->PINMODE_OD0|=0x01<<28;
LPC_PINCON->I2CPADCFG=0x0;
LPC_I2C0->I2SCLL=t/2;
LPC_I2C0->I2SCLH=t/2;
LPC_I2C0->I2CONSET=(1< } LPC的IIC使用起來是依靠狀態(tài)組合來判定傳輸狀態(tài)的,而不是像其他單片機依靠標志位識別, 每次控制設備執(zhí)行一個動作之后檢測返回的狀態(tài)位對不對,就可以判定傳輸是否成功,相應的傳送代碼如下 //等待指定的狀態(tài) //失敗返回1 成功返回0 u8 WaitResponse(u8 response) { u8 retry=200; while(--retry) { DelayUs(1); if(STATE==response)break; } if(retry)return0; elsereturn1; } u8 IIC0Start(void) { LPC_I2C0->I2CONCLR=(1< LPC_I2C0->I2CONSET=(1< returnWaitResponse(STATUS_SENDSTART); } u8 IIC0RepeatStart(void) { //repeat start LPC_I2C0->I2CONCLR=(1< LPC_I2C0->I2CONSET=(1< returnWaitResponse(STATUS_REPEATSTART); } u8 IIC0SendWriteAddr(u8 addr) { //dev_addr LPC_I2C0->I2DAT=addr; LPC_I2C0->I2CONSET=(1< LPC_I2C0->I2CONCLR=(1< returnWaitResponse(STATUS_SENDSLAVE_ACK); } u8 IIC0SendData(u8 data) { LPC_I2C0->I2DAT=data; LPC_I2C0->I2CONSET=(1< LPC_I2C0->I2CONCLR=(1< returnWaitResponse(STATUS_SENDDATA_ACK); } u8 IIC0SendStop(void) { LPC_I2C0->I2CONCLR=(1< LPC_I2C0->I2CONCLR=(1< return0; } u8 IIC0SendReadAddr(u8 addr) { LPC_I2C0->I2DAT=addr; LPC_I2C0->I2CONSET=(1< LPC_I2C0->I2CONCLR=(1< returnWaitResponse(STATUS_READADDR_ACK); } u8 IIC0ReadData(u8*value,u8 ack) { if(ack) { LPC_I2C0->I2CONSET=(1< LPC_I2C0->I2CONCLR=(1< if(WaitResponse(STATUS_RECV_ACK))return1; } else { LPC_I2C0->I2CONCLR=(1< if(WaitResponse(STATUS_RECV_NACK))return1; } *value=LPC_I2C0->I2DAT; return0; } 返回的狀態(tài)代碼在系統(tǒng)中的定義為 #define STATUS_SENDSTART 0X08 #define STATUS_REPEATSTART 0X10 #define STATUS_SENDSLAVE_ACK 0X18 #define STATUS_SENDSLAVE_NACK 0X20 #define STATUS_SENDDATA_ACK 0X28 #define STATUS_SENDDATA_NACK 0X30 #define STATUS_LOSS 0X38 #define STATUS_READADDR_NACK 0X48 #define STATUS_READADDR_ACK 0X40 #define STATUS_RECV_ACK 0X50 #define STATUS_RECV_NACK 0X58 通過這一套api就可以完成iic通訊,以下是eeprom的例子 u8 At24cxxWriteBuffer(u16 writeAddr,u8*bufferStart,u8 len) { u8 ret=0; u8 i=0; ret=HwIIC1Start(); // 發(fā)送開始條件 if(ret)return1; if(EE_TYPE>AT24C16) { ret=HwIIC1SendWriteAddr(AT_DEVICE_ADDR); //發(fā)送器件地址 if(ret)return1; ret=HwIIC1SendData((u8)writeAddr>>8);//發(fā)送高八位地址 if(ret)return1; } else { ret=HwIIC1SendWriteAddr(AT_DEVICE_ADDR+((writeAddr/256)<<1)); //發(fā)送器件地址0XA0,寫數(shù)據(jù) if(ret)return1; } ret=HwIIC1SendData((u8)writeAddr); //發(fā)送低八位地址 if(ret)return1; for(i=0;i { ret=HwIIC1SendData(*(bufferStart+i));//發(fā)送數(shù)據(jù) if(ret)return1; } HwIIC1SendStop(); //發(fā)送停止位 DelayMs(5);//5ms等待寫入完成 return0; } u8 At24cxxReadBuffer(u16 readAddr,u8*bufferStart,u8 len) { u8 ret=0; u8 i=0; ret=HwIIC1Start(); // 發(fā)送開始條件 if(ret)return1; if(EE_TYPE>AT24C16) { ret=HwIIC1SendWriteAddr(AT_DEVICE_ADDR); //發(fā)送器件地址 if(ret)return1; ret=HwIIC1SendData((u8)readAddr>>8); //發(fā)送高八位地址 if(ret)return1; } else { ret=HwIIC1SendWriteAddr(AT_DEVICE_ADDR+((readAddr/256)<<1)); //發(fā)送器件地址0XA0,寫數(shù)據(jù) if(ret)return1; } ret=HwIIC1SendData((u8)readAddr);//發(fā)送低八位地址 if(ret)return1; ret=HwIIC1RepeatStart(); //重發(fā)start if(ret)returnret; ret=HwIIC1SendReadAddr(AT_DEVICE_ADDR+1); //進入接收模式 if(ret)returnret; for(i=0;i { ret=HwIIC1ReadData(bufferStart+i,1); //發(fā)送ACK if(ret)returnret; } ret=HwIIC1ReadData(bufferStart+len-1,0);//讀取不發(fā)送ACK if(ret)returnret; HwIIC1SendStop();//產(chǎn)生一個停止條件 return0; }