完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
任务摘要
阅读学习野火开发板资料(零死角玩转stm32-中级篇、零死角玩转 STM32F103—指南者)和网上资源,熟悉 脉冲宽度调制(PWM)和数模/模数转换原理。完成以下实验:一、PWM简介 PWM是Pulse Width Modulation的缩写,中文意思就是脉冲宽度调 制,简称脉宽调制。它是利用微处理器的数字输出来对模拟电路进行控 制的一种非常有效的技术,其控制简单、灵活和动态响应好等优点而成 为电力电子技术最广泛应用的控制方式,其应用领域包括测量,通信, 功率控制与变换,电动机控制、伺服控制、调光、开关电源,甚至某些 音频放大器,因此学习PWM具有十分重要的现实意义。 STM32F1 PWM介绍 STM32F1除了基本定时器TIM6和TIM7,其他定时器都可以产生PWM输出 。其中高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出 。而通用定时器也能同时产生多达 4路的 PWM 输出,这些在定时器中断 章节中已经介绍过。 PWM的输出其实就是对外输出脉宽可调(即占空比调节)的方波信号 ,信号频率是由自动重装寄存器 ARR 的值决定,占空比由比较寄存器 CCR 的值决定。 PWM输出比较模式总共有8种,具体由寄存器 CCMRx 的位 OCxM[2:0] 配置。我们这里只讲解最常用的两种PWM输出模式:PWM1和PWM2, PWM1和PWM2这两种模式用法差不多,区别之处就是输出电平的极性不 同。 PWM边沿对齐模式 当 TIMx_CR1 寄存器中的 DIR 位为低时执行递增计数,计数器CNT从 0 计数到自动重载值(TIMx_ARR 寄存器的内容),然后重新从 0 开始 计数并生成计数器上溢事件。 以 PWM 模式 1 为例。只要TIMx_CNT < TIMx_CCRx, PWM 参考信号 OCxREF 便为有效的高电平,否则为无效的低电平。如果 TIMx_CCRx 中 的比较值小于自动重载值(TIMx_ARR 中),则 OCxREF 保持为“ 1”。 如果比较值为 0, 则 OCxREF 保持为“ 0”。 PWM中心对齐模式 在中心对齐模式下,计数器 CNT 是工作做递增/递减模式下。开始的 时候, 计数器CNT 从 0 开始计数到自动重载值减 1(ARR-1),生成计数 器上溢事件;然后从自动重载值开始向下计数到 1 并生成计数器下溢事 件。之后从 0 开始重新计数。 PWM输出配置步骤 (1)使能定时器及端口时钟,并设置引脚复用器映射 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);GPIO_PinRemapConfig(GPIO_FullRemap_TIM3,ENABLE); 可选的参数在 stm32f10x_gpio.h 都已经列出来非常详细GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出 (2)初始化定时器参数,包含自动重装值,分频系数,计数方式等 void TIM_TimeBaseInit(TIM_TypeDef*TIMx,TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct); 二、STM32F103输出PWM波形图 1、文档查找 在野火官方资料库中,找到“TIM—通用定时器-4路PWM输出”文件夹, 打开keil project 对打开的工程进行编译,成功通过且无报错 2、代码程序 main.c函数 // TIM¡ªÍ¨Óö¨Ê±Æ÷-4·PWMÊä³öÓ¦ÓÃ#include "stm32f10x.h"#include "bsp_led.h"#include "bsp_GeneralTim.h" /** * @brief Ö÷º¯Êý * @param ÎÞ * @retval ÎÞ */int main(void){ /* led ¶Ë¿ÚÅäÖà */ LED_GPIO_Config(); /* ¶¨Ê±Æ÷³õʼ»¯ */ GENERAL_TIM_Init(); while(1) { }} 主要代码 void TIM3_Int_Init(u16 arr,u16 psc){ TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能 TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 计数到5000为500ms TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 10Khz的计数频率 TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位 TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断 NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能 NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器 TIM_Cmd(TIM3, ENABLE); //使能TIMx外设 }//定时器3中断服务程序void TIM3_IRQHandler(void) //TIM3中断{ if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源 { TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除TIMx的中断待处理位:TIM 中断源 LED1=!LED1; }}//TIM3 PWM部分初始化 //PWM输出初始化//arr:自动重装值//psc:时钟预分频数void TIM3_PWM_Init(u16 arr,u16 psc){ GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能定时器3时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); //使能GPIO外设和AFIO复用功能模块时钟 GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //Timer3部分重映射 TIM3_CH2->PB5 //设置该引脚为复用输出功能,输出TIM3 CH2的PWM脉冲波形 GPIOB.5 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //TIM_CH2 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO //初始化TIM3 TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位 //初始化TIM3 Channel2 PWM模式 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高 TIM_OC2Init(TIM3, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM3 OC2 TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能TIM3在CCR2上的预装载寄存器 TIM_Cmd(TIM3, ENABLE); //使能TIM3 } 3、环境配置 相关配置 魔术棒–Debug–配置如下(选中Use Simulator) 按照图示进行操作 4、结果展示 效果显示 示波器显示: 三、DAC简介 1、认识DAC DAC(中文:数字模拟转换器)是一种将数字信号转换为模拟信号(以电流、电压或电荷的形式)的设备。电脑对声音这种信号不能直接处理,先把它转化成电脑能识别的数字信号,就要用到声卡中的DAC,它把声音信号转换成数字信号,要分两步进行,即采样和转换。(更多认识可参考资料什么是DAC_adc是什么意思) adc: Analog-to-Digital Converter的缩写,意思是模/数转换器。实现把模拟信号转变为数字量的设备称为模数(A/D)转换器,简称ADC 实现把把数字量转变为模拟量的设备称为数模(D/A)转换器, 2、2khz的正弦波输出 计算公式 先对正弦波进行采样,取出一定的点放到数组中,再去执行输出代码。这里采用Matlab进行采样点的获取。 文档有两个脚本用MATLAB打开如下(信号系统实验时已经安装MATLAB,这里不说安装步骤,大家可以搜索相关教程) 运行如图 对首行份数进行修改如下 保存后再次运行如图 我们可以对比采样份数不同,正弦图像变化。 修改后代码 %用于产生正弦数据表,输出到文件dac_sinWave.c 文件中,复制到c语言数组即可n = 2*pi/3600 : 2*pi/3600 : 2*pi %分成3600等份a = sin(n)+1; %求取sin函数值并向上平移一个单位,消除负数值a = a * 3.3/2; %调整幅值,使范围限制为0~3.3 r = a* (2.^12) /3.3 %求取dac数值,12位dac LSB = 3.3/2.^12 r = uint16(r); %把double型数据转化成16位整型数据 for i = 1:32 if r(i) > 4095 %限制数据最大不超过4095 r(i) = 4095endend dlmwrite('dac_sinWave.c',r); %把数据写入到文件,方便添加到stm32工程中plot(n,r,'.') %把这些点画出来 查看样点 自动保存到以下c文件 打开此文件,然后复制 打开 DAC-输出正弦波 的工程keil文件 将复制的全部粘贴到 uint16_t Sine12bit数组中 编译main.c函数生成hex文件 3、输出波形 示波器波形 4、蜂鸣器 将板子上的PA4或PA5接上蜂鸣器,并接地,便可让蜂鸣器发出声音 四、数字音频数据转换为模拟音频波形输出 方法介绍 首先用音频制作工具如audition制作一段数字化的2khz正弦波wav文件,制作时须指定采样频率、量化位数和通道数,以及时间长度。MCU资源有限,建议采样8khz,量化16bit,单通道,时长仅仅2秒左右。音频wav数据可以用类似汉字字模的保存方式,直接copy到Keil代码中数组中,不必使用SD卡上的wav文件(野火开发板是读取SD卡上的wav文件)。1、软件下载 此次试验需要下载三个软件进行,一是 Adobe Audition CS6,二是notepad++,三是Uedit32。为大家附上下载链接; Adobe Audition CS6 含汉化补丁+破解补丁. (网站内也附有详细的安装教程,供大家参考) notepad++. uedit32中文破解版 v25.0.0.53绿色版. (可参考网页进行相关操作。) 将文件中所有的压缩包解压到当前文件目录下,然后按照网址所提示的安装教程进行安装。 2.软件使用 1.Adobe Audition CS6 打开Adobe Audition CS6,找到下载歌曲路径,点击打开 音频显示 鼠标拖动截取片段,点击存储 下拉设置格式,其采样类型与格式设置都会改变,点击确定 2.Uedit32 将保存的文件用Uedit32打开 打开后界面显示如下 选择复制(16进制复制,快捷键Ctrl+A) 新建文件,然后粘贴复制内容到新文件 CTRL+A 鼠标右键 选择范围 输入起始的行号和列号,选中内容 复制选中的内容 3.notepad++ notepad++ 软件,将以上复制的内容粘贴进去 删除不需要的尾行,将该文本复制下来。 打开 38-DAC—输出正弦波 工程文件 将文本复制进uint16_t Sine12bit[]数组中去,并删掉中括号里面的数据 编译main函数 3.结果显示 程序烧录,结果显示 五、总结 对STM32的PWM和DAC的输出波形有了一定的了解,也明白了如何使用单片机进行波形输出。内容写得较为详细,希望对你有所帮助。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1786 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1622 浏览 1 评论
1089 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
730 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1680 浏览 2 评论
1942浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
739浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
576浏览 3评论
599浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
561浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-25 18:22 , Processed in 0.914838 second(s), Total 78, Slave 62 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号