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 )用得上

因為時間問題不多介紹了,畫圖一下就能明白為什么要這個判斷

 

記錄到這里就結束了,感覺記得東西有點亂

今天也加油啊

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM