stm32+AHT10-硬件模拟I2C采集温湿度数据通过usart1在串口助手中打印,开发过程详解

工程已经调试好了,需要的小伙伴在留言处留下邮箱

我已经上传在CSDN,https://download.csdn.net/download/qq_41840148/12185225

我硬件模拟的是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 }
I2C_Start
 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_Stop

上面从数据手册截的图下面的字已经解释了开始信号和停止信号的过程了嘛

这里也重复一遍吧

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 }
init_AHT10

第二个触发测量的函数

 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 }
startMeasure_AHT10

第三个发送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 }
read_AHT10

第四个计算温湿度值的内容和第三个组合在一起了

手册中有个基本命令集,前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 }
reset_AHT10

那么到这里我们要用的代码已经基本完成了

如果仔细看我们代码完全是按照手册里面的图来编程的

到了最后一步,把上面四个函数写成一个流程函数就可以使用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 }
read_AHT10_once

 这里还有一张表10没有介绍

他在采集数据的最后一步if( (readByte[0] & 0x68) == 0x08 )用得上

因为时间问题不多介绍了,画图一下就能明白为什么要这个判断

记录到这里就结束了,感觉记得东西有点乱

今天也加油啊

猜你喜欢

转载自www.cnblogs.com/hjf-log/p/stm32-aht10.html