博客
关于我
STM32普通io口模拟pwm输出的三种方法
阅读量:631 次
发布时间:2019-03-14

本文共 3395 字,大约阅读时间需要 11 分钟。

STM32F103RB普通I/O口模拟PWM输出的三种方法

定时器中断产生PWM

如何用I/O口生成PWM?这简单,只需实现高低电平周期性切换即可。确定PWM频率后,这一周期就能被精确量化。频率确定后,想要调整占空比只需设定高电平时间的比例即可。以1kHz的频率为例,周期为1ms。如果我们想实现70%的占空比,那么高电平段的持续时间应为0.7ms。在定时器中断中,我们可以设定每0.1ms触发一次中断,通过计数器记录中断次数。当中断次数达到7次时,就可以切换到低电平状态。

第一种方法代码示例

//#include "stm32f10x.h"

#include "stdio.h"#include "usart.h"#include "tim.h"#include "led.h"#include "misc.h"

void TIM2_NVIC(void);void TIM2_Init(void);unsigned char ucLed;unsigned char ucLck;int main(void){SysTick_Config(72000); // 定时1ms (HCLK = 72MHz)TIM2_Init();TIM2_NVIC();LED_Init();while(1){LED_Disp(ucLed);}}

unsigned int count=0;unsigned int i;

void TIM2_IRQHandler(void){count++;if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET){if(count%10){//占空比调整ucLed = (ucLed == 0xFF) ? 0x00 : 0xFF;LED_Disp(ucLed);}}}

这里的i是用于改变占空比的变量,通过让i做延时,使得PWM变化频率变大,产生呼吸灯的效果。通过延时处理,我们可以让占空比变化的频率与实际需求相匹配,避免直接用i++让变化过快或过慢。

第二种方法

比较+周期中断

此种方法通过定时器中的比较通道实现PWM输出。我们可以不使用IO口进行比较操作,而是在中断处理函数中直接设定输出状态。这种方式的配置相对简单,灵活度较高。通过设置定时器的比较值,可以直接控制PWM的占空比。

第二种方法代码示例

//#include "led.h"

#include "misc.h"#include "stdio.h"

void TIM2_Config(uint16_t duty1);unsigned char ucLed;unsigned int Compare2=100;unsigned int ulTick;

int main(void){SysTick_Config(72000); // 定时1ms (HCLK = 72MHz)TIM2_Config(999/4); // 25%占空比TIM_SetCompare2(TIM2, Compare2);LED_Init();while(1){if(ulTick%1000 == 0){Compare2 += 50;if(Compare2 > 999){Compare2 = 100;}TIM_SetCompare2(TIM2, Compare2);}}}

void TIM2_Config(uint16_t duty1){TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_OCInitTypeDef TIM_OCInitStructure;NVIC_InitTypeDef NVIC_InitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);TIM_TimeBaseStructure.TIM_Period = 999;  // 1kHzTIM_TimeBaseStructure.TIM_Prescaler = 71;  // 预分频系数TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);TIM_ClearFlag(TIM2, TIM_FLAG_Update);TIM_ITConfig(TIM2, TIM_IT_Update|TIM_IT_CC2, ENABLE);TIM_PrescalerConfig(TIM2, 71, TIM_PSCReloadMode_Immediate);TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable;TIM_OCInitStructure.TIM_Pulse = duty1;TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;TIM_OC2Init(TIM2, &TIM_OCInitStructure);TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);TIM_Cmd(TIM2, ENABLE);// 中断处理函数void TIM2_IRQHandler(void){    if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET){        ucLed = 0x00;        LED_Disp(ucLed);        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);    }    else if(TIM_GetITStatus(TIM2, TIM_IT_CC2) != RESET){        ucLed = 0xff;        LED_Disp(ucLed);        TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);    }}void SysTick_Handler(void){    ulTick++;}

}

通过ulTick控制定时器周期,我们可以在循环中动态调整占空比,实现呼吸灯效果。这种方式简单且灵活,适合需要复杂占空比控制的场景。

第三种方法

系统滴答定时器

第三种方法基于系统滴答定时器(SysTick)。这种方法与第一种方法原理相同,主要通过在中断服务函数中控制I/O口状态切换实现PWM输出。需要注意的是,系统滴答定时器的配置和使用需要遵循特定的规则,建议参考开发板的用户手册或参考资料。

完整工程下载

支持第六个工程(包含两种方法)

作者:江多多 (在校学生) 版权所有,欢迎保留原文链接进行转载! 不忘初心,牢记使命,努力成为一名优秀的嵌入式工程师! (我的第六篇博客)

你可能感兴趣的文章
Mysql 笔记
查看>>
MySQL 精选 60 道面试题(含答案)
查看>>
mysql 索引
查看>>
MySQL 索引失效的 15 种场景!
查看>>
MySQL 索引深入解析及优化策略
查看>>
MySQL 索引的面试题总结
查看>>
mysql 索引类型以及创建
查看>>
MySQL 索引连环问题,你能答对几个?
查看>>
Mysql 索引问题集锦
查看>>
Mysql 纵表转换为横表
查看>>
mysql 编译安装 window篇
查看>>
mysql 网络目录_联机目录数据库
查看>>
MySQL 聚簇索引&&二级索引&&辅助索引
查看>>
Mysql 脏页 脏读 脏数据
查看>>
mysql 自增id和UUID做主键性能分析,及最优方案
查看>>
Mysql 自定义函数
查看>>
mysql 行转列 列转行
查看>>
Mysql 表分区
查看>>
mysql 表的操作
查看>>
mysql 视图,视图更新删除
查看>>