完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
一.CC2540管脚设置 /*********定义通信管脚**********/ #define SCL P1_5 #define SDA P1_6 /********************设置管脚输入输出*********************/ /* * 根据数据手册 PxSEL寄存器 确定每个端口引脚是做GPIO还是外设IO * PxDIR寄存器 确定端口引脚作为输入还是输出 */ void SDA_OUT(void) { P1SEL &= ~(1 << 6); P1DIR |= (1 << 6); } void SCL_OUT(void) { P1SEL &= ~(1 << 5); P1DIR |= (1 << 5); } void SDA_IN(void) { P1SEL &= ~(1 << 6); P1DIR &=~(1 << 1); } /********************设置管脚高低电平*********************/ void SDA_HIGH(void) { SDA = 1; } void SDA_LOW(void) { SDA = 0; } void SCL_HIGH(void) { SCL = 1; } void SCL_LOW(void) { SCL = 0; } 二.I2C开始和停止信号 i2c_start() A HIGH to LOW transition on the SDA line while SCL is HIGH defines a START condition. void i2c_Start(void) { SCL_LOW(); SDA_HIGH(); SCL_HIGH(); IIC_DELAY(); SDA_LOW(); } i2c_stop() A low-to-high transition on the SDA line while the SCL is high defines a STOP condition. void i2c_Stop(void) { SCL_LOW(); SDA_LOW(); SCL_HIGH(); IIC_DELAY(); SDA_HIGH(); } 三.数据传输 SCL引脚高电平时,SDA数据有效。数据先传递MSB最后是LSB。 /******************读数据*******************/ unsigned char i2c_read_byte(void) { unsigned char i; unsigned char data = 0; SDA_IN(); //设置SDA引脚为输入,为读数据做准备 for(i=0;i<8;i++) { SCL_LOW(); IIC_DELAY(); SCL_HIGH(); //SCL低 延时 SCL高 模拟出第一个脉冲 if(SDA_READ()) { data |= 0x01; } else { data &= ~0x01; //SCL高电平且SDA稳定时,SDA数据有效 } //SDA_READ()读出管脚SDA管脚的电平,并记录到data 当中 data = data<<1; //data向左移位为下一位数据腾出一个bit IIC_DELAY(); } SDA_OUT(); //还原SDA为输出状态 SCL_LOW(); //拉低SCL return data; } /******************写数据*******************/ void i2c_write_byte(unsigned char data) { unsigned char i; SCL_LOW(); //拉低SCL电平,准备发送数据(SCL一变高电平,对应的SDA电平就被读走了,所以要先设置SDA的电平再制造SCL上的脉冲) for(i=0;i<8;i++) { IIC_DELAY(); if(data & 0x80) { SDA_HIGH(); } else { SDA_LOW(); } //设置SDA电平 SCL_HIGH(); //SCL拉高,发送数据 IIC_DELAY(); SCL_LOW(); IIC_DELAY(); data=data<<1; } } 四.ACK和NACK信号 数据传完后的第一个脉冲对应ACK信号,此时SDA=1对应NACK,SDA=0对应ACK。 Each byte of data (including the address byte) is followed by one ACK bit from the receiver. The ACK bit allows the receiver to communicate to the transmitter that the byte was successfully received and another byte may be sent. Before the receiver can send an ACK, the transmitter must release the SDA line. To send an ACK bit, the receiver shall pull down the SDA line during the low phase of the ACK/NACK-related clock period (period 9), so that the SDA line is stable low during the high phase of the ACK/NACK-related clock period. Setup and hold times must be taken into account. When the SDA line remains high during the ACK/NACK-related clock period, this is interpreted as a NACK. There are several conditions that lead to the generation of a NACK: The receiver is unable to receive or transmit because it is performing some real-time function and is not ready to start communication with the master. During the transfer, the receiver gets data or commands that it does not understand. During the transfer, the receiver cannot receive any more data bytes. A master-receiver is done reading data and indicates this to the slave through a NACK. /******************读ack信号*******************/ uint8_t i2c_ReadACK(void) { uint8_t ack; SCL_LOW(); //SCL引脚拉低,准备发出第九个脉冲 SDA_IN(); //设置SDA引脚输入 IIC_DELAY(); SCL_HIGH(); //SCL引脚拉高,发出第九个脉冲 ack=SDA_READ(); //SCL高电平时数据有效,读取SDA的电平,放到ACK中 IIC_DELAY(); SDA_OUT(); //SDA还原为输出 SCL_LOW(); SDA_HIGH(); return ack; } /******************写ack信号*******************/ void i2c_SendACK(void) { SCL_LOW(); //SCL低电平准备发出脉冲 SDA_LOW(); //SDA低电平 IIC_DELAY(); SCL_HIGH(); //SCL拉高,第九个脉冲发出,此时SDA是低电平 IIC_DELAY(); SCL_LOW(); SDA_HIGH(); } /******************写nack信号*******************/ void i2c_SendNACK(void) { SCL_LOW(); //SCL低电平准备发出脉冲 SDA_HIGH(); //SDA高电平 IIC_DELAY(); SCL_HIGH(); //SCL拉高,第九个脉冲发出,此时SDA是高电平 IIC_DELAY(); SCL_LOW(); SDA_HIGH(); } 五.组合以上时序 uint8_t Read(uint8_t addr, uint8_t reg) { uint8_t data; i2c_Start(); i2c_write_byte(addr<<1); i2c_ReadACK(); i2c_write_byte(reg); i2c_ReadACK(); i2c_Start(); i2c_write_byte((addr<<1)+1); i2c_ReadACK(); data=i2c_read_byte(); i2c_SendNACK(); i2c_Stop(); return data; } void Write_Byte(uint8_t addr, uint8_t reg, uint8_t val) { i2c_Start(); i2c_write_byte(addr<<1); i2c_ReadACK(); i2c_write_byte(reg); i2c_ReadACK(); i2c_write_byte(val); i2c_ReadACK(); i2c_Stop(); } 六.逻辑分析仪查看结果 |
|
|
|
只有小组成员才能发言,加入小组>>
3277 浏览 9 评论
2950 浏览 16 评论
3454 浏览 1 评论
8983 浏览 16 评论
4044 浏览 18 评论
1092浏览 3评论
566浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
561浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2297浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1854浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-19 16:34 , Processed in 0.978289 second(s), Total 51, Slave 41 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号