STM32CubeMX的使用,配置DMA串口

这次记录下最近调用的外设。DMA以前用得很少,只通过ADC采集使用,开启后就直接读那个数组就可以了。

我对dma的理解就是不占用cpu,数据传输速度快,可以直接从外设和内存间相互读取。

目前的工作用的芯片只能使用hal库开发,stm32g0系列性价比高。用cubemx把基础外设全配置跑了一遍,给我最大感受就是方便快捷,在st自家芯片中移植性强。

时钟和晶振配置不多说了,网上都很全了,可以不使用外部晶振,但HCLK最大只能到64M,最好还是外接晶振让系统更可靠稳定吧。

这里我创建了个新的ioc文件,之前写了10多个传感器的板子不想动了,这篇文章算是我头一个记录hal+cubemx的记录(虽然之前自己已经写过不少了),顺便把引脚更改写下,希望能帮助到新人。

STM32CubeMX的使用,配置DMA串口_第1张图片

Baud Rate(波特率):两边设备通讯需要相同,这里我设定的是115200

其它基础设置数据位,无校验位,停止位,没特殊要求我按的默认。

进阶选项看需求,我这里收发都需要,其它没有设置。

STM32CubeMX的使用,配置DMA串口_第2张图片

一些暂时用不到的设置,错误返回值默认使能的。

传输数据高位在前默认没有使能,一般spi通讯先读MSB。

STM32CubeMX的使用,配置DMA串口_第3张图片

当启用功能后,GPIO会自动帮你设置好,可以自行更改。 

STM32CubeMX的使用,配置DMA串口_第4张图片左键点下对应的引脚进行复用 

串口功能开启后,引脚就变绿了,如果没有在左边开启串口,引脚会是黄色的。

STM32CubeMX的使用,配置DMA串口_第5张图片右键选择第一项,可写个对此引脚写个标签,建议写,以后方便移植,也好直观看出引脚功能。

STM32CubeMX的使用,配置DMA串口_第6张图片STM32CubeMX的使用,配置DMA串口_第7张图片

 在生成的工程中,main.h里也会出现宏定义

STM32CubeMX的使用,配置DMA串口_第8张图片

中断记得要勾上,系统会自动给你初始化好nvic的中断优先级。

STM32CubeMX的使用,配置DMA串口_第9张图片

DMA这里点击 Add 进行添加,把发送和接收添加到对应的DMA通道里。

STM32CubeMX的使用,配置DMA串口_第10张图片

 单击一行,出现设置。

优先级为低。

1:模式为普通。调用一次dma发送函数只发一次,而Circular为循环。调用一次后就不需要管它了,直接读取放进形参的数组/指针

(如果开启多个串口dma,请务必注意发送间隔,不然有时会发送意义不明的数值。接收也改为普通模式)

 数据长度是字节(8位)

STM32CubeMX的使用,配置DMA串口_第11张图片在工程管理中选择自己使用的编译器。

STM32CubeMX的使用,配置DMA串口_第12张图片

1:仅赋值需要的库文件

2: 勾选这个选项后,初始化的外设会自动生成到别的文件夹,不勾选的话全部生成在main.c

 STM32CubeMX的使用,配置DMA串口_第13张图片

进阶选项中可以设置初始化函数的顺序,之前在网上看到别人说过如果DMA初始化不在串口前面,串口中初始化里有对应DMA的设置,DMA就会失效。我在使用前会把相应的底层库看一遍,目前定时器,串口,AD,PWM,输入捕获,IIC(这个地址要注意下,要结合需要驱动的芯片手册)的使用都没有任何问题。

STM32CubeMX的使用,配置DMA串口_第14张图片生成代码。

接下来直接看代码。

和标准库不同的是,hal库使用的是回调函数,之前我们在中断服务函数里写中断程序,现在全使用回调函数。

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) 
{
	if(htim==&htim17)  //定时器17 1ms
	{
		if(Sys_Data.Updata_Time.MH440D++>100)
		{
				Sys_Data.Updata_TimeFlag.MH440D=1;
				Sys_Data.Updata_Time.MH440D=0;
		}			
	}
}

串口程序这里没有使用回调函数。

#include "MH440D.h"


/*和校验*/
uint8_t GetCheckSum(uint8_t *packet)
{
	uint8_t i, checksum;
	for( i = 1; i < 8; i++)
	{
	checksum += packet[i];
	}
	checksum = 0xff-checksum;
	checksum += 1;
	return checksum;
}

void MH440D_SendCom(_MH440D* MH440D)
{
	uint8_t i;
	uint8_t Sendbuff[9]={0xff,MH440D->CH4_N,MH440D->CH4_Com,0,0,0,0,0,0};

	MH440D->CheckSum=GetCheckSum(Sendbuff);
	Sendbuff[8]=MH440D->CheckSum;
	memcpy(MH440D->SendBuff,Sendbuff,9);    //复制数组
	
	HAL_UART_Transmit_DMA(&huart1,MH440D->SendBuff ,9);    //发送一次
	
}

FlagStatus MH440D_Read(_MH440D* MH440D)
{
		HAL_UART_Receive_DMA(&huart1,MH440D->RecBuff ,9 );
	
			if( MH440D->RecBuff[0]==0XFF  && MH440D->RecBuff[1] ==0x86)    //判断设备首地址和命令
			{
				
				 MH440D->CheckSum =GetCheckSum(MH440D->RecBuff); 
				 if(MH440D->RecBuff[8]==MH440D->CheckSum)
				 {
					 
					  MH440D->CH4_H=MH440D->RecBuff[2];       //读出传感器数据
					  MH440D->CH4_L=MH440D->RecBuff[3];
						return 1;	
				 }
				 
				 else
						return  0;
				
			}
			else
				return 0;
}

接收我使用的是循环读取,其实调用一次就可以了,但我在主函数循环里还是重复调用了。

模拟了下发送和接收。

 STM32CubeMX的使用,配置DMA串口_第15张图片

我以前写接收时,每次接收只读一位,然后写的比较复杂,从开始位来判断标志位,循环读多少,来判断对方芯片发送的格式和校验,一不小心写错保存的数据就出差错了,十分麻烦。发现用DMA直接将数组/指针首地址放入后,确定好数据长度,可直接存取正确的顺序,剩下只需要处理数据就好了。spi和iic也差不多,基本上是对变量的长度和地址进行操作。以前也很少用硬件,全是用的io模拟,理解通信协议后 ,我在使用过的芯片,pic,stc系列(51/12/8/15我都当做51核了),stm32系列都能很好移植了。

 学生时期用了4年多标准库,工作时候有机会使用到了cubemx生成代码+hal库,还是挺爽的,但我还是少不了看寄存器手册的地方= =

也是头一次我开始尝试写结构体套结构体,以前只直接struct,各种函数调用,套来套去,现在根据公司要求规则,换了个写法,正在慢慢改进。

你可能感兴趣的:(stm32,stm32,单片机,物联网,DMA,串口通信)