1
、初始化函数
//
功能:串口
2
初始化
//
参数:波特率
//
返回:无
void uart2_init(u32 bound){
//GPIO
端口设置
GPIO_InitTypeDef GPIO_InitStructure;
7
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
//
使能
GPIOA
时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
//
使能
USART2
时钟
//USART2_TX
GPIOA.2
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
//PA.2
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
//
复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure);//
初始化
GPIOA.2
//USART2_RX
GPIOA.3
初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
//PA3
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
//
浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
//
初始化
GPIOA.3
//Usart1 NVIC
配置
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;
//
抢占优先级
3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
//
子优先级
3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
//IRQ
通道使能
NVIC_Init(&NVIC_InitStructure);
//
根据指定的参数初始化
VIC
寄存器
//USART
初始化设置
USART_InitStructure.USART_BaudRate = bound;
//
串口波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
//
字长为
8
位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_1;
//
一个停止位
USART_InitStructure.USART_Parity = USART_Parity_No;
//
无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
//
无硬件数据流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
//
收发模式
USART_Init(USART2, &USART_InitStructure);
//
初始化串口
2
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
//
开启串口接受中断
USART_Cmd(USART2, ENABLE);
//
使能串口
2
}
2
、中断接收数据函数。
WIFI
模块返回的数据就是通过这个中断函数收到的,接着通过另一个函数
AddUartChar()
把收到的字符保存起来。
void USART2_IRQHandler(void)
//
串口
2
中断服务程序
{
u8 Res;
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
{
Res=USART_ReceiveData(USART2);
//
读取接收到的字节数据
AddUartChar((unsigned char) Res);
}
}
3
、串口发送数据函数。所有的
AT
命令以及参数就是通过
USART2_send_buff
函数发送出去的。
//
功能:发送数据到串口
2
//
参数:
buf,
数据指针
len:
数据长度
//
返回:无
void USART2_send_buff(u8* buf,u32 len)
{
u32 i;
for(i=0;i<len;i++)
USART2_send_char(buf[i]);
}
4
、接收
ESP8266
数据结构介绍。我们先看一下
esp8266.h
里定义的一个结构
AtParseCmd
,这个结构就
是用于保存
WIFI
模块返回的响应和主动码。结构如下:
//AT
命令解析
typedef struct _at_parse_cmd_
{
u8 line[MAX_AT_PARSE_LINE][MAX_AT_PARSE_LEN];
//AT
命令
__IO u16 count[MAX_AT_PARSE_LINE];
//
每一行字数
__IO u8 insertIdx;
//
插入行索引
__IO u8 parseIdx;
//
解析行索引
__IO u16 insertCurCount;
//
插入的位置
u8 laseCH;
//
插入的最后一个字符
}AtParseCmd;
在前面,我们讲过
WIFI
模块返回的响应和主动码都是以
”\r\n”
回车换行分隔的,每一行的开头和未尾
都带有
”\r\n”
回车换行。在结构
AtParseCmd
里,
”
u8 line[MAX_AT_PARSE_LINE][MAX_AT_PARSE_LEN];
”
用于保存
WIFi
模块返回的命令,一共可以保存
MAX_AT_PARSE_LINE
行,每行
MAX_AT_PARSE_LEN
个字符,和这个结构相关的
有两个函数,一个是写入一个是读取。
5
、插入串口
2
数据到数组。写入结构
AtParseCmd
的函数为
AddUartChar()
,这个函数在
esp8266.c
里,代
码如下:
//
串口
2
收到一个字符,插入到插入到数组里,
//
根据收到的数据是否是
\r
或者
\n
切换到下一行
void AddUartChar(unsigned char c)
{
u8 index=esp8266.parseAt.insertIdx;
//
插入的行
u16 count=esp8266.parseAt.count[index];
//
插入的位置
static u8 lastCH=0;
if(count>=MAX_AT_PARSE_LEN)
{
changeLine();
//
进入下一行,等待插入
}
else
{
esp8266.parseAt.line[index][count]=c;
esp8266.parseAt.insertCurCount++;
esp8266.parseAt.count[index]+=1;
//
如果正在发送短消息,收到
>
号就换行
if(count==0&&c=='>')
{
changeLine();
//
进入下一行,等待插入
}
else if(lastCH=='\r'&& c=='\n')
{
changeLine();
//
进入下一行,等待插入
}
}
lastCH=c;
//
记录最后一个字符
}
在函数
AddUartChar()
里,换行处理是指把当前保存数据的行数加
1
,从下一行的
0
位置重新插入数据:
//
换一行,用于插入新接收的字符串
void changeLine()
{
u8 index=0;
8
esp8266.parseAt.insertCurCount=0;
esp8266.parseAt.insertIdx++;
if(esp8266.parseAt.insertIdx>=MAX_AT_PARSE_LINE)
{
esp8266.parseAt.insertIdx=0;
}
//
清空存在位置
index=esp8266.parseAt.insertIdx;
memset(esp8266.parseAt.line[index], 0, MAX_AT_PARSE_LEN);
esp8266.parseAt.count[index]=0;
}
6
、从数组读取一行数据。读取结构
AtParseCmd
的函数为
ESP8266_GetLine()
,这个函数一般是在
STM32
发送完
AT
命令之后调用,用于读取
WIFI
模块返回的数据。这个函数在
esp8266.c
里,代码如下:
//
取出一行串口
3
数据
//<buff>
接收数据的缓冲
//
返回:接收到的数据长度,
0
表示没有数据接收
u16 ESP8266_GetLine(char* buff)
{
static u8 line=0;
static u16 insertCount=0;
static u8 checkCount=0;
memset(buff, 0, MAX_AT_PARSE_LEN);
if(esp8266.parseAt.parseIdx==esp8266.parseAt.insertIdx)
{
//
数据插入行和数据解析行行号一样,表示没有整行的数据读取
if(line==esp8266.parseAt.parseIdx
&& esp8266.parseAt.count[line]>0
&& insertCount==esp8266.parseAt.count[line])
{
checkCount++;
}
else
{
line=esp8266.parseAt.parseIdx;
insertCount=esp8266.parseAt.count[line];
checkCount=0;
}
if(checkCount>3)
{
changeLine();
//
读
3
次,行数和字数都不变,就主动换行
ESP8266_Printf("*******changeLine*******\r\n");
}
return 0;
}
else
{
//
数据插入行和数据解析行行号不一样,表示有整行的数据读取
u16 len=0;
u8 index=esp8266.parseAt.parseIdx;
//
读取的行
//
读取行的内容
len=esp8266.parseAt.count[index];
memcpy(buff, esp8266.parseAt.line[index], len);
ESP8266_Printf("[%d],[%d],%s",esp8266.parseAt.parseIdx,len,esp8266.parseAt.line[index]);
9
memset(esp8266.parseAt.line[index], 0, MAX_AT_PARSE_LEN);
esp8266.parseAt.count[index]=0;
//
变成下一索引
esp8266.parseAt.parseIdx++;
if(esp8266.parseAt.parseIdx>=MAX_AT_PARSE_LINE)
{
esp8266.parseAt.parseIdx=0;
}
line=0;
insertCount=0;
checkCount=0;
return len;
}
return 0;
}
下面代码链接:https://pan.baidu.com/s/1Re5-sowRpLD1HHPquex5Cw
提取码:vz0q
提取码:vz0q