作者寄語:
在我學(xué)習(xí)單片機(jī)串口發(fā)送與接收數(shù)據(jù)的時候,對串口的掌握不熟悉,看了不少的學(xué)習(xí)資料。今天與大家分享使用HAL庫封裝ESP8266經(jīng)過串口發(fā)送與接收數(shù)據(jù)的函數(shù)。當(dāng)然,我會用很詳細(xì)的過程帶著大家去了解程序,因?yàn)槲乙彩菑囊粋€初學(xué)者慢慢走過來的。在這里我也感謝教過我知識的那些老師與分享知識的同學(xué)們。
正文
一、使用STM32CubeMX創(chuàng)建KEIL程序
1、打開STM32CubeMX軟件后,選擇STM32F103C8T6的MCU,在可視化界面對我們所需要的引腳進(jìn)行功能配置。
圖1.1 STM32CubeMX可視化界面2、本次使用串口編寫代碼,需要對串口IO口的引腳配置。
PA10→USART1_RX
PA9 →USART1_TX
圖1.2 引腳IO口配置3、配置完成后,生成我們所需要的keil文件。
二、串口程序的編寫
我們使用到的是ESP8266WIFI模塊的UDP通信方式,所以我們需要編寫一個方便我們發(fā)送與接收AT指令的串口代碼。
1、清空接收數(shù)據(jù)的函數(shù)void ESP8266_RecieveClear(void)
void ESP8266_RecieveClear(void)//向模塊發(fā)送數(shù)據(jù)
{
memset((uint8_t *)usart_rx_buf, 0 ,200);//metset數(shù)據(jù)清空函數(shù)
//把usart_rx_but里面的200數(shù)據(jù)全部賦值為0
}
void *memset(void *buffer, int c, int count)
// buffer:為指針或是數(shù)組
// c:是賦給buffer的值
// count:是buffer的長度
2、數(shù)據(jù)發(fā)送的函數(shù)uint8_t ESP8266_SendCMD(char *cmd, char *reply, uint16_t time)
我們先來看HAL庫自帶的串口發(fā)送函數(shù):
USART1_Transmit(uint8_t *data, uint16_t len, uint16_t time)
這個串口發(fā)送函數(shù)顯然是只管發(fā)送數(shù)據(jù),不管數(shù)據(jù)是否發(fā)送成功。對于我們接下來的操作肯定是不行的。
首先我們要了解講解編寫的函數(shù)功能:
①,數(shù)據(jù)發(fā)送并且接收返回的數(shù)據(jù),已達(dá)到判斷AT指令是否發(fā)送成功(例如發(fā)送AT,返回給OK或者ERROR)
②,數(shù)據(jù)發(fā)送等待時間自定義(因?yàn)锳T指令每個指令數(shù)據(jù)返回的時間不同,我們需要對不同的AT指令設(shè)置不同的等待時間。
例如:我們上課時間為45分鐘,課間休息時間10分鐘,如果我們設(shè)置上課時間和課間休息都為45分鐘,那肯定是不行的。)
③,程序基本適用于所有的AT指令操作。
uint8_t ESP8266_SendCMD(char *cmd, char *reply, uint16_t time)
//因?yàn)槲覀儼l(fā)送數(shù)據(jù)后接收的數(shù)據(jù)要去判斷返回的數(shù)據(jù)和設(shè)置去判斷的數(shù)據(jù)正確與否,此時就需要去讓他傳回一個參數(shù)。
//char *cmd -- 發(fā)送的AT指令
//char *repley -- 判斷的數(shù)據(jù)
//uint16_t time --數(shù)據(jù)等待的時間,當(dāng)設(shè)置time為20ms時,20ms內(nèi)收到數(shù)據(jù),就返回正常,大于20ms未返回數(shù)據(jù),就返回異常。
uint8_t ESP8266_SendCMD(char *cmd, char *reply, uint16_t time)
{
char Save_Buf[256] = {0};//保存收到的數(shù)據(jù)
//發(fā)送數(shù)據(jù)函數(shù),AT指令每次發(fā)送數(shù)據(jù)都需要加入\r\n,所以需要對這個函數(shù)進(jìn)行封裝。
//因此每次要對CMD數(shù)據(jù)判斷是否有結(jié)尾換行字符,有換行字符就不處理,沒有換行字符就增加換行字符
//ESP8266_RecieveClear(cmd, sizeof);
//使用strcat函數(shù)來進(jìn)行兩個字符的拼接,也可以使用strcpy
//例如a = "abc", b = "def";
//strcat(a,b); 結(jié)果a = "abcdef"
1,保存?zhèn)魅氲闹噶? Strcat(Save_Buf, cmd);//先把cmd的數(shù)據(jù)保存在Save_Buf
//使用strstr函數(shù)判斷Save_Buf有沒有換行字符
//例如a = '"abc", b = "c", c = "efg"
//strstr(a, b) = 3
//strstr(a, c) = 0(或者NULL)
2,處理AT指令(添加換行)
if(strstr(Save_Buf, "\r\n") == 0)
{
//能夠進(jìn)入這里說明Save_Buf沒有"\r\n",所以要給Save_Buf添加\r\n
Strcat(Save_Buf, "\r\n");//Save_Buf增加\r\n
}
3,清空數(shù)據(jù),防止之前的數(shù)據(jù)未被清理,影響后面使用
//為防止之前的數(shù)據(jù)未被清理,所以在這里清空一下Save_Buf里的數(shù)據(jù)
ESP8266_RecieveClear();
4,發(fā)送數(shù)據(jù)
//此時使用數(shù)據(jù)發(fā)送函數(shù)
ESP8266_RecieveClear((uint8_t *)Save_Buf, sizeof(Save_Buf), 500);
5,接收數(shù)據(jù)
memset((uint8_t *)Save_Buf, 0 ,256);//清理數(shù)據(jù)Save_Buf
USART1_Recieve(Save_Buf);
6,判斷接收的數(shù)據(jù)是否與reply數(shù)據(jù)相同
//Time的時間等待,若時間內(nèi)AT指令發(fā)送成功,返回為1,否則為0
while(time != 0)
{
//判斷Save_Buf有數(shù)據(jù)
if(USART1_Receive((uint8_t *)Save_Buf))
{
//發(fā)回的數(shù)據(jù)與repley校驗(yàn),相同返回1,不相同繼續(xù)判斷
if(strstr(Save_Buf, reply))
{
printf("%s Send OK");
return 1;
}
else
{
time --;
HAL_Delay(1);//比如time為500,在500ms內(nèi)一直去判斷接收的數(shù)據(jù)是否正確
}
}
}
//超過time時間內(nèi)沒有返回reply的數(shù)據(jù),就返回失敗
printf("%s Send Error");
}
如何使用數(shù)據(jù)發(fā)送函數(shù)呢?
當(dāng)我們給ESP8266模塊發(fā)送AT指令時,看一下返回的結(jié)果:
AT \r\n
OK
如果不加\r\n
AT
Error
數(shù)據(jù)發(fā)送函數(shù)的使用:
ESP8266_SendCMD("AT", "OK", 500);
//解析:給模塊發(fā)送AT指令,500ms之內(nèi)返回"OK",說明數(shù)據(jù)發(fā)送成功。
//若返回Error,說明數(shù)據(jù)發(fā)送失敗?;蛘叱瑫r500ms也會返回失敗
大家多提建議,我們一起學(xué)習(xí)成長。
審核編輯:湯梓紅
評論
查看更多