首先在乐鑫官方的参考文档里面只有简单的几句话:
官方参考文档里有关串口中断的描述
ESP8266_RTOS_SDK 默认使⽤ UART0 打印调试信息,默认波特率为 74880。用户可以在 user_init 中⾃定义初始化 UART,参考 uart_init_new 实现。UART 驱动示例: \ESP8266_RTOS_SDK\driver_lib\driver\uart.c
以初始化 UART0 为例。定义 UART 参数:
UART_ConfigTypeDef uart_config;
uart_config.baud_rate = BIT_RATE_74880;
uart_config.data_bits = UART_WordLength_8b;
uart_config.parity = USART_Parity_None;
uart_config.stop_bits = USART_StopBits_1;
uart_config.flow_ctrl = USART_HardwareFlowControl_None;
uart_config.UART_RxFlowThresh = 120;
uart_config.UART_InverseMask = UART_None_Inverse;
UART_ParamConfig(UART0, &uart_config);
注册 UART 中断处理函数,使能 UART 中断:
UART_IntrConfTypeDef uart_intr;
编程示例
uart_intr.UART_IntrEnMask = UART_RXFIFO_TOUT_INT_ENA | UART_FRM_ERR_INT_ENA | UART_RXFIFO_FULL_INT_ENA | UART_TXFIFO_EMPTY_INT_ENA;
uart_intr.UART_RX_FifoFullIntrThresh = 10;
uart_intr.UART_RX_TimeOutIntrThresh = 2;
uart_intr.UART_TX_FifoEmptyIntrThresh = 20;
UART_IntrConfig(UART0, &uart_intr);
UART_SetPrintPort(UART0);
UART_intr_handler_register(uart0_rx_intr_handler);
ETS_UART_INTR_ENABLE();
然后就没有更多的解释了!
从这篇博客里看到:http://blog.sina.com.cn/s/blog_ed2c83c30102xc0o.html
要达到上述三点要求,其实现思路大致如下:
UART_IntrConfTypeDef uart_intr;
uart_intr.UART_IntrEnMask = UART_FRM_ERR_INT_ENA | UART_RXFIFO_FULL_INT_ENA | UART_RXFIFO_TOUT_INT_ENA;
uart_intr.UART_RX_FifoFullIntrThresh = 63;
uart_intr.UART_RX_TimeOutIntrThresh = 20;
uart_intr.UART_TX_FifoEmptyIntrThresh = 20;
UART_IntrConfig(UART0, &uart_intr);
它的思想就是:
- 首先注册中断服务函数,并注册完成之后马上初始化一个队列(便于将数据在任务之间传递)和开始一个串口任务
- 编写中断服务函数,在中断服务函数中判断条件,可以设置为串口数据溢出时就把数据发送到队列
- 在串口任务中只要一检测到队列中有数据发送就马上用串口打印出来。
user_main.c(删除了一些不必要的代码)
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "esp_common.h"
#include "esp_wifi.h"
#include "uart.h"
#include "apps/sntp.h"
#include "iot_export.h"
#include "aliyun_port.h"
#include "aliyun_config.h"
#include "ota.h"
#include "mqtt.h"
int got_ip_flag = 0;
ota_info_t *p_ota_info = NULL;
enum {
UART_EVENT_RX_CHAR,
UART_EVENT_MAX
};
typedef struct _os_event_ {
uint32 event;
uint32 param;
} os_event_t;
xTaskHandle xUartTaskHandle;
xQueueHandle xQueueUart;
LOCAL STATUS
uart_tx_one_char(uint8 uart, uint8 TxChar)
{
while (true) {
uint32 fifo_cnt = READ_PERI_REG(UART_STATUS(uart)) & (UART_TXFIFO_CNT << UART_TXFIFO_CNT_S);
if ((fifo_cnt >> UART_TXFIFO_CNT_S & UART_TXFIFO_CNT) < 126) {
break;
}
}
WRITE_PERI_REG(UART_FIFO(uart) , TxChar);
return OK;
}
// 串口处理任务 步骤:3
LOCAL void
user_uart_task(void *pvParameters)
{
os_event_t e;
for (;;) {
if (xQueueReceive(xQueueUart, (void *)&e, (portTickType)portMAX_DELAY)) {
switch (e.event) {
case UART_EVENT_RX_CHAR:
printf("%c", e.param); // 打印一个字符
break;
default:
break;
}
}
}
vTaskDelete(NULL);
}
// 串口中断服务函数 步骤:2
LOCAL void
user_uart0_rx_intr_handler(void *para)
{
os_event_t e;
portBASE_TYPE xHigherPriorityTaskWoken;
uint8 RcvChar;
uint8 uart_no = UART0;//UartDev.buff_uart_no;
uint8 fifo_len = 0;
uint8 buf_idx = 0;
uint8 fifo_tmp[128] = {0};
uint32 uart_intr_status = READ_PERI_REG(UART_INT_ST(uart_no)) ;
while (uart_intr_status != 0x0) {
if (UART_FRM_ERR_INT_ST == (uart_intr_status & UART_FRM_ERR_INT_ST)) {
//printf("FRM_ERR\r\n");
WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_FRM_ERR_INT_CLR);
} else if (UART_RXFIFO_FULL_INT_ST == (uart_intr_status & UART_RXFIFO_FULL_INT_ST)) { // 串口数据溢出
//printf("*************full\r\n");
fifo_len = (READ_PERI_REG(UART_STATUS(UART0)) >> UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT;
buf_idx = 0;
/* while (buf_idx < fifo_len) {
uart_tx_one_char(UART0, READ_PERI_REG(UART_FIFO(UART0)) & 0xFF);
buf_idx++;
} */
RcvChar = READ_PERI_REG(UART_FIFO(uart_no)) & 0xFF; // 将一个字符拷贝过去
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR);
// 设置为串口接收溢出时就将数据传到队列
e.event = UART_EVENT_RX_CHAR;
e.param = RcvChar;
xQueueSendFromISR(xQueueUart, (void *)&e, &xHigherPriorityTaskWoken); // 将数据发送到队列一次只有一次字符
portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
}
uart_intr_status = READ_PERI_REG(UART_INT_ST(uart_no)) ;
}
}
// 串口中断初始化 步骤:1
void
user_uart_init(void)
{
UART_WaitTxFifoEmpty(UART0);
UART_WaitTxFifoEmpty(UART1);
UART_ConfigTypeDef uart_config;
uart_config.baud_rate = BIT_RATE_115200;
uart_config.data_bits = UART_WordLength_8b;
uart_config.parity = USART_Parity_None;
uart_config.stop_bits = USART_StopBits_1;
uart_config.flow_ctrl = USART_HardwareFlowControl_None;
uart_config.UART_RxFlowThresh = 120;
uart_config.UART_InverseMask = UART_None_Inverse;
UART_ParamConfig(UART0, &uart_config);
UART_IntrConfTypeDef uart_intr;
uart_intr.UART_IntrEnMask = UART_RXFIFO_TOUT_INT_ENA | UART_FRM_ERR_INT_ENA | UART_RXFIFO_FULL_INT_ENA | UART_TXFIFO_EMPTY_INT_ENA;
uart_intr.UART_RX_FifoFullIntrThresh = 10; // 设置10个字符就溢出
uart_intr.UART_RX_TimeOutIntrThresh = 10;
uart_intr.UART_TX_FifoEmptyIntrThresh = 20;
UART_IntrConfig(UART0, &uart_intr);
UART_SetPrintPort(UART0);
UART_intr_handler_register(user_uart0_rx_intr_handler, NULL);
ETS_UART_INTR_ENABLE();
// 中断设置完成以后就马上初始化队列和创建串口处理任务
xQueueUart = xQueueCreate(32, sizeof(os_event_t));
xTaskCreate(user_uart_task, (uint8 const *)"uTask", 512, NULL, 5, &xUartTaskHandle);
}
void user_init(void)
{
user_uart_init();
}