ESP8266:web
本次STM32控制ESP8266使用的ESP芯片版本是ESP8266-01S,主機MCU使用的是STM32F1C8T6。json
ESP8266是樂鑫公司的一款WIFI芯片(Soc),而且能夠被看成MCU使用。實際上,ESP系列芯片是一款發行量巨大,性價比極高的芯片。api
本次我想要實現的功能是獲取網絡時間供MCU使用,因此選擇結構簡單的一款封裝——ESP01S,ESP01S的具體參數以下(圖源:安信可ESP8266開發手冊)數組
與STM32 C8T6的鏈接方式以下:(圖源:安信可ESP8266開發手冊)網絡
ESP8266的通訊方式是串口通訊,因爲我的開發需求,我選擇的是USART2接口,實際串口可自主選擇。app
程序初始化(usart2.c):函數
須要初始化的片上外設有USART2,具體以下:spa
void USART2_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //GPIO時鐘 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE); //串口外設時鐘 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //推輓複用輸出 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOA,&GPIO_InitStructure); GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING; //浮空輸入 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOA,&GPIO_InitStructure); USART_InitStructure.USART_BaudRate = 115200 ; //波特率,這裏改成115200與ESP8266通訊 USART_InitStructure.USART_WordLength=USART_WordLength_8b; //數據幀字長 8位 USART_InitStructure.USART_StopBits=USART_StopBits_1; //配置中止位 1個 USART_InitStructure.USART_Parity=USART_Parity_No; //校驗位,無校驗位 USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None; //不使用用硬件流控制 USART_InitStructure.USART_Mode=USART_Mode_Tx|USART_Mode_Rx; //收發一體 USART_Init(USART2,&USART_InitStructure); //完成初始化 USART_Cmd(USART2,ENABLE); //使能串口 USART_ITConfig(USART2,USART_IT_RXNE,ENABLE); //使能串口中斷 //優先級配置 NVIC_InitStructure.NVIC_IRQChannel=USART2_IRQn; NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0; NVIC_InitStructure.NVIC_IRQChannelSubPriority=0; NVIC_Init(&NVIC_InitStructure); }
由於咱們須要發送,接收ESP芯片的信息,因此這裏需重定向printf函數到串口,並定義接收中斷函數(接收中斷函數部分參考網上大佬思路)3d
//輸出重定向 int fputc(int ch, FILE *f) { while((USART2->SR&0X40)==0);//循環發送,直到發送完畢 USART2->DR = (u8) ch; return ch; }
//接收中斷 void USART2_IRQHandler(void) { u8 Res; if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) { Res =USART_ReceiveData(USART2); //讀取接收到的數據 if((USART_RX_STA2&0x8000)==0)//接收未完成 { if(USART_RX_STA2&0x4000)//接收到了0x7D} { if(Res!=0x7D)USART_RX_STA2=0;//接收錯誤,從新開始 else USART_RX_STA2|=0x8000; //接收完成了 } else //還沒收到0X7D } { if(Res==0x7D)USART_RX_STA2|=0x4000; else { USART_RX_BUF2[USART_RX_STA2&0X3FFF]=Res ; USART_RX_STA2++; if(USART_RX_STA2>(1024-1))USART_RX_STA2=0;//接收數據錯誤,從新開始接收 } } } } }
在接收中斷中,有兩個變量在函數頭進行全局聲明,並在頭文件中進行extern聲明,方便其餘函數使用。code
其中USART_RX_BUF2[512]用於接收數據,長度自定。
//usart2.c函數頭
#include "stm32f10x.h" #include "stm32f10x_usart.h" #include "usart2.h" #include <stdio.h> u8 USART_RX_BUF2[512]; u16 USART_RX_STA2;
向ESP8266發送信息
接下來,進行ESP01.c文件的構建,首先想要得到時間,必須先鏈接互聯網。
void ESP01_Getweb(void) { delay_ms(50); printf("AT+CWMODE=1"); delay_ms(50); RST_ON; delay_ms(100); RST_OFF; delay_ms(50); USART_RX_STA2=0x0000; printf("AT+CWJAP=\"WIFI name\",\"password\""); delay_ms(1000); //注意delay時間限制 delay_ms(1000); delay_ms(1000); delay_ms(1000); delay_ms(1000); }
這裏延時狀況由具體狀況而定,可適當縮短。ESP的鏈接僅需一次便可,下次在一樣的環境下可自主登入。
而後是獲取網絡時間,這裏須要調用一個網絡API接口,這個接口會返回標準網絡時間。
void ESP01_Gettime(void) { printf("AT+CIPMUX=0\r\n"); delay_ms(500); printf("AT+CIPSTART=\"TCP\",\"api.k780.com\",80\r\n"); delay_ms(1600); printf("AT+CIPMODE=1\r\n"); delay_ms(500); printf("AT+CIPSEND\r\n"); delay_ms(500); USART_RX_STA2=0x0000; //使數據從數組頭開始記錄 printf("GET http://api.k780.com:88/?app=life.time&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=json&HTTP/1.1\r\n"); delay_ms(1600); }
這裏延時能夠根據自身狀況而定,實際上在每次發送指令後,ESP都會返回數據,能夠由此判斷是否接收成功數據。
接收完成後,數據會儲存在USART_RX_BUF2這個數組中,經過提取有效信息,便可獲取時間,自此,經過ESP獲取時間就完成了(實測成功)。
(因爲我的水平有限,在程序中,可能會出現冗餘或低效的地方,請注意) =)