串口的空闲中断与DMA——高级应用

目录

  • 前言
  • 程序

前言

串口中断接收数据,例如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);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值