找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4329|回复: 8
收起左侧

STC8A单片机PWM疑问

[复制链接]
ID:612392 发表于 2020-7-2 18:32 | 显示全部楼层 |阅读模式
5黑币
各位大神,小弟在看STC8A系统单片机的规格书时,对PWM的CL/CH寄存器有点疑问。
如果我在主函数里对CH/CL寄存器赋了初值,启动计数器,当第一次溢出后,需要进入中断对CH/CL重新赋值吗?如果不进中断赋值,下次是不是就从0开始计数了?另外,进中断后,再次赋值后,是否还要再启动计数器?
谢谢。

最佳答案

查看完整内容

我给你来个程序, 可以参考一下 单片机SPWM波 产生正弦波的源程序及工具 http://www.51hei.com/bbs/dpj-55510-1.html
回复

使用道具 举报

ID:155507 发表于 2020-7-2 18:32 | 显示全部楼层
我给你来个程序, 可以参考一下



  1. //一个SPWM带有死区的程序 用STC8A8K64S4A12单片机编写的SPWM
  2. //介绍了一种高性能微机控制的单相 SPWM 变频调速系统
  3. // SPWM信号经低通滤波后可变换为正弦波,窄带范围内的方波经低通滤波后可变换为相应频率的正弦波
  4. //程序能用,如果不是你想要的频率,那就 自己改一下数据 记得同时要替换数组里面的值

  5. #define         MAIN_Fosc                24000000L        //定义主时钟

  6. #include        "STC8.H"
  7. unsigned int code T_SinTable[]={         //SPWM正弦波查表200个值
  8. 1220, 1256, 1292, 1328, 1364, 1400, 1435, 1471, 1506, 1541,  //1
  9. 1575, 1610, 1643, 1677, 1710, 1742, 1774, 1805, 1836, 1866,  //2
  10. 1896, 1925, 1953, 1981, 2007, 2033, 2058, 2083, 2106, 2129,  //3
  11. 2150, 2171, 2191, 2210, 2228, 2245, 2261, 2275, 2289, 2302,  //4
  12. 2314, 2324, 2334, 2342, 2350, 2356, 2361, 2365, 2368, 2369,  //5
  13. 2370, 2369, 2368, 2365, 2361, 2356, 2350, 2342, 2334, 2324,  //6
  14. 2314, 2302, 2289, 2275, 2261, 2245, 2228, 2210, 2191, 2171,  //7
  15. 2150, 2129, 2106, 2083, 2058, 2033, 2007, 1981, 1953, 1925,  //8
  16. 1896, 1866, 1836, 1805, 1774, 1742, 1710, 1677, 1643, 1610,  //9
  17. 1575, 1541, 1506, 1471, 1435, 1400, 1364, 1328, 1292, 1256,  //10
  18. 1220, 1184, 1148, 1112, 1076, 1040, 1005, 969, 934, 899,  //11
  19. 865, 830, 797, 763, 730, 698, 666, 635, 604, 574,  //12
  20. 544, 515, 487, 459, 433, 407, 382, 357, 334, 311,  //13
  21. 290, 269, 249, 230, 212, 195, 179, 165, 151, 138,  //14
  22. 126, 116, 106, 98, 90, 84, 79, 75, 72, 71,         //15
  23. 70, 71, 72, 75, 79, 84, 90, 98, 106, 116,          //16
  24. 126, 138, 151, 165, 179, 195, 212, 230, 249, 269,  //17
  25. 290, 311, 334, 357, 382, 407, 433, 459, 487, 515,  //18
  26. 544, 574, 604, 635, 666, 698, 730, 763, 797, 830,  //19
  27. 865, 899, 934, 969, 1005, 1040, 1076, 1112, 1148, 1184,  //20

  28. };

  29. #define        PwmClk_1T        0
  30. #define        PwmClk_2T        1
  31. #define        PwmClk_3T        2
  32. #define        PwmClk_4T        3
  33. #define        PwmClk_5T        4
  34. #define        PwmClk_6T        5
  35. #define        PwmClk_7T        6
  36. #define        PwmClk_8T        7
  37. #define        PwmClk_9T        8
  38. #define        PwmClk_10T        9
  39. #define        PwmClk_11T        10
  40. #define        PwmClk_12T        11
  41. #define        PwmClk_13T        12
  42. #define        PwmClk_14T        13
  43. #define        PwmClk_15T        14
  44. #define        PwmClk_16T        15
  45. #define        PwmClk_T2        16

  46. #define        EAXSFR()                P_SW2 |=  0x80        /* MOVX A,@DPTR/MOVX @DPTR,A指令的操作对象为扩展SFR(XSFR) */
  47. #define        EAXRAM()                P_SW2 &= ~0x80        /* MOVX A,@DPTR/MOVX @DPTR,A指令的操作对象为扩展RAM(XRAM) */
  48. #define        PWM_Enable()        PWMCR |=  0x80        /* 使能PWM波形发生器,PWM计数器开始计数 */
  49. #define        PWM_Disable()        PWMCR &= ~0x80        /* 关闭PWM波形发生器 */
  50. #define P2n_standard(bitn)                        P2M1 &= ~(bitn),        P2M0 &= ~(bitn)
  51. #define P2n_push_pull(bitn)                        P2M1 &= ~(bitn),        P2M0 |=  (bitn)
  52. #define P2n_pure_input(bitn)                P2M1 |=  (bitn),        P2M0 &= ~(bitn)
  53. #define P2n_open_drain(bitn)                P2M1 |=  (bitn),        P2M0 |=  (bitn)
  54. #define        PWM_VECTOR                22

  55. #define        PWM_DeadZone        12        /* 死区时钟数, 6 ~ 24之间  */
  56. typedef unsigned char         u8;
  57. typedef unsigned int          u16;
  58. typedef unsigned long         u32;

  59. sbit OE245 =P4^1;
  60. sbit LED_OUT =P3^3;
  61. //LED是自己任意定义且容易记忆的符号
  62. #define Port P1                         //设置CPU和模块的通讯接口

  63. u8        PWM_Index;        //SPWM查表索引

  64. void delay(unsigned long d) //延时函数
  65. {
  66.   while(d--);
  67. }

  68. //========================================================================
  69. // 函数: void        PWM_config(void)
  70. // 描述: PWM配置函数。
  71. // 参数: none.
  72. // 返回: none.
  73. // 版本: VER1.0
  74. // 日期:
  75. // 备注:
  76. //========================================================================
  77. void        PWM_config(void)
  78. {

  79.   EAXSFR();                        // 访问XFR

  80.   PWM3T1 = 65; // 第一个翻转计数

  81.   PWM3T2=1220;         // 第二个翻转计数
  82.   PWM3CR =0;         // PWM3输出选择P2.3, 无中断
  83.   PWM3CR  |=  0x80;        // 相应PWM通道的端口为PWM输出口,受PWM波形发生器控制 ENC30
  84.   PWM3CR &= ~0x40;        // 设置PWM输出端口的初始电平为0 C3INI

  85.   P23 = 0;
  86.   P2n_push_pull(1<<3);        //IO初始化, 上电时为高阻

  87.   PWM4T1= 65-PWM_DeadZone;                        // 第一个翻转计数低字节
  88.        
  89.   PWM4T2 = (1220+PWM_DeadZone); // 第二个翻转计数高字节
  90.        
  91.   PWM4CR = 0;        // PWM4输出选择P2.2, 无中断
  92.   PWM4CR  |=  0x80;        // 相应PWM通道的端口为PWM输出口,受PWM波形发生器控制 ENC40
  93.   //        PWMCFG &= ~0x04;        // 设置PWM输出端口的初始电平为0  C4INI
  94.   PWM4CR |=  0x40;        // 设置PWM输出端口的初始电平为1
  95.   P24 = 1;
  96.   P2n_push_pull(1<<4);        //IO初始化, 上电时为高阻

  97.   PWMC = 2400;        // PWM计数器的高字节  //设置PWM周期为 2400 个PWM时钟  1/( 1/24M * 2400) =10KHz

  98.   PWMCKS = PwmClk_1T;        // 时钟源: PwmClk_1T,PwmClk_2T, ... PwmClk_16T, PwmClk_Timer2

  99.   EAXRAM();                        // 恢复访问XRAM
  100.   
  101.   PWMCR |= ENPWM;                // 使能PWM波形发生器,PWM计数器开始计数
  102.   //        PWMCR &= ~ECBI;                // 禁止PWM计数器归零中断
  103.   PWMCR |=  ECBI;                // 允许PWM计数器归零中断

  104.   //        PWMFDCR = ENFD | FLTFLIO | FDIO;        //PWM失效中断控制,  ENFD | FLTFLIO | EFDI | FDCMP | FDIO
  105. }


  106. /*********** 主程序 ***********************************/
  107. void main(void)
  108. {
  109.   unsigned char i;
  110.   OE245 =0;
  111.   LED_OUT =1;
  112.   PWM_config();        //初始化PWM
  113.   PWM_Enable(); //启动PWM模块
  114.   EA = 1;                //允许全局中断

  115.   while (1)     //主循环
  116.   {
  117.     for(i=1;i!=0;i<<=1)  // 0000 0000
  118.     {
  119.       Port =~i; //0111 1111
  120.       delay(200000);  //用于改变闪烁频率
  121.     }
  122.            //主循环中添加其他需要一直工作的程序
  123.   }
  124. }


  125. /********************* PWM中断函数************************/

  126. void PWM_int (void) interrupt PWM_VECTOR
  127. {
  128.   u16        j;
  129.   u8        SW2_tmp;

  130.   if(PWMCFG & CBIF)        //PWM计数器归零中断标志 PWMCFG
  131.   {
  132.     PWMCFG &= ~CBIF;        //清除中断标志

  133.     SW2_tmp = P_SW2;        //保存SW2设置
  134.     EAXSFR();                //访问XFR

  135.     j = T_SinTable[PWM_Index]; //相应频率的正弦波的值

  136.     PWM3T2H = (u8)(j >> 8);        //第二个翻转计数高字节

  137.     PWM3T2L  = (u8)j;                        //第二个翻转计数低字节

  138.     j += PWM_DeadZone;                //死区
  139.     // 指向PWM4

  140.     PWM4T2H = (u8)(j >> 8);        //第二个翻转计数高字节
  141.    
  142.     PWM4T2L = (u8)j;                        //第二个翻转计数低字节
  143.     P_SW2 = SW2_tmp;        //恢复SW2设置

  144.     if(++PWM_Index >= 200)        PWM_Index = 0; //执行200次

  145.   }

  146. }

  147. /*
  148. 单片机SPWM波 产生正弦波的源程序及工具
  149. http://www.51hei.com/bbs/dpj-55510-1.html

  150. */


复制代码



单片机SPWM波 产生正弦波的源程序及工具
http://www.51hei.com/bbs/dpj-55510-1.html

回复

使用道具 举报

ID:155507 发表于 2020-7-2 22:23 | 显示全部楼层
PWM的CL/CH寄存器是内部用,实际应用中 不需要对CH/CL寄存器赋了初值


  1. //PWM调光
  2. #include "reg51.h"
  3. #include "intrins.h"

  4. //测试工作频率为11.0592MHz

  5. #define CYCLE           0x1000

  6. sfr     P_SW2       =   0xba;
  7. sfr     PWMCFG      =   0xf1;
  8. sfr     PWMIF       =   0xf6;
  9. sfr     PWMFDCR     =   0xf7;
  10. sfr     PWMCR       =   0xfe;

  11. #define PWMC            (*(unsigned int volatile xdata *)0xfff0)
  12. #define PWMCKS          (*(unsigned char volatile xdata *)0xfff2)
  13. #define TADCP           (*(unsigned int volatile xdata *)0xfff3)
  14. #define PWM0T1          (*(unsigned int volatile xdata *)0xff00)
  15. #define PWM0T2          (*(unsigned int volatile xdata *)0xff02)
  16. #define PWM0CR          (*(unsigned char volatile xdata *)0xff04)
  17. #define PWM0HLD         (*(unsigned char volatile xdata *)0xff05)
  18. #define PWM1T1          (*(unsigned int volatile xdata *)0xff10)
  19. #define PWM1T2          (*(unsigned int volatile xdata *)0xff12)
  20. #define PWM1CR          (*(unsigned char volatile xdata *)0xff14)
  21. #define PWM1HLD         (*(unsigned char volatile xdata *)0xff15)
  22. #define PWM2T1          (*(unsigned int volatile xdata *)0xff20)
  23. #define PWM2T2          (*(unsigned int volatile xdata *)0xff22)
  24. #define PWM2CR          (*(unsigned char volatile xdata *)0xff24)
  25. #define PWM2HLD         (*(unsigned char volatile xdata *)0xff25)
  26. #define PWM3T1          (*(unsigned int volatile xdata *)0xff30)
  27. #define PWM3T2          (*(unsigned int volatile xdata *)0xff32)
  28. #define PWM3CR          (*(unsigned char volatile xdata *)0xff34)
  29. #define PWM3HLD         (*(unsigned char volatile xdata *)0xff35)
  30. #define PWM4T1          (*(unsigned int volatile xdata *)0xff40)
  31. #define PWM4T2          (*(unsigned int volatile xdata *)0xff42)
  32. #define PWM4CR          (*(unsigned char volatile xdata *)0xff44)
  33. #define PWM4HLD         (*(unsigned char volatile xdata *)0xff45)
  34. #define PWM5T1          (*(unsigned int volatile xdata *)0xff50)
  35. #define PWM5T2          (*(unsigned int volatile xdata *)0xff52)
  36. #define PWM5CR          (*(unsigned char volatile xdata *)0xff54)
  37. #define PWM5HLD         (*(unsigned char volatile xdata *)0xff55)
  38. #define PWM6T1          (*(unsigned int volatile xdata *)0xff60)
  39. #define PWM6T2          (*(unsigned int volatile xdata *)0xff62)
  40. #define PWM6CR          (*(unsigned char volatile xdata *)0xff64)
  41. #define PWM6HLD         (*(unsigned char volatile xdata *)0xff65)
  42. #define PWM7T1          (*(unsigned int volatile xdata *)0xff70)
  43. #define PWM7T2          (*(unsigned int volatile xdata *)0xff72)
  44. #define PWM7CR          (*(unsigned char volatile xdata *)0xff74)
  45. #define PWM7HLD         (*(unsigned char volatile xdata *)0xff75)

  46. void PWM_Isr() interrupt 22
  47. {
  48.     static bit dir = 1;
  49.     static int val = 0;

  50.     if (PWMCFG & 0x80)
  51.     {
  52.         PWMCFG &= ~0x80;                        //清中断标志
  53.         if (dir)
  54.         {
  55.             val++;
  56.             if (val >= CYCLE) dir = 0;
  57.         }
  58.         else
  59.         {
  60.             val--;
  61.             if (val <= 1) dir = 1;
  62.         }
  63.         _push_(P_SW2);
  64.         P_SW2 |= 0x80;
  65.         PWM0T2 = val;   //PWM0在计数值为 val 地方输出高电平
  66.         _pop_(P_SW2);
  67.     }
  68. }

  69. void main()
  70. {
  71.     P_SW2 = 0x80;
  72.     PWMCKS = 0x00;                              // PWM时钟为系统时钟
  73.     PWMC = CYCLE;                               //设置PWM周期为
  74.     PWM0T1= 0x0000;   //PWM0在计数值为0000H地方输出低电平
  75.     PWM0T2= 0x0001;   //PWM0在计数值为0000H地方输出高电平
  76.     PWM0CR= 0x80;                               //使能PWM0输出
  77.     P_SW2 = 0x00;

  78.     PWMCR = 0xc0;                               //启动PWM模块
  79.     EA = 1;

  80.     while (1);
  81. }

复制代码
回复

使用道具 举报

ID:612392 发表于 2020-7-3 08:24 | 显示全部楼层
angmall 发表于 2020-7-2 22:23
PWM的CL/CH寄存器是内部用,实际应用中 不需要对CH/CL寄存器赋了初值

angmall大神,你好。
如果不对CH/CL赋值,那么如果主频一旦定好,PWM的频也就被定下来了(固定为1~1/12的主频)。如果我的T0定时器已被占用,但我又想要我自己设定的PWM频率,应该怎么操作呢?
如果想得到可变的PWM频率,是不是只能用T0实现?我的理解对吗?
谢谢大神。
回复

使用道具 举报

ID:147710 发表于 2020-7-3 13:55 | 显示全部楼层
貌似跟T0没啥关系 duty.jpg

回复

使用道具 举报

ID:612392 发表于 2020-7-3 16:22 | 显示全部楼层
XTXB 发表于 2020-7-3 13:55
貌似跟T0没啥关系

这个应该是有死区的PWM应用?当CPS为010时,可选T0溢出脉冲作为PWM时钟源。可以达到控制PWM频率的问题。
我现在希望用STC8A做DC12V转AC220V逆变器,SPWM方式生产AC220正弦波。所以希望在不使用T0的情况下,控制我想要的PWM频率。占空比已经是确定的了,基于SPWM每周期点数就定下来了。
回复

使用道具 举报

ID:147710 发表于 2020-7-3 17:09 | 显示全部楼层
不需要用T0,用的是STC8A的增强型PWM,在PWM中断中按正弦波改变脉宽即可: pwm.jpg

回复

使用道具 举报

ID:612392 发表于 2020-7-4 09:15 | 显示全部楼层
angmall 发表于 2020-7-3 19:51
我给你来个程序, 可以参考一下

非常感谢!我动手试试。
回复

使用道具 举报

ID:337139 发表于 2021-7-6 14:44 | 显示全部楼层
非常感谢,马上调试!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表