Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
I2C_IIC
模拟IIC_I2C
10
传感器使用I2C-TOOL获取到设备地址与说明书上不一致,按说明书编写死活获取不到数据
发布于 2024-05-23 18:50:43 浏览:701
订阅该版
**RTT写的代码** ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240523/754353181d2c955fd0b7c801f8775d73.png.webp) 返回错误 Failed to read gas concentration, error code: -8 修改后代码如下,还是返回错误代码-8 ```c static rt_device_t i2c_bus = NULL; #define SLAVE_ADDR 0x2A #define READ_CMD 0xA1 static rt_err_t read_gas_concentration(struct rt_i2c_bus_device *bus, uint16_t *concentration) { rt_uint8_t cmd_buf[2] = {0xA1, 0x55}; rt_uint8_t data_buf[2] = {0, 0}; struct rt_i2c_msg msgs[2]; rt_err_t result; // 步骤1:发送命令和从机地址 msgs[0].addr = SLAVE_ADDR; msgs[0].flags = RT_I2C_WR; msgs[0].buf = cmd_buf; msgs[0].len = sizeof(cmd_buf); // 步骤2:读取气体浓度的两个字节 msgs[1].addr = SLAVE_ADDR; msgs[1].flags = RT_I2C_RD; msgs[1].buf = data_buf; msgs[1].len = sizeof(data_buf); result = rt_i2c_transfer(bus, msgs, 2); if (result != 2) { LOG_D("Reading gas concentration failed with error code: %d\n", result); return -RT_ERROR; } // 计算气体浓度 *concentration = (data_buf[0] << 8) | data_buf[1]; LOG_D("Gas concentration: %d\n", *concentration); return RT_EOK; } ``` **传感器规格书内说明如下:** ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240523/e602a4d2034b57f556aa8573406d29a1.png.webp) 说明:读取出来的数据为当前气体浓度。 浓度值计算公式:气体浓度=DATA(高位)*256+DATA(低位) 5.6读取流程: 该传感器上电后需要预热,时长 30 秒左右。预热完成后,进入正常工作状态。接入I2C 总线, 主机发送读命令后进入读取状态,传感器会立即返回一个 16 位数据值,该数据表示当前检测的气体浓度值,浓度值计算公式:气体浓度=DATA(高位)*256+DATA(低位)。 下图是一次I2C 通信过程的读取时序:起始信号 start,发送从机地址 0x54,接收到从机应答信号 ACK, 发送读命令 0xA1,接收到从机应答信号ACK;起始信号 start,发送从机地址 0x55,接收到从机应答信号ACK,读取气体浓度高字节,发送到从机应答信号ACK, 读取气体浓度低字节,结束信号Stop。 ```c /*读取浓度*/ static uint16_t IIC_Read_Byte(u8 reg) { uint8_t rec_data; I2C_Start(); I2C_SendByte(0x54); I2C_WaitAck(); I2C_SendByte(0xe1); I2C_WaitAck(); I2C_Start(); I2C_SendByte(0x55); I2C_WaitAck(); rec_data = I2C_RecvByte(); rec_data16 = rec_data; I2C_SendACK(0); rec_data = I2C_RecvByte(); rec_data16 = rec_data16 << 8 | rec_data; I2C_Stop(); return rec_data16; } /*起始信号*/ u8 I2C_Start(void) { SDA1H; I2C_delay(); SCL1H; I2C_delay(); if (!SDAread) return 0; SDA1L; I2C_delay(); if (SDAread) return 0; SCL1L; I2C_delay(); return 1; } /*发送一个字节*/ void I2C_SendByte(u8 SendByte) //数据从高位到低位// { u8 i = 8; SCL1L; for (i = 0; i < 8; i++) //8位计数器 { if (SendByte & 0x80) //SDA准备 SDA1H; else SDA1L; SCL1H; //拉高时钟,给从机采样 I2C_delay(); //延时保持IIC时钟频率,也是给从机采样有充足时间 SCL1L; //拉低时钟,给SDA准备 I2C_delay(); //延时保持IIC时钟频率 SendByte <<= 1; //移出数据的最高位 } } /*等待ACK*/ u8 I2C_WaitAck(void) //返回为:=1有ACK,=0无ACK { uint16_t i = 0; SDA1H; //释放SDA SCL1H; //SCL拉高进行采样 while (SDAread) //等待SDA拉低 { i++; //等待计数 if (i == 1000) //超时跳出循环 break; } if (SDAread) //再次判断SDA是否拉低 { SCL1L; return 0; //从机应答失败,返回0 } I2C_delay(); //延时保证时钟频率低于40K, SCL1L; I2C_delay(); //延时保证时钟频率低于40K, return 1; //从机应答成功,返回1 } /*接受八位数据*/ u8 I2C_RecvByte(void) //数据从高位到低位// { u8 i = 8; u8 ReceiveByte = 0; SDA1H; //释放SDA,给从机使用 I2C_delay(); //延时给从机准备SDA时间 for (i = 0; i < 8; i++) //8位计数器 { ReceiveByte <<= 1; SCL1H; //拉高时钟线,采样从机SDA if (SDAread) //读数据 ReceiveByte |= 0x01; I2C_delay(); //延时保持IIC时钟频率 SCL1L; //拉低时钟线,处理接收到的数据 I2C_delay(); //延时给从机准备SDA时间 } return ReceiveByte; } /*结束信号*/ void I2C_Stop(void) { SCL1L; I2C_delay(); SDA1L; I2C_delay(); SCL1H; I2C_delay(); SDA1H; I2C_delay(); } /*IIC等待延时*/ void I2C_delay(void) { int x = 5; u8 i = 100; x = i * x; while (x--); } void I2C_SendACK(u8 i) { if (i == 1) SDA1H; else SDA1L; SCL1H; I2C_delay(); SCL1L; I2C_delay(); } ```
查看更多
winfeng
认证专家
2024-05-24
这家伙很懒,什么也没写!
参考这篇:https://club.rt-thread.org/ask/question/c3382a54e3b500fb.html 注意,你的传感器需要写两个字节(命令A1和从机地址55)msg[0],读2个字节msg[1];
5
个回答
默认排序
按发布时间排序
xiaorui
认证专家
2024-05-23
小睿手办 https://item.taobao.com/item.htm?id=674889867009
不管啥问题,先接上逻辑分析仪。
Rb君
认证专家
2024-05-23
这家伙很懒,什么也没写!
用RTT的设备驱动框架写呗,I2C框架,我之前用这个软件包都是验证扫描从机ID的
NickZhou
2024-05-23
这家伙很懒,什么也没写!
各位大哥可以帮帮忙看看为何读取不到数值吗
StackYuan
认证专家
2024-05-28
这家伙很懒,什么也没写!
最后一帧貌似有问题的,从机在交代完成数据后没有返回ACK,这个逻辑可能与主机需要的不符,进而造成了P状态,主机那边出现了错误。。即便这样返回了错误状态,你的数据缓冲区应该已经收到对应的数据了 另外,并不是所有传感器严格遵循I2C通用标准:一些传感器本质上使用了MCU模拟IO的方式做I2C从机,那么它存在较大的时序风险,例如SCL频率不能超过或者小于xxx Hz;或者通信时序上选择了非标,例如9bit位宽、ACK和NACK的自定义等。 I2C这块有很多不严谨的地方,例如7bit还是8bit地址表示,复位广播帧等,这些都是新手容易掉进去的坑,有逻辑分析仪作为佐证是很棒的方法 我觉得以上都不是问题,你买传感器卖家提供的代码如果不是很想用,但也许可能需要多看一眼一些细节之处
撰写答案
登录
注册新账号
关注者
0
被浏览
701
关于作者
NickZhou
这家伙很懒,什么也没写!
提问
1
回答
1
被采纳
0
关注TA
发私信
相关问题
1
NXP的I2C应该比ST的好用吧
2
Use of I2C device driver
3
关于I2C 驱动问题请教
4
我如何知道这个iic的io配置和我电路设计的是一致的?
5
I2C模拟读操作失败,不知道问什么进不去读函数
6
RTT的I2C有官方文档资料没有
7
求 STM32F103 IIC 自定义IO初始化 代码
8
报一个LPC4008代码中I2C的bug
9
RTOS IIC总线使用
10
关于在RTT中使用STM32 I2C的疑问
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
【RT-Thread】【ci】【scons】将ci.attachconfig.yml和scons结合使用
2
Rt-thread中OTA下载后,bootloader不搬程序
3
ulog 日志 LOG_HEX 输出时间改为本地日期时间
4
在RT-Thread Studio中构建前执行python命令
5
研究一了一段时间RTT,直接标准版上手太难,想用nano,但又舍不得组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
I2C_IIC
ESP8266
UART
WIZnet_W5500
ota在线升级
cubemx
PWM
flash
freemodbus
BSP
packages_软件包
潘多拉开发板_Pandora
定时器
ADC
flashDB
GD32
socket
编译报错
中断
Debug
rt_mq_消息队列_msg_queue
SFUD
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
xusiwei1236
8
个答案
2
次被采纳
踩姑娘的小蘑菇
1
个答案
2
次被采纳
用户名由3_15位
9
个答案
1
次被采纳
bernard
4
个答案
1
次被采纳
RTT_逍遥
3
个答案
1
次被采纳
本月文章贡献
聚散无由
2
篇文章
15
次点赞
catcatbing
2
篇文章
5
次点赞
Wade
2
篇文章
4
次点赞
Ghost_Girls
1
篇文章
7
次点赞
xiaorui
1
篇文章
2
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部