|  |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright (c) 2006-2021, RT-Thread Development Team | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * SPDX-License-Identifier: Apache-2.0 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Change Logs: | 
					
						
							|  |  |  |  * Date           Author       Notes | 
					
						
							|  |  |  |  * 2025-10-25     Administrator       the first version | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | # include <rtthread.h>
 | 
					
						
							|  |  |  | # include <rtdevice.h>
 | 
					
						
							|  |  |  | # include <board.h>
 | 
					
						
							|  |  |  | #include "uart_framework.h"
 | 
					
						
							|  |  |  | #include "data_comm.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define LOG_TAG              "uart.rx"
 | 
					
						
							|  |  |  | #define LOG_LVL              LOG_LVL_DBG
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define UART_NAME           "uart2"
 | 
					
						
							|  |  |  | #define UART_BAUD_RATE      BAUD_RATE_115200
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define RS485RD             GET_PIN(A,10)
 | 
					
						
							|  |  |  | #define RS485_RX()          rt_pin_write(RS485RD, 0)
 | 
					
						
							|  |  |  | #define RS485_TX()          rt_pin_write(RS485RD, 1)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define RECV_BUF_SIZE       (512)
 | 
					
						
							|  |  |  | #define FRAME_TIMEOUT_MS    20
 | 
					
						
							|  |  |  | #define SEND_INTERVAL_MS    0
 | 
					
						
							|  |  |  | #define REQUEST_TIMEOUT_MS  250
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static uart_framework_t uf = RT_NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void rs485_set_tx(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     RS485_TX(); | 
					
						
							|  |  |  |     rt_thread_mdelay(1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void rs485_set_rx(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     rt_thread_mdelay(1); | 
					
						
							|  |  |  |     RS485_RX(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void rs485_gpio_init(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     rt_pin_mode(RS485RD, PIN_MODE_OUTPUT); | 
					
						
							|  |  |  |     rs485_set_rx(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static rt_err_t uart_rs485_init(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     rt_device_t serial_device = rt_device_find(UART_NAME); | 
					
						
							|  |  |  |     if (serial_device == RT_NULL) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         rt_kprintf("not find the serial device:%s!", UART_NAME); | 
					
						
							|  |  |  |         return -RT_ERROR; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* 修改串口配置 */ | 
					
						
							|  |  |  |     struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; | 
					
						
							|  |  |  |     config.baud_rate = UART_BAUD_RATE; | 
					
						
							|  |  |  |     config.bufsz = RECV_BUF_SIZE;   // 接收缓冲区大小
 | 
					
						
							|  |  |  |     rt_device_control(serial_device, RT_DEVICE_CTRL_CONFIG, &config); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     rs485_gpio_init(); | 
					
						
							|  |  |  |     struct uart_framework_cfg cfg = { .uart_name = UART_NAME, .max_frame_size = RECV_BUF_SIZE, .frame_interval_ms = | 
					
						
							|  |  |  |     FRAME_TIMEOUT_MS, .send_interval_ms = SEND_INTERVAL_MS, .rs485_txd = rs485_set_tx, .rs485_rxd = rs485_set_rx }; | 
					
						
							|  |  |  |     //如果不是485,则配置rs485_txd和rs485_rxd为RT_NULL
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     uf = uart_framework_create(&cfg); | 
					
						
							|  |  |  |     if (uf == RT_NULL) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         rt_kprintf("SCCM link create failed on %s\n", UART_NAME); | 
					
						
							|  |  |  |         return -RT_ERROR; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         rt_kprintf("SCCM link create success on %s!\n", UART_NAME); | 
					
						
							|  |  |  |         return RT_EOK; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static rt_err_t frame_handler(rt_uint8_t *data, rt_size_t size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     //解析数据
 | 
					
						
							|  |  |  |     rt_err_t res; | 
					
						
							|  |  |  |     struct proc_request *req = rt_malloc(sizeof(struct proc_request)); | 
					
						
							|  |  |  |     if (!req){ return RT_ERROR;} | 
					
						
							|  |  |  |     rt_strncpy(req->input, (const char *)data, sizeof(req->input)); | 
					
						
							|  |  |  |     req->input_len = size; | 
					
						
							|  |  |  |     req->sem = rt_malloc(sizeof(struct rt_semaphore)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!req->sem) { | 
					
						
							|  |  |  |         rt_free(req); | 
					
						
							|  |  |  |         return RT_ERROR; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     rt_sem_init(req->sem, "uart_resp", 0, RT_IPC_FLAG_FIFO); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // 发送到处理线程
 | 
					
						
							|  |  |  |     if (rt_mq_send(proc_mq, &req, sizeof(req)) == RT_EOK) | 
					
						
							|  |  |  |     {   // 等待处理完成
 | 
					
						
							|  |  |  |         if (rt_sem_take(req->sem, RT_WAITING_FOREVER) == RT_EOK) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             res=  uart_framework_send(uf, (rt_uint8_t *)req->output, req->output_len); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     // 清理
 | 
					
						
							|  |  |  |     rt_sem_detach(req->sem);  // 或 rt_sem_delete
 | 
					
						
							|  |  |  |     rt_free(req->sem); | 
					
						
							|  |  |  |     rt_free(req); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void rs485_rx_handler(void *params) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     while (1) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if(uart_framework_receive(uf, RT_WAITING_FOREVER, RT_NULL, RT_NULL, 0) == RT_EOK) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             frame_handler(uf->rx_buf, uf->rx_size); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int app_uart_rs485_startup(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     rt_err_t rst; | 
					
						
							|  |  |  |     rst = uart_rs485_init(); | 
					
						
							|  |  |  |     if (rst != RT_EOK) | 
					
						
							|  |  |  |         return rst; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     rt_thread_t t = rt_thread_create("rs485rx", rs485_rx_handler, RT_NULL, 1024 * 4, 12, 20); | 
					
						
							|  |  |  |     if (t == RT_NULL) | 
					
						
							|  |  |  |         return -RT_ENOMEM; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     rst = rt_thread_startup(t); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return rst; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | //INIT_APP_EXPORT(app_uart_rs485_startup);
 |