目录
一、实验准备
实验目的:
阅读学习野火开发板资料(零死角玩转stm32-中级篇、零死角玩转 STM32F103—指南者)和网上资源,熟悉脉冲宽度调制(PWM)和数模/模数转换原理。完成以下实验:
- 用STM32F103输出一路PWM波形,建议采用定时器方法。野火和网上大多数资源采用此方法,有完整源码。用示波器观察输出波形。
- 用STM32F103的DAC功能完成以下波形输出,用示波器观察波形,并用蜂鸣器或手机耳机收听输出声音效果、感受歌曲的音质差异。
- 输出一个周期2khz的正弦波(循环)。此波形驱动作用至蜂鸣器或喇叭,会呈现一个“滴…”的单音;
- 将一段数字音频歌曲数据转换为模拟音频波形输出(循环);
提示:首先用音频制作工具如audition制作一段数字化的2khz正弦波wav文件,制作时须指定采样频率、量化位数和通道数,以及时间长度。MCU资源有限,建议采样8khz,量化16bit,单通道,时长仅仅2秒左右。音频wav数据可以用类似汉字字模的保存方式,直接copy到Keil代码中数组中,不必使用SD卡上的wav文件(野火开发板是读取SD卡上的wav文件)。
在成功完成单音音频的还原输出后(示波器观察),再实验转换一首你喜欢的歌曲片段为wav文件,进行还原输出。
实验工具:
硬件:野火指南者开发板
软件:keil 5、Audition、WavToC
二、使用定时器完成PWM波形输出
1.PWM简介
- PWM是 Pulse Width Modulation 的缩写,中文意思就是脉冲宽度调制,简称脉宽调制。
- 它是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,其控制简单、灵活和动态响应好等优点而成为电力电子技术最广泛应用的控制方式。
- PWM是一种对模拟信号电平进行数字编码的方法,通过高分辨率计数器的使用,方波的占空比被调制用来对一个具体模拟信号的电平进行编码。
例子如下图:PWM等效正弦波
其划分方式是将正弦半波分成 N 等分,可看成 N个彼此相连的脉冲序列,宽度相等,但幅值不等;接下来使用矩形脉冲代替,而各个矩形脉冲等幅,不等宽,中点与脉冲序列重合,脉冲宽度按正弦规律变化,脉冲的总面积(冲量)与正弦半波相等。这个脉冲波形被称为SPWM 波形,是一种极其典型的 PWM 波形。
定时器3的输出通道引脚:
TIM3_CH1:PA6,完全重映像PC6
TIM3_CH2:PA7,完全重映像PC7
TIM3_CH3:PB0,完全重映像PC8
TIM3_CH4:PB1,完全重映像PC9
2.相关工程
我本次实验使用的工程是野火STM32F103-mini开发板资料\1-程序源码_教程文档\1《STM32库开发实战指南》(标准库源码)【优先学习】\1-书籍配套例程-F103RCMINI\32-TIM—高级定时器\3-TIM—高级定时器-PWM输入捕获
或者直接使用以下链接
链接:https://pan.baidu.com/s/1OqQOXjhiV_TPu65sdoV24Q
提取码:tj44
解压并打开工程后,打开main.c
文件,在main函数前定义以下函数,以实现定时器TIM1的初始化
//PWM输出初始化
//arr:自动重装值
//psc:时钟预分频数
void TIM1_PWM_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);//
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE); //使能GPIO外设时钟使能
//设置该引脚为复用输出功能,输出TIM1 CH1的PWM脉冲波形
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //TIM_CH1,引脚是PA8
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 80K
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 不分频
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
TIM_OC1Init(TIM1, &TIM_OCInitStructure); //根据TIM_OCInitStruct中指定的参数初始化外设TIMx
TIM_CtrlPWMOutputs(TIM1,ENABLE); //MOE 主输出使能
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); //CH1预装载使能
TIM_ARRPreloadConfig(TIM1, ENABLE); //使能TIMx在ARR上的预装载寄存器
TIM_Cmd(TIM1, ENABLE); //使能TIM1
}
main函数
int main(void)
{
u16 led0pwmval=0;
u8 dir=1;
//delay_init(); //延时函数初始化
//LED_Init(); //初始化与LED连接的硬件接口
TIM1_PWM_Init(899,0);//不分频。PWM频率=72000/(899+1)=80Khz
while(1)
{
//delay_ms(10);
if(dir)led0pwmval++;
else led0pwmval--;
if(led0pwmval>300)dir=0;
if(led0pwmval==0)dir=1;
TIM_SetCompare1(TIM1,led0pwmval);//设置不同的占空比
}
}
3.keil仿真
编译完成后,进行设置
点击调试,然后确定
选择逻辑分析器
拖动窗口将其展示出来
点击setup
,添加PORTA
,将Display Type设置成Bit
,选择自己喜欢的颜色,然后就可以点击close关闭了
点击run,一段时间后结束
然后就能显示出波形图了,可以看到占空比在逐渐发生变化
可以使用鼠标滚轮查看
生成.hex文件后将程序烧录到板子上
4.示波器演示效果
三、使用DAC输出波形
1.DAC简介
DAC,数模转换器,又称D/A转换器,简称DAC,它是把数字量转变成模拟的器件,主要由数字寄存器、模拟电子开关、位权网络、求和运算放大器和基准电压源(或恒流源)组成。用存于数字寄存器的数字量的各位数码,分别控制对应位的模拟电子开关,使数码为1的位在位权网络上产生与其位权成正比的电流值,再由运算放大器对各电流值求和,并转换成电压值。
DAC框图
名称 | 型号类型 | 注释 |
---|---|---|
VREF+ | 输入,正模拟参考电压 | 2.4V ≤ V REF+ ≤ V DDA (3.3V) |
VDDA | 输入,模拟电源 | 模拟电源 |
VSSA | 模拟输出信号 | DAC通道x的模拟输出 |
2.DAC输出正弦波
这里我使用的例子是野火官方的工程
链接:https://pan.baidu.com/s/1Zj_UHdquiT5nCtw76ohweQ
提取码:zz0t
野火使用的是踩点输出波形
编译烧录进开发板后即可运行,示波器演示效果如下:
3.数字音频数据转模拟音频波形输出
打开Audition,文件
→打开
,找到歌曲文件
截取一段音频,右键选择存储选区
,先改格式为Wave PCM
,接着更改采用类型
使用WavToC将wav文件转换为C语言代码
将数组内的代码粘到刚刚的正弦波工程中去
数据太多编译时会报错,我只留下了一部分
编译后将程序烧录到开发板中,示波器演示效果如下:
四、参考
①(stm32f103学习总结)—stm32 PMW输出实验
②STM32F103使用TIM DMA DAC实现播放WAV音乐
③使用STM32F103输出PWM波形
④Keil5的仿真调试
⑤DAC(数模转换模块)-STM32F103