news 2026/2/4 6:26:03

STM32之串口(三)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
STM32之串口(三)

1.wifi模块(esp8266)

1.1 介绍

• ESP8266 是一款高性能的 WIFI串口模块,可以实现透明传输,可以利用串口与单片机进行通讯,从而编程实现控制 ESP8266。如图:

1.2 常见AT指令

• 上电后发送AT指令测试通信及模块功能是否正常,如图:

• 通过一下命令配置成9600波特率,如图:

• 设置工作模式,如图:

• 以设备模式接入家中路由器配置,发送指令AT+CWJAP="这是wifi","这是密码"如果成功接入wifi返回如下图:

连接TCP Server:

打开网络助手,设立TCP服务器。

在网络助手,设置协议为TCP服务器,写入本地IP和对应端口。

• 连接服务器,发送指令AT+CIPSTART="TCP","服务器IP","端口",成功如下图:

发送数据,如图:

透传模式,如图:

退出透传模式,如图:

2. 实操

2.1 ESP8266连接TCP服务器

• 在esp8266.c

#include "esp8266.h" #include "stdio.h" #include "string.h" #include "delay.h" #include "stdarg.h" UART_HandleTypeDef esp8266_handle = {0};//串口的句柄 uint8_t esp8266_rx_buf[ESP8266_RX_BUF_SIZE];//定义接收的数据存放位置 uint16_t esp8266_cnt = 0;//计数器,表示接收了多少个数 uint16_t esp8266_cntPre = 0;//保存接收前一个数是第几个数 uint8_t esp8266_tx_buf[ESP8266_TX_BUF_SIZE]; //串口初始化 void esp8266_uart_init(uint32_t baudrate){ esp8266_handle.Instance = USART2;//选择串口1 esp8266_handle.Init.BaudRate = baudrate; esp8266_handle.Init.Mode = UART_MODE_TX_RX; esp8266_handle.Init.Parity = UART_PARITY_NONE;//不打开检验位 esp8266_handle.Init.StopBits = UART_STOPBITS_1;//1个停止位 esp8266_handle.Init.WordLength = UART_WORDLENGTH_8B;//传输字长为8位 esp8266_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE;//硬件流不打开 HAL_UART_Init(&esp8266_handle); } uint8_t esp8266_wait_receive(){ if(esp8266_cnt == 0) return ESP8266_ERROR; if(esp8266_cnt == esp8266_cntPre){ esp8266_cnt = 0; return ESP8266_EOK; } esp8266_cntPre = esp8266_cnt; return ESP8266_ERROR; } void esp8266_clear(){ memset(esp8266_rx_buf,0,sizeof(esp8266_rx_buf)); esp8266_cnt = 0; } void esp8266_reveice_data(){//接收数据 if(esp8266_wait_receive() == ESP8266_EOK){ printf("esp8266 recv: %s\r\n",esp8266_rx_buf); esp8266_clear(); } } void esp8266_send_data(char * fmt,...){//发数据给服务器 va_list ap; va_start(ap,fmt); vsprintf((char *)esp8266_tx_buf,fmt,ap); va_end(ap); HAL_UART_Transmit(&esp8266_handle,esp8266_tx_buf,strlen((char *)esp8266_tx_buf),100); } uint8_t esp8266_send_cmd(char* cmd,char* res){//重点。cmd是发的什么类型的AT指令,res是返回的结果 esp8266_clear();//发送之前,清空一下接收缓冲区。 uint8_t timeout = 250; HAL_UART_Transmit(&esp8266_handle,(uint8_t *)cmd,strlen(cmd),100);//发给wifi模块。 while(timeout--){//等待2.5s,等待返回 if(esp8266_wait_receive() == ESP8266_EOK){ if(strstr((char *)esp8266_rx_buf,res) != NULL){ return ESP8266_EOK; } } delay_ms(10); } return ESP8266_ERROR; } void esp8266_test(){ esp8266_send_data("this is from esp8266\r\n"); esp8266_reveice_data();//接收数据 } uint8_t esp8266_set_mode(uint8_t mode){ switch(mode){ case ESP8266_STA_MODE: return esp8266_send_cmd("AT+CWMODE=1\r\n","OK"); case ESP8266_AP_MODE: return esp8266_send_cmd("AT+CWMODE=2\r\n","OK"); case ESP8266_STA_AP_MODE: return esp8266_send_cmd("AT+CWMODE=3\r\n","OK"); default: return ESP8266_EINVET; } } uint8_t esp8266_join_ap(char* ssid,char* pwd){ char cmd[64]; sprintf(cmd,"AT+CWJAP=\"%s\",\"%s\"\r\n",ssid,pwd); return esp8266_send_cmd(cmd,"WIFI GOT IP"); } uint8_t esp8266_single_connect(uint8_t mode){ char cmd[64]; sprintf(cmd,"AT+CIPMUX=%d\r\n",mode); return esp8266_send_cmd(cmd,"OK"); } uint8_t esp8266_at_test(){ return esp8266_send_cmd("AT\r\n","OK"); } uint8_t esp8266_connect_tcp_sever(char* sever_id,char* sever_potr){ char cmd[64]; sprintf(cmd,"AT+CIPSTART=\"TCP\",\"%s\",%s\r\n",sever_id,sever_potr); return esp8266_send_cmd(cmd,"CONNECT"); } uint8_t esp8266_send_unvarnished(){ uint8_t ret ; ret = esp8266_send_cmd("AT+CIPMODE=1\r\n","OK"); ret += esp8266_send_cmd("AT+CIPSEND\r\n",">"); if(ret == ESP8266_EOK) return ESP8266_EOK; else return ESP8266_ERROR; } void esp8266_init(uint32_t baudrate){ printf("esp8266初始化开始...\r\n"); esp8266_uart_init(baudrate); //下面还有一些初始化 printf("1. 测试esp8266是否存在...\r\n"); while(esp8266_at_test()) delay_ms(500); printf("2. 设置工作模式为STA...\r\n"); while(esp8266_set_mode(ESP8266_STA_MODE)) delay_ms(500); printf("3. 设置单路链接模式...\r\n"); while(esp8266_single_connect(ESP8266_SINGLE_MODE)) delay_ms(500); printf("4. 连接wifi,SSID: %s, PWD: %s\r\n", WIFI_SSID, WIFI_PWD); while(esp8266_join_ap(WIFI_SSID,WIFI_PWD)) delay_ms(1500); printf("5. 连接TCP服务器,server_ip:%s, server_port:%s\r\n", TCP_SERVER_IP, TCP_SERVER_PORT); while(esp8266_connect_tcp_sever(TCP_SERVER_IP,TCP_SERVER_PORT)) delay_ms(500); printf("6. 进入到透传模式...\r\n"); while(esp8266_send_unvarnished()) delay_ms(500); printf("ESP8266已连接上TCP服务器并进入透传模式\r\n"); printf("ESP8266初始化完成!\r\n"); } void USART2_IRQHandler(){ uint8_t receive_data = 0; if(__HAL_UART_GET_FLAG(&esp8266_handle,UART_FLAG_RXNE) != RESET){//看是不是被置1了 if(esp8266_cnt >= sizeof(esp8266_rx_buf)) esp8266_cnt = 0;//接收前需要判断一下,,esp8266_cnt是否超出总长度esp8266_RX_BUF_SIZE HAL_UART_Receive(&esp8266_handle,&receive_data,1,1000);//接收数据 esp8266_rx_buf[esp8266_cnt++] = receive_data;//把接收到的数据放进数组 //HAL_UART_Transmit(&esp8266_handle,&receive_data,1,1000); } }

• 头文件

#ifndef __ESP8266_H__ #define __ESP8266_H__ #include "stdio.h" #include "sys.h" #define ESP8266_RX_BUF_SIZE 128 #define ESP8266_TX_BUF_SIZE 64 #define ESP8266_EOK 0 #define ESP8266_ERROR 1 #define ESP8266_ETIMEOUT 2 #define ESP8266_EINVET 3 #define ESP8266_STA_MODE 1 #define ESP8266_AP_MODE 2 #define ESP8266_STA_AP_MODE 3 #define ESP8266_SINGLE_MODE 0 #define ESP8266_MULTI_MODE 1 #define WIFI_SSID "iphone" #define WIFI_PWD "12345678" #define TCP_SERVER_IP "172.20.10.4" #define TCP_SERVER_PORT "8080" void esp8266_init(uint32_t baudrate); void esp8266_reveice_data(); #endif

uart1.c

#include "sys.h" #include "uart1.h" #include "string.h" UART_HandleTypeDef uart1_handle; /* UART1句柄 */ uint8_t uart1_rx_buf[UART1_RX_BUF_SIZE]; /* UART1接收缓冲区 */ uint16_t uart1_rx_len = 0; /* UART1接收字符长度 */ /** * @brief 重定义fputc函数 * @note printf函数最终会通过调用fputc输出字符串到串口 */ int fputc(int ch, FILE *f) { while ((USART1->SR & 0X40) == 0); /* 等待上一个字符发送完成 */ USART1->DR = (uint8_t)ch; /* 将要发送的字符 ch 写入到DR寄存器 */ return ch; } /** * @brief 串口1初始化函数 * @param baudrate: 波特率, 根据自己需要设置波特率值 * @retval 无 */ void uart1_init(uint32_t baudrate) { /*UART1 初始化设置*/ uart1_handle.Instance = USART1; /* USART1 */ uart1_handle.Init.BaudRate = baudrate; /* 波特率 */ uart1_handle.Init.WordLength = UART_WORDLENGTH_8B; /* 字长为8位数据格式 */ uart1_handle.Init.StopBits = UART_STOPBITS_1; /* 一个停止位 */ uart1_handle.Init.Parity = UART_PARITY_NONE; /* 无奇偶校验位 */ uart1_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE; /* 无硬件流控 */ uart1_handle.Init.Mode = UART_MODE_TX_RX; /* 收发模式 */ HAL_UART_Init(&uart1_handle); /* HAL_UART_Init()会使能UART1 */ } /** * @brief UART底层初始化函数 * @param huart: UART句柄类型指针 * @note 此函数会被HAL_UART_Init()调用 * 完成时钟使能,引脚配置,中断配置 * @retval 无 */ void HAL_UART_MspInit(UART_HandleTypeDef *huart) { GPIO_InitTypeDef gpio_init_struct; if (huart->Instance == USART1) /* 如果是串口1,进行串口1 MSP初始化 */ { __HAL_RCC_GPIOA_CLK_ENABLE(); /* 使能串口TX脚时钟 */ __HAL_RCC_USART1_CLK_ENABLE(); /* 使能串口时钟 */ gpio_init_struct.Pin = GPIO_PIN_9; /* 串口发送引脚号 */ gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 复用推挽输出 */ gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */ gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* IO速度设置为高速 */ HAL_GPIO_Init(GPIOA, &gpio_init_struct); gpio_init_struct.Pin = GPIO_PIN_10; /* 串口RX脚 模式设置 */ gpio_init_struct.Mode = GPIO_MODE_AF_INPUT; HAL_GPIO_Init(GPIOA, &gpio_init_struct); /* 串口RX脚 必须设置成输入模式 */ HAL_NVIC_EnableIRQ(USART1_IRQn); /* 使能USART1中断通道 */ HAL_NVIC_SetPriority(USART1_IRQn, 3, 3); /* 组2,最低优先级:抢占优先级3,子优先级3 */ __HAL_UART_ENABLE_IT(huart, UART_IT_RXNE); /* 使能UART1接收中断 */ __HAL_UART_ENABLE_IT(huart, UART_IT_IDLE); /* 使能UART1总线空闲中断 */ }else if(huart->Instance == USART2){ GPIO_InitTypeDef gpio_init = {0}; __HAL_RCC_GPIOA_CLK_ENABLE();//使能GPIO时钟 __HAL_RCC_USART2_CLK_ENABLE(); gpio_init.Mode = GPIO_MODE_AF_PP;//TX线是看GPIO外设配置为复用推挽 gpio_init.Pin = GPIO_PIN_2; gpio_init.Pull = GPIO_PULLUP;//默认上拉 gpio_init.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA,&gpio_init);//初始化gpio gpio_init.Mode = GPIO_MODE_INPUT;//RX线是看GPIO外设配置为上拉输入 gpio_init.Pin = GPIO_PIN_3; HAL_GPIO_Init(GPIOA,&gpio_init);//初始化gpio HAL_NVIC_SetPriority(USART2_IRQn,3,3); HAL_NVIC_EnableIRQ(USART2_IRQn); __HAL_UART_ENABLE_IT(huart,UART_IT_RXNE);//使能RXNE中断 //__HAL_UART_ENABLE_IT(huart,UART_IT_IDLE);//使能空闲中断 } } /** * @brief UART1接收缓冲区清除 * @param 无 * @retval 无 */ void uart1_rx_clear(void) { memset(uart1_rx_buf, 0, sizeof(uart1_rx_buf)); /* 清空接收缓冲区 */ uart1_rx_len = 0; /* 接收计数器清零 */ } /** * @brief 串口1中断服务函数 * @note 在此使用接收中断及空闲中断,实现不定长数据收发 * @param 无 * @retval 无 */ void USART1_IRQHandler(void) { uint8_t receive_data = 0; if(__HAL_UART_GET_FLAG(&uart1_handle, UART_FLAG_RXNE) != RESET){ /* 获取接收RXNE标志位是否被置位 */ if(uart1_rx_len >= sizeof(uart1_rx_buf)) /* 如果接收的字符数大于接收缓冲区大小, */ uart1_rx_len = 0; /* 则将接收计数器清零 */ HAL_UART_Receive(&uart1_handle, &receive_data, 1, 1000); /* 接收一个字符 */ uart1_rx_buf[uart1_rx_len++] = receive_data; /* 将接收到的字符保存在接收缓冲区 */ } if (__HAL_UART_GET_FLAG(&uart1_handle, UART_FLAG_IDLE) != RESET) /* 获取接收空闲中断标志位是否被置位 */ { printf("recv: %s\r\n", uart1_rx_buf); /* 将接收到的数据打印出来 */ uart1_rx_clear(); __HAL_UART_CLEAR_IDLEFLAG(&uart1_handle); /* 清除UART总线空闲中断 */ } }

main.c

#include "sys.h" #include "uart1.h" #include "delay.h" #include "led.h" #include "esp8266.h" int main(void) { HAL_Init(); /* 初始化HAL库 */ stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */ led_init(); /* LED初始化 */ uart1_init(115200); esp8266_init(9600); printf("hello world\r\n"); while(1) { esp8266_test(); delay_ms(500); } }

2.2 实战ESP8266作为服务器

esp8266.c

#include "esp8266.h" #include "stdio.h" #include "string.h" #include "delay.h" #include "stdarg.h" UART_HandleTypeDef esp8266_handle = {0};//串口的句柄 uint8_t esp8266_rx_buf[ESP8266_RX_BUF_SIZE];//定义接收的数据存放位置 uint16_t esp8266_cnt = 0;//计数器,表示接收了多少个数 uint16_t esp8266_cntPre = 0;//保存接收前一个数是第几个数 //uint8_t esp8266_tx_buf[ESP8266_TX_BUF_SIZE]; //串口初始化 void esp8266_uart_init(uint32_t baudrate){ esp8266_handle.Instance = USART2;//选择串口1 esp8266_handle.Init.BaudRate = baudrate; esp8266_handle.Init.Mode = UART_MODE_TX_RX; esp8266_handle.Init.Parity = UART_PARITY_NONE;//不打开检验位 esp8266_handle.Init.StopBits = UART_STOPBITS_1;//1个停止位 esp8266_handle.Init.WordLength = UART_WORDLENGTH_8B;//传输字长为8位 esp8266_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE;//硬件流不打开 HAL_UART_Init(&esp8266_handle); } uint8_t esp8266_wait_receive(){ if(esp8266_cnt == 0) return ESP8266_ERROR; if(esp8266_cnt == esp8266_cntPre){ esp8266_cnt = 0; return ESP8266_EOK; } esp8266_cntPre = esp8266_cnt; return ESP8266_ERROR; } void esp8266_clear(){ memset(esp8266_rx_buf,0,sizeof(esp8266_rx_buf)); esp8266_cnt = 0; } void esp8266_reveice_data(){ if(esp8266_wait_receive() == ESP8266_EOK){ printf("esp8266 recv: %s\r\n",esp8266_rx_buf);//接收客户端发来的数据 esp8266_clear(); } } //void esp8266_send_data(char * fmt,...){ // // va_list ap; // va_start(ap,fmt); // vsprintf((char *)esp8266_tx_buf,fmt,ap); // va_end(ap); // // HAL_UART_Transmit(&esp8266_handle,esp8266_tx_buf,strlen((char *)esp8266_tx_buf),100); //} uint8_t esp8266_send_cmd(char* cmd,char* res){ esp8266_clear();//发送之前,清空一下接收缓冲区。 uint8_t timeout = 250; HAL_UART_Transmit(&esp8266_handle,(uint8_t *)cmd,strlen(cmd),100); while(timeout--){ if(esp8266_wait_receive() == ESP8266_EOK){ if(strstr((char *)esp8266_rx_buf,res) != NULL){ return ESP8266_EOK; } } delay_ms(10); } return ESP8266_ERROR; } //void esp8266_test(){ // esp8266_send_cmd("AT+CIPSEND=0,6\r\n",">"); // esp8266_send_data("abcd\r\n"); // // //} uint8_t esp8266_set_mode(uint8_t mode){ switch(mode){ case ESP8266_STA_MODE: return esp8266_send_cmd("AT+CWM0ODE=1\r\n","OK"); case ESP8266_AP_MODE: return esp8266_send_cmd("AT+CWMODE=2\r\n","OK"); case ESP8266_STA_AP_MODE: return esp8266_send_cmd("AT+CWMODE=3\r\n","OK"); default: return ESP8266_EINVET; } } uint8_t esp8266_multp_connect(uint8_t mode){ char cmd[64]; sprintf(cmd,"AT+CIPMUX=%d\r\n",mode); return esp8266_send_cmd(cmd,"OK"); } uint8_t esp8266_at_test(){ return esp8266_send_cmd("AT\r\n","OK"); } uint8_t esp8266_build_tcp_Server(){ return esp8266_send_cmd("AT+CIPSERVER=1\r\n","OK"); } void esp8266_init(uint32_t baudrate){ printf("esp8266初始化开始...\r\n"); esp8266_uart_init(baudrate); //下面还有一些初始化 printf("1. 测试esp8266是否存在...\r\n"); while(esp8266_at_test()) delay_ms(500); printf("2. 设置工作模式为AP...\r\n"); while(esp8266_set_mode(ESP8266_AP_MODE)) delay_ms(500); printf("3. 使能多链接...\r\n"); while(esp8266_multp_connect(ESP8266_MULTI_MODE)) delay_ms(500); printf("4. 建立TCPServer\r\n"); while(esp8266_build_tcp_Server()) delay_ms(1500); printf("ESP8266初始化完成!\r\n"); } void USART2_IRQHandler(){ uint8_t receive_data = 0; if(__HAL_UART_GET_FLAG(&esp8266_handle,UART_FLAG_RXNE) != RESET){//看是不是被置1了 if(esp8266_cnt >= sizeof(esp8266_rx_buf)) esp8266_cnt = 0;//接收前需要判断一下,,esp8266_cnt是否超出总长度esp8266_RX_BUF_SIZE HAL_UART_Receive(&esp8266_handle,&receive_data,1,1000);//接收数据 esp8266_rx_buf[esp8266_cnt++] = receive_data;//把接收到的数据放进数组 //HAL_UART_Transmit(&esp8266_handle,&receive_data,1,1000); } }

在esp8266.h

#ifndef __ESP8266_H__ #define __ESP8266_H__ #include "stdio.h" #include "sys.h" #define ESP8266_RX_BUF_SIZE 128 #define ESP8266_TX_BUF_SIZE 64 #define ESP8266_EOK 0 #define ESP8266_ERROR 1 #define ESP8266_ETIMEOUT 2 #define ESP8266_EINVET 3 #define ESP8266_STA_MODE 1 #define ESP8266_AP_MODE 2 #define ESP8266_STA_AP_MODE 3 #define ESP8266_SINGLE_MODE 0 #define ESP8266_MULTI_MODE 1 #define WIFI_SSID "iphone" #define WIFI_PWD "12345678" #define TCP_SERVER_IP "172.20.10.4" #define TCP_SERVER_PORT "8080" void esp8266_init(uint32_t baudrate); void esp8266_reveice_data(); #endif

在和uart1.c上面第一个实操一样

main.c

#include "sys.h" #include "uart1.h" #include "delay.h" #include "led.h" #include "esp8266.h" int main(void) { HAL_Init(); /* 初始化HAL库 */ stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */ led_init(); /* LED初始化 */ uart1_init(115200); esp8266_init(9600); printf("hello world\r\n"); while(1) { //esp8266_test(); esp8266_reveice_data(); delay_ms(10); } }

3.3 wifi控制风扇

在uart1.c和实操1一样的。

在esp8266.c

#include "esp8266.h" #include "stdio.h" #include "string.h" #include "delay.h" #include "stdarg.h" #include "fan.h" UART_HandleTypeDef esp8266_handle = {0};//串口的句柄 uint8_t esp8266_rx_buf[ESP8266_RX_BUF_SIZE];//定义接收的数据存放位置 uint16_t esp8266_cnt = 0;//计数器,表示接收了多少个数 uint16_t esp8266_cntPre = 0;//保存接收前一个数是第几个数 uint8_t esp8266_tx_buf[ESP8266_TX_BUF_SIZE]; //串口初始化 void esp8266_uart_init(uint32_t baudrate){ esp8266_handle.Instance = USART2;//选择串口2 esp8266_handle.Init.BaudRate = baudrate; esp8266_handle.Init.Mode = UART_MODE_TX_RX; esp8266_handle.Init.Parity = UART_PARITY_NONE;//不打开检验位 esp8266_handle.Init.StopBits = UART_STOPBITS_1;//1个停止位 esp8266_handle.Init.WordLength = UART_WORDLENGTH_8B;//传输字长为8位 esp8266_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE;//硬件流不打开 HAL_UART_Init(&esp8266_handle); } uint8_t esp8266_wait_receive(){ if(esp8266_cnt == 0) return ESP8266_ERROR; if(esp8266_cnt == esp8266_cntPre){ esp8266_cnt = 0; return ESP8266_EOK; } esp8266_cntPre = esp8266_cnt; return ESP8266_ERROR; } void esp8266_clear(){ memset(esp8266_rx_buf,0,sizeof(esp8266_rx_buf)); esp8266_cnt = 0; } uint16_t esp8266_reveice_data(char * recv_data){ if(esp8266_wait_receive() == ESP8266_EOK){ printf("esp8266 recv: %s\r\n",esp8266_rx_buf); memcpy(recv_data,esp8266_rx_buf,strlen((char *)esp8266_rx_buf));//把接收区的数据拷贝出去 esp8266_clear(); return strlen(recv_data); } return 0; } //void esp8266_send_data(char * fmt,...){ // // va_list ap; // va_start(ap,fmt); // vsprintf((char *)esp8266_tx_buf,fmt,ap); // va_end(ap); // // HAL_UART_Transmit(&esp8266_handle,esp8266_tx_buf,strlen((char *)esp8266_tx_buf),100); //} uint8_t esp8266_send_cmd(char* cmd,char* res){ esp8266_clear();//发送之前,清空一下接收缓冲区。 uint8_t timeout = 250; HAL_UART_Transmit(&esp8266_handle,(uint8_t *)cmd,strlen(cmd),100); while(timeout--){ if(esp8266_wait_receive() == ESP8266_EOK){ if(strstr((char *)esp8266_rx_buf,res) != NULL){ return ESP8266_EOK; } } delay_ms(10); } return ESP8266_ERROR; } //void esp8266_test(){ // esp8266_send_data("this is from esp8266\r\n"); // // esp8266_reveice_data(); //} uint8_t esp8266_set_mode(uint8_t mode){ switch(mode){ case ESP8266_STA_MODE: return esp8266_send_cmd("AT+CWMODE=1\r\n","OK"); case ESP8266_AP_MODE: return esp8266_send_cmd("AT+CWMODE=2\r\n","OK"); case ESP8266_STA_AP_MODE: return esp8266_send_cmd("AT+CWMODE=3\r\n","OK"); default: return ESP8266_EINVET; } } uint8_t esp8266_join_ap(char* ssid,char* pwd){ char cmd[64]; sprintf(cmd,"AT+CWJAP=\"%s\",\"%s\"\r\n",ssid,pwd); return esp8266_send_cmd(cmd,"WIFI GOT IP"); } uint8_t esp8266_single_connect(uint8_t mode){ char cmd[64]; sprintf(cmd,"AT+CIPMUX=%d\r\n",mode); return esp8266_send_cmd(cmd,"OK"); } uint8_t esp8266_at_test(){ return esp8266_send_cmd("AT\r\n","OK"); } uint8_t esp8266_connect_tcp_sever(char* sever_id,char* sever_potr){ char cmd[64]; sprintf(cmd,"AT+CIPSTART=\"TCP\",\"%s\",%s\r\n",sever_id,sever_potr); return esp8266_send_cmd(cmd,"CONNECT"); } uint8_t esp8266_send_unvarnished(){ uint8_t ret ; ret = esp8266_send_cmd("AT+CIPMODE=1\r\n","OK"); ret += esp8266_send_cmd("AT+CIPSEND\r\n",">"); if(ret == ESP8266_EOK) return ESP8266_EOK; else return ESP8266_ERROR; } void esp8266_init(uint32_t baudrate){ printf("esp8266初始化开始...\r\n"); esp8266_uart_init(baudrate); //下面还有一些初始化 printf("1. 测试esp8266是否存在...\r\n"); while(esp8266_at_test()) delay_ms(500); printf("2. 设置工作模式为STA...\r\n"); while(esp8266_set_mode(ESP8266_STA_MODE)) delay_ms(500); printf("3. 设置单路链接模式...\r\n"); while(esp8266_single_connect(ESP8266_SINGLE_MODE)) delay_ms(500); printf("4. 连接wifi,SSID: %s, PWD: %s\r\n", WIFI_SSID, WIFI_PWD); while(esp8266_join_ap(WIFI_SSID,WIFI_PWD)) delay_ms(1500); printf("5. 连接TCP服务器,server_ip:%s, server_port:%s\r\n", TCP_SERVER_IP, TCP_SERVER_PORT); while(esp8266_connect_tcp_sever(TCP_SERVER_IP,TCP_SERVER_PORT)) delay_ms(500); printf("6. 进入到透传模式...\r\n"); while(esp8266_send_unvarnished()) delay_ms(500); printf("ESP8266已连接上TCP服务器并进入透传模式\r\n"); printf("ESP8266初始化完成!\r\n"); } void USART2_IRQHandler(){ uint8_t receive_data = 0; if(__HAL_UART_GET_FLAG(&esp8266_handle,UART_FLAG_RXNE) != RESET){//看是不是被置1了 if(esp8266_cnt >= sizeof(esp8266_rx_buf)) esp8266_cnt = 0;//接收前需要判断一下,,esp8266_cnt是否超出总长度esp8266_RX_BUF_SIZE HAL_UART_Receive(&esp8266_handle,&receive_data,1,1000);//接收数据 esp8266_rx_buf[esp8266_cnt++] = receive_data;//把接收到的数据放进数组 //esp8266_clear(); //HAL_UART_Transmit(&esp8266_handle,&receive_data,1,1000); } }

• main.c

#include "sys.h" #include "uart1.h" #include "delay.h" #include "led.h" #include "esp8266.h" #include "fan.h" #include "string.h" int main(void) { HAL_Init(); /* 初始化HAL库 */ stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */ led_init(); /* LED初始化 */ uart1_init(115200); esp8266_init(9600); fan_init(); printf("hello world\r\n"); char recv_data[ESP8266_RX_BUF_SIZE]; while(1) { esp8266_reveice_data(recv_data); if(strstr(recv_data,"ON") != NULL) fan_on(); else if(strstr(recv_data,"OFF") != NULL) fan_off(); delay_ms(10); } }

在fan.c

#include "fan.h" void fan_init(){//继电器可以看作成一个开关,开关连接着负载,这里的负载是个喇叭 GPIO_InitTypeDef gpio_init = {0}; __HAL_RCC_GPIOB_CLK_ENABLE();//使能GPIO时钟 gpio_init.Mode = GPIO_MODE_OUTPUT_PP; gpio_init.Pin = GPIO_PIN_6;//推挽输出 gpio_init.Pull = GPIO_PULLUP;//默认上拉 gpio_init.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOB,&gpio_init);//初始化gpio fan_off();//关灯 } void fan_on(){ HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_RESET); } void fan_off(){ HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_SET); } uint8_t get_fan_staut(){ return (uint8_t) HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_6); }

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/3 2:21:46

YOLOv9内存泄漏排查:长时间运行稳定性测试

YOLOv9内存泄漏排查:长时间运行稳定性测试 在工业级AI视觉部署中,模型能否稳定运行数小时甚至数天,往往比单次推理的毫秒级延迟更重要。我们曾遇到一个典型问题:YOLOv9官方镜像在持续视频流推理任务中,每小时内存占用…

作者头像 李华
网站建设 2026/2/3 8:59:05

NewBie-image-Exp0.1已知Bug修复清单:预装镜像省去调试时间

NewBie-image-Exp0.1已知Bug修复清单:预装镜像省去调试时间 NewBie-image-Exp0.1 本镜像已深度预配置了 NewBie-image-Exp0.1 所需的全部环境、依赖与修复后的源码,实现了动漫生成能力的“开箱即用”。通过简单的指令,您即可立即体验 3.5B 参…

作者头像 李华
网站建设 2026/2/2 16:56:04

5步实现跨平台字体统一:面向前端开发者的免费解决方案

5步实现跨平台字体统一:面向前端开发者的免费解决方案 【免费下载链接】PingFangSC PingFangSC字体包文件、苹果平方字体文件,包含ttf和woff2格式 项目地址: https://gitcode.com/gh_mirrors/pi/PingFangSC 你是否遇到过这样的困境:精…

作者头像 李华
网站建设 2026/2/2 23:56:51

YOLO26机器人视觉:抓取定位系统开发实战指南

YOLO26机器人视觉:抓取定位系统开发实战指南 在工业机器人、智能分拣和自动化装配场景中,精准、快速、鲁棒的物体定位能力是抓取任务成败的关键。传统方法依赖固定光照、高精度标定和手工特征设计,面对复杂背景、遮挡、小目标或动态环境时往…

作者头像 李华
网站建设 2026/2/4 4:28:51

2026年AI+教育趋势分析:开源Qwen模型助力儿童内容创作入门必看

2026年AI教育趋势分析:开源Qwen模型助力儿童内容创作入门必看 1. 为什么儿童内容创作正在迎来“轻量化”拐点 过去三年,教育科技圈有个明显变化:老师和家长不再追问“AI能不能替代人工”,而是更关心“孩子能不能自己用起来”。 …

作者头像 李华
网站建设 2026/2/3 2:48:22

腾讯混元A13B:130亿参数实现超强代理任务性能

腾讯混元A13B:130亿参数实现超强代理任务性能 【免费下载链接】Hunyuan-A13B-Instruct-GGUF 腾讯Hunyuan-A13B-Instruct-GGUF是高效开源大模型,采用MoE架构,800亿总参数中仅130亿激活,性能媲美大模型。支持256K超长上下文&#xf…

作者头像 李华