LPC2478的IIC使用
LPC2478带有三个IIC接口,每个IIC都可以工作在主机或者从机模式下,LPC的IIC的架构是一种状态机的形式,在不同的的时间做不同的工作之后有不同的状态来表示,
简单来说,就是发送起始字节之后会有一个状态,接收到ACK之后会有一个状态,软件上根据已知的外设状态来进行下一步操作
具体的状态请查看数据手册,IIC的可用寄存器如下
对应不同的驱动方式,例如I2EN为1+STA为1,代表发送起始位+从机地址
将置位寄存器的数据清零,BIT一一对应
状态机的核心
数据发送缓存
从机地址,最高位读写位硬件自动加上
还有两个寄存器是SCL低电平占空比和高电平占空比,均为50%即可
具体代码如下所示
#ifndef __IIC0_H_ #define __IIC0_H_ #include "common.h" #include "lpc24xx.h" #include "clock.h" #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 void IIC0Init(u32 baud); u8 IIC0Start(void); u8 IIC0SendWriteAddr(u8 addr); u8 IIC0SendData(u8 data); u8 IIC0SendStop(void); u8 IIC0SendReadAddr(u8 addr); u8 IIC0ReadData(u8* value,u8 ack); u8 IIC0RepeatStart(void); #endif
#include "iic.h" #define I20EN 6 //接口使能 #define STA 5 //起始标志 #define STO 4 //停止标志 #define SI 3 //中断标志 #define AA 2 //应答标志 #define I20ENC 6 // #define STAC 5 #define SIC 3 #define AAC 2 #define STATE (I20STAT & 0xf8) void IIC0Init(u32 baud) { u32 t = (SystemCoreClock/4)/baud; //打开IIC时钟 PCONP |= (1 << 7); //配置IIC引脚 sda PINSEL1 &= ~(0x03<<22); PINSEL1 |= (0x01<<22); PINMODE1 &= ~(0x03<<22); PINMODE1 |= (0x01<<22); //scl PINSEL1 &= ~(0x03<<24); PINSEL1 |= (0x01<<24); PINMODE1 &= ~(0x03<<24); PINMODE1 |= (0x01<<24); I20SCLL = t/2; I20SCLH = t/2; I20CONSET = (1<<I20EN);//接口使能 } //等待指定的状态 //失败返回1 成功返回0 u8 WaitResponse(u8 response) { u8 retry = 200; while(--retry) { if(STATE == response)break; } if(retry)return 0; else return 1; } u8 IIC0Start(void) { I20CONCLR = (1<<SIC)|(1<<STAC)|(1<<AAC); //Start I20CONSET = (1<<STA); return WaitResponse(STATUS_SENDSTART); } u8 IIC0RepeatStart(void) { //repeat start I20CONCLR = (1<<SIC); I20CONSET = (1<<STA); return WaitResponse(STATUS_REPEATSTART); } u8 IIC0SendWriteAddr(u8 addr) { //dev_addr I20DAT = addr; I20CONSET = (1<<AA); I20CONCLR = (1<<SIC)|(1<<STAC); return WaitResponse(STATUS_SENDSLAVE_ACK); } u8 IIC0SendData(u8 data) { I20DAT = data; I20CONSET = (1<<AA); I20CONCLR = (1<<SIC); return WaitResponse(STATUS_SENDDATA_ACK); } u8 IIC0SendStop(void) { I20CONCLR = (1<<SIC)|(1<<STAC)|(1<<AAC); I20CONSET = (1<<STO); I20CONCLR = (1<<SIC); return 0; } u8 IIC0SendReadAddr(u8 addr) { I20DAT = addr; I20CONSET = (1<<AA); I20CONCLR = (1<<SIC)|(1<<STAC); return WaitResponse(STATUS_READADDR_ACK); } u8 IIC0ReadData(u8* value,u8 ack) { if(ack) { I20CONSET = (1<<AA); I20CONCLR = (1<<SIC); if( WaitResponse(STATUS_RECV_ACK))return 1; } else { I20CONCLR = (1<<AAC)|(1<<SIC); if(WaitResponse(STATUS_RECV_NACK))return 1; } *value = I20DAT; return 0; }