硬件使用
- STM32F103 RCT6
- ESP8266 (WiFi 模块)
软件使用
- keil5 MDK环境
- 串口调试助手
实现说明
通过 ESP8266 中 AT 手册可知,可以通过 AT 指令让 ESP8266 模块执行对应命令。
那如何发送数据给 ESP8266 模块呢?
没错,就是通过串口发送数据!
1. 第一步就是要初始化串口
**注意:** STM32 的 Tx 连 ESP8266模块的 Rx, STM32 的 Rx 连 ESP8266模块的 Tx ,查询 STM32 手册可以了解
void Usart2_Init(unsigned int baud)
{
GPIO_InitTypeDef gpio_initstruct;
USART_InitTypeDef usart_initstruct;
NVIC_InitTypeDef nvic_initstruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); //使能 USART2
gpio_initstruct.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
gpio_initstruct.GPIO_Pin = GPIO_Pin_2; //PA2 TXD
gpio_initstruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &gpio_initstruct);
gpio_initstruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
gpio_initstruct.GPIO_Pin = GPIO_Pin_3; //PA3 RXD
gpio_initstruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &gpio_initstruct);
usart_initstruct.USART_BaudRate = baud; //设置波特率
usart_initstruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
//无硬件流控制
usart_initstruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //设置 串口模式,接受和发送
usart_initstruct.USART_Parity = USART_Parity_No; //无校验位
usart_initstruct.USART_StopBits = USART_StopBits_1; //无停止位
usart_initstruct.USART_WordLength = USART_WordLength_8b; //8位数据位
USART_Init(USART2, &usart_initstruct);
USART_Cmd(USART2, ENABLE); //使能串口
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); //使能接受中断
nvic_initstruct.NVIC_IRQChannel = USART2_IRQn;
nvic_initstruct.NVIC_IRQChannelCmd = ENABLE;
nvic_initstruct.NVIC_IRQChannelPreemptionPriority = 0;
nvic_initstruct.NVIC_IRQChannelSubPriority = 0;
NVIC_Init(&nvic_initstruct);
}
##### 2.设置串口中断
void USART2_IRQHandler(void)
{
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收中断
{
if(esp8266_cnt >= sizeof(esp8266_buf)) esp8266_cnt = 0; //防止串口被刷爆,设置一个 esp8266缓冲区的长度 = esp8266_cnt
esp8266_buf[esp8266_cnt++] = USART2->DR; //USART2->DR 表示串口循环发送缓冲区数据
USART_ClearFlag(USART2, USART_FLAG_RXNE); //清除 USARTx 的待处理标志位,一定要用
}
}
##### 3.定义串口发送函数
**原本串口只能发送一个字符,要编写函数发送字符串**
void Usart2_SendString(unsigned char *str, unsigned short len)
{
unsigned short count = 0;
for(; count < len; count++)
{
USART_SendData(USART2, *str++); //发送数据
while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET); //等待发送完成,每发送一位数据,USART_FLAG_TC = SET,跳出循环
}
}
##### 4.ESP8266发送命令数据
_Bool ESP8266_SendCmd(char *cmd, char *res, u16 time) //_Bool 为自定义数据,可以采取宏定义方式
{
Usart2_SendString((unsigned char *)cmd, strlen((const char *)cmd));//串口发送数据
while(time–)
{
if(ESP8266_WaitRecive() == REV_OK) //发送是否完成
{
if(strstr((const char *)esp8266_buf, res) != NULL) //检索到关键词(根据 AT 指令手册可以查询到 输入不同命令,所返回不同的值)
{
ESP8266_Clear(); //清空ESP8266串口缓存
return 0;
}
}
delay_ms(10);
}
return 1;
}
判断是否发送命令是否成功函数解释
_Bool ESP8266_WaitRecive(void)
{
if(esp8266_cnt == 0) //如果发送命令数据长度为0
return REV_WAIT; //REV_WAIT=1
if(esp8266_cnt == esp8266_cntPre) //判断上一次命令数据长度和这一次相等,长度赋值为USART2_IRQHandler 串口中断函数中 esp8266_buf[esp8266_cnt++] = USART2->DR; 语句在 esp8266_cnt++ ,自增中完成赋值
{
esp8266_cnt = 0; //将 esp8266_cnt 置为0
return REV_OK; //REV_OK = 0
}
esp8266_cntPre = esp8266_cnt; //一般使用该函数,都是使用 while 循环语句,第一次收到的命令数据长度,赋值给 esp8266_cntPre,再一次进入该函数,再进行上个 if判断
return REV_WAIT; //返回 1 ,表示循环继续
}
##### 5.发送想要发送的任意字符函数
void ESP8266_SendData(unsigned char *data, unsigned short len)
{
char cmdBuf[32];
ESP8266_Clear(); //清空缓存
sprintf(cmdBuf, “AT+CIPSEND=%d\r\n”, len); //AT 指令中关于发送字符串的命令
if(!ESP8266_SendCmd(cmdBuf, “>”, 200)) //AT 指令中 ESP8266 收到该命令后应该收到‘>’
{
Usart2_SendString(data, len); //收到该命令后可以 通过串口发送字符串了
}
}
##### 6.ESP8266 模块初始化
void ESP8266_Init(void)
{
ESP8266_Clear();
printf("AT\r\n");
while(ESP8266_SendCmd("AT\r\n\r", "OK", 200)) //AT 指令测试 模块是否正常
delay_ms(500);
printf("CWMODE\r\n");
while(ESP8266_SendCmd("AT+CWMODE=1\r\n", "OK", 200)) //设置成 STA 模式
delay_ms(500);
printf("AT+CWDHCP\r\n"); //串口调试打印相关信息
while(ESP8266_SendCmd("AT+CWDHCP=1,1\r\n", "OK", 200)) //STA 运行 DHCPC,使得运行 DHCPC 设备具有上网的能力,后面一个 1 ,代表设置成 STA,前面一个 1 代表开启 DHCP,DHCP 是自动给内网机器分配 IP 地址的协议!
delay_ms(500);
printf("CWJAP\r\n");