IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32G431串口DMA发送 -> 正文阅读

[嵌入式]STM32G431串口DMA发送

1. G4系列DMA简介

首先介绍一下G4系列的DMA情况。
32的G4系列虽然说是基于M4内核的,但是他的DMA通道映射和大家较为常见的F407有较大差异,先贴上几张参考手册中的图片:
在这里插入图片描述
在这里插入图片描述
不知道大家看到这两张图片后能想到什么,相信有看过H7和F4的DMA的朋友一定能反应过来,不错,STM32G4系列基于M4的内核,并且具有和H7一样的DMAMUX(DMA请求复用器)。不熟悉的朋友也没关系,DMAMUX其实就相当于是一个选择器,可以把外设的DMA请求映射到我们的DMA通道上(这么解释可能不对,但我觉得比较形象)。而且最重要的是,这个选择一共有115的外设DMA请求,也就是说这115个DMA请求每一个都可以映射到任何一个DMA通道上。这一点就比F4要方便了,我记得F4的DMA通道是固定的,G4乃至H7就要自由很多。
在这里插入图片描述
G4系列和H7、F4有一点不同的就是,G4没有数据流(STREAMS)这一说法,而是统一使用通道(CHANNELS)来代替,这一点可能会引起大家的误解,其实这俩是一样的。然后,DMAMUX一共是16条通道,0~7对应DMA1,8到15对应DMA2。

2. 代码编写

(1)串口部分的代码就不多说了,如下所示:

void my_uart_init(uint32_t baud){
	__HAL_RCC_USART1_CLK_ENABLE();
	
	UART_HandleTypeStr.Instance = USART1;
	UART_HandleTypeStr.Init.BaudRate = baud;
	UART_HandleTypeStr.Init.HwFlowCtl = UART_HWCONTROL_NONE;
	UART_HandleTypeStr.Init.ClockPrescaler = UART_PRESCALER_DIV1;
	UART_HandleTypeStr.Init.Mode = UART_MODE_TX_RX;
	UART_HandleTypeStr.Init.Parity = UART_PARITY_NONE;
	UART_HandleTypeStr.Init.StopBits = UART_STOPBITS_1;
	UART_HandleTypeStr.Init.WordLength = UART_WORDLENGTH_8B;
	
	HAL_UART_Init(&UART_HandleTypeStr);
	
	HAL_UART_Receive_IT(&UART_HandleTypeStr,receive_buf,sizeof(receive_buf));
}

(2)DMA初始化
其实DMA的初始化和我们之前的外设初始化很像:
① DMA1和DMAMUX的时钟;
② 使用__HAL_LINKDMA将外设和DMA通道链接起来;
③ 结构体配置;
④ DMA DeIint,这一步的目的是为了先复位DMA通道及其参数;
⑤ DMA Init,初始化DMA及其参数。
*⑥ 中断配置,这一步可以不配置,关于DMA中断又是一个比较复杂的话题了,这边就先不赘述了。

void my_dma_init(void){
	__HAL_RCC_DMA1_CLK_ENABLE();		//开启时钟
	__HAL_RCC_DMAMUX1_CLK_ENABLE();		//开启DMA复用器时钟
	
	__HAL_LINKDMA(&UART_HandleTypeStr,hdmatx,DMA_HandleTypeStr);	//外设DMA链接建立
	
	DMA_HandleTypeStr.Instance = DMA1_Channel1;DMA_HandleTypeStr.Instance = DMA1_Channel1;
	DMA_HandleTypeStr.Init.Direction = DMA_MEMORY_TO_PERIPH;
	DMA_HandleTypeStr.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
	DMA_HandleTypeStr.Init.MemInc = DMA_MINC_ENABLE;
	DMA_HandleTypeStr.Init.Mode = DMA_NORMAL;			//模式配置:普通模式/循环模式
	DMA_HandleTypeStr.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
	DMA_HandleTypeStr.Init.PeriphInc = DMA_PINC_DISABLE;
	DMA_HandleTypeStr.Init.Priority = DMA_PRIORITY_HIGH;
	DMA_HandleTypeStr.Init.Request = DMA_REQUEST_USART1_TX;
	
	if(HAL_DMA_DeInit(&DMA_HandleTypeStr) != HAL_OK)
		while(1);
	
	if(HAL_DMA_Init(&DMA_HandleTypeStr) != HAL_OK)
		while(1);
	
//	HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);			//这边配置DMA中断,如果不想要中断的话,那就
//	HAL_NVIC_SetPriority(DMA1_Channel1_IRQn,2,2);	//使用查询法然后手动清空标志位
}													//__HAL_DMA_GET_FLAG()
													//__HAL_DMA_CLEAR_FLAG()

这边就介绍几个参数:
① DMA_HandleTypeStr.Instance = DMA1_Channel1;
在这里插入图片描述
这个参数就是类似于F4或H7的STREAM的选择,DMA1、2各有6个通道选择。

② DMA_HandleTypeStr.Init.Mode = DMA_NORMAL;
在这里插入图片描述
这个模式的话,顾名思义,NORMAL也就是常规发送,发一次就停了,CIRCULAR也就是循环发送,CIRCULAR会一直不断地发送,传输一次后会自动按照相同配置重新传输,周而复始直至被控制停止或传输发生错误。

③ DMA_HandleTypeStr.Init.Request = DMA_REQUEST_USART1_TX;
在这里插入图片描述
这个参数就很重要了,就是我们之前所说的115个外设DMA请求,我们选择需要的外设请求。

剩余的几个参数就不多提了,基本上和其他型号的32一样。

(3)主函数

int main(void)
{
	HAL_Init();
	my_system_clk_config();
	uart_init(115200);
	my_gpio_init();
	my_dma_init();
	
	printf("USART1 DMA TEST\n");
	
	HAL_UART_Transmit_DMA(&UART_HandleTypeStr,send_data,sizeof(send_data));	//开启串口1DMA传输
	while(1){
		if(__HAL_DMA_GET_FLAG(&DMA_HandleTypeStr,DMA_FLAG_TC1)){
			__HAL_DMA_CLEAR_FLAG(&DMA_HandleTypeStr,DMA_FLAG_TC1);	//清楚DMA传输完成标志位
			HAL_UART_DMAStop(&UART_HandleTypeStr);					//传输完成之后停下DMA
		}
		HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_4);	//让MCU控制LED翻转
		HAL_Delay(500);
	}
}

测试的话,模仿正点原子的DMA测试程序,在while之前调用HAL_UART_Transmit_DMA函数进行发送,然后while循环里面闪灯,然后等待DMA发送完成标志位被置位后清空标志位,停止DMA发送。

以上就是工程的主要内容了,现象就不贴上来了,就是打印 “Hello World!” 在上位机上。

工程链接:
添加链接描述

3. 插入说明

在这里插入图片描述
不知道大家有没有过和我一样的疑问,HAL_DMA_Start和HAL_DMA_Start_IT这俩函数都没用到,那么这俩函数又是怎么去调用的呢?(没疑问的朋友自动忽略哈)
其实打开HAL_UART_Transmit_DMA函数体内如下所示
在这里插入图片描述
这边里面已经调用了HAL_DMA_Start_IT这个函数了,也就是说,我们调用HAL_UART_Transmit_DMA这个函数之后,HAL库是自动开启DMA中断的,但是我们一没有设置中断优先级(这个问题不大,32有默认的优先级,这个参考手册NVIC那一节),而没有定义中断服务函数(这个好像问题也不是很大,网上有人说会进入默认的中断服务函数,这个我也不知道,有待考究)但是真正的问题是,中断标志位没有清除!这边应用安富莱的手册中的一段话:
在这里插入图片描述
在这里插入图片描述
这边就说这么多了,DMA的中断系统相当复杂,我也不知道自己是不是完全搞懂了,如果有朋友明白的,欢迎批评指正😀。

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-02-26 11:46:32  更:2022-02-26 11:48:02 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 9:53:21-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码