【STM32+HAL】DAC+DMA输出波形实现

一、准备工作:


有关CUBEMX的初始化配置,参见我的另一篇blog:【STM32+HAL】CUBEMX初始化配置

二、所用工具:


1、芯片: STM32F407ZGT6

2、STM32CubeMx软件

3、IDE: MDK-Keil软件

4、STM32F4xxHAL库

三、实现功能:


1、DAC+DMA输出波形

2、按键切换波形及频率

3、串口打印当前波形以及频率值

四、HAL库配置 (初始配置完成):

1、开启DAC

这里开启的是通道一

Output Buffer:关闭后可输出更低的电压值

Trigger:触发方式,这里选择TIM2定时器触发

Wave generation mode:关闭后可输出自定义波形

2、开启DMA

Mode:选择循环

Data Width:发送数据长度,半字即可

3、配置定时器

初始化定时器触发频率为1:84MHZ / 84 / 100 =1000HZ

触发事件选择“更新触发事件”

4、配置按键

根据你的原理图选择合适的参数

5、配置中断优先级

 至此,CUBEMX配置完成

五、KEIL填写代码:

1、初始化DAC、DMA、TIM2

	HAL_TIM_Base_Start(&htim2);
	HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1,DAC_ALIGN_12B_R,0);
	HAL_DAC_Start(&hdac, DAC_CHANNEL_1);

2、按键中断改变波形频率

直流电压:0-3V,按键可调,步进0.1V

方波:Vpp=3V,频率1k-10k,步进1k

三角波:Vpp=3V,频率5k-10k,步进1k

正弦波:Vpp=3V,频率25k-50k,步进5k

MC波:自定义波形,频率200HZ,VPP=2V

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	UNUSED(GPIO_Pin);
	if(GPIO_Pin == GPIO_PIN_0){   //按键切换波形
		HAL_Delay(20);
		if(GPIO_Pin == GPIO_PIN_0){
			dac_mode=(dac_mode+1)%5;  //一共5种波形
			switch(dac_mode){
				case 0: //直流电压
				dy_10=0;
				pl_100=2;
				HAL_DAC_Stop_DMA(&hdac, DAC_CHANNEL_1);
				//HAL_DAC_Stop(&hdac, DAC_CHANNEL_1);
				HAL_Delay(3);
				HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1,DAC_ALIGN_12B_R,dy);
				HAL_DAC_Start(&hdac, DAC_CHANNEL_1);
				break;
				case 1:  //方波
				pl_100=10;
				dy_10=30;
				finds(65625/pl_100/10,&B,&C);
				HAL_DAC_Stop(&hdac, DAC_CHANNEL_1);
				HAL_Delay(3);
				HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t*)&Square, 128, DAC_ALIGN_12B_R);break;
				case 2:  //三角波
				pl_100=50;
				finds(65625/pl_100/10,&B,&C);
				dy_10=30;
				HAL_DAC_Stop_DMA(&hdac, DAC_CHANNEL_1);
				HAL_Delay(3);
				HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t*)&Triangle, 128, DAC_ALIGN_12B_R);break;
				case 3:  //正弦波
				pl_100=250;
				finds(262500/pl_100/10,&B,&C);
				dy_10=30;
				HAL_DAC_Stop_DMA(&hdac, DAC_CHANNEL_1);
				HAL_Delay(3);
				HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t*)&Sin, 32, DAC_ALIGN_12B_R);break;
				case 4:  //MC波
				pl_100=2;
				TIM2->ARR=100-1;
				TIM2->PSC=36-1;
				dy_10=20;
				HAL_DAC_Stop_DMA(&hdac, DAC_CHANNEL_1);
				HAL_Delay(3);
				HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t*)&MC, 300,     DAC_ALIGN_12B_R);
				break;
				default:break;
			}    
		}
	}

	if(GPIO_Pin == GPIO_PIN_8){  //按键切换电压
		HAL_Delay(20);
		if(GPIO_Pin == GPIO_PIN_8){
			if(dy_10 > 30) dy_10=0;
			else dy_10=dy_10+1;
		dy=dy_10*4096/33+20;
		//HAL_DAC_Stop(&hdac, DAC_CHANNEL_1);
		HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1,DAC_ALIGN_12B_R,dy);
		HAL_DAC_Start(&hdac, DAC_CHANNEL_1);
		}
	}

	if(GPIO_Pin == GPIO_PIN_9){  //按键切换频率
		HAL_Delay(20);
		if(GPIO_Pin == GPIO_PIN_9){
			switch(dac_mode){
				case 1: pl_100 = (pl_100>=100)?10:pl_100+10;finds(65625/pl_100/10,&B,&C);break;
				case 2: pl_100 = (pl_100>=100)?50:pl_100+10;finds(65625/pl_100/10,&B,&C);break;
				case 3: pl_100 = (pl_100>=500)?250:pl_100+50;finds(262500/pl_100/10,&B,&C);break;
				default: pl_100 = 2;break;
			}
		}
	}
	printf("模式:%s 频率:%dHz   Vpp:%.1fV\r\n\r\n\r\n\r\n",Mode[dac_mode],pl_100*100,(double)dy_10/10);  //串口输出
}

3、自定义函数finds

此函数计算当频率pl给定时,PSC和ARR乘积何时最接近pl

void finds(int A, int *B, int *C) {
	int sqrtA = sqrt(A),ii;
	for (ii = sqrtA; ii > 0; ii--) {
		if (A % ii == 0) {
			int j = A / ii;
			if (j <= 65535) {
				*B = ii;
				*C = j;
				break;
			}
		}
	}
	TIM2->ARR=*C-1;
	TIM2->PSC=*B-1;
}

完工

六、原理讲解

STM32CubeMX学习笔记(20)——DAC接口使用(输出正弦波)

【STM32】HAL库 STM32CubeMX教程十---DAC

STM32cubemx教程 DAC+TIM+DMA

七、源码提供(包括各波形的数据数组)

STM32DAC+DMA输出波形

八、更多DMA应用

详见【STM32+HAL】DMA应用

  • 9
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值