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<<I2EN);//接口使能
}
LPC的IIC使用起来是依靠状态组合来判定传输状态的,而不是像其他单片机依靠标志位识别,
每次控制设备执行一个动作之后检测返回的状态位对不对,就可以判定传输是否成功,相应的传送代码如下
//等待指定的状态
//失败返回1 成功返回0
u8 WaitResponse(u8 response)
{
u8 retry = 200;
while(--retry)
{
DelayUs(1);
if(STATE == response)break;
}
if(retry)return 0;
else return 1;
}
u8 IIC0Start(void)
{
LPC_I2C0->I2CONCLR = (1<<SIC)|(1<<STAC)|(1<<AAC);
//Start
LPC_I2C0->I2CONSET = (1<<STA);
return WaitResponse(STATUS_SENDSTART);
}
u8 IIC0RepeatStart(void)
{
//repeat start
LPC_I2C0->I2CONCLR = (1<<SIC);
LPC_I2C0->I2CONSET = (1<<STA);
return WaitResponse(STATUS_REPEATSTART);
}
u8 IIC0SendWriteAddr(u8 addr)
{
//dev_addr
LPC_I2C0->I2DAT = addr;
LPC_I2C0->I2CONSET = (1<<AA);
LPC_I2C0->I2CONCLR = (1<<SIC)|(1<<STAC);
return WaitResponse(STATUS_SENDSLAVE_ACK);
}
u8 IIC0SendData(u8 data)
{
LPC_I2C0->I2DAT = data;
LPC_I2C0->I2CONSET = (1<<AA);
LPC_I2C0->I2CONCLR = (1<<SIC);
return WaitResponse(STATUS_SENDDATA_ACK);
}
u8 IIC0SendStop(void)
{
LPC_I2C0->I2CONCLR = (1<<SIC)|(1<<STAC)|(1<<AAC);
LPC_I2C0->I2CONSET = (1<<STO);
LPC_I2C0->I2CONCLR = (1<<SIC);
return 0;
}
u8 IIC0SendReadAddr(u8 addr)
{
LPC_I2C0->I2DAT = addr;
LPC_I2C0->I2CONSET = (1<<AA);
LPC_I2C0->I2CONCLR = (1<<SIC)|(1<<STAC);
return WaitResponse(STATUS_READADDR_ACK);
}
u8 IIC0ReadData(u8* value,u8 ack)
{
if(ack)
{
LPC_I2C0->I2CONSET = (1<<AA);
LPC_I2C0->I2CONCLR = (1<<SIC);
if( WaitResponse(STATUS_RECV_ACK))return 1;
}
else
{
LPC_I2C0->I2CONCLR = (1<<AAC)|(1<<SIC);
if(WaitResponse(STATUS_RECV_NACK))return 1;
}
*value = LPC_I2C0->I2DAT;
return 0;
}
返回的状态代码在系统中的定义为
#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)return 1;
if(EE_TYPE > AT24C16)
{
ret = HwIIC1SendWriteAddr(AT_DEVICE_ADDR); //发送器件地址
if(ret)return 1;
ret = HwIIC1SendData((u8)writeAddr>>8); //发送高八位地址
if(ret)return 1;
}
else
{
ret = HwIIC1SendWriteAddr(AT_DEVICE_ADDR+((writeAddr/256)<<1)); //发送器件地址0XA0,写数据
if(ret)return 1;
}
ret = HwIIC1SendData((u8)writeAddr); //发送低八位地址
if(ret)return 1;
for(i = 0; i < len; i++)
{
ret = HwIIC1SendData(*(bufferStart+i)); //发送数据
if(ret)return 1;
}
HwIIC1SendStop(); //发送停止位
DelayMs(5); //5ms等待写入完成
return 0;
}
u8 At24cxxReadBuffer(u16 readAddr,u8* bufferStart,u8 len)
{
u8 ret = 0;
u8 i = 0;
ret = HwIIC1Start(); // 发送开始条件
if(ret)return 1;
if(EE_TYPE > AT24C16)
{
ret = HwIIC1SendWriteAddr(AT_DEVICE_ADDR); //发送器件地址
if(ret)return 1;
ret = HwIIC1SendData((u8)readAddr>>8); //发送高八位地址
if(ret)return 1;
}
else
{
ret = HwIIC1SendWriteAddr(AT_DEVICE_ADDR+((readAddr/256)<<1)); //发送器件地址0XA0,写数据
if(ret)return 1;
}
ret = HwIIC1SendData((u8)readAddr); //发送低八位地址
if(ret)return 1;
ret = HwIIC1RepeatStart(); //重发start
if(ret)return ret;
ret = HwIIC1SendReadAddr(AT_DEVICE_ADDR+1); //进入接收模式
if(ret)return ret;
for(i = 0; i < len-1; i++)
{
ret = HwIIC1ReadData(bufferStart+i,1); //发送ACK
if(ret)return ret;
}
ret = HwIIC1ReadData(bufferStart+len-1,0);//读取不发送ACK
if(ret)return ret;
HwIIC1SendStop();//产生一个停止条件
return 0;
}
转载于:https://www.cnblogs.com/dengxiaojun/p/4338678.html
LPC1768的iic通讯相关推荐
- 树莓派IIC通讯获取BMI08x IMU数据进行姿态解算,并通过UART/TCP在rviz上显示
截至2021年,树莓派出的最新款应该是Raspberry Pi 400,设计得跟键盘一样,很难想象到这是个树莓派,尤其是它的标语写的很好"你的下一个电脑,何必是电脑",不言而喻.反 ...
- ARM+SD2405 IIC_RTC驱动编写及IIC通讯协议
IIC通讯协议 协议简介 IIC(inter-integrated Circuit集成电路总线)总线支持设备之间的短距离通信,用于处理器和一些外围设备之间的接口,它需要两根信号线来完成信息交换,它是由 ...
- 示波器观察IIC通讯协议-STM32F4读写24C08EEPROM时序图-新人首更
示波器观察时序不是因为好奇,是因为遇到了问题 STM32F4探索者开发板板载24C02EEPROM,自制了一块开发板,需要存储容量更大的24C08A芯片,焊接后发现开发板上能成功运行的程序,在自己的板 ...
- STM32之IIC通讯-SHT30温湿度采集
一.实验目的:通过单片机普通IO口,模拟IIC时序,掌握IIC通讯协议. 二.实验用到的主控芯片:STM32F103RCT6,IIC通讯引脚IIC_SDA:PC11,IIC_SCL:PC12 三.SH ...
- 8、RH850 F1 IIC通讯功能和配置
前言: 续上章节UART后,此章讲解的IIC也是最常见的串行通讯,广泛应用于单片机和单片机之间通讯.同样这里IIC的具体原理讲解就不做介绍,不清楚的朋友可移步up主的个人专栏 ---- "串 ...
- Bq769XX IIC 通讯 ALERT引脚
Bq769X 初入BMS,很可能会选用到TI的这颗料,扩展性和可用性都还不错.但是在调试过程中,会有几个点让初入的人摸不着点. IIC通讯 TI的这个通讯准确说叫Mbus,但是实际与IIC通讯差异不大 ...
- #C51 IIC通讯(底层配置时序)
系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 例如: 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 系列文章目录 前言 一.场景 二.I ...
- STM32之IIC通讯升级版--SHT30温湿度读取
针对上篇文章对于程序可移植性不强的问题进行优化,基本思路是首先搭建好IIC底层驱动程序,该程序可用于任何IIC通讯设备,然后针对不同的IIC设备单独编写应用程序,本篇文章仍以SHT30为例. 一.II ...
- STM32与Atmega8之间IIC通讯
STM32(主机)与Atmega8(从机)之间IIC通讯 注:本文仅供学习交流,有侵权之处,我将及时删除. 1.电路连接 2.代码 https://pan.baidu.com/s/1ni2OGHiM9 ...
最新文章
- 实战Nagios+Ganglia发送警告信息,短信,微信等
- python中标识符下划线用作开头_python python中那些双下划线开头的那些函数都是干啥用用的...
- tomcat 外网访问不了_免费云服务器/jdk环境配置/Tomcat简单配置
- 为你的项目启用可空引用类型
- android 访问sqlite,android中访问已有的sqlite数据库
- 那两个告扎克伯格抄袭的斜杠青年,后来怎么样了?
- 转载:Android Display架构分析--侧重高通平台
- 限定概率抽奖_LOL:欧皇一次抽奖得16个永久皮肤 把老马亏得坐公交啦
- 芯片上链,英特尔加入蚂蚁区块链生态
- LeetCode:Restore IP Addresses
- 固态硬盘用软件测试掉速严重,SSD固态硬盘掉速怎么办?手动执行TRIM指令缓解固态硬盘掉速方法...
- jmeter之badboy
- 5V升压充电12.6V锂电池方案
- QT 打开PDF文件或图片文件
- draft伦理——第七章
- 移动端 meta 解释
- EasyCVR家庭远程视频监控解决方案
- 端口映射工具PortTunnel
- 双十一大促有哪些数码好物值得推荐?好用的数码好物清单表分享
- c语言文件按字节读取整数,C语言逐行读取文件