項(xiàng)目需要在stm32上開發(fā)MQTT址否,同時(shí)MQTT協(xié)議基于TCP/IP協(xié)議,因此先在探索者開發(fā)板上調(diào)通基于TCP的WiFi通信,同時(shí)采集溫濕度數(shù)據(jù)霎肯,上傳至PC端的網(wǎng)絡(luò)調(diào)試助手服務(wù)端趾痘,為后面開發(fā)MQTT做準(zhǔn)備慢哈。
1、準(zhǔn)備工作
1.1.STM32F4開發(fā)板
1.2.DHT11溫濕度傳感器
DHT11是一款有已校準(zhǔn)數(shù)字信號輸出的溫濕度傳感器永票。 其精度濕度±5%RH卵贱, 溫度±2℃,量程濕度20-90%RH侣集, 溫度0~50℃键俱。傳感器包括一個(gè)電阻式感濕元件和一個(gè)NTC測溫元件,并與一個(gè)高性能8位單片機(jī)相連接世分。每個(gè)DHT11傳感器都在極為精確的濕度校驗(yàn)室中進(jìn)行校準(zhǔn)编振。校準(zhǔn)系數(shù)以程序的形式存在OTP內(nèi)存中,傳感器內(nèi)部在檢測信號的處理過程中要調(diào)用這些校準(zhǔn)系數(shù)臭埋。單線制串行接口踪央,使系統(tǒng)集成變得簡易快捷。
1.3.esp8266 WiFi模塊
esp8266模塊采用串口與MCU進(jìn)行通信瓢阴,內(nèi)置TCP/IP協(xié)議棧畅蹂,能夠?qū)崿F(xiàn)串口與WiFi之間的轉(zhuǎn)換,模塊支持串口轉(zhuǎn)WiFi STA炫掐、串口轉(zhuǎn)AP和WiFi STA+WiFiAP的模式魁莉,從而快速構(gòu)建串口-WiFi數(shù)據(jù)傳輸方案。
2. esp8266模塊使用
2.1 esp8266模塊使用介紹
esp8266模塊使用方便募胃,開發(fā)過程中可使用AT指令對模塊進(jìn)行操作旗唁,及可使用stm32的串口發(fā)送相關(guān)AT指令控制模塊。模塊作為TCP連接客戶端時(shí)使用的AT指令如下所示:
AT:測試模塊是否工作正常
AT+RST:復(fù)位模塊狀態(tài)
設(shè)置客戶端模式
AT+CWMODE=1:客服端 Station
AT+CWMODE=2:用戶端 AP
AT+CWMODE=3:雙端Station+AP
AT+CWJAP="wifi名","密碼":連接指定WiFi
TCP連接:AT+CIPSTART="TCP","目標(biāo)IP",目標(biāo)端口號 如:AT+CIPSTART="TCP","192.168.1.1",8080
開啟傳透模式:AT+CIPMODE=1 關(guān)閉穿透模式:AT+CIPMODE=0
開啟透傳后痹束,使用AT+CIPSEND開啟數(shù)據(jù)發(fā)送
TCP發(fā)送數(shù)據(jù)到服務(wù)器全流程如下:
1. AT 檢測模塊是否工作正常
2. AT+CIPMODE=0 關(guān)閉透傳
3. AT+CWMODE=1 客服端STA模式
4. AT+CWJAP="wifi","password"
5. AT+CIPSTART="TCP","目標(biāo)ip地址",目標(biāo)端口
6. AT+CIPMODE=0 開啟透傳
發(fā)送數(shù)據(jù)有兩種方法
一 1. AT+CIPSEND (開啟傳輸數(shù)據(jù))
2. > (這個(gè)符號代表等待輸入,回車發(fā)送,在程序里用\r\n轉(zhuǎn)義發(fā)送)
3. +++ (發(fā)送+++代表退出發(fā)送,串口助手里需要關(guān)閉發(fā)送新行才能關(guān)閉發(fā)送,程序里用+++\r\n關(guān)閉)
二 1. AT+CIPSEND=num (指定發(fā)送數(shù)據(jù)長度,由于指定長度,達(dá)到長度后會自動(dòng)發(fā)送,并退出發(fā)送)
2. > (這個(gè)符號代表等待輸入,回車發(fā)送,在程序里用\r\n轉(zhuǎn)義發(fā)送)
2.2 STM32操作esp8266模塊
在實(shí)際使用中检疫,STM32通過串口發(fā)送相關(guān)的AT指令給模塊進(jìn)行相應(yīng)的操作。芯片上電后祷嘶,首先進(jìn)行串口3的初始化屎媳,初始化中波特率設(shè)置為115200夺溢,同時(shí)配置一個(gè)100ms的定時(shí)器中斷,用于判斷數(shù)據(jù)接收的連續(xù)性烛谊。這里也編寫了相應(yīng)的串口3中斷服務(wù)函數(shù)风响,用于接收WiFi模塊收到的數(shù)據(jù)。串口3中斷服務(wù)函數(shù)如下:
//通過判斷接收連續(xù)2個(gè)字符之間的時(shí)間差不大于100ms來決定是不是一次連續(xù)的數(shù)據(jù).
//如果2個(gè)字符接收間隔超過100ms,則認(rèn)為不是1次連續(xù)數(shù)據(jù).也就是超過100ms沒有接收到
//任何數(shù)據(jù),則表示此次接收完畢.
//接收到的數(shù)據(jù)狀態(tài)
//[15]:0,沒有接收到數(shù)據(jù);1,接收到了一批數(shù)據(jù).
//[14:0]:接收到的數(shù)據(jù)長度
u16 USART3_RX_STA=0;
void USART3_IRQHandler(void)
{
u8 res;
if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)//接收到數(shù)據(jù)
{
res =USART_ReceiveData(USART3);
if((USART3_RX_STA&(1<<15))==0)//接收完的一批數(shù)據(jù),還沒有被處理,則不再接收其他數(shù)據(jù)
{
if(USART3_RX_STA<USART3_MAX_RECV_LEN) //還可以接收數(shù)據(jù)
{
TIM_SetCounter(TIM7,0);//計(jì)數(shù)器清空
if(USART3_RX_STA==0)
TIM_Cmd(TIM7, ENABLE); //使能定時(shí)器7
USART3_RX_BUF[USART3_RX_STA++]=res; //記錄接收到的值
}else
{
USART3_RX_STA|=1<<15; //強(qiáng)制標(biāo)記接收完成
}
}
}
}
串口3初始化完成后丹禀,通過發(fā)送AT指令進(jìn)行WiFi模塊的初始化状勤,這里編寫了esp8266_init()函數(shù)對模塊進(jìn)行了相關(guān)的配置,代碼如下:
void esp8266_init(void)
{
u8 *p;
p=mymalloc(SRAMIN,100); //申請100字節(jié)的內(nèi)存
atk_8266_quit_trans();
POINT_COLOR=RED;//設(shè)置字體為紅色
LCD_ShowString(30,50,200,16,16,"Wifi Connecting...");
while(atk_8266_send_cmd("AT","OK",20)); //檢查WiFi模塊是否在線
{
atk_8266_quit_trans(); //退出透傳
atk_8266_send_cmd("AT+CIPMODE=0","OK",200); //關(guān)閉透傳模式
}
while(atk_8266_send_cmd("ATE0","OK",20));//關(guān)閉回顯
atk_8266_send_cmd("AT+CWMODE=3","OK",50); //設(shè)置為STA模式
atk_8266_send_cmd("AT+RST","OK",40);
delay_ms(1000);
delay_ms(1000);
delay_ms(1000);
delay_ms(1000);
atk_8266_send_cmd("AT+CWAUTOCONN=0","OK",50);
sprintf((char*)p,"AT+CWJAP=\"%s\",\"%s\"",wifiap_ssid,wifiap_password);
atk_8266_send_cmd(p,"OK",800); //連接AP
delay_ms(3000);
delay_ms(2000);
atk_8266_send_cmd("AT+CIPMUX=0","OK",20);
sprintf((char*)p,"AT+CIPSTART=\"TCP\",\"%s\",%s",(u8*)ip,(u8*)portnum);
while(atk_8266_send_cmd(p,"OK",200)){} //連接服務(wù)端
Connect_Flag=1;
atk_8266_send_cmd("AT+CIPMODE=1","OK",200); //開啟透傳
myfree(SRAMIN,p); //釋放內(nèi)存
}
其中双泪,服務(wù)器用了PC端的網(wǎng)絡(luò)調(diào)試助手進(jìn)行模擬持搜,WiFi模塊與PC同時(shí)連接同一個(gè)WiFi熱點(diǎn),在PC上開啟網(wǎng)絡(luò)調(diào)試助手作為服務(wù)器焙矛,IP地址為局域網(wǎng)內(nèi)分配給PC的I地址葫盼,端口號自己定義,如下圖所示:
esp8266模塊配置完成后村斟,當(dāng)需要通過WiFi發(fā)送數(shù)據(jù)時(shí)贫导,調(diào)用串口3發(fā)送函數(shù)即可向服務(wù)器發(fā)送數(shù)據(jù)。串口3發(fā)送數(shù)據(jù)可以使用庫函數(shù)USART_SendData(USART_TypeDef* USARTx, uint16_t Data)蟆盹,這里使用該庫函數(shù)重新封裝了一個(gè)串口發(fā)送函數(shù)脱盲,可以進(jìn)行固定長度的數(shù)據(jù)幀發(fā)送。
/************串口3的發(fā)送函數(shù)************/
//串口3,printf 函數(shù)
//確保一次發(fā)送數(shù)據(jù)不超過USART3_MAX_SEND_LEN字節(jié)
void u3_printf(char* fmt,...)
{
u16 i,j;
va_list ap;
va_start(ap,fmt);
vsprintf((char*)USART3_TX_BUF,fmt,ap);
va_end(ap);
i=strlen((const char*)USART3_TX_BUF);//此次發(fā)送數(shù)據(jù)的長度
for(j=0;j<i;j++)//循環(huán)發(fā)送數(shù)據(jù)
{
while(USART_GetFlagStatus(USART3,USART_FLAG_TC)==RESET); //等待上次傳輸完成
USART_SendData(USART3,(uint8_t)USART3_TX_BUF[j]); //發(fā)送數(shù)據(jù)到串口3
}
}
3.DHT11溫濕度模塊
3.1 模塊介紹
DHT11與單片機(jī)之間能采用簡單的單總線進(jìn)行通信日缨,僅僅需要一個(gè)I/O口。傳感器內(nèi)部濕度和溫度數(shù)據(jù)40Bit的數(shù)據(jù)一次性傳給單片機(jī)掖看,數(shù)據(jù)采用校驗(yàn)和方式進(jìn)行校驗(yàn)匣距,有效的保證數(shù)據(jù)傳輸?shù)臏?zhǔn)確性。
從DHT11讀取的溫濕度數(shù)據(jù)組成如下所示:
3.2 STM32操作DHT11
檢測DHT11是否正常
//等待DHT11的回應(yīng)
//返回1:未檢測到DHT11的存在
//返回0:存在
u8 DHT11_Check(void)
{
u8 retry=0;
DHT11_IO_IN();//SET INPUT
while (DHT11_DQ_IN&&retry<100)//DHT11會拉低40~80us
{
retry++;
delay_us(1);
};
if(retry>=100)return 1;
else retry=0;
while (!DHT11_DQ_IN&&retry<100)//DHT11拉低后會再次拉高40~80us
{
retry++;
delay_us(1);
};
if(retry>=100)return 1;
return 0;
}
DHT11讀取溫濕度并校驗(yàn)
//從DHT11讀取一次數(shù)據(jù)
//temp:溫度值(范圍:0~50°)
//humi:濕度值(范圍:20%~90%)
//返回值:0,正常;1,讀取失敗
u8 DHT11_Read_Data(u8 *temp,u8 *humi)
{
u8 buf[5];
u8 i;
DHT11_Rst();
if(DHT11_Check()==0)
{
for(i=0;i<5;i++)//讀取40位數(shù)據(jù)
{
buf[i]=DHT11_Read_Byte();
}
if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
{
*humi=buf[0];
*temp=buf[2];
}
}else return 1;
return 0;
}
4.運(yùn)行結(jié)果
配置好DHT11和esp8266模塊后哎壳,在主函數(shù)while(1)中循環(huán)計(jì)時(shí)毅待,定時(shí)讀取溫濕度數(shù)據(jù)并通過WiFi上傳至PC端。
while(1)
{
if(t%10==0)//每100ms讀取一次
{
DHT11_Read_Data(&temperature,&humidity); //讀取溫濕度值
LCD_ShowNum(30+40,150,temperature,2,16); //顯示溫度
LCD_ShowNum(30+40,170,humidity,2,16); //顯示濕度
atk_8266_quit_trans();
atk_8266_send_cmd("AT+CIPSEND","OK",20); //開始透傳
sprintf((char*)p,"溫度為:%d℃,濕度為:%d %\r\n",temperature,humidity);
u3_printf("%s",p);
}
delay_ms(100);
t++;
}
這里同時(shí)用到了LCD顯示屏在開發(fā)板上顯示溫濕度的數(shù)據(jù)归榕,作為輔助功能尸红,本文就不展開講LCD的配置與使用了。
開發(fā)板上讀取溫濕度的結(jié)果圖如下
在PC端網(wǎng)絡(luò)調(diào)試助手上也定時(shí)接收到了溫濕度數(shù)據(jù)刹泄。