LPC1768的iic通讯
扫描二维码
随时随地手机看文章
LPC1768有三路IIC,其中IIC0支持高速模式和plus模式,另外两路是普通IIC,使用IIC的过程如下
首先依然是打开IIC时钟,同时打开GPIO时钟
然后配置引脚为IIC功能
另外,因为iic0支持plus结构,所以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使用起来是依靠状态组合来判定传输状态的,而不是像其他单片机依靠标志位识别, 每次控制设备执行一个动作之后检测返回的状态位对不对,就可以判定传输是否成功,相应的传送代码如下 //等待指定的状态 //失败返回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; } 返回的状态代码在系统中的定义为 #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(); // 发送开始条件 if(ret)return1; if(EE_TYPE>AT24C16) { ret=HwIIC1SendWriteAddr(AT_DEVICE_ADDR); //发送器件地址 if(ret)return1; ret=HwIIC1SendData((u8)writeAddr>>8);//发送高八位地址 if(ret)return1; } else { ret=HwIIC1SendWriteAddr(AT_DEVICE_ADDR+((writeAddr/256)<<1)); //发送器件地址0XA0,写数据 if(ret)return1; } ret=HwIIC1SendData((u8)writeAddr); //发送低八位地址 if(ret)return1; for(i=0;i { ret=HwIIC1SendData(*(bufferStart+i));//发送数据 if(ret)return1; } HwIIC1SendStop(); //发送停止位 DelayMs(5);//5ms等待写入完成 return0; } u8 At24cxxReadBuffer(u16 readAddr,u8*bufferStart,u8 len) { u8 ret=0; u8 i=0; ret=HwIIC1Start(); // 发送开始条件 if(ret)return1; if(EE_TYPE>AT24C16) { ret=HwIIC1SendWriteAddr(AT_DEVICE_ADDR); //发送器件地址 if(ret)return1; ret=HwIIC1SendData((u8)readAddr>>8); //发送高八位地址 if(ret)return1; } else { ret=HwIIC1SendWriteAddr(AT_DEVICE_ADDR+((readAddr/256)<<1)); //发送器件地址0XA0,写数据 if(ret)return1; } ret=HwIIC1SendData((u8)readAddr);//发送低八位地址 if(ret)return1; ret=HwIIC1RepeatStart(); //重发start if(ret)returnret; ret=HwIIC1SendReadAddr(AT_DEVICE_ADDR+1); //进入接收模式 if(ret)returnret; for(i=0;i { ret=HwIIC1ReadData(bufferStart+i,1); //发送ACK if(ret)returnret; } ret=HwIIC1ReadData(bufferStart+len-1,0);//读取不发送ACK if(ret)returnret; HwIIC1SendStop();//产生一个停止条件 return0; }