一、硬件介紹
1.MCU:STM32F103C8T6
2.ESP8266:正點原子WIFI模塊
3.串口模塊:正點原子串口模塊
二、準備工作
我們對Markdown編輯器進行了一些功能拓展與語法支持,除了標準的Markdown編輯器功能,我們增加了如下幾點新功能,幫助你用它寫博客:
-
ESP8266固件刷寫
我用的是安信可的固件,可以在官網(wǎng)上下載。正點原子也提供相關的刷寫教程 -
硬件連接
單片機的串口3連接WiFi模塊。WiFi模塊的Vcc接3.3V。串口1接在串口模塊上。
三、STM32主要代碼介紹
mcu跟wifi模塊的代碼實現(xiàn)(涉及串口、定時器):
-
實現(xiàn)思想
單片機向esp8266模塊發(fā)送at指令,并且在一定的時間內(nèi)等待esp8266的回復,如果回復錯誤的指令或者超時回復就把錯誤通過串口1發(fā)送到電腦上。 -
代碼介紹
AT指令發(fā)送函數(shù)
uint8_t esp8266_send_cmd(char *cmd, char *ack, uint16_t waittime) //ESP8266發(fā)送指令(底層函數(shù))
{
uint8_t res = 0;
USART3_RX_STA = 0;
memset(USART3_RX_BUF,0,USART3_REC_LEN); //將串口3的緩存空間清0
WIFI_printf("%s\r\n", cmd); //調(diào)用WIFI模塊專用的發(fā)送函數(shù)
if(waittime) //需要等待應答
{
while(--waittime) //等待倒計時
{
HAL_Delay(10);//HAL庫延時函數(shù)
if(USART3_RX_STA&0x8000) //接收到期待的應答結果
{
if(esp8266_check_cmd((uint8_t *)ack))
{
printf("回復信息:%s\r\n",(uint8_t *)ack);//反饋應答信息
break; //得到有效數(shù)據(jù)
}
USART3_RX_STA=0; //串口3標志位清0
}
}
if(waittime==0)res=1;
}
return res;
}
uint8_t* esp8266_check_cmd(uint8_t *str) //ESP8266檢查指令(底層函數(shù))
{
char *strx=0;
if(USART3_RX_STA&0X8000) //接收到一次數(shù)據(jù)了
{
USART3_RX_BUF[USART3_RX_STA&0X7FFF] = 0; //添加結束符
printf("%s\r\n",(char*)USART3_RX_BUF);
strx=strstr((const char*)USART3_RX_BUF,(const char*)str);
}
return (uint8_t*)strx;
}
uint8_t esp8266_quit_trans(void) //ESP8266退出判斷(底層函數(shù))
{
while((USART3->SR&0X40)==0); //等待發(fā)送空
USART3->DR='+';
HAL_Delay(15); //大于串口組幀時間(10ms)
while((USART3->SR&0X40)==0); //等待發(fā)送空
USART3->DR='+';
HAL_Delay(15); //大于串口組幀時間(10ms)
while((USART3->SR&0X40)==0); //等待發(fā)送空
USART3->DR='+';
HAL_Delay(500); //等待500ms
return esp8266_send_cmd("AT","OK",20); //退出透傳判斷
}
接收狀態(tài)標記、接收緩沖、接收狀態(tài)標記的宏定義
uint8_t USART1_RX_BUF[USART1_REC_LEN];//接收緩沖,最大USART_REC_LEN個字節(jié).
uint16_t USART1_RX_STA=0;//接收狀態(tài)標記//bit15:接收完成標志,bit14:接收到0x0d,bit13~0:接收到的有效字節(jié)數(shù)目
uint8_t USART1_NewData;//當前串口中斷接收的1個字節(jié)數(shù)據(jù)的緩存
uint8_t USART2_RX_BUF[USART2_REC_LEN];//接收緩沖,最大USART_REC_LEN個字節(jié).
uint16_t USART2_RX_STA=0;//接收狀態(tài)標記//bit15:接收完成標志,bit14:接收到0x0d,bit13~0:接收到的有效字節(jié)數(shù)目
uint8_t USART2_NewData;//當前串口中斷接收的1個字節(jié)數(shù)據(jù)的緩存
uint8_t RS485orBT;//當RS485orBT標志位為1時是RS485模式,為0時是藍牙模式
uint8_t USART3_RX_BUF[USART3_REC_LEN];//接收緩沖,最大USART_REC_LEN個字節(jié).
uint16_t USART3_RX_STA=0;//接收狀態(tài)標記//bit15:接收完成標志,bit14:接收到0x0d,bit13~0:接收到的有效字節(jié)數(shù)目
uint8_t USART3_NewData;//當前串口中斷接收的1個字節(jié)數(shù)據(jù)的緩存
串口3跟esp8266通信的底層函數(shù)
void WIFI_printf (char *fmt, ...)
{
char buff[USART3_REC_LEN+1]; //用于存放轉(zhuǎn)換后的數(shù)據(jù) [長度]
uint16_t i=0;
va_list arg_ptr;
va_start(arg_ptr, fmt);
vsnprintf(buff, USART3_REC_LEN+1, fmt, arg_ptr);//數(shù)據(jù)轉(zhuǎn)換
i=strlen(buff);//得出數(shù)據(jù)長度
if(strlen(buff)>USART3_REC_LEN)i=USART3_REC_LEN;//如果長度大于最大值,則長度等于最大值(多出部分忽略)
HAL_UART_Transmit(&huart3,(uint8_t *)buff,i,0xffff);//串口發(fā)送函數(shù)(串口號,內(nèi)容,數(shù)量,溢出時間)
va_end(arg_ptr);
}
//WIFI模塊在TCP模式下的數(shù)據(jù)發(fā)送:TCP發(fā)送的規(guī)定是先發(fā)AT+CIPSEND=數(shù)量,等待返回“>“后再發(fā)送數(shù)據(jù)內(nèi)容。
//調(diào)用方法:WIFI_TCP_SEND("123\r\n"); //TCP方式發(fā)送字符123和回車換行
void WIFI_TCP_SEND (char *fmt, ...)
{
char buff[USART3_REC_LEN+1]; //用于存放轉(zhuǎn)換后的數(shù)據(jù) [長度]
uint16_t i=0;
va_list arg_ptr;
va_start(arg_ptr, fmt);
vsnprintf(buff, USART3_REC_LEN+1, fmt, arg_ptr);//數(shù)據(jù)轉(zhuǎn)換
i=strlen(buff);//得出數(shù)據(jù)長度
if(strlen(buff)>USART3_REC_LEN)i=USART3_REC_LEN;//如果長度大于最大值,則長度等于最大值(多出部分忽略)
WIFI_printf("AT+CIPSEND=%d\r\n",i);//先發(fā)送AT指令和數(shù)據(jù)數(shù)量
HAL_Delay(100);//等待WIFI模塊返回">",此處沒做返回是不是">"的判斷。穩(wěn)定性要求高的項目要另加判斷。
HAL_UART_Transmit(&huart3,(uint8_t *)buff,i,0xffff);//發(fā)送數(shù)據(jù)內(nèi)容(串口號,內(nèi)容,數(shù)量,溢出時間)
va_end(arg_ptr);
}
串口1的重定向和串口3、定時器的中斷回調(diào)函數(shù),文章來源:http://www.zghlxwxcb.cn/news/detail-426749.html
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)//串口中斷回調(diào)函數(shù)
{
if(huart ==&huart3)//判斷中斷來源(串口3:WIFI模塊)//接收完的一批數(shù)據(jù),還沒有被處理,則不再接收其他數(shù)據(jù)
{
if(USART3_RX_STA<USART3_REC_LEN)//還可以接收數(shù)據(jù)
{
__HAL_TIM_SET_COUNTER(&htim2,0); //計數(shù)器清空
if(USART3_RX_STA==0) //使能定時器2的中斷
{
__HAL_TIM_ENABLE(&htim2); //使能定時器2
}
USART3_RX_BUF[USART3_RX_STA++] = USART3_NewData;//最新接收數(shù)據(jù)放入數(shù)組
}
else
{
USART3_RX_STA|=0x8000;//強制標記接收完成
}
HAL_UART_Receive_IT(&huart3,(uint8_t *)&USART3_NewData,1); //再開啟串口3接收中斷
}
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim ==&htim2)//判斷是否是定時器2中斷(定時器到時表示一組字符串接收結束)
{
USART3_RX_BUF[USART3_RX_STA&0X7FFF]=0;//添加結束符
USART3_RX_STA|=0x8000;//接收標志位最高位置1表示接收完成
__HAL_TIM_CLEAR_FLAG(&htim2,TIM_EVENTSOURCE_UPDATE );//清除TIM2更新中斷標志
__HAL_TIM_DISABLE(&htim2);//關閉定時器2
}
}
int fputc(int ch, FILE *f) //串口重定向
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
return ch;
}
##不想寫了,主要核心代碼可以參考正點原子的,大家不懂的可以私信,看到一定回復。文章來源地址http://www.zghlxwxcb.cn/news/detail-426749.html
到了這里,關于STM32F103C8T6+ESP8266WIFI+DHT11模塊連接巴法云的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!