[技术问答] 定时器任意占空比pwm

[复制链接]
 楼主| wwppd 发表于 2023-5-21 14:30 | 显示全部楼层 |阅读模式


  1. #include < reg52.h >
  2.     sbit PWMOUT = P1 ^ 7; //方波输出通道
  3. sbit KEY1 = P3 ^ 0;
  4. sbit KEY2 = P3 ^ 1;
  5. sbit KEY3 = P3 ^ 2;
  6. unsigned char HighRH = 0; //高电平重载值的高字节
  7. unsigned char HighRL = 0; //高电平重载值的低字节
  8. unsigned char LowRH = 0; //低电平重载值的高字节
  9. unsigned char LowRL = 0; //低电平重载值的低字节
  10. unsigned char KeySta[4] = { //按键的当前状态
  11.     1, 1, 1, 1
  12. };
  13. void ConfigPWM(unsigned int fr, unsigned char dc); //启动PWM,fr是频率,dc为占空比
  14. void ClosePWM(); //关闭方波输出
  15. void KeyScan(); //按键扫描函数,需在定时中断中调用
  16. void KeyDriver(); //按键驱动函数,检测按键动作,调度相应动作函数,需在主循环中调用

  17. void main() {
  18.         unsigned int i;
  19.         EA = 1; //开总中断
  20.         while (1) {
  21.             //ConfigPWM(100, 5);                //频率100Hz,占空比10%
  22.             for (i = 0; i < 40000; i++); //不断发送ConfigPWM中的方波
  23.             //ClosePWM();      
  24.             KeyScan();
  25.             KeyDriver();
  26.         }
  27.     }
  28.     /* 配置并启动PWM,fr-频率,dc-占空比 */
  29. void ConfigPWM(unsigned int fr, unsigned char dc) {
  30.         unsigned int high, low;
  31.         unsigned long tmp;
  32.         tmp = (11059200 / 12) / fr; //计算一个周期所需的计数值
  33.         high = (tmp * dc) / 100; //计算高电平所需的计数值
  34.         low = tmp - high; //计算低电平所需的计数值
  35.         high = 65536 - high + 12; //计算高电平的重载值并补偿中断延时
  36.         low = 65536 - low + 12; //计算低电平的重载值并补偿中断延时
  37.         HighRH = (unsigned char)(high >> 8); //高电平重载值拆分为高低字节
  38.         HighRL = (unsigned char) high;
  39.         LowRH = (unsigned char)(low >> 8); //低电平重载值拆分为高低字节
  40.         LowRL = (unsigned char) low;
  41.         TMOD &= 0xF0; //清零T0 的控制位
  42.         TMOD |= 0x01; //配置T0 为模式1
  43.         TH0 = HighRH; //加载T0 重载值
  44.         TL0 = HighRL;
  45.         ET0 = 1; //使能T0 中断
  46.         TR0 = 1; //启动T0
  47.         PWMOUT = 1; //输出高电平
  48.     }
  49.     /* 关闭PWM */
  50. void ClosePWM() {
  51.         TR0 = 0; //停止定时器
  52.         ET0 = 0; //禁止中断
  53.         PWMOUT = 0; //输出低电平
  54.     }
  55.     /* 按键扫描函数,需在定时中断中调用 */
  56. void KeyScan() {
  57.         unsigned char i;
  58.         static unsigned char keybuf[4] = { //按键扫描缓冲区
  59.             0xFF, 0xFF, 0xFF, 0xFF
  60.         };
  61.         //按键值移入缓冲区
  62.         keybuf[0] = (keybuf[0] << 1) | KEY1; //按键按下的时候,KEY会变成0XFF,使得keybuf = 0x00
  63.         keybuf[1] = (keybuf[1] << 1) | KEY2;
  64.         keybuf[2] = (keybuf[2] << 1) | KEY3;
  65.         //消抖后更新按键状态
  66.         for (i = 0; i < 3; i++) {
  67.             if (keybuf[i] == 0x00) { //连续8 次扫描值为0,即16ms 内都是按下状态时,可认为按键已稳定的按下
  68.                 KeySta[i] = 0;
  69.             } else if (keybuf[i] == 0xFF) { //连续8 次扫描值为1,即16ms 内都是弹起状态时,可认为按键已稳定的弹起
  70.                 KeySta[i] = 1;
  71.             }
  72.         }
  73.     }
  74.     /* 按键驱动函数,检测按键动作,调度相应动作函数,需在主循环中调用 */
  75. void KeyDriver() {
  76.         unsigned char i;
  77.         static unsigned char backup[4] = {
  78.             1, 1, 1, 1
  79.         }; //备份按键扫描
  80.         for (i = 0; i < 4; i++) //循环检测4 个按键
  81.         {
  82.             if (backup[i] != KeySta[i]) //检测按键动作
  83.             { //如果不一样,代表该按键已经被按下
  84.                 if (backup[i] != 0) //按键按下时执行动作
  85.                 {
  86.                     if (i == 0) //按键为0,旋转-90
  87.                     {
  88.                         ConfigPWM(50, 3); //频率50Hz,20ms,占空比10%
  89.                         for (i = 0; i < 40000; i++);
  90.                         ClosePWM();

  91.                     } else if (i == 1) //按键为1,旋转0
  92.                     {
  93.                         ConfigPWM(50, 8); //频率50Hz,20ms,占空比3%
  94.                         for (i = 0; i < 40000; i++);
  95.                         ClosePWM();
  96.                     } else if (i == 2) //按键为0,旋转90
  97.                     {
  98.                         ConfigPWM(50, 13); //频率50Hz,20ms,占空比8%
  99.                         for (i = 0; i < 40000; i++);
  100.                         ClosePWM();
  101.                     }
  102.                 }
  103.                 backup[i] = KeySta[i]; //刷新前一次的备份值
  104.             }
  105.         }
  106.     }
  107.     /* T0 中断服务函数,产生PWM 输出 */
  108. void InterruptTimer0() interrupt 1 {
  109.     //如果一开始是高,那么中断到了之后输出低即可完成PWM
  110.     if (PWMOUT == 1) //当前输出为高电平时,装载低电平值并输出低电平
  111.     {
  112.         TH0 = LowRH;
  113.         TL0 = LowRL;
  114.         PWMOUT = 0;
  115.     }
  116.     //如果一开始是低,那么中断到了之后输出高即可开始产生PWM
  117.     else //当前输出为低电平时,装载高电平值并输出高电平
  118.     {
  119.         TH0 = HighRH;
  120.         TL0 = HighRL;
  121.         PWMOUT = 1;
  122.     }
  123. }


tpgf 发表于 2023-6-5 15:32 | 显示全部楼层
所有的定时器都可以实现任意的占空比吗?还是说必须使用特殊的定时器啊
nawu 发表于 2023-6-5 16:13 | 显示全部楼层
tpgf 发表于 2023-6-5 15:32
所有的定时器都可以实现任意的占空比吗?还是说必须使用特殊的定时器啊

好像不可以吧 至少普通的定时器不能实现任意占空比
aoyi 发表于 2023-6-5 16:27 | 显示全部楼层
为什么我看到有的帖子说不能实现百分百占空比呢
zljiu 发表于 2023-6-5 16:47 | 显示全部楼层
通常情况下我们如何消除pwm的死区部分呢
gwsan 发表于 2023-6-5 16:59 | 显示全部楼层
我们使用普通的引脚可以模拟这种pwm的输出吗
tfqi 发表于 2023-6-5 17:23 | 显示全部楼层
gwsan 发表于 2023-6-5 16:59
我们使用普通的引脚可以模拟这种pwm的输出吗

不如专用的模块方便 只需要配置就行 你的想法还得io进行配合
belindagraham 发表于 2023-6-6 15:22 | 显示全部楼层
怎么用定时器中断控制pwm的占空比
pixhw 发表于 2023-6-7 13:10 | 显示全部楼层
调速占空比根据实际情况如何调节?
modesty3jonah 发表于 2023-6-7 21:32 | 显示全部楼层
通过修改计数值和重载值,可以动态地改变PWM信号的占空比
jtracy3 发表于 2023-6-8 22:18 | 显示全部楼层
根据所需的占空比和定时器的计数时间,计算出相应的计数值和重载值。
burgessmaggie 发表于 2023-6-8 23:16 | 显示全部楼层
用51单片机定时器中断产生两路占空比可调的pwm波形
mattlincoln 发表于 2023-6-10 10:17 | 显示全部楼层
用定时器怎么调节占空比?               
modesty3jonah 发表于 2023-6-10 10:48 | 显示全部楼层
如何在每周期修改pwm占空比               
10299823 发表于 2023-6-10 11:31 | 显示全部楼层
选择一款合适的定时器,并进行相应的初始化配置。其中,定时器的计数时间需要根据实际需求进行设置,一般可以选择10us或20us左右的时间间隔。
everyrobin 发表于 2023-6-10 11:41 | 显示全部楼层
基本原理是使用定时器来产生固定频率的脉冲信号,通过改变占空比来控制输出信号的电平。
jtracy3 发表于 2023-6-10 12:07 | 显示全部楼层
在定时器中断处理函数中不断更新计数值和重载值,从而产生固定频率和任意占空比的PWM信号。
tabmone 发表于 2023-6-10 12:20 | 显示全部楼层
定时器任意占空比PWM技术是一种常见的工业控制技术,它可以实现电机调速、LED调光等应用。
chenqianqian 发表于 2023-6-11 19:37 来自手机 | 显示全部楼层
任意占空比是通过改变计时值实现的。
georgeliu2016 发表于 2023-7-1 14:01 | 显示全部楼层
点呼吸灯效果杠杠的。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

55

主题

3062

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部