STM32F4_PWM DAC

news2024/11/23 14:12:35

目录

1. 为什么需要使用PWM DAC

2. PWM DAC简介

3. 硬件设计

4. 软件设计

4.1 main.c

4.2 PWMDAC.c

4.3 PWMDAC.h


1. 为什么需要使用PWM DAC

        虽然STM32F4自带DAC模块,但是在有些时候,可能出现两个DAC不够用的情况(STM32F4只有两个DAC),更有甚者,STM32的某些型号是没有板载DAC模块的;这里可能会有很多学习过51单片机的读者发问,为什么不像51一样采用专用的 D/A芯片 来实现,其实这样是可以的,但是会带来成本的增加。

        STM32的所有芯片都有PWM输出功能,并且STM32F4有19个PWM输出通道,16个通用通道,资源丰富。因此,我们可以使用 PWM+RC滤波来实现一个PWM DAC

2. PWM DAC简介

        有时候,STM32F4自带的 2 路DAC可能不够用,需要多路DAC,外扩DAC的成本又比较高。此时,我们可以利用STM32F4的 PWM+简单的RC滤波来实现DAC输出 ,从而节省成本。在精度要求不是很高的时候,PWM+RC滤波的DAC输出方式,是一种非常廉价的解决方案。

PWM称作脉冲宽度调制。其本质就是一种周期一定,而高低电平占空比可调的方波。

其中:T 是单片机中计数脉冲的基本周期,也就是STM32F4定时器的计数频率的倒数。

        N是PWM波一个周期的计数脉冲个数,也就是STM32F4的ARR-1的值。

        n是PWM波一个周期中高电平的计数脉冲个数,也就是STM32F4的CCRx的值。

        V_{H}V_{L}分别是PWM波的高低电平电压值,k为谐波次数,t为时间。

将分段函数展开为傅里叶级数得到:

从②式可以看出,式中第1个方括弧为直流分量,第2项为1次谐波分量,第3项为大于1次的高次谐波分量如果我们希望只要直流分量,不要1次谐波分量和多次谐波分量的话,需要借助滤波器滤掉谐波。

式②中的直流分量与 n 成线性关系,并随着n从0到N,直流分量从VL到VL+VH之间变化。这正是电压输出的DAC所需要的。因此,如果能把式②中除直流分量外的谐波过滤掉,则可以得到从PWM波到电压输出DAC的转换,即:PWM波可以通过一个低通滤波器进行解调。式②中的第2项的幅度和相角与n有关,频率为1/(NT),其实就是PWM的输出频率。该频率是设计低通滤波器的依据。如果能把1次谐波很好过滤掉,则高次谐波就应该基本不存在了。 

低通滤波器 是容许低于截止频率的信号通过,但高于截止频率的信号不能通过的电子滤波装置。换句话说,他将信号的频谱分离为将要通过的频率分量和将被阻塞的频率分量,且这部分被阻塞的频率分量是高频分量。而这个通过和阻塞的临界值被称为截止频率。

截止频率 从频域响应的角度讲,当保持输入信号的幅度不变,改变频率使输出信号降至最大值的0.707倍,即用频响特性来表述即为-3dB点处即为截止频率,它是用来说明频率特性指标的一个特殊频率。

通过对上面公式的分析,可以得到PWM DAC的分辨率为:

        分辨率=log2(N)

假设n的最小变化为1,当N=256的时候,分辨率就是8位。STM32F4的定时器大部分都是16位的(TIM2和TIM5是32位的),可以很容易得到更高的分辨率,分辨率越高,速度就越慢。

在8位分辨条件下,我们一般要求 1 次谐波对输出电压的影响不超过1个位的精度,也就是3.3/256=0.01289V。假设VH为3.3V,VL为0V,那么一次谐波的最大值是2*3.3/π=2.1V,这变相的要求我们的RC滤波电路提供至少-20lg(2.1/0.01289)=-44dB的衰减。

STM32F4的定时器最快的计数频率是168Mhz,某些定时器只能到84M;以84M频率为例介绍,8位分辨率的时候,PWM频率为84M/256=328.125Khz。如果是1阶RC滤波,则要求截止频率为2.07Khz,如果是2阶RC滤波,则要求截止频率为26.14Khz。

二阶RC滤波截止频率计算公式:

f=1/2π RC

公式要求R20*C34=R21*C35=RC。

根据计算得截止频率为33.8Khz,超过了26.14Khz,和二阶RC滤波的截止频率有出入的原因是该电路我们还需要用作PWM DAC音频输出,音频信号带宽是22.05Khz,为了让音频信号能够通过该低通滤波,同时为了标准化参数选取,所以确定了这样的参数。实测精度在0.5LSB左右

3. 硬件设计

本次实验,我们使用STM32F4的TIM9_CH2(PA3)输出PWM,经过二阶RC滤波后,转换为直流输出,实现PWM DAC。

 注意:

        本次实验需要用 ADC 采集 DAC 产生的模拟信号,也就是输出电压值,所以在硬件上需要将 PWM DAC 和 ADC 短接。

特别的:

        上图中功能 PWM DAC 和 USART2_RX 共用 PA3 引脚,所以在本实验中,必须拔了 P9 上面 PA3(RX)跳线帽,否则会影响转换结果。

4. 软件设计

        本次实验通过ADC通道5(PA5)读取PWM DAC输出,并在LCD模块上显示相关数值,通过按键控制PWM DAC的输出值。

4.1 main.c

#include "stm32f4xx.h"
#include "delay.h"
#include "usart.h"
#include "LED.h"
#include "lcd.h"
#include "usmart.h"
#include "ADC.h"
#include "KEY.h"
#include "DAC.h"
#include "PWMDAC.h"

//LCD状态设置函数
void led_set(u8 sta)//只要工程目录下有usmart调试函数,主函数就必须调用这两个函数
{
	LED1=sta;
}
//函数参数调用测试函数
void test_fun(void(*ledset)(u8),u8 sta)
{
	led_set(sta);
}
int main(void)
{
	u16 adcx,pwmval=0;
	float temp;
	u8 t=0,key;
	delay_init(168);
	uart_init(115200);
	LED_Init();
	LCD_Init();
	Adc_Init();
	Key_Init();
	TIM9_CH2_PWM_Init(255,0);//TIM9 PWM初始化  Fpwm=168M/256=656.25Khz
	POINT_COLOR=RED;
	LCD_ShowString(30,50,200,16,16,"Explorer STM32F4");
	LCD_ShowString(30,70,200,16,16,"PWM DAC Test");
	LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");
	LCD_ShowString(30,110,200,16,16,"2023/20/23");
	LCD_ShowString(30,130,200,16,16,"WK_UP:+  KEY1:-");
	POINT_COLOR=BLUE;
	LCD_ShowString(30,150,200,16,16,"DAC VAL");
	LCD_ShowString(30,170,200,16,16,"DAC VOL:0.000V");
	LCD_ShowString(30,190,200,16,16,"ADC VOL:0.000V");
	TIM_SetCompare2(TIM9,pwmval);  //初始值
	while(1)
	{
		t++;
		key=KEY_Scan(0);
		if(key==4)// 表示KEY_UP按键按下
		{
			if(pwmval<250)  //pwmval介于0~250之间
				pwmval=pwmval+10;
			TIM_SetCompare2(TIM9,pwmval);  //输出
		}
		else if(key==2)  //表示KEY1按下
		{
			if(pwmval>10)
				pwmval=pwmval-10;
			else
				pwmval=0;
			TIM_SetCompare2(TIM9,pwmval);  //输出
		}
		if(t==10||key==2||key==4)  //有按键按下或者定时时间到了
		{
			adcx=TIM_GetCapture2(TIM9);  //获取DAC寄存器的数值
			LCD_ShowxNum(30+8*8,150,adcx,3,16,0);   //显示DAC寄存器值
			temp=(float)adcx*(3.3/256);  //通过公式转化得到DAC电压值
			adcx=temp; //电压值一定是介于0~3.3V,adcx设置的为整型,所以将temp赋值给adcx,adcx得到temp的整数部分
			LCD_ShowxNum(30+8*8,170,temp,1,16,0);//显示整数部分
			temp=temp-adcx;
			temp=temp*1000;
			LCD_ShowxNum(30+8*10,170,temp,3,16,0x80); //显示小数部分
			adcx=Get_Adc_Average(ADC_Channel_5,20); //得到ADC转换值
			temp=(float)adcx*(3.3/4096);  //通过公式计算得到ADC电压值
			adcx=temp;  //同理得到电压值的整数部分
			LCD_ShowxNum(30+8*8,190,temp,1,16,0);  //显示电压值整数部分
			temp=temp-adcx;
			temp=temp*1000;
			LCD_ShowxNum(30+8*10,190,temp,3,16,0x80);  //显示电压值的小数部分
			t=0;
			LED0=!LED0;
		}
		delay_ms(10);
	}
}

4.2 PWMDAC.c

#include "stm32f4xx.h"              
#include "PWMDAC.h"
#include "Timer.h"

//arr:自动重装载值  psc:预分频值
void TIM9_CH2_PWM_Init(u16 arr,u16 psc)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM9,ENABLE);// TIM9时钟使能 PA3引脚复用功能TIM9_CH2
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);  //使能GPIOA时钟,因为要用到PA3引脚
	 
	//初始化GPIOA PA3
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3;
	GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	//因为PA3引脚复用了很多功能,所以规定每次只能使用引脚的一个功能,所以GPIO模式为复用时,需要调用引脚复用函数
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource3,GPIO_AF_TIM9);//将PA3引脚复用为定时器9
	
	//初始化定时器9
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//向上计数模式
	TIM_TimeBaseInitStructure.TIM_Period=arr;
	TIM_TimeBaseInitStructure.TIM_Prescaler=psc;
	TIM_TimeBaseInit(TIM9,&TIM_TimeBaseInitStructure);
	
	//初始化TIM9 Channel2 PWM模式 
	TIM_OCInitTypeDef TIM_OCInitStructure;
	TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;
	TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//输出比较使能
	TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;//输出极性高
	TIM_OCInitStructure.TIM_Pulse=0;
	TIM_OC2Init(TIM9,&TIM_OCInitStructure);  //初始化外设TIM9 OC2
	
	TIM_OC2PreloadConfig(TIM9,TIM_OCPreload_Enable); //使能预装载寄存器
	TIM_ARRPreloadConfig(TIM9,ENABLE);  //ARPE使能
	TIM_Cmd(TIM9,ENABLE);//使能TIM9
}

4.3 PWMDAC.h

#ifndef _PWMDAC__H_
#define _PWMDAC__H_


void TIM9_CH2_PWM_Init(u16 arr,u16 psc);
	
#endif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/540435.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

看过来!一文揭秘为什么选TikTokTikTok数据怎么分析

为什么要选择TikTok开小店&#xff1f;以及商家在运营TikTok之前要了解掌握哪些TikTok相关数据&#xff1f;要分析哪些数据、怎么看TikTok数据才能让商家更快更及时地改进优化自己的TikTok营销策略&#xff1f;往下看。 一、选择TikTok开小店的原因&#xff1a; 1. TK作为一个…

《终身成长》笔记五——随心所欲地夸奖孩子们以成长为目标的努力过程

目录 经典摘录 校园暴力&#xff1a;对“复仇”的思考 施暴者&#xff1a;欺凌与评判息息相关 父母或老师&#xff1a;关于成功和失败的信息 是否意味着&#xff0c;当我们的孩子取得了不起的成就的时候&#xff0c;我们不能热情地表扬他们呢&#xff1f; 关于失败的信息 经…

在moveit2中实现四连杆及曲柄滑块

对于一些特殊的&#xff08;比如说机械构件闭环的、存在被动关节的&#xff09;运动模型&#xff0c;该如何用urdf模型描述该模型&#xff0c;且在MoveIt2中进行仿真&#xff1f;下面提供一个思路&#xff0c;仅供参考。 四连杆机构 结构介绍 该机构的组成如下图所示。 粉红…

加密解密软件VMProtect入门使用教程(九)许可制度之许可系统功能

VMProtect是新一代软件保护实用程序。VMProtect支持德尔菲、Borland C Builder、Visual C/C、Visual Basic&#xff08;本机&#xff09;、Virtual Pascal和XCode编译器。 同时&#xff0c;VMProtect有一个内置的反汇编程序&#xff0c;可以与Windows和Mac OS X可执行文件一起…

前端综合项目-个人博客网页设计

个人博客前端部分设计 文章目录 前端综合项目-个人博客网页设计1. 预计效果2. 公共样式设计2.1 背景设计2.2 导航栏设计2.3 博客列表页和博客详情页的共同内容2.3.1 页面划分css设计2.3.2 左侧card内容2.3.3 右侧article内容 3. 博客列表页4. 博客详情页5. 博客登录页5.1 页面划…

赛效:怎么在99医院库平台查询科室医生坐诊的时间?

如果想要了解更多生活中常用的工具的使用方法&#xff0c;可进入赛效官方网站查看应用软件或者应用问答栏目查看详情。 很多人在去医院就诊时&#xff0c;往往会提前查询下就诊医院当天坐诊的医生有哪些&#xff0c;如果可以直接在网上进行预约的话&#xff0c;通过网络预约要…

word中图标格式的美化

目录 1. 修改行号2. 调整图表格式2.1 方法1 &#xff08;不推荐&#xff09;2.2 方法2 3. 参考链接 1. 修改行号 2. 调整图表格式 要达到下图的效果 2.1 方法1 &#xff08;不推荐&#xff09; 利用“一系列格式操作”设置表格格式。&#xff08;该方法不具有可复制性&#…

网络性能测试工具

什么是网络测试 网络测试是用于定量或定性测量 IT 基础架构性能的过程。这是一个原始级别的故障识别&#xff0c;不需要大量的历史数据。对于更高级的监视&#xff0c;使用网络监视工具。 什么是网络测试工具 网络测试工具是一组工具&#xff0c;可帮助测量网络各个方面的性…

ASO优化之如何选择手游的行业词和竞品词

应用商店的搜索关键词转化率占应用总下载转化率的65%。这表明&#xff0c;用户会知道自己想要什么&#xff0c;更倾向于去应用商店寻找特定的应用程序。因此如果能让他们相信我们的应用正是他们所寻找的&#xff0c;那么关键词优化就很重要了。 那么我们该如何选择手游的行业词…

中文文献如何查找下载最高效

提到查找下载中文文献我们就会想到知网、万方、维普等中国知名数据库&#xff0c;很多高校都订购了这些数据库资源&#xff0c;但各个高校订购的资源不仅内容上不一样&#xff0c;而且都不是数据库的全部资源&#xff0c;超出订购范围的文献资源是下载不到的&#xff0c;如下图…

探索iOS之CoreAudio核心音频框架

iOS的CoreAudio分为三层&#xff1a;应用服务层、驱动层、硬件层。其中&#xff0c;应用服务层包括&#xff1a;AudioQueue Service、AudioPlayer Service、AudioSession Service、AudioFile Service、AudioUnit等。 一、CoreAudio整体架构 CoreAudio的整体架构自顶向下是Ser…

求最小生成树(Prim算法与Kruskal算法与并查集)

目录 1、案例要求2、算法设计与实现2.1 Prim算法2.1.1 构造无向图2.1.2 编写Prim算法函数2.1.3 实现代码2.1.4 运行结果截图 2.2 Kruskal算法2.2.1 构造无向图2.2.2 编写并查集UnionFind类2.2.3 编写Kruskal算法2.2.4 实现代码2.2.5 运行结果截图 3、总结 1、案例要求 利用贪心…

CameraLink 高清医学影像分析模块

FMC-XM202是一款基于FMC接口标准的1路CameraLink Full模式&#xff08;或者2路CameraLink Base模式&#xff09;采集、1路HDMI&#xff08;DVI&#xff09;视频输出的子卡模块&#xff0c;该模块具有2个CameraLink端口&#xff08;SDR&#xff0c;26PIN&#xff09;&#xff0c…

简单线性线性回归

文章目录 brief直线回归的一般形式参数计算y观测值和回归值的关系基本前提假定假设检验直线回归的变异来源自由度问题&#xff1a;假设检验 多元线性回归 brief 当研究两个有因果关系的变量时&#xff0c;我们希望建立一个方程式表示两者的关系&#xff0c;这样有一个变量得知…

公司里的5种人,建议马上开除

作者| Mr.K 编辑| Emma 来源| 技术领导力(ID&#xff1a;jishulingdaoli) 多年前&#xff0c;马云在某期湖畔大学开学演讲时&#xff0c;说了一句经典名言&#xff1a;“小公司的成败在于你聘请什么样的人&#xff0c;大公司的成败在于你开除什么样的人。”K哥觉得&#xff0…

Ocean Optics USB2000光谱仪无法在Win10/8系统运行

1、问题描述 USB2000型光谱仪&#xff0c;由于生产年代过于久远&#xff0c;虽然能被Win10系统识别&#xff0c;但是驱动程序安装完成后依然报错&#xff0c; 提示&#xff1a;该设备无法启动。&#xff08;代码 10&#xff09; 请求USB BOS 描述符失败。 运行SpectraSuite软件…

操作系统原理 —— 什么是信号量,信号量如何实现进程互斥、进程同步?(十五)

在之前的章节中&#xff0c;我们提到了进程互斥&#xff0c;以及进程互斥实现的几种方式&#xff0c;那么今天我们再来讲解一种&#xff0c;基于 信号量 来实现进程之间的同步、互斥的方式。 用户进程可以通过使用操作性提供的一对原语来对信号量进行操作&#xff0c;从而很方…

C语言基础知识:C语言中的指针

目录 1、为什么需要指针? 2、指针是什么&#xff1f; 3、指针与变量的关系 4、指针的分类 5、指针的用法 6、指针的运算 7、野指针 8、指针使用时的注意事项 同C语言中其他变量一样&#xff0c;把指针也可以看成是一种变量。不过&#xff0c;这种变量专门存储地址值。…

vscode链接远程服务器开发c++项目

因为要在linux环境下开发c应用&#xff0c;需要一个比较好用的远程工具。之前做深度学习的时候一直用vscode链接服务器写python&#xff0c;感觉用起来很舒服。 vscode下载安装这些就略过了&#xff0c;从插件安装和配置文件开始介绍 参考文章&#xff1a;https://zhuanlan.zh…

如何做一份精致的性能测试报告?

相比于普通的功能测试&#xff0c;性能测试对测试工程师的技能要求更高&#xff0c;一般来说&#xff0c;也只有中高级测试工程师才会有机会做性能测试。 对于题主关心的问题&#xff0c;我拆分出下面三个部分来做解答&#xff1a; 1、性能测试报告的目的 2、性能测试过程中的关…