ESP8266 non_os串口打印重定向到uart1

本文介绍ESP8266中uart0与uart1的配置方法,uart0用于外设通讯,uart1的TXD1用于打印log。通过uart_init_2()函数初始化,设置波特率,实现串口重定向。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

通常我们会使用ESP8266的uart0和外设通讯,uart1的RXD1用于和Flash通讯,但是TXD1可以用于打印log。
查看uart.c

void ICACHE_FLASH_ATTR
uart_init_2(UartBautRate uart0_br, UartBautRate uart1_br)
{
    // rom use 74880 baut_rate, here reinitialize
    UartDev.baut_rate = uart0_br;
    UartDev.exist_parity = STICK_PARITY_EN;
    UartDev.parity = EVEN_BITS;
    UartDev.stop_bits = ONE_STOP_BIT;
    UartDev.data_bits = EIGHT_BITS;
	
    uart_config(UART0);
    UartDev.baut_rate = uart1_br;
    uart_config(UART1);
    ETS_UART_INTR_ENABLE();

    // install uart1 putc callback
    os_install_putc1((void *)uart1_write_char);//print output at UART1
}

最后一行就是重定向串口打印。
所以我们只需要在初始化的时候,使用uart_init_2()就可以了。

uart_init_2(115200,115200);
uint8_t esp8266_rx_buf[ESP8266_RX_SIZE]; uint8_t esp8266_tx_buf[ESP8266_TX_SIZE]; uint8_t esp8266_rx_len = 0,esp8266_rx_len_prev = -1; //esp8266_init UART_HandleTypeDef esp8266_handle = {0}; void esp8266_uart_init(uint32_t baudrate) { esp8266_handle.Instance = USART2; esp8266_handle.Init.BaudRate = baudrate; esp8266_handle.Init.Parity = UART_PARITY_NONE; esp8266_handle.Init.Mode = UART_MODE_TX_RX; esp8266_handle.Init.StopBits = UART_STOPBITS_1; esp8266_handle.Init.WordLength = UART_WORDLENGTH_8B; esp8266_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE; HAL_UART_Init(&esp8266_handle); HAL_NVIC_SetPriority(USART2_IRQn,2,2); HAL_NVIC_EnableIRQ(USART2_IRQn); } void USART2_IRQHandler(void) { uint8_t receive_data = 0; if(__HAL_UART_GET_FLAG(&esp8266_handle,UART_FLAG_RXNE) != RESET) { if(esp8266_rx_len >= ESP8266_RX_SIZE) esp8266_rx_len = 0; HAL_UART_Receive(&esp8266_handle,&receive_data,1,100); esp8266_rx_buf[esp8266_rx_len++] = receive_data; } } void esp8266_send_data(char* format,...) { va_list args; uint8_t len; va_start(args,format); vsprintf((char*)esp8266_tx_buf,format,args); len = strlen((char*)esp8266_tx_buf); HAL_UART_Transmit(&esp8266_handle,esp8266_tx_buf,len,100); } void clear_rx_buf(void) { for(uint8_t i = 0;i < esp8266_rx_len;i++) { esp8266_rx_buf[i] = 0; } esp8266_rx_len = esp8266_rx_len_prev = 0; } //esp8266_wait_recive_data uint8_t esp8266_wait_recive_data(void) { if(esp8266_rx_len == 0) return ESP8266_REEOR; if(esp8266_rx_len_prev == esp8266_rx_len) { esp8266_rx_len = 0; return ESP8266_ROK; } esp8266_rx_len_prev = esp8266_rx_len; return ESP8266_REEOR; } void esp8266_receive_data(void) { if(esp8266_wait_recive_data() == ESP8266_ROK) { printf("esp8266 recv:%s",esp8266_rx_buf); clear_rx_buf(); } } //esp8266_send_cmd uint8_t esp8266_send_cmd(char* cmd,char* res) { uint8_t time_out = 250; clear_rx_buf(); HAL_UART_Transmit(&esp8266_handle, (uint8_t *)cmd, strlen(cmd), 100); while(time_out--) { if(esp8266_wait_recive_data() == ESP8266_ROK) { if(strstr((const char*)esp8266_rx_buf, res) != NULL) return ESP8266_ROK; else return ESP8266_REEOR; } delay_ms(10); } return ESP8266_REEOR; } uint8_t esp8266_at_test(void) { return esp8266_send_cmd("AT\r\n","OK"); } uint8_t esp8266_set_mode(uint8_t mode) { char cmd[64]; sprintf(cmd,"AT+CWMODE=%d\r\n",mode); return esp8266_send_cmd(cmd,"OK"); } uint8_t esp8266_connection_mode(uint8_t mode) { char cmd[64]; sprintf(cmd,"AT+CIPMUX=%d\r\n",mode); return esp8266_send_cmd(cmd,"OK"); } 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_connect_tcp_server(char *server_ip, char *server_port) { char cmd[64]; sprintf(cmd,"AT+CIPSTART=\"TCP\",\"%s\",%s\r\n",TCP_SERVER_IP,TCP_SERVER_PORT); return esp8266_send_cmd(cmd,"CONNECT"); } uint8_t esp8266_enter_unvarnished(void) { uint8_t ret; ret = esp8266_send_cmd("AT+CIPMODE=1\r\n", "OK"); ret += esp8266_send_cmd("AT+CIPSEND\r\n", ">"); if (ret == ESP8266_ROK) return ESP8266_ROK; else return ESP8266_REEOR; } void esp8266_init(uint32_t baudrate) { esp8266_uart_init(baudrate); if(esp8266_at_test() == ESP8266_ROK) printf("OK\r\n"); printf("准备配置STA中...\r\n"); while(esp8266_set_mode(ESP8266_STA_MODE)); printf("成功配置STA模式\r\n"); printf("准备配置多联通中...\r\n"); while(esp8266_connection_mode(ESP8266_MULTI_CONNECTION)); printf("成功配置多联通模式\r\n"); printf("准备连接网络...\r\n"); while(esp8266_join_ap(WIFI_SSID,WIFI_PWD)); printf("成功连接网络->%s\r\n",WIFI_SSID); printf("准备连接TCP中...\r\n"); while(esp8266_connect_tcp_server(TCP_SERVER_IP,TCP_SERVER_PORT)) delay_ms(500); printf("成功连接TCP服务器\r\n"); printf("准备设置穿透模式中...\r\n"); while(esp8266_enter_unvarnished()); printf("成功设置穿透模式\r\n"); }while(esp8266_enter_unvarnished());一直循环是上面原因
最新发布
07-21
<think>根据提供的代码,问题出现在`esp8266_enter_unvarnished`函数被调用时,由于返回错误(`ESP8266_REEOR`)导致循环无法退出。具体分析如下: 1. **函数逻辑**:`esp8266_enter_unvarnished`函数执行两个AT命令: - 发送`AT+CIPMODE=1\r\n`,期望响应"OK" - 发送`AT+CIPSEND\r\n`,期望响应">" 如果两个命令都成功(返回`ESP8266_ROK`),则函数返回`ESP8266_ROK`,否则返回`ESP8266_REEOR`。 2. **循环卡住的原因**:在`esp8266_init`函数中,调用`while(esp8266_enter_unvarnished());`,这意味着只要`esp8266_enter_unvarnished`返回非零(即`ESP8266_REEOR`),就会一直循环。 3. **可能的原因**: - **AT命令响应不符合预期**:模块没有返回"OK"或">"。例如: - 当前模块可能不在透传模式支持的状态(需要先建立TCP连接)。 - 波特率不匹配导致数据接收错误。 - 网络连接不稳定或服务器未就绪。 - **响应超时**:在`esp8266_send_cmd`函数中,超时时间设置为250*10ms=2.5秒,如果模块响应时间超过2.5秒,会返回错误。 - **数据接收问题**:串口接收中断服务函数(`USART2_IRQHandler`)可能未正确接收数据,导致`esp8266_rx_buf`中没有数据或数据不完整。 4. **调试建议**: - 在`esp8266_send_cmd`函数中添加调试信息,打印发送的命令和接收到的响应,以便观察实际响应。 - 检查串口通信:确保波特率设置正确,且串口线连接稳定。 - 确认模块状态:在进入透传模式前,确保TCP连接已成功建立(即`esp8266_connect_tcp_server`已返回成功)。 **修正代码示例(调试用)**: 在`esp8266_send_cmd`函数中加入打印信息: ```c uint8_t esp8266_send_cmd(char* cmd, char* res) { ... // 原有代码 while(time_out--) { if(esp8266_wait_recive_data() == ESP8266_ROK) { printf("Received: %s", esp8266_rx_buf); // 打印接收到的数据 if(strstr((const char*)esp8266_rx_buf, res) != NULL) return ESP8266_ROK; else return ESP8266_REEOR; // 响应不匹配 } delay_ms(10); } printf("Timeout waiting for response to: %s", cmd); // 超时打印 return ESP8266_REEOR; } ``` §§相关问题§§ 1. 在ESP8266进入透传模式前需要满足哪些先决条件? 2. 如何通过串口调试工具手动验证ESP8266透传模式的AT命令流程? 3. 当`AT+CIPSEND`命令返回错误时,可能的原因有哪些? 4. 如何优化串口接收中断函数以确保长数据包的完整性? 5. 在透传模式下如何安全退出并返回AT命令模式?</think>根据提供的代码,`while(esp8266_enter_unvarnished())` 陷入死循环的原因是 **`esp8266_enter_unvarnished()` 函数始终返回错误状态(`ESP8266_REEOR`)**。以下是具体原因分析和解决方案: ### 问题原因分析 1. **AT命令执行失败**: - 函数尝试执行两个关键AT命令: ```c ret = esp8266_send_cmd("AT+CIPMODE=1\r\n", "OK"); // 设置透传模式 ret += esp8266_send_cmd("AT+CIPSEND\r\n", ">"); // 启动透传 ``` - 若任一命令失败(未收到预期响应),函数返回 `ESP8266_REEOR` 2. **常见失败场景**: - **TCP连接未就绪**:必须在建立TCP连接后(`AT+CIPSTART`成功)才能进入透传 - **响应超时**:`esp8266_send_cmd` 中的250次重试(2.5秒)可能不足 - **数据残留**:`clear_rx_buf()` 未彻底清空接收缓冲区,导致旧数据干扰新响应 - **硬件流控缺失**:高波特率下未启用RTS/CTS流控导致数据丢失 3. **关键代码缺陷**: ```c // 错误:未检查两个命令的独立状态 if (ret == ESP8266_ROK) // ret是两次返回值的和(0或1或2) return ESP8266_ROK; ``` - 应改为: ```c if (ret == 2 * ESP8266_ROK) // 需两个命令都成功 ``` ### 解决方案 1. **修复函数逻辑**: ```c uint8_t esp8266_enter_unvarnished(void) { uint8_t ret1 = esp8266_send_cmd("AT+CIPMODE=1\r\n", "OK"); uint8_t ret2 = esp8266_send_cmd("AT+CIPSEND\r\n", ">"); return (ret1 == ESP8266_ROK && ret2 == ESP8266_ROK) ? ESP8266_ROK : ESP8266_REEOR; } ``` 2. **增加调试输出**: ```c uint8_t esp8266_send_cmd(char* cmd, char* res) { ... printf("[SEND] %s", cmd); // 添加发送日志 while(time_out--) { if(esp8266_wait_recive_data() == ESP8266_ROK) { printf("[RECV] %s", esp8266_rx_buf); // 添加接收日志 ... } } } ``` 3. **延长超时时间**(网络操作需要更久): ```c uint8_t time_out = 500; // 改为5秒 (500*10ms) ``` 4. **确保TCP连接成功**: 在调用前添加状态检查: ```c while(!esp8266_check_tcp_connected()); // 实现TCP连接状态检测 ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值