stm32+AHT10-硬件模拟I2C采集温湿度数据通过usart1在串口助手中打印,开发过程详解
工程已经调试好了,需要的小伙伴在留言处留下邮箱
我已经上传在
链接:https://pan.baidu.com/s/1AR1sqO29ZrZluRJz_P6yyQ?pwd=bbpr
提取码:bbpr
我硬件模拟的是PB6和PB7,PB7做SDA,PB6做SCL
还有两个孔肯定就是3.3V和GND啦,接线方法就这样,不上图了
给大家看一下模块的样子
还有在串口助手中打印的图片
除了温度和湿度的数据,那些上面打印的上面"start1234------成功了"都是我代码调试的过程
因为懒就没有删除啦,大家如果自己使用可以自己决定去留
显示的温度湿度我也没有打印出单位,可以自行加上
看完效果了现在来讲一下开发的过程
1、首先是准备一个IO口模拟I2C的工程,这个网上资源实在是太多了就不重复了
2、在http://www.aosong.com/奥松电子的官网找到AHT10的规格书,我这里的是19年10月15的规格书
3、接下来就可以开始看着规格书来编程了
那么翻到AHT10数据手册,也就是规格书的第7页5 传感器通讯
这个程序样例也是C写的,我看格式应该猜是arduino的,没去注意,我们继续
那么5.1啥的告诉你传感器要上电这种我们就跳过吧
应该不会有人忘记传感器要供电吧...
5.2告诉我们I2C每次传输数据都要有个启动和停止嘛
那么我们先写好这两个函数的代码

1 void I2C_Start(void) 2 { 3 SDA_OUT(); 4 IIC_SCL = 1; 5 delay_ms(4); 6 7 IIC_SDA = 1; 8 delay_ms(4); 9 IIC_SDA = 0; 10 delay_ms(4); 11 12 IIC_SCL = 0; 13 delay_ms(4); 14 }

1 void I2C_Stop(void) 2 { 3 SDA_OUT(); 4 IIC_SDA = 0; 5 delay_ms(4); 6 7 IIC_SCL = 1; 8 delay_ms(4); 9 10 IIC_SDA = 1; 11 delay_ms(4); 12 }
上面从数据手册截的图下面的字已经解释了开始信号和停止信号的过程了嘛
这里也重复一遍吧
I2C的启动:SCL为高电平时,SDA的电平从高变到低,这就是启动信号
I2C的停止:SCL为高电平时,SDA的电平从低变到高,这就是停止信号
另外提一个I2C协议的东西,假如我已经启动传输数据了,当SCL为高电平的时候,SDA是不允许变动电平的,必须保持稳定
传输数据中,SCL为高时,数据传输SDA数据必须保持其中一种状态
当传输完成时,SCL拉低时,SDA才可以变动电平等待下一次发送
我们继续
5.3主机stm32往从机AHT10发送命令
从实物图的那个103电阻我们也可以看出AHT10的设备地址是0x38
那么添加一个SDA的方向我们要传输的数据是什么呢
假设我们SDA的方向是主机往从机写内容W:‘0’
我用画图描述一下
就是往0x38后面添加一个0,最前面的数据丢掉,转为新的16进制数据0x70
1110 0001代表初始化也就是0xE1
1010 1100代表温湿度测量也就是0xBA
我们继续下一页来到传感器的读取流程
这个流程的函数我们写一下,代码中if else打印的内容是调试过程可以删除
第一个使能位Bit[3]不为1时的函数,初始化代码

1 void init_AHT10(void) 2 { 3 I2C_Start(); 4 5 I2C_WriteByte(0x70); 6 ack_status = Receive_ACK(); 7 if(ack_status) printf("3"); 8 else printf("3-n-"); 9 I2C_WriteByte(0xE1); 10 ack_status = Receive_ACK(); 11 if(ack_status) printf("4"); 12 else printf("4-n-"); 13 I2C_WriteByte(0x08); 14 ack_status = Receive_ACK(); 15 if(ack_status) printf("5"); 16 else printf("5-n-"); 17 I2C_WriteByte(0x00); 18 ack_status = Receive_ACK(); 19 if(ack_status) printf("6"); 20 else printf("6-n-"); 21 I2C_Stop(); 22 }
第二个触发测量的函数

1 void startMeasure_AHT10(void) 2 { 3 //------------ 4 I2C_Start(); 5 6 I2C_WriteByte(0x70); 7 ack_status = Receive_ACK(); 8 if(ack_status) printf("7"); 9 else printf("7-n-"); 10 I2C_WriteByte(0xAC); 11 ack_status = Receive_ACK(); 12 if(ack_status) printf("8"); 13 else printf("8-n-"); 14 I2C_WriteByte(0x33); 15 ack_status = Receive_ACK(); 16 if(ack_status) printf("9"); 17 else printf("9-n-"); 18 I2C_WriteByte(0x00); 19 ack_status = Receive_ACK(); 20 if(ack_status) printf("10"); 21 else printf("10-n-"); 22 I2C_Stop(); 23 }
第三个发送0x71读取采集的温湿度数据

1 void read_AHT10(void) 2 { 3 uint8_t i; 4 5 for(i=0; i<6; i++) 6 { 7 readByte[i]=0; 8 } 9 10 //------------- 11 I2C_Start(); 12 13 I2C_WriteByte(0x71); 14 ack_status = Receive_ACK(); 15 if(ack_status) printf("11"); 16 else printf("11-n-"); 17 readByte[0]= I2C_ReadByte(); 18 printf("test0:%d",readByte[0]); 19 Send_ACK(); 20 21 readByte[1]= I2C_ReadByte(); 22 printf("test1:%d",readByte[1]); 23 Send_ACK(); 24 25 readByte[2]= I2C_ReadByte(); 26 printf("test2:%d",readByte[2]); 27 Send_ACK(); 28 29 readByte[3]= I2C_ReadByte(); 30 printf("test3:%d",readByte[3]); 31 Send_ACK(); 32 33 readByte[4]= I2C_ReadByte(); 34 printf("test4:%d",readByte[4]); 35 Send_ACK(); 36 37 readByte[5]= I2C_ReadByte(); 38 printf("test5:%d",readByte[5]); 39 SendNot_Ack(); 40 //Send_ACK(); 41 42 I2C_Stop(); 43 44 //-------------- 45 if( (readByte[0] & 0x68) == 0x08 ) 46 { 47 H1 = readByte[1]; 48 H1 = (H1<<8) | readByte[2]; 49 H1 = (H1<<8) | readByte[3]; 50 H1 = H1>>4; 51 52 H1 = (H1*1000)/1024/1024; 53 54 T1 = readByte[3]; 55 T1 = T1 & 0x0000000F; 56 T1 = (T1<<8) | readByte[4]; 57 T1 = (T1<<8) | readByte[5]; 58 59 T1 = (T1*2000)/1024/1024 - 500; 60 61 AHT10_OutData[0] = (H1>>8) & 0x000000FF; 62 AHT10_OutData[1] = H1 & 0x000000FF; 63 64 AHT10_OutData[2] = (T1>>8) & 0x000000FF; 65 AHT10_OutData[3] = T1 & 0x000000FF; 66 printf("成功了"); 67 } 68 else 69 { 70 AHT10_OutData[0] = 0xFF; 71 AHT10_OutData[1] = 0xFF; 72 73 AHT10_OutData[2] = 0xFF; 74 AHT10_OutData[3] = 0xFF; 75 printf("失败了"); 76 77 } 78 printf("\r\n"); 79 printf("温度:%d%d.%d",T1/100,(T1/10)%10,T1%10); 80 printf("湿度:%d%d.%d",H1/100,(H1/10)%10,H1%10); 81 printf("\r\n"); 82 }
第四个计算温湿度值的内容和第三个组合在一起了
手册中有个基本命令集,前2个我们已经在上面的代码实现了,把软复位也完成一下

1 void reset_AHT10(void) 2 { 3 4 I2C_Start(); 5 6 I2C_WriteByte(0x70); 7 ack_status = Receive_ACK(); 8 if(ack_status) printf("1"); 9 else printf("1-n-"); 10 I2C_WriteByte(0xBA); 11 ack_status = Receive_ACK(); 12 if(ack_status) printf("2"); 13 else printf("2-n-"); 14 I2C_Stop(); 15 16 /* 17 AHT10_OutData[0] = 0; 18 AHT10_OutData[1] = 0; 19 AHT10_OutData[2] = 0; 20 AHT10_OutData[3] = 0; 21 */ 22 }
那么到这里我们要用的代码已经基本完成了
如果仔细看我们代码完全是按照手册里面的图来编程的
到了最后一步,把上面四个函数写成一个流程函数就可以使用AHT10显示温湿度
流程里面我们默认校准使能为0,开头进行一次软复位在执行采集流程

1 void read_AHT10_once(void) 2 { 3 delay_ms(10); 4 5 reset_AHT10(); 6 delay_ms(10); 7 8 init_AHT10(); 9 delay_ms(10); 10 11 startMeasure_AHT10(); 12 delay_ms(80); 13 14 read_AHT10(); 15 delay_ms(5); 16 }
这里还有一张表10没有介绍
他在采集数据的最后一步if( (readByte[0] & 0x68) == 0x08 )用得上
因为时间问题不多介绍了,画图一下就能明白为什么要这个判断
记录到这里就结束了,感觉记得东西有点乱
今天也加油啊
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现