#include "board.h" #include "hard_rc_sbus.h" #include "stdbool.h" #include "hpm_uart_drv.h" #include "test.h" // 与串口3一致 // 如果使用发送和接收都是串口2 那就不需要在sbus_out里面再次进行串口初始化 /*hpm6750没有串口空闲中断 不能使用UART iRQ+DMA 这里采用的是FIFO+超时中断*/ #define SBUS_UART2_RX HPM_UART2 #define SBUS_UART2_CLK_NAME clock_uart2 #define SBUS_UART2_IRQ IRQn_UART2 #define SBUS_UART2_BAUD 115200 #define SBUS_UART2_IRQ_RANK 2 /* 接收缓冲区 */ ATTR_PLACE_AT_NONCACHEABLE uint8_t uart2_dma_rx_buf[UART2_RX_LENDTH_MAX]; /* 全局变量 */ static volatile uint16_t sbus_rx_index = 0; static volatile bool sbus_frame_ready = false; static volatile uint16_t sbus_frame_length = 0; static volatile uint32_t rx_interrupt_count = 0; /* 外部函数声明 */ extern void recv_rcsbus_data_hookfunction(unsigned int len, uint8_t *data); /** * @brief UART中断服务函数 */ SDK_DECLARE_EXT_ISR_M(SBUS_UART2_IRQ, uart2_sbus_isr) void uart2_sbus_isr(void) { uint8_t irq_id = uart_get_irq_id(SBUS_UART2_RX); uint8_t count = 0; /* 处理FIFO阈值中断 - 批量读取数据 */ if (irq_id == uart_intr_id_rx_data_avail) { rx_interrupt_count++; /* 从FIFO中读取数据 */ while (uart_check_status(SBUS_UART2_RX, uart_stat_data_ready)) { count++; uart2_dma_rx_buf[sbus_rx_index++] = uart_read_byte(SBUS_UART2_RX); /* 防止缓冲区溢出 */ if (sbus_rx_index >= UART2_RX_LENDTH_MAX) { sbus_rx_index = 0; /* 环形缓冲,溢出后从头开始 */ } /*in order to ensure rx fifo there are remaining bytes*/ if (count > 12) { break; } } } /* 处理FIFO超时中断 - 一帧数据接收完成 */ if (irq_id == uart_intr_id_rx_timeout) { rx_interrupt_count++; /* 读取FIFO中剩余的所有数据 */ while (uart_check_status(SBUS_UART2_RX, uart_stat_data_ready)) { uart2_dma_rx_buf[sbus_rx_index++] = uart_read_byte(SBUS_UART2_RX); // 回调解析数据 } recv_rcsbus_data_hookfunction(sbus_rx_index, uart2_dma_rx_buf); // recv_rcsbus_data_hookfunction(sbus_rx_index, sbus_rx_buf); /* 标记一帧SBUS数据接收完成 */ sbus_frame_ready = true; sbus_frame_length = sbus_rx_index; /* 记录当前帧长度 */ sbus_rx_index = 0; } } static void rc_uart2_pin_config(void) // 如果使用的是同一个串口的rx 和tx 就初始化1次 { HPM_IOC->PAD[IOC_PAD_PB21].FUNC_CTL = IOC_PB21_FUNC_CTL_UART2_RXD; HPM_IOC->PAD[IOC_PAD_PB22].FUNC_CTL = IOC_PB22_FUNC_CTL_UART2_TXD; } /** * @brief SBUS初始化 */ void rc_sbus_init(uint32_t baud) { uart_config_t config = {0}; hpm_stat_t stat; /* 初始化UART */ rc_uart2_pin_config(); clock_set_source_divider(SBUS_UART2_CLK_NAME, clk_src_osc24m, 1); clock_add_to_group(SBUS_UART2_CLK_NAME, 0); uint32_t freq = clock_get_frequency(SBUS_UART2_CLK_NAME); printf("uart2 clk fre %d\r\n", freq); /* UART默认配置 */ uart_default_config(SBUS_UART2_RX, &config); /* SBUS参数配置 */ config.baudrate = baud; /* 100000bps */ config.word_length = word_length_8_bits; /* 9位数据(8位+偶校验) */ config.num_of_stop_bits = stop_bits_2; /* 2停止位 */ config.parity = parity_even; /* 偶校验 */ config.fifo_enable = true; /* 使能FIFO */ config.src_freq_in_hz = clock_get_frequency(SBUS_UART2_CLK_NAME); /* 设置FIFO阈值 - 设为接近一帧的长度 要小于实际期望接收的字节数 25 */ config.rx_fifo_level = uart_rx_fifo_trg_gt_three_quarters; /* 约24字节 */ stat = uart_init(SBUS_UART2_RX, &config); if (stat != status_success) { printf("SBUS UART2 RX init failed\n"); while (1); } /* 使能UART中断(FIFO阈值+超时) */ uart_enable_irq(SBUS_UART2_RX, uart_intr_rx_data_avail_or_timeout); /* 使能中断控制器 */ intc_m_enable_irq_with_priority(SBUS_UART2_IRQ, SBUS_UART2_IRQ_RANK); /* 初始化变量 */ sbus_rx_index = 0; sbus_frame_ready = false; rx_interrupt_count = 0; printf("SBUS initialized with FIFO + timeout interrupt\n"); } /* uart2 rx_irq demo 2026/03/15 pass*/ #ifdef UART2_RX_TEST void uart2_sbus_test(void) { // char c = 0; rc_sbus_init(SBUS_UART2_BAUD); while(1) { // c++; board_delay_ms(500); if(sbus_frame_ready) { sbus_frame_ready = false; while(sbus_frame_length--) { printf(" %c ",uart2_dma_rx_buf[sbus_frame_length]); } } // UART3_Put_Char(c); // pass } } #endif