STM32与正点原子ESP8266的结合
1、准备
STM32F103C8T6单片机
ATK-ESP8266(原子云固件)
杜邦线
2、接线
ESP8266
IO_0 烧录固件使用,不需连接
RST 模块复位,接任意IO,低电平有效
RXD 模块接收,接PB10
TXD 模块发送,接PB11
GND 电源地
VCC 电源5V
STM32F103C8T6
3、原子云
注册原子云,建立ESP8266设备
设备名称和密码任意,
在分组管理创建一个分组添加这个设备。
4、控制ESP8266初始化
1、连接 RST 的 IO 拉低再拉高,使模块复位
2、AT指令测试:(串口 PB10)发送 “AT”,(串口 PB11)收到 “OK”;
3、设置 Station 工作模式:发 AT+CWMODE=1,回 OK;
4、软件复位:发 AT+RST,回 OK;
5、关闭回显:发 ATE0,回 OK;
6、连接WIFI:发 AT+CWJAP="WIFI_ID","WIFI_Password",回 WIFI GOT IP
WIFI_ID 和 WIFI_Password 对应连接的 WIFI 名字和密码
7、获取IP地址:发 AT+CIFSR,回 OK
8、连接原子云:发AT+ATKCLDSTA="ID","Password",回CLOUD CONNECTED
ID 和 Password 对应原子云设备编号和密码
以上接收都没问题后就可以后,单片机就可以通过串口3和原子云通信。
5、控制代码
1、串口3正常初始化,波特率115200,开启串口中断和串口空闲中断,可以使用CubeMX生成;
2、串口收发函数( UART3_Rx_flg在串口空闲置1 )
// UART3
uint8_t UART3_Rx_Buf[UART3_Rx_COUNT] = {0}; //USART3存储接收数据
uint8_t UART3_data = 0; //USART3接收数据缓存
uint16_t UART3_Rx_cnt = 0; //USART3接受数据计数器
uint8_t UART3_Rx_flg = 0; //USART3接收完成标志
uint8_t UART3_Tx_Buf[UART3_Tx_COUNT] = {0}; //USART3发送缓冲
/**
* @brief UART3 printf
* @param fmt: 待打印的数据
* @retval 无
*/
void usart3_printf(char *fmt, ...)
{
va_list ap;
uint16_t len;
va_start(ap, fmt);
vsprintf((char *)UART3_Tx_Buf, fmt, ap);
va_end(ap);
len = strlen((const char *)UART3_Tx_Buf);
HAL_UART_Transmit(&huart3, UART3_Tx_Buf, len, HAL_MAX_DELAY);
}
/**
* @brief UART3 清标志位
* @param 无
* @retval 无
*/
void usart3_close_flag(void)
{
UART3_Rx_cnt = 0;
UART3_Rx_flg = 0;
}
/**
* @brief UART3 接收到的一帧数据
* @param 无
* @retval NULL: 未接收到一帧数据
* 其他: 接收到的一帧数据
*/
uint8_t *usart3_uart_dat(void)
{
if (UART3_Rx_flg == 1)
{
UART3_Rx_Buf[UART3_Rx_cnt] = '\0';
return UART3_Rx_Buf;
}
else
{
return NULL;
}
}
/**
* @brief 获取 UART3 接收到的一帧数据的长度
* @param 无
* @retval 0 : 未接收到一帧数据
* 其他: 接收到的一帧数据的长度
*/
uint16_t usart3_uart_dat_len(void)
{
if (UART3_Rx_flg == 1)
{
return UART3_Rx_cnt;
}
else
{
return 0;
}
}
3、ESP8266初始化(8266子函数在正点原子ESP8266随便一个板型例程找,一样)
#define WIFI_ID(a) (a ? "vivo X80" : "JC-R&D") //WIFI名称
#define WIFI_PASSWORD(a) (a ? "YQY1122334455" : "jc12345678") //WIFI密码
#define WIFI_SERVER_ID "11111111111111111111" //原子云设备编号
#define WIFI_SERVER_PASSWORD "12345678" //原子云设备密码
/**
* @brief ATK-MW8266D初始化
* @retval 0: ATK-MW8266D初始化成功,函数执行成功
* 1: ATK-MW8266D初始化失败,函数执行失败
*/
void ATK_MW8266D_Init(void)
{
uint8_t flag; //返回标志
char ip_buf[16]; //ip地址
atk_mw8266d_reset(); /* ATK-MW8266D硬件复位 */
flag = atk_mw8266d_at_test(); /* ATK-MW8266D AT指令测试 */
if (flag != ATK_MW8266D_EOK) // 有错
{
OLED_ShowString_fun("8266 Init ERROR");
printf("ATK-MW8266 Init ERROR\r\n");
while(1);
}
OLED_ShowString_fun("8266 Init OK");
printf("ATK-MW8266 Init OK\r\n");
// flag = atk_mw8266d_restore(); /* 恢复出厂设置 */
// flag += atk_mw8266d_at_test(); /* AT测试 */
flag = atk_mw8266d_set_mode(1); /* Station模式 */
flag += atk_mw8266d_sw_reset(); /* 软件复位 */
flag += atk_mw8266d_ate_config(0); /* 关闭回显功能 */
flag += atk_mw8266d_join_ap(WIFI_ID(1), WIFI_PASSWORD(1)); /* 连接WIFI */
flag += atk_mw8266d_get_ip(ip_buf); /* 获取IP地址 */
if (flag != 0) // 有错
{
OLED_ShowString_fun("8266 Wifi ERROR");
printf("ATK-MW8266 Wifi ERROR\r\n");
while (1);
}
OLED_ShowString_fun("8266 Wifi OK");
printf("ATK-MW8266 Wifi OK\r\n");
flag = atk_mw8266d_connect_atkcld(WIFI_SERVER_ID, WIFI_SERVER_PASSWORD); /* 连接原子云 */
if (flag != 0)
{
OLED_ShowString_fun("8266 Link ERROR");
printf("ATK-MW8266 Link ERROR\r\n");
while (1);
}
OLED_ShowString_fun("8266 Link OK");
printf("ATK-MW8266 Link OK\r\n");
usart3_close_flag(); /* 清标志位 */
}
/**
* @brief ATK-MW8266D发送AT指令
* @param cmd : 待发送的AT指令
* ack : 等待的响应
* timeout: 等待超时时间
* @retval 0: 函数执行成功
* 2: 等待期望应答超时,函数执行失败
*/
uint8_t atk_mw8266d_send_at_cmd(char *cmd, char *ack, uint32_t timeout)
{
uint8_t *ret = NULL;
usart3_close_flag();
usart3_printf("%s\r\n", cmd);
if ((ack == NULL) || (timeout == 0))
{
return ATK_MW8266D_EOK;
}
else
{
while (timeout > 0)
{
ret = usart3_uart_dat();
if (ret != NULL)
{
if (strstr((const char *)ret, ack) != NULL)
{
return ATK_MW8266D_EOK;
}
else
{
usart3_close_flag();
}
}
timeout--;
delay_ms(1);
}
return ATK_MW8266D_ETIMEOUT;
}
}
4、主函数
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
uint8_t* buf;
char oled_buf[64];
uint8_t run_flag = 0;
uint8_t flag = 1;
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM3_Init();
HAL_TIM_Base_Start_IT(&htim3);
MX_USART1_UART_Init();
HAL_UART_Receive_IT(&huart1, (uint8_t *)UART1_temp, REC_LENGTH);
printf("USART1 Init");
MX_USART3_UART_Init();
HAL_UART_Receive_IT(&huart3, &UART3_data, 1);
HAL_UART_Transmit(&huart3, "USART3 Init", 11, HAL_MAX_DELAY);
MX_I2C1_Init();
OLED_Init();
OLED_ShowString_fun("OLED_OK!");
ATK_MW8266D_Init(); //ATK-MW8266D初始化
while(1)
{
buf = usart3_uart_dat(); /* 接收来自ATK-MW8266D UART的一帧数据 */
if (buf != NULL)
{
sprintf(oled_buf, "%s", buf);
OLED_ShowString_fun(oled_buf);
if(!strcmp((char*)buf, "open"))
{
run_flag = 1;
}
if(!strcmp((char*)buf, "close"))
{
run_flag = 0;
}
usart3_close_flag(); /* 重开开始接收来自ATK-MW8266D UART的数据 */
}
}
}
作者:无敌暴龙战士朵拉