基于STM32实现制作简易信号发生器
利用pwm dac实现dds信号发生功能,具体是使用到了版上的pwm和lpf电路以实现dac功能,通过读表生成不同频率的方波、正弦波、三角波。
标签
STM32
DDS
2022寒假在家练
葫芦卡
更新2022-03-01
哈尔滨工业大学
3443

项目介绍

这个是寒假在家一起练的第二个任务,利用板上的pwm和lpf电路实现信号发生功能,能够生成0-100KHZ的正弦波、三角波、方波,偏置是1.5V,幅度是0-1.5V。

实现的功能

输出正弦波、方波、三角波、频率为0-100khz,每次可改变1khz,幅度为0-1500mv,一次可改变150mv。

设计思路

因为板子上没有ad,所以要用pwm和滤波电路实现输出某一电压的功能,也受到lpf的限制,pwm的频率不能太低,我采用读表法来输出这三种波,用dma循环传输数组给pwm,通过读表的时候,跳着读来实现频率的改变,改变幅度是通过乘以个数。

遇到的困难

困难还是挺多的,因为自己前置课程都没有开始学,所以什么知识都依靠百度,第一个困难就是点灯,点灯点了两天,最后群里大佬发现是编译器版本的问题,然后就是功能的实现,一开始是通过定时器改变pwm的占空比来实现正弦波的输出,但这样只能实现频率很小的正弦波,然后又开始了解dds的知识,但用pwm模拟dds的文章还是很少,自己半懂不懂的瞎搞,主要思路是读表(在代码中实时生成应该也可以,这样幅度的改变会精准些,但我不知道spwm的公式,就直接用spwm软件生成的表),如果这些点挨着读就是生成1khz,隔一个读就是生成2khz,,,但这样还是有问题,当频率很小的时候,读的点会较多,频率还可以,但是频率大点的时候,没法整除,而且差距还小(比如1000除以95得10,1000除以96也得10),这是一开始的思路,即改变dma传输数组的大小,这个数组只包含一个波形而已,后来又好好想了想,发现可以不改变dma传输数组的大小,点不够了,可以循环读表,直到把dma数组填满(如果再加上定时器改变pwm占空比那一部分,是可以实现1khz之下的输出的)。

改变幅度乘以一个数,小数转成整数,它的精度会不怎么好,所以就想到了要不就每次改变都重新生成,但是spwm的公式不明白,再加上flash挺大的,就直接用spwm软件生成了10个表,对应10个挡的幅度,至于三角波是自己手打的,就直接乘数了,不准就不准吧。

编码器采用的下降沿捕获,捕获a的变化,再判断b的电平,网上找的思路,但正反转经常性判断错,所以干脆就不管正转反转了,是的没错,它只有由大变小,再变为最大这一条路可走。

屏幕的使用是我遇到困难最多的,因为其他模块网上资源教学还是蛮多的,这方面我没有找到很多,光点亮它就花费了一天时间,直播看了好多遍,幸好这个项目用到的不多。

硬件介绍与流程图

硬件就用到了lpf、几个按键和屏幕,lpf是二阶低通再加个跟随器,自己算一下截止频率。

Folv5dhqWfFmufYdwJ6wjxSq7idP

FsEAvehqxb6labkAJGyS27UQRhU_

代码

输入捕获部分

	HAL_TIM_Base_Start_IT(&htim2);
	b_last=HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_15);
	while(flag_tim2<=20){
		if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_15)!=b_last){
			HAL_TIM_Base_Stop_IT(&htim2);
			flag_tim2=0;
			if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_15)==1){
				HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_14);

						  HAL_TIM_PWM_Stop_DMA(&htim3, TIM_CHANNEL_3);
							switch(pat){
							case 0:
									fv=fv+1;
									if(fv==10)fv=0;
								break;
							case 1:
								  fre=fre+1;
								  if(fre==101)fre=1;
								break;
							case 2:
								mode=mode+1;
								if(mode==3)mode=0;
								break;
							}
							OLED_Clear();
							switch(mode){
							    case 0:
									OLED_ShowString(10, 0, "Square    ", 8, 1);
								break;
								case 1:
									OLED_ShowString(10, 0, "sine      ", 8, 1);
								break;
								case 2:
									OLED_ShowString(10, 0, "Triangular", 8, 1);
								break;
								}
							sprintf((char*)Vpp,"%d  ",1500-fv*150);
						    OLED_ShowString(42, 10, Vpp, 8, 1);
							sprintf((char*)FV,"%d    ",fre);
							OLED_ShowString(30, 20, FV, 8, 1);
							OLED_Menu();
							OLED_Refresh();
						 buff_try();
						 HAL_TIM_PWM_Start_DMA(&htim3, TIM_CHANNEL_3, (uint32_t*)buff_value, j);
				break;
			}
			else if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_15)==0){

				break;
			}
		break;
		}
	}
	HAL_TIM_Base_Stop_IT(&htim2);
	flag_tim2=0;

效果展示

Fhs7Q4EVrcgLZuhlqGsEFCc7q6_W

心得体会

这一次的寒假一起练项目对我个人来说是一个不小的挑战,因为我可以说只学过微积分,这些知识都是开学后才会学的,真的是从0开始。一开始我无从下手,听过几节直播课后,开始着手查找资料,选择性学习,系统学习肯定来不及。很感谢群里大佬们的答疑解惑还有硬禾提供的帮助,拼拼凑凑的完成了这个设计。经过这次锻炼,我不但了解了stm32的一些知识,还没有在寒假期间肥肥瘫,每一天我都有学一些新知识,这是习惯的养成,希望下一次硬禾的项目中,还会有我的身影。

 

附件下载
oled.zip
团队介绍
哈尔滨工业大学
团队成员
葫芦卡
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号