完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
本帖最后由 8号菜刀 于 2015-9-22 13:21 编辑
/* 作者:天空 日期:2014.5.12 功能:利用GPIO口模拟I2C总线,对传感器寄存器读取数据 注意:如果需要移植些文件到其他设备上,需要更改的函数地方 1、利用GPIO口模拟的数据线SDA和时钟线SCL,注意需要更改GPIO口 2、从设备地址。不同的从设备,地址不一样,注意修改。(在I2C写寄存器和读寄存器的函数中,如果是写,在读的地址上加1.) 经验:利用GPIO口模拟I2C总线时,需要注意的是,在应答信号和读数据的时候,一定要将SDA数据线配置为输入。 */ #define SCL P0_5//定义P0.5口为时钟线 #define SDA P0_4//定义P0.4口为数据线 typedef unsigned int uint; typedef unsigned char uchar; typedef unsigned short ushort; /*延时函数*/ void Delay(void) { } /*I2C总线实始化,将P0.4和P0.5配置为输出口,并且拉高*/ /* I2C总线的开始时序: 1、将数据线SDA和时钟线SCL全部拉高 */ void I2C_Init(void) { P0SEL &= ~0x30;//将P0.4和P0.5配置为GPIO口 P0DIR |= 0x30;//将P0.4和P0.5配置为输出 P0 |= 0x30;//将P0.4和P0.5设置为高电平 } /*I2C总线的开始信号*/ /* I2C总线的开始时序: 1、将SDA数据线拉高 2、将SCL时钟线拉高,延时一段时间 3、在SCL为高电平时,拉低SDA,延时一段时间 总结:就是在SCL为高电平时,在SDA上给一个下降沿,表示开始信号。 */ void I2C_Start(void) { SDA = 1; SCL = 1; Delay(); SDA = 0; Delay(); } /*I2C总线的停止信号*/ /* I2C总线的停止时序: 1、将SDA数据线拉低 2、将SCL数据线拉高,延时一段时间 3、在SCL为高电平时,将SDA数据线拉高,延时一段时间 总结:在SCL为高电平时,在SDA上给一下上升沿,表示停止信号。 */ void I2C_Stop(void) { SDA = 0; SCL = 1; Delay(); SDA = 1; Delay(); } /*I2C总线的应答信号*/ /* I2C总线应答时序: 1、首先是需要将模拟数据线的SDA口配置为输入口。 2、将时钟线SCL拉高,延时一段时间 3、等待从设备应答,从设备应答时,SDA上会产生一个高电平,主设备的GPIO口检测到高电平,则表示应答成功。 4、如果检测到应答信号,则拉SCL时钟线拉低。延时一段时间。 5、将模拟SDA口的GPIO口配置为输出。 */ void I2C_Ack(void) { P0DIR &= ~0x10;//注意这里,数据线应该设置为输入 uint i = 0; SCL = 1; Delay(); //等待应答 while((SDA == 1)&&(i<255)) i++; SCL = 0; Delay(); P0DIR |= 0x10;//将数据线SDA设置为输出 } /*I2C总线写数据函数,将要写的数据传递给形参I2CBuf*/ /* I2C写数据时序: 注意:由于I2C属于串行总线,所以数据都是一位一位的传输 1、将SCL时钟线拉高,准备传输数据,延时一段时间 2、将I2CBuf的最高位传输到SDA数据线上 3、拉低SCL时钟线,延时一段时间 小结:当SCL有一个上升沿时,传输数据。 以上三步表示传输完一位数据。然后将I2CBuf左移一位,再重复以上三步。 最后,将SCL位低,延时一段时间,再将SDA位高,延时一段时间。此操作是为了释放时钟线SCL和数据线SDA. */ void I2C_Write(uint I2CBuf) { uint iwi; for(iwi = 0; iwi < 8; iwi++) { SCL = 0; Delay(); if(I2CBuf & 0x80) SDA = 1; else SDA = 0; SCL = 1; Delay(); I2CBuf = I2CBuf << 1; } SCL = 0; Delay(); SDA = 1; Delay(); } /*I2C总线读数据函数,该函数具有返回值I2CBuf*/ /* I2C读数据函数的时序: 注意:首先需要将模拟SDA数据线的GPIO口配置为输入 1、将时钟线SCL拉高,延时一段时间 2、读取数据线SDA上的电平,然后写入I2CBuf的最低位。 3、拉低SCL时钟线,延时一段时间 小结:当SCL有一个下降沿时,读取数据。 以上三步表示读取一位数据,读一个字节,需要重复以上操作步骤8次。 */ uint I2C_Read(void) { uint iri; uint I2CBuf = 0; P0DIR &= ~0x10;//注意这里,需要将SDA配置为输入。 Delay(); for(iri = 0; iri < 8; iri++) { I2CBuf = I2CBuf << 1;//此步不可少 SCL = 1; Delay(); if(SDA == 1) I2CBuf |= 0x01; else I2CBuf &= 0xfe; SCL = 0; Delay(); } P0DIR |= 0X10;//将SDA配置为输出 return I2CBuf;//将读到的数据存入I2CBuf中,然后返回给主调函数 } /* I2C总线写寄存器函数,将寄存器地址传给形参RegAdd,将要写入的数据传递给RegValue。 注意:地址和数据最好都采用十六进制 */ /* I2C写寄存器函数的时序: 1、主设备先发出一个开始信号 2、然后写入从设备地址。每一个从设备的地址是唯一的。 3、主设备接收应答信号 4、主设备向从设备写入寄存器的地址 5、主设备接收应答信号 6、主设备向从设备写入数据 7、主设备接收应答信号 8、主设备发出停止信号 */ void I2C_WriteReg(uint RegAdd, uint RegValue) { I2C_Start(); I2C_Write(0xd0);//0xd0是从设置的地址,不同的设备,地址不同。所以移植些函数时,需要更改此处。 I2C_Ack(); I2C_Write(RegAdd);//先写地址,此地址为需要写入数据的寄存器地址 I2C_Ack(); I2C_Write(RegValue);//写入数据 I2C_Ack(); I2C_Stop(); } /*I2C总线读寄存器函数,将需要读取数据的寄存器的地址传递给形参RegAdd,此函数有返回值*/ /* I2C读寄存器函数的时序: 1、主设备发出开始信号 2、写入从设备地址 3、主设备接收从设备发来的应答信号 4、写入寄存器地址 5、主设备接收应答信号 6、主设备再次发出开始信号 7、主设备向从设备写入(从设备的地址+1),此时加1表示要从寄存器中读数据 8、从设备给出应答信号 9、从从设备的寄存器中读出数据传给变量 10、主设备发出停止信号 11、返回读出的数据 */ uint I2C_ReadReg(uint RegAdd) { uchar date; I2C_Start(); I2C_Write(0xd0);//先写入从设备的地址。表示要向从设备中写地址和数据 I2C_Ack(); I2C_Write(RegAdd);//写入寄存器的地址,数据将从些地址中读出 I2C_Ack(); I2C_Start(); I2C_Write(0xd1);//从设备的地址加1,表示要读从设备中寄存器的数据 I2C_Ack(); date = I2C_Read();//从地址RegAdd中读出数据 I2C_Stop(); return date;//将读出的数据存入date中,然后返回给主调函数。 } |
|
相关推荐
5 个讨论
|
|
感谢分享,回去试一试
|
|
|
|
|
|
好东西啊啊啊啊啊啊啊啊啊啊啊啊啊
|
|
|
|
|
|
国外伺服技术方案转让
编码器采用研发17-bit(160000ppr)高分辨率增量编码器; 转子磁铁采用稀土永磁材料;高速冲压模日本进口矽钢片铁芯 内置位置、速度和扭矩控制模式,支持外部模拟量控制;匹配公司自主研发17-bit高分辨率增量编码器;支持RS232、RS485通讯规格,标准Modbus通讯协议;精密控制、性能稳定、性价比高。 采用抗干扰和防震动设计,适用范围广,性能稳定;类型包含17-bit、20-bit增量式和绝对值编码器。 产品广泛应用于制造业(攻丝机、绕线机、雕铣机、数控车床、数控加工中心、线切割机、铣床、磨床、注塑机、绣花机、纺织机、包装机、印刷机、激光雕刻机、木工机械等),工业自动化(机器人、机械手臂、生产线自动化飞镖机械等),航空业、汽车工业、新能源(风能、电动汽车等)以及其他机械自动化工控领域。 扣扣:二五一二二六二四七一 |
|
|
|
|
|
不好意思,请问您能跟我具体说一下是怎么操作吗?因为我现在有一个传感器,然后需要用到GPIO口模拟I2C,开发板是TQ2440的,在其上移植了Linux系统。所以我的传感器驱动是按照接I2C的样子写还是写寄存器那样的驱动?
|
|
|
|
|
|
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-5 06:01 , Processed in 0.785468 second(s), Total 52, Slave 42 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号