目录
- 前言
- 程序
前言
串口中断接收数据,例如AT指令发送与接收。检测到数据寄存器有数据后触发串口中断,在中断服务函数中,将数据寄存器值存到内存中,并清理非空标志位
,这种传统做法是传输一个字节产生一次中断。
现在使用DMA,数据寄存器有数据后,DMA自动把数据寄存器值存到指定位置,DMA规定传输n个字节后串口空闲了,然后触发串口中断,在中断服务函数中,清理空闲标志位
,这种做法是串口接收到n个字节后产生一次中断。
程序
- 串口初始化
- DMA初始化
- 串口中断服务函数
static void Usb2ComDmaInit(void)
{
/* 使能DMA时钟;*/
rcu_periph_clock_enable(g_uartHwInfo.rcuDma);
/* 复位DMA通道;*/
dma_deinit(g_uartHwInfo.dmaNo, g_uartHwInfo.dmaCh);
dma_parameter_struct dmaStruct;
/* 配置传输方向;*/
dmaStruct.direction = DMA_PERIPHERAL_TO_MEMORY;
/* 配置数据源地址;*/
dmaStruct.periph_addr = USART0_DATA_ADDR;
/* 配置源地址是固定的还是增长的;*/
dmaStruct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
/* 配置源数据传输位宽;*/
dmaStruct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
/* 配置数据目的地址;*/
dmaStruct.memory_addr = (uint32_t)g_rcvDataBuf;
/* 配置目的地址是固定的还是增长的;*/
dmaStruct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
/* 配置目的数据传输位宽;*/
dmaStruct.memory_width = DMA_MEMORY_WIDTH_8BIT;
/* 配置数据传输最大次数;*/
dmaStruct.number = MAX_BUF_SIZE;
/* 配置DMA通道优先级;*/
dmaStruct.priority = DMA_PRIORITY_HIGH;
dma_init(g_uartHwInfo.dmaNo, g_uartHwInfo.dmaCh, &dmaStruct);
/* 使能UART接收数据使用DMA;*/
usart_dma_receive_config(g_uartHwInfo.uartNo, USART_RECEIVE_DMA_ENABLE);
/* 使能DMA通道;*/
dma_channel_enable(g_uartHwInfo.dmaNo, g_uartHwInfo.dmaCh);
}
static void Usb2ComGpioInit(void)
{
rcu_periph_clock_enable(g_uartHwInfo.rcuGpio);
gpio_init(g_uartHwInfo.gpio, GPIO_MODE_AF_PP, GPIO_OSPEED_10MHZ, g_uartHwInfo.txPin);
gpio_init(g_uartHwInfo.gpio, GPIO_MODE_IPU, GPIO_OSPEED_10MHZ, g_uartHwInfo.rxPin);
}
static void Usb2ComUartInit(uint32_t baudRate)
{
/* 使能UART时钟;*/
rcu_periph_clock_enable(g_uartHwInfo.rcuUart);
/* 复位UART;*/
usart_deinit (g_uartHwInfo.uartNo);
/* 通过USART_CTL0寄存器的WL设置字长;*/
//usart_word_length_set(g_uartHwInfo.uartNo, USART_WL_8BIT);
/* 通过USART_CTL0寄存器的PCEN设置校验位;*/
//usart_parity_config(g_uartHwInfo.uartNo, USART_PM_NONE);
/* 在USART_CTL1寄存器中写STB[1:0]位来设置停止位的长度;*/
//usart_stop_bit_set(g_uartHwInfo.uartNo, USART_STB_1BIT);
/* 在USART_BAUD寄存器中设置波特率;*/
usart_baudrate_set(g_uartHwInfo.uartNo, baudRate);
/* 在USART_CTL0寄存器中设置TEN位,使能发送功能;*/
usart_transmit_config(g_uartHwInfo.uartNo, USART_TRANSMIT_ENABLE);
/* 在USART_CTL0寄存器中设置TEN位,使能接收功能;*/
usart_receive_config(g_uartHwInfo.uartNo, USART_RECEIVE_ENABLE);
/* 使能串口接收空闲中断;*/
usart_interrupt_enable(g_uartHwInfo.uartNo, USART_INT_IDLE);
/* 使能串口中断;*/
nvic_irq_enable(g_uartHwInfo.irq, 0, 0);
/* 在USART_CTL0寄存器中置位UEN位,使能UART;*/
usart_enable(g_uartHwInfo.uartNo);
}
/**
***********************************************************
* @brief 串口0中断服务函数
* @param
* @return
***********************************************************
*/
void USART0_IRQHandler(void)
{
if (usart_interrupt_flag_get(g_uartHwInfo.uartNo, USART_INT_FLAG_IDLE) != RESET)
{
usart_interrupt_flag_clear(g_uartHwInfo.uartNo, USART_INT_FLAG_IDLE); //第一步,读取stat0寄存器,清除IDLE标志位
usart_data_receive(g_uartHwInfo.uartNo); //第二步,读取数据寄存器,清除IDLE标志位
if (PACKET_DATA_LEN == (MAX_BUF_SIZE - dma_transfer_number_get(g_uartHwInfo.dmaNo, g_uartHwInfo.dmaCh)))
{
g_pktRcvd = true;
}
dma_channel_disable(g_uartHwInfo.dmaNo, g_uartHwInfo.dmaCh);
dma_transfer_number_config(g_uartHwInfo.dmaNo, g_uartHwInfo.dmaCh, MAX_BUF_SIZE);
dma_channel_enable(g_uartHwInfo.dmaNo, g_uartHwInfo.dmaCh);
}
}