工程已經調試好了,需要的小伙伴在留言處留下郵箱
我已經上傳在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 }

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 )用得上
因為時間問題不多介紹了,畫圖一下就能明白為什么要這個判斷
記錄到這里就結束了,感覺記得東西有點亂
今天也加油啊