完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
一、PWM
1、PWM介绍 PWM是 Pulse Width Modulation 的缩写,中文意思就是脉冲宽度调 制,简称脉宽调制。STM32F1除了基本定时器TIM6和TIM7,其他定时器都可以产生PWM输出 。其中高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出 。而通用定时器也能同时产生多达 4路的 PWM 输出,这些在定时器中断 章节中已经介绍过。 PWM的输出其实就是对外输出脉宽可调(即占空比调节)的方波信号 ,信号频率是由自动重装寄存器 ARR 的值决定,占空比由比较寄存器 CCR 的值决定。 PWM输出比较模式总共有8种,具体由寄存器 CCMRx 的位 OCxM[2:0] 配置。最常用的两种PWM输出模式:PWM1和PWM2: PWM输出配置: 使能定时器及端口时钟,并设置引脚复用器映射 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;//复用推挽输出 初始化定时器参数,包含自动重装值,分频系数,计数方式等 void TIM_TimeBaseInit(TIM_TypeDef*TIMx,TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct); 初始化PWM输出参数,包含PWM模式、输出极性,使能等 void TIM_OCxInit(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct); 开启定时器 void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState); TIM_Cmd(TIM3,ENABLE); //开启定时器 修改TIMx_CCRx的值控制占空比 void TIM_SetCompare1(TIM_TypeDef* TIMx, uint32_t Compare1); 使能TIMx在CCRx上的预装载寄存器 使能输出比较预装载库函数是: void TIM_OCxPreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload); 第一个参数用于选择定时器,第二个参数用于选择使能还是失能输出比较预装载寄存器,可选择为TIM_OCPreload_Enable、TIM_OCPreload_Disable。 使能 TIMx 在 ARR 上的预装载寄存器允许位 使能 TIMx 在 ARR 上的预装载寄存器允许位库函数是: void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState); //第一个参数用于选择定时器,第二个参数用于选择使能还是失能。 高级定时器要想输出PWM波形,必须要设置一个 MOE 位(TIMx_BDTR 的第 15 位),以使能主输出,否则不会输出 PWM。库函数设置的函数为: void TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx, FunctionalState NewState); 2、用STM32F103输出一路PWM波形 实验代码可参考野火官方给的资料。 部分代码: void LED_GPIO_Config(void) { /*定义一个GPIO_InitTypeDef类型的结构体*/ GPIO_InitTypeDef GPIO_InitStructure; /*开启LED相关的GPIO外设时钟*/ RCC_APB2PeriphClockCmd( LED1_GPIO_CLK | LED2_GPIO_CLK | LED3_GPIO_CLK, ENABLE); /*选择要控制的GPIO引脚*/ GPIO_InitStructure.GPIO_Pin = LED1_GPIO_PIN; /*设置引脚模式为通用推挽输出*/ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; /*设置引脚速率为50MHz */ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; /*调用库函数,初始化GPIO*/ GPIO_Init(LED1_GPIO_PORT, &GPIO_InitStructure); /*选择要控制的GPIO引脚*/ GPIO_InitStructure.GPIO_Pin = LED2_GPIO_PIN; /*调用库函数,初始化GPIO*/ GPIO_Init(LED2_GPIO_PORT, &GPIO_InitStructure); /*选择要控制的GPIO引脚*/ GPIO_InitStructure.GPIO_Pin = LED3_GPIO_PIN; /*调用库函数,初始化GPIOF*/ GPIO_Init(LED3_GPIO_PORT, &GPIO_InitStructure); /* 关闭所有led灯 */ GPIO_SetBits(LED1_GPIO_PORT, LED1_GPIO_PIN); /* 关闭所有led灯 */ GPIO_SetBits(LED2_GPIO_PORT, LED2_GPIO_PIN); /* 关闭所有led灯 */ GPIO_SetBits(LED3_GPIO_PORT, LED3_GPIO_PIN); } main.c函数: int main(void) { /* led 端口配置 */ LED_GPIO_Config(); /* 定时器初始化 */ GENERAL_TIM_Init(); while(1) { } } 点击Options For Target进行如下配置: 然后点击OK。 接下来点击仿真按钮: 最后点击运行仿真: 结果如下: 二、用STM32F103的DAC功能完成波形输出 1、DAC简介 DAC 为数字/模拟转换模块,故名思议,它的作用就是把输入的数字编码,转换成对应的模拟电压输出,它的功能与 ADC 相反。在常见的数字信号系统中,大部分传感器信号被化成电压信号,而 ADC 把电压模拟信号转换成易于计算机存储、处理的数字编码,由计算机处理完成后,再由 DAC 输出电压模拟信号,该电压模拟信号常常用来驱动某些执行器件,使人类易于感知。如音频信号的采集及还原就是这样一个过程。 STM32 具有片上 DAC 外设,它的分辨率可配置为 8 位或 12 位的数字输入信号,具有两个 DAC 输出通道,这两个通道互不影响,每个通道都可以使用 DMA 功能,都具有出错检测能力,可外部触发。 2、输出一个周期2khz的正弦波 打开野火官方的的DAC例程,在此例程上进行操作。 根据定时器的配置,可推算出正弦波频率的计算方式: 可根据上述公式计算出周期为2KHz的正弦波的定时周期为1125。 */ static void DAC_TIM_Config(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; /* 使能TIM2时钟,TIM2CLK 为72M */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); /* TIM2基本定时器配置 */ // TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); TIM_TimeBaseStructure.TIM_Period = (1125-1); //定时周期 1125 TIM_TimeBaseStructure.TIM_Prescaler = 0x0; //预分频,不分频 72M / (0+1) = 72M TIM_TimeBaseStructure.TIM_ClockDivision = 0x0; //时钟分频系数 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式 TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); /* 配置TIM2触发源 */ TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update); /* 使能TIM2 */ TIM_Cmd(TIM2, ENABLE); } 在这里插入图片描述 3、将一段数字音频歌曲数据转换为模拟音频波形输出 首先下载一首自己喜欢的歌曲,用Adobe Audition CS6打开; 然后截取歌曲的一部分: 保存为.wav文件,且频率为8kHz,量化16bit; 然后用UltraEdit打开刚刚我们保存的文件; 点击Ctrl+A全选,右键选择“十六进制复制选定视图”; 然后新建文件,粘贴; 右键“选择范围”; 将选中的内容复制下来,放在一个新文件里面,然后用notepad++打开,点击编辑→列块编辑→插入文本,生成结果如下: 将上面得到的十六进制文本复制(由于太长,我只选择了一部分); 0x52 ,0x49 ,0x46 ,0x46 ,0xCC ,0x51 ,0x01 ,0x00 ,0x57 ,0x41 ,0x56 ,0x45 ,0x66 ,0x6D ,0x74 ,0x20 ,0x12 ,0x00 ,0x00 ,0x00 ,0x01 ,0x00 ,0x01 ,0x00 ,0x40 ,0x1F ,0x00 ,0x00 ,0x80 ,0x3E ,0x00 ,0x00 ,0x02 ,0x00 ,0x10 ,0x00 ,0x00 ,0x00 ,0x64 ,0x61 ,0x74 ,0x61 ,0x8E ,0x37 ,0x01 ,0x00 ,0x5E ,0xFF ,0x85 ,0x00 ,0xA7 ,0x01 ,0x90 ,0x00 ,0xBE ,0xFF ,0x08 ,0x00 ,0xFE ,0x00 ,0xC5 ,0xFC ,0x79 ,0x00 ,0xCD ,0xFE ,0xEA ,0xFF ,0x3B ,0xFF ,0xC7 ,0x00 ,0xE6 ,0x00 ,0xA4 ,0xFF ,0x8D ,0xFF ,0x82 ,0x01 ,0xDD ,0xFF ,0x7A ,0x00 ,0x6B ,0x00 ,0xFF ,0xFF ,0xEE ,0xFF ,0x5F ,0x00 ,0x4D ,0xFF ,0x94 ,0xFF ,0x15 ,0x00 ,0xD4 ,0xFE ,0xD5 ,0x00 ,0xB2 ,0xFF ,0xAE ,0x00 ,0xBA ,0x00 ,0x38 ,0x01 ,0x4D ,0xFF ,0x65 ,0x00 ,0x83 ,0xFE ,0x21 ,0xFF ,0xF5 ,0xFF ,0x0A ,0x00 ,0x20 ,0xFF ,0xBA ,0x00 ,0xA1 ,0x00 ,0x5A ,0x00 ,0x07 ,0x00 ,0x27 ,0x00 ,0xA2 ,0x00 ,0x96 ,0xFF ,0xB7 ,0x00 ,0x6F ,0x00 ,0xA0 ,0xFF ,0x4F ,0x00 ,0x29 ,0xFF ,0xCE ,0xFF ,0x77 ,0x00 ,0x3A ,0xFE ,0x46 ,0x01 ,0xF7 ,0xFE ,0x08 ,0x02 ,0x5F ,0x00 ,0x4B ,0x00 ,0x98 ,0x00 ,0x69 ,0xFF ,0x9E ,0xFE ,0x61 ,0xFE ,0xE4 ,0xFF ,0x4C ,0x00 ,0xBB ,0xFF ,0xE6 ,0x00 ,0x62 ,0x00 ,0x48 ,0xFF ,0xF6 ,0xFF ,0xE6 ,0xFF ,0xB3 ,0x00 ,0x89 ,0xFF , 然后复制到代码当中: 然后连接硬件,下载程序,运行仿真: 三、总结 PWM和DAC有些难,作为初学者还需要慢慢理解和实践。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1754 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1613 浏览 1 评论
1053 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
721 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1667 浏览 2 评论
1931浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
718浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
562浏览 3评论
587浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
546浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-19 16:09 , Processed in 2.789427 second(s), Total 76, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号