原文地址:http://m.codes51.com/article/detail_318577.html
esp8266的STM32驱动,数据发送接收由DMA完成,释放CPU。
目前只能发送返回消息为成功或失败的AT命令,并判断是否成功,详见esp8266_cmd();其它返回消息不可预知的命令(如查看AP,IP等)未实现,也用不着。以查询的方式判断有无消息,是什么样的消息,返回消息类型,如果是收到了数据,则会保存在指定的地址,并给出长度,详见esp8266_parse();当连接建立后,给远程发送数据用esp8266_send(),它会在数据实际发送成功前返回,剩下的活由DMA完成,然后请耐心地等待消息,想知道结果就调用esp8266_parse(),它会根据返回的消息判断发送有无成功,并返回。
文中的“消息”是指ESP8266发的指示状态的,“数据”指通过网络收发的。
头文件
#ifndef ESP8266_H #define ESP8266_H #include "main.h"#define RXBUFFERSIZE 1024 #define HEADER_LENGTH 19 //pos : current postion, pos_end: right side of the last received characterexternint pos, pos_end; externchar aRxBuffer[RXBUFFERSIZE]; // DAM receiving, no interrupt, // this var is set in esp8266_send(), and reset in esp8266_parse if sent ok, you don't need to set/reset it, just read it;externbool esp8266_sending; typedef enum { NO_EVENT, LINK, UNLINK, PAYLOAD, SEND_OK, SEND_ERROR, RST }esp8266_event_t; //send "AT\r\n" to test whether it exist and then reset it, if both action is succeed, return true;bool esp8266_init(void); // check whether there is new data come, if not ,return NO_EVENT; else parse the type of the new message; // if there is a payload, the first parameter is used to store payload it received, the second is the length;esp8266_event_t esp8266_parse( uint8_t *payload, int *payload_length ); //return how many characters have been received and update pos_endint update_length(void); // if len = -6, means copy the last 6 charsvoid copy_buffer(uint8_t *tmp, int len); //cmd is sent, echo is the last chars means OK. if received extra chars after "OK\r\n" and the task is interrupted, it maybe fail, but this seldom happensbool esp8266_cmd(char *cmd, char *echo, int timeout); // cmd send in blocking mode, data is send in DMA mode, return before send ok; it will check esp8266_sending, you don't need to check;bool esp8266_send(int socket, uint8_t *data, int length); //not implemented //bool esp8266_list_AP(void);#endif
主文件
#include "esp8266.h"extern UART_HandleTypeDef UartHandle; externchar aRxBuffer[RXBUFFERSIZE]; extern __IO ITStatus UartReady; char aRxBuffer[RXBUFFERSIZE]; int pos=0, pos_end; bool esp8266_sending = false; bool esp8266_init(){ int length; // if the mcu and esp8266 are powered up at the same time, mcu will receive some info, have to ignore it.while(1){ // waiting until the receive buffer stop increase; HAL_Delay(100); length = update_length(); if( length > 0 ){ pos += length; pos %= RXBUFFERSIZE; continue; }else{ break; } } if( esp8266_cmd("AT\r\n", "\r\nOK\r\n", 100) ){ if( esp8266_cmd("AT+RST\r\n", "\r\nready\r\n", 2000) ){ returntrue; }else{ returnfalse; } }else{ returnfalse; } } // in order to avoid push & pop and easy to debug, put the big data outsidestaticchar cmd_echo[16]; bool esp8266_cmd(char *cmd, char *echo, int timeout){ int time, length=0, compare_length = strlen(echo); while(!UartReady); HAL_UART_Transmit( &UartHandle, (uint8_t *)cmd, strlen(cmd), 0xffff); time = HAL_GetTick(); while( HAL_GetTick() - time < timeout ){ // waiting "xxx\r\nOK\r\n length = update_length(); if( length > compare_length ){ copy_buffer((uint8_t *)cmd_echo, -1*compare_length); if( 0 == strncmp(cmd_echo, echo, compare_length) ){ pos += length; pos %= RXBUFFERSIZE; returntrue; } } } // should move pos to the end, maybe the response is "no changed" which is the same as "OK", if you don't move it, the next cmd maybe fail pos += length; pos %= RXBUFFERSIZE; returnfalse; } bool esp8266_send(int socket, uint8_t *data, int length){ char cmd[20]; if( esp8266_sending ){ returnfalse; } sprintf(cmd, "AT+CIPSEND=%d,%d\r\n", socket, length); if( esp8266_cmd(cmd, "\r\n> ", 200) ){ while(!UartReady); HAL_UART_Transmit_DMA(&UartHandle, (uint8_t *)data, length); UartReady = RESET; esp8266_sending = true; returntrue; }else{ //while(1); // convenient to debugreturnfalse; } } int update_length(){ int length; pos_end = RXBUFFERSIZE - __HAL_DMA_GET_COUNTER( UartHandle.hdmarx ); if( pos_end >= pos ){ length = pos_end - pos; }else{ length = (RXBUFFERSIZE + pos_end) - pos; } //p1 = aRxBuffer + pos; //p2 = aRxBuffer + pos_end;return length; } void copy_buffer(uint8_t *tmp, int length){ int pos_tmp; char *p1; if( length > 0){ pos_tmp = (pos + length) % RXBUFFERSIZE; p1 = aRxBuffer + pos; if( pos_tmp > pos ){ memcpy(tmp, p1, length); }else{ memcpy( tmp, p1, RXBUFFERSIZE-pos ); memcpy( tmp + RXBUFFERSIZE-pos, aRxBuffer, pos_tmp ); } }else{ length *= -1; pos_tmp = ( pos_end - length ); if( pos_tmp < 0 ){ pos_tmp += RXBUFFERSIZE; } p1 = aRxBuffer + pos_tmp; if( pos_end > pos_tmp ){ memcpy(tmp, p1, length); }else{ memcpy( tmp, p1, RXBUFFERSIZE-pos_tmp ); memcpy( tmp + RXBUFFERSIZE-pos_tmp, aRxBuffer, pos_end ); } } } staticchar header[16]; esp8266_event_t esp8266_parse(uint8_t *payload, int *payload_length){ int length, length_expected; int pos_tmp, pos_end2; char *p3, *p4; copy_buffer((uint8_t *)header, 6); length = update_length(); if( length < 6 ){ return NO_EVENT; } if( esp8266_sending ){ // sendingif( length >= 11 ){ pos_end2 = pos_end; if( pos_end2 < pos ){ pos_end2 += RXBUFFERSIZE; } for( pos_tmp = pos; pos_tmp <= pos_end2 - 10; pos_tmp++ ){ //"\r\nSEND OK\r\n"if( aRxBuffer[ pos_tmp%RXBUFFERSIZE ] == '\n' ){ if( aRxBuffer[ (pos_tmp + 7)%RXBUFFERSIZE ] == 'K' ){ pos += pos_tmp-pos+10; pos %= RXBUFFERSIZE; esp8266_sending = false; return SEND_OK; }else{ return SEND_ERROR; } } } return NO_EVENT; }else{ return NO_EVENT; } } if( length >=6 && (0 == strncmp(header, "Link", 4)) ){ // link pos += 6; pos %= RXBUFFERSIZE; return LINK; }elseif( length >=8 && (0 == strncmp(header, "Unlink", 6)) ){ // unlink pos += 8; pos %= RXBUFFERSIZE; return UNLINK; }elseif( length > HEADER_LENGTH && (0 == strncmp(header, "\r\n+IPD", 6)) ){ // "\r\n+IPD=0,478:xxx\r\nOK\r\n" copy_buffer((uint8_t *)header, 16); p3 = header+9; p4 = strchr( (char *)p3, ':' ); *p4 = '\0'; *payload_length = atoi(p3); length_expected = *payload_length + HEADER_LENGTH - 3 + strlen(p3); *(payload + *payload_length) = '\0'; if( length < length_expected ){ //HEADER_LENGTH include "478", but the lenght is variablereturn NO_EVENT; } // now we have got a payload pos += (10 + strlen(p3)); pos %= RXBUFFERSIZE; copy_buffer( payload, *payload_length); pos += *payload_length + 6 ; pos %= RXBUFFERSIZE; return PAYLOAD; }else{ return NO_EVENT; } }