本帖最后由 we_1195536316 于 2025-7-2 15:34 编辑
最近在做一个无线串口透传软件,为了实现低波特率不间断传输的功能,我需要当串口接收数据达到56字节(无线打包长度)时启动无线传输,并且串口继续接收后面的数据,当串口接收超时或数据长度刚好整除56时再次启动无线传输直到串口不再有数据为止。我软件里面同时打开了UART_RXDMA_IRQ和UART_RXDONE_IRQ中断,但是中断貌似不按预期发生,总是同时发生,我自己根据极为有限的资料发现了几个嫌疑点,根据DMA初始化函数的描述:
/**
* @brief Receive an amount of data in DMA mode.
* @param[in] RecvAddr - Pointer to data buffer, it must be 4-bytes aligned.
* @param[in] RecvBufLen - Length of DMA in bytes, it must be multiple of 16,the maximum value can be up to 4079,
* RecvBufLen contains the first four bytes to indicate the received length,so uart packet length needs to be no larger than (recBuffLen - 4).
* @return none
* @note -# If the dma receive length reaches the set length, the uart is still receiving data, no rxtimeout is generated,
* the dma will continue to receive, but no buff overflow occurs, and the loopback receive overwrites the received data.
*/
void uart_recbuff_init(unsigned char *RecvAddr, unsigned short RecvBufLen)
可知参数RecvBufLen必须是16的倍数,而我需要的设置值是56并非16倍数,这个算一个问题。另外上面的描述最后一行还提到当dma接收数据超过设置长度不会发生buff溢出事件只会继续覆盖最前面的数据,这算是我发现的第二个问题。不知道我理解的对不对,另外是否有高人有办法实现我的功能需求。
以下是我UART DMA的初始化代码:
void uart_dma_init(void)
{
static const uint32_t Baudrate_tab[] = {1200,2400,4800,9600,19200,38400,57600,115200,230400,460800};
static const UART_ParityTypeDef Parity_tab[] = {PARITY_NONE,PARITY_EVEN,PARITY_ODD,PARITY_NONE,PARITY_EVEN};
static const UART_StopBitTypeDef StopBit_tab[] = {STOP_BIT_ONE,STOP_BIT_ONE,STOP_BIT_ONE_DOT_FIVE,STOP_BIT_TWO};
sleep_ms(2000); //leave enough time for SWS_reset when power on
gpio_set_func(RS485_T1R0,AS_GPIO);
gpio_set_output_en(RS485_T1R0, 1); //enable output
gpio_set_input_en(RS485_T1R0,0); //disable input
gpio_write(RS485_T1R0, 0); //SET RS485 RX
//note: dma addr must be set first before any other uart initialization! (confirmed by sihui)
uart_recbuff_init( (unsigned char *)rec_uart, 56);
#if( UART_WIRE_MODE == UART_1WIRE_MODE)
uart_set_rtx_pin(UART_RTX_PIN);// the status of rtx line will be rx by default,if there is a send-action,the status of rtx-line will changed to tx,and changed to rx immediately if send over.
uart_rtx_en();
#elif(( UART_WIRE_MODE == UART_2WIRE_MODE))
uart_gpio_set(UART_TX_PIN, UART_RX_PIN);// uart tx/rx pin set
#endif
uart_reset(); //uart module power-on again.
if (ConfigIfo.UartBaudRate>9 || ConfigIfo.UartParity>4 || ConfigIfo.UartStopBits>3) {
ConfigIfo.UartBaudRate = 7;ConfigIfo.UartParity = 0;ConfigIfo.UartStopBits = 1;
}
//baud rate: 115200
uart_init_baudrate(Baudrate_tab[ConfigIfo.UartBaudRate],CLOCK_SYS_CLOCK_HZ,Parity_tab[ConfigIfo.UartParity], StopBit_tab[ConfigIfo.UartStopBits]);
uart_dma_enable(1, 1); //uart data in hardware buffer moved by dma, so we need enable them first
uart_rxdone_irq_en();
irq_enable_type(FLD_IRQ_DMA_EN);// uart_rx use dma_rx irq
dma_chn_irq_enable(FLD_DMA_CHN_UART_RX, 1);//uart Rx dma irq enable
uart_mask_tx_done_irq_enable();
uart_mask_error_irq_enable();// open uart_error_mask,when stop bit error or parity error,it will enter error_interrupt.
irq_enable_type(FLD_IRQ_UART_EN);// uart_tx use uart_txdone irq
irq_enable();
#if( FLOW_CTR == USE_CTS )
uart_set_cts(1, STOP_VOLT, UART_CTS_PIN);
#elif( FLOW_CTR == USE_RTS )
uart_set_rts(1, RTS_MODE, RTS_THRESH, RTS_INVERT,UART_RTS_PIN);
#endif
}
|