2332|2

565

帖子

0

TA的资源

一粒金砂(高级)

楼主
 

【AT-START-F425测评】+ 串口空闲中断与DMA [复制链接]

 

0、前言

上节使用串口空闲中断和接收中断实现了串口不定长数据接收,本文使用DMA的方式接收串口数据。

 

1、两种方式特点分析

串口接收中断的特点:每接收一个数据,需要进一次中断,会不断打断正常程序的执行,在接收数据期间,cpu会不断切换上下文,消耗cpu的时间。

使用DMA接收的优势:配置好DMA之后,让DMA控制器去接收,不需要cpu参与,节省了cpu的时间,提高了cpu的利用率。

 

2、如何判断串口数据接收完成

这里使用空闲中断,当产生空闲中断的时候,就认为是一帧数据传输完成了。

 

3、关于AT32F425的DMA

可以看出有1个DMA控制器,支持7个通道;

支持8位、16位、32位数据宽度;

最大支持65535个数据传输;

DMA支持的外设ADC、I2C、SPI、TIME、USART等。

 

4、DMA通道配置

 可以看出,任何一个通道的请求来源,都可以弹性配置,而不是固定的几个,这也是AT32F425的DMA的一个特色之处。

 

5、代码实现

(1)缓冲区定义

#define UART_MAX_BUFF_LEN    255

uint8_t UartBuff[UART_MAX_BUFF_LEN];
uint8_t UartIdle=0;
uint8_t UartLen=0;

(2)串口初始化

void UartInit(void)
{
	gpio_init_type gpio_init_struct;
   	crm_periph_clock_enable(CRM_USART1_PERIPH_CLOCK, TRUE);  

	/* enable the usart1 and gpio clock */
	crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);

	gpio_default_para_init(&gpio_init_struct);

	/* configure the usart1 tx/rx pin */
	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_6 | GPIO_PINS_7;
	gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
	gpio_init(GPIOB, &gpio_init_struct);
 
	/* config usart1 iomux */
	gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE6, GPIO_MUX_0); 
	gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE7, GPIO_MUX_0);


	/* config usart1 nvic interrupt */
	nvic_irq_enable(USART1_IRQn, 3, 0);
  
	/* configure usart1 param */
	usart_init(USART1, 115200, USART_DATA_8BITS, USART_STOP_1_BIT);
	usart_parity_selection_config(USART1, USART_PARITY_NONE);
    usart_hardware_flow_control_set(USART1,USART_HARDWARE_FLOW_NONE);

	usart_transmitter_enable(USART1, TRUE);
	usart_receiver_enable(USART1, TRUE);
	  
	usart_dma_receiver_enable(USART1, TRUE);  

	usart_interrupt_enable(USART1, USART_IDLE_INT, TRUE);

	usart_enable(USART1, TRUE);
	
	void UartDmaRxInit(void);
	UartDmaRxInit();
}

(3)串口1接收DMA配置

这里传输方向是外设到内存,外设就是串口,内存是数据缓冲区;

接收到数据后要保存起来,因此内存每次自增。

void UartDmaRxInit(void)
{
  dma_init_type dma_init_struct;  
  
  /* enable dma1 clock */
  crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);  
	
  dma_reset(DMA1_CHANNEL1);
  dma_default_para_init(&dma_init_struct);  
  dma_init_struct.buffer_size = UART_MAX_BUFF_LEN;
  dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;
  dma_init_struct.memory_base_addr = (uint32_t)UartBuff;
  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_CHANNEL1, &dma_init_struct);
  
  /* config flexible dma for usart1 rx */
  dma_flexible_config(DMA1, FLEX_CHANNEL1, DMA_FLEXIBLE_UART1_RX);
  
  dma_channel_enable(DMA1_CHANNEL1, TRUE);
}

(4)串口中断

这里只用到了空闲中断,产生空闲中断后,读取接收到的数据长度。

void USART1_IRQHandler(void)
{
	if(usart_flag_get(USART1,USART_IDLEF_FLAG)!= RESET)
	{
		UartDmaRxData();   
		usart_data_receive(USART1);
	}
}

(5)串口DMA接收

void UartDmaRxData(void)
{
	dma_channel_enable(DMA1_CHANNEL1, FALSE); //先暂时关闭dma
	dma_flag_clear(DMA1_FDT1_FLAG);  
	
	UartLen=UART_MAX_BUFF_LEN-dma_data_number_get(DMA1_CHANNEL1); //获取接收的长度
		
	dma_data_number_set(DMA1_CHANNEL1, UART_MAX_BUFF_LEN); //重新设置长度

	UartIdle=1;  //一帧数据接收完成标志
}

(6)应用层处理

void UartPro(void)
{
	if(UartLen&&UartIdle)
	{
		printf("Recv:%d,[",UartLen);
		UartSend(UartBuff,UartLen);

		printf("]\r\n");
		
		UartLen=0;
		UartIdle=0;
		dma_channel_enable(DMA1_CHANNEL1, TRUE); //重新打开DMA
	}
}

(7)其他代码

void UartSend(uint8_t *data,uint8_t len)
{
	for(uint8_t i=0; i<len;i++)
	{
		while (RESET == usart_flag_get(USART1, USART_TDC_FLAG));
		usart_data_transmit(USART1, data[i]);
	}
}

/* retarget the C library printf function to the USART */
int fputc(int ch, FILE *f)
{
	while(usart_flag_get(USART1, USART_TDC_FLAG) == RESET);
	usart_data_transmit(USART1, (uint8_t) ch);
	
    return ch;
}

6、测试

 

 

 

 

 

 

最新回复

对串口你是整得熟烂了呀,这对新接手的小伙伴是很好的教材,学习了。辛苦了哈  详情 回复 发表于 2022-4-15 11:32
点赞 关注(1)
个人签名stm32/LoRa物联网:304350312
 
 

回复
举报

6960

帖子

11

TA的资源

版主

沙发
 
对串口你是整得熟烂了呀,这对新接手的小伙伴是很好的教材,学习了。辛苦了哈
 
 
 

回复

565

帖子

0

TA的资源

一粒金砂(高级)

板凳
 
lugl4313820 发表于 2022-4-15 11:32 对串口你是整得熟烂了呀,这对新接手的小伙伴是很好的教材,学习了。辛苦了哈

个人签名stm32/LoRa物联网:304350312
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表