本帖最后由 一路向北lm 于 2022-3-16 11:08 编辑
杂谈6 串口空闲中断 + DMA 不定长数据帧接收 串口不定长数据帧扮演者很重要的角色,我想一个写通讯的程序不会撸这段代码怎么能行呢?借着雅特力这块宝地,开始造起来! 第一步串口GPIO初始化 //****************************************************************
//****** 串口GPIO初始化函数
//****** 输入参数: 无
//****** 返回值: 无
//****************************************************************
static void PhyUartGpioInit()
{
gpio_init_type gpio_init_struct;
crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
gpio_default_para_init(&gpio_init_struct);
gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
gpio_init_struct.gpio_pins = GPIO_PINS_9|GPIO_PINS_10;
gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
gpio_init(GPIOA, &gpio_init_struct);
gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE9, GPIO_MUX_1);
gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE10, GPIO_MUX_1);
}
第二步 串口参数初始化 //****************************************************************
//****** 串口参数初始化函数
//****** 输入参数: uint32_t baudrate 波特率
//****** 返回值: 无
//****************************************************************
static void PhyUartCoreInit(uint32_t baudrate)
{
crm_periph_clock_enable(CRM_USART1_PERIPH_CLOCK, TRUE);
usart_init(USART1, baudrate, USART_DATA_8BITS, USART_STOP_1_BIT);
usart_parity_selection_config(USART1, USART_PARITY_NONE);
usart_transmitter_enable(USART1, TRUE);
usart_receiver_enable(USART1, TRUE);
usart_dma_receiver_enable(USART1, TRUE);
nvic_irq_enable(USART1_IRQn, 0, 0);
usart_interrupt_enable(USART1, USART_IDLE_INT, TRUE);
usart_enable(USART1, TRUE);
}
第三步 串口DMA初始化 //****************************************************************
//****** 串口DMA参数初始化函数
//****** 输入参数: 无
//****** 返回值: 无
//****************************************************************
void PhyUartDmaInit()
{
dma_init_type dma_init_struct;
crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);
dma_reset(DMA1_CHANNEL3);
dma_default_para_init(&dma_init_struct);
dma_init_struct.buffer_size = USART_RX_BUFFER_SIZE;
dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;
dma_init_struct.memory_base_addr = (uint32_t)UartRxBuffer;
dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE;
dma_init_struct.memory_inc_enable = TRUE;
dma_init_struct.peripheral_base_addr = (uint32_t)&USART1->dt;
dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE;
dma_init_struct.peripheral_inc_enable = FALSE;
dma_init_struct.priority = DMA_PRIORITY_MEDIUM;
dma_init_struct.loop_mode_enable = FALSE;
dma_init(DMA1_CHANNEL3, &dma_init_struct);
dma_channel_enable(DMA1_CHANNEL3, TRUE);
}
第四步 串口初始化,以上三个**合力! //****************************************************************
//****** 串口初始化函数
//****** 输入参数: 无
//****** 返回值: 无
//****************************************************************
void PhyUartInit()
{
PhyUartGpioInit();
PhyUartDmaInit();
PhyUartCoreInit(115200);
}
第五步 最关键的一步,串口空闲中断处理函数! //****************************************************************
//****** 串口中断处理函数
//****** 输入参数: 无
//****** 返回值: 无
//****************************************************************
void USART1_IRQHandler()
{
uint16_t rc_len;
if(usart_flag_get(USART1, USART_IDLEF_FLAG) != RESET)
{
usart_data_receive(USART1);
dma_channel_enable(DMA1_CHANNEL3,FALSE);
rc_len = USART_RX_BUFFER_SIZE - dma_data_number_get(DMA1_CHANNEL3);
dma_data_number_set(DMA1_CHANNEL3, USART_RX_BUFFER_SIZE);
dma_channel_enable(DMA1_CHANNEL3,TRUE);
if((UartRxBuffer[1]>=0x80) && (UartRxBuffer[1]<=0x90)) //使用命令码过滤错误帧
{
UartRecvSta = 1;
UartFramRecvLen = rc_len;
}
else
{
UartFramRecvLen = 0;
UartRecvSta = 0;
}
}
}
最后,在补充一些变量哈,大家知道它是怎么来的。 #define USART_RX_BUFFER_SIZE 1024
uint8_t UartRxBuffer[1024]; //串口接收帧Buffer
uint16_t UartFramRecvLen; //串口接收帧长度
uint8_t UartRecvSta; //串口接收帧完成标志位
|