串口通讯为RS232通讯,接收采用中断方式(数据处理是消息队列+消息缓冲区),发送是查询方式(利用通知确定要发送的数据内容)。
本程序参考乐鑫官方示例,但做了如下修改:
1. 采用消息缓冲区进行接收数据处理,是因为当数据较长时接收中断并不能一次接收到一帧完整数据(取决于默认设置)。
2. 采用通知实现发送数据内容选择,是为了更高效的对发送进行控制。
首先在一个公共头文件def.h声明一个通知变量,为的是在主函数中发送通知给串口处理源文件的发送任务函数。
extern TaskHandle_t UartTxTask_NotifyHandle;
串口处理头文件uhf.h中内容。
- #define UART_UHF UART_NUM_2
-
- esp_err_t uart2_init(int baud,int bufSize);
串口处理源文件uhf.c中变量定义部分
- static const char *UART2_TAG = "uart2_events";
-
- static QueueHandle_t uart2_rx_queue;
- static uint8_t uart2_send_buf[512]={1,2,3,4,5,6,7,8};
- static uint8_t uart2_recv_buf[512];
- static int uart2_sendnum;
- static int uart2_recvnum;
-
- static MessageBufferHandle_t uart2_MsgBufHandle;
-
- TaskHandle_t UartTxTask_NotifyHandle;
串口处理源文件uhf.c中实现串口初始化和发送接收任务创建部分
-
-
- //-------------------------串口2初始化---------------------------
- esp_err_t uart2_init(int baud,int bufSize)
- {
- esp_log_level_set(UART2_TAG, ESP_LOG_INFO);
-
- /* Configure parameters of an UART driver,
- * communication pins and install the driver */
- uart_config_t uart_config = {
- .baud_rate = baud,
- .data_bits = UART_DATA_8_BITS,
- .parity = UART_PARITY_DISABLE,
- .stop_bits = UART_STOP_BITS_1,
- .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
- .source_clk = UART_SCLK_APB,
- };
- //Install UART driver, and get the queue.
- uart_driver_install(UART_UHF, bufSize * 2, bufSize * 2, 20, &uart2_rx_queue, 0);
- uart_param_config(UART_UHF, &uart_config);
-
- //Set UART log level
- esp_log_level_set(UART2_TAG, ESP_LOG_INFO);
- //Set UART pins
- uart_set_pin(UART_UHF, 21, 19, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
- //Reset the pattern queue length to record at most 20 pattern positions.
- uart_pattern_queue_reset(UART_UHF, 20);
-
- uart_enable_rx_intr(UART_UHF);
- //创建发送和接收任务
- uart2_MsgBufHandle = xMessageBufferCreate(1500);
- if(uart2_MsgBufHandle != NULL){
- xTaskCreate(uart2_event_task, "uart2_event_task", bufSize*2, NULL, configMAX_PRIORITIES-1, NULL);
- xTaskCreate(uart2_rx_task, "uart2_rx_task", bufSize*2, NULL, configMAX_PRIORITIES-3, NULL);
- xTaskCreate(uart2_tx_task, "uart2_tx_task", bufSize*2, NULL, configMAX_PRIORITIES-5, &UartTxTask_NotifyHandle);
- }
- return ESP_OK;
- }
串口处理源文件uhf.c中接收中断处理和数据缓存和解析,根据通讯协议确定接收数据是否完成和正确(协议不同处理方式需做相应调整)。
- //-------------------------串口2接收任务---------------------------
- static void uart2_rx_task(void *arg)
- {
- static const char *TX_TASK_TAG = "TX_TASK";
- int len = 0;
- uint16_t crc;
- int num;
- static uint8_t frame_buf[512];
- static int frame_header = 0;
- BaseType_t xHigherPriorityTaskWoken = pdFALSE;
-
- esp_log_level_set(TX_TASK_TAG, ESP_LOG_INFO);
- while (1) {
- vTaskDelay(10 / portTICK_PERIOD_MS);
- num = xMessageBufferReceiveFromISR(uart2_MsgBufHandle,frame_buf,sizeof(frame_buf),&xHigherPriorityTaskWoken);
- datacopy(&uart2_recv_buf[uart2_recvnum],frame_buf,num);
- uart2_recvnum += num;
- //接收数据长度需满足最小要求
- if((uart2_recvnum-frame_header) < 9) continue;
- //定位帧头位置
- if(uart2_recv_buf[frame_header] != 0x5A){
- frame_header++;
- continue;
- }
- //找到了正取的帧头,然后需要判断是否是一组完整的数据帧,CRC校验是否正确
- len = uart2_recv_buf[frame_header+5]*256 + uart2_recv_buf[frame_header+6];
- if((uart2_recvnum-frame_header) >= (len + 9))
- {
- // if(DEBUG_ON) printf("uart2 recv end,data len = %4d \r\n", uart2_recvnum);
- // for(int i=0;i
- crc = crc16_CCITT(&uart2_recv_buf[frame_header+1],len + 9-3);
- if((((crc & 0xff00)>>8) != uart2_recv_buf[len + 9-2]) || ((crc & 0x00ff) != uart2_recv_buf[len + 9-1]))
- {
- frame_header++;
- if(DEBUG_ON) printf("uart2 crc error!\r\n");
- }
- else//找到正取的数据帧
- {
- datacopy(frame_buf,&uart2_recv_buf[frame_header],len + 9);
- uart2_recvnum = uart2_recvnum - frame_header - len - 9;
- if(uart2_recvnum > 0) datacopy(uart2_recv_buf,&uart2_recv_buf[frame_header+len + 9],uart2_recvnum);
- //处理接收到的数据
- frame_handing(frame_buf);
-
- }
- }
- }
- }
- //-------------------------串口2接收事件---------------------------
- static void uart2_event_task(void *pvParameters)
- {
- uart_event_t event;
- BaseType_t xHigherPriorityTaskWoken = pdFALSE;
-
- uint8_t* dtmp = (uint8_t*) malloc(256);
- for(;;) {
- //Waiting for UART event.
- if(xQueueReceive(uart2_rx_queue, (void * )&event, (portTickType)portMAX_DELAY)) {
- bzero(dtmp, 256);
- // if(DEBUG_ON) ESP_LOGI(UART2_TAG, "uart[%d] event:", UART_UHF);
- switch(event.type) {
- //Event of UART receving data
- /*We'd better handler data event fast, there would be much more data events than
- other types of events. If we take too much time on data event, the queue might
- be full.*/
- case UART_DATA:
- // if(DEBUG_ON) ESP_LOGI(UART2_TAG, "[UART event DATA]: %d", event.size);
- uart_read_bytes(UART_UHF, dtmp, event.size, portMAX_DELAY);
- //xMessageBufferSend(MsgBufHandle,dtmp,event.size, portMAX_DELAY);
- xMessageBufferSendFromISR(uart2_MsgBufHandle,dtmp,event.size, &xHigherPriorityTaskWoken);
- break;
- //Event of HW FIFO overflow detected
- case UART_FIFO_OVF:
- if(DEBUG_ON) ESP_LOGI(UART2_TAG, "hw fifo overflow");
- // If fifo overflow happened, you should consider adding flow control for your application.
- // The ISR has already reset the rx FIFO,
- // As an example, we directly flush the rx buffer here in order to read more data.
- uart_flush_input(UART_UHF);
- xQueueReset(uart2_rx_queue);
- break;
- //Event of UART ring buffer full
- case UART_BUFFER_FULL:
- if(DEBUG_ON) ESP_LOGI(UART2_TAG, "ring buffer full");
- // If buffer full happened, you should consider encreasing your buffer size
- // As an example, we directly flush the rx buffer here in order to read more data.
- uart_flush_input(UART_UHF);
- xQueueReset(uart2_rx_queue);
- break;
- //Event of UART RX break detected
- case UART_BREAK:
- if(DEBUG_ON) ESP_LOGI(UART2_TAG, "uart rx break");
- break;
- //Event of UART parity check error
- case UART_PARITY_ERR:
- if(DEBUG_ON) ESP_LOGI(UART2_TAG, "uart parity error");
- break;
- //Event of UART frame error
- case UART_FRAME_ERR:
- if(DEBUG_ON) ESP_LOGI(UART2_TAG, "uart frame error");
- break;
- default:
- if(DEBUG_ON) ESP_LOGI(UART2_TAG, "uart event type: %d", event.type);
- break;
- }
- }
- }
- free(dtmp);
- dtmp = NULL;
- vTaskDelete(NULL);
- }
串口处理源文件uhf.c中发送处理
- //-------------------------串口2发送任务---------------------------
- static void uart2_tx_task(void *arg)
- {
- static const char *TX_TASK_TAG = "TX_TASK";
- uint32_t ulNotifiedValue = 0;
- esp_log_level_set(TX_TASK_TAG, ESP_LOG_INFO);
- while (1) {
- vTaskDelay(10 / portTICK_PERIOD_MS);
- xTaskNotifyWait(0, ULONG_MAX,&ulNotifiedValue, pdMS_TO_TICKS(0));
- if((ulNotifiedValue & 0x0100) == 0x0100)//停止
- {
- stop();
- uart_write_bytes(UART_UHF, uart2_send_buf, uart2_sendnum);
- if(DEBUG_ON) printf("Send stop to UHF!\n");
- }
- else if((ulNotifiedValue & 0x0200) == 0x0200)//读TID
- {
- stop();
- uart_write_bytes(UART_UHF, uart2_send_buf, uart2_sendnum);
- vTaskDelay(50 / portTICK_PERIOD_MS);//发送间隔
- read_tid();
- uart_write_bytes(UART_UHF, uart2_send_buf, uart2_sendnum);
- if(DEBUG_ON) printf("Send read TID to UHF!\n");
- }
-
- ulNotifiedValue = 0;
- }
- }
main.c文件中主函数
- void app_main(void)
- {
- uart2_init(115200,2048);
- read = 1;
- while (1)
- {
- vTaskDelay(5000 / portTICK_PERIOD_MS);
- if(read){
- read = 0;
- xTaskNotify(UartTxTask_NotifyHandle,0x0200,eSetBits);//读TID
- }
- else{
- read = 1;
- xTaskNotify(UartTxTask_NotifyHandle,0x0100,eSetBits);//停止
- }
- }
- }