找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1707|回复: 5
打印 上一主题 下一主题
收起左侧

STC8H单片机输出互补PWM程序,怎么使其停止输出

[复制链接]
跳转到指定楼层
楼主
ID:140489 发表于 2024-7-18 17:36 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
STC8H单片机输出互补PWM,怎么使其停止输出,像下面这样写PWMA_CR1 &= 0xF0; //停止计时,不能停止计时,还是有波形输出,请大师们帮我想想办法

if(flag_onoff==1)//开灯
{
P_SW2 |= 0x80; //扩展寄存器(XFR)访问使能
PWMA_CR1 |= 0x01; //开始计时
UpdatePwm();
}
else //关灯
{
P_SW2 |= 0x80; //扩展寄存器(XFR)访问使能
PWMA_CR1 &= 0xF0; //停止计时

// UpdatePwm();
// PWA=0;
// PWB=0;
}

单片机源程序如下:
  1. /*************  功能说明    **************

  2. 本例程基于STC8H1K16为主控芯片编写测试,STC8H系列芯片可通用参考.

  3. 高级PWM定时器 PWM1P/PWM1N,PWM2P/PWM2N,PWM3P/PWM3N,PWM4P/PWM4N 每个通道都可独立实现PWM输出,或者两两互补对称输出.

  4. 使用PWM1P,PWM1N产生互补的PWM.

  5. 本程序从P1.0(PWM1P)输出正相脉冲, 从P1.1(PWM1N)输出反相脉冲(互补).

  6. ******************************************/

  7. #include <STC8H.H>       //包含此头文件后,不需要再包含"reg51.h"头文件
  8. #include <intrins.h>


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

  10. typedef     unsigned char   u8;
  11. typedef     unsigned int    u16;
  12. typedef     unsigned long   u32;

  13. /****************************** 用户定义宏 ***********************************/

  14. #define PWM1_1      0x00        //P:P1.0  N:P1.1
  15. #define PWM1_2      0x01        //P:P2.0  N:P2.1
  16. #define PWM1_3      0x02        //P:P6.0  N:P6.1

  17. #define PWM2_1      0x00        //P:P1.2/P5.4  N:P1.3
  18. #define PWM2_2      0x04        //P:P2.2  N:P2.3
  19. #define PWM2_3      0x08        //P:P6.2  N:P6.3

  20. #define PWM3_1      0x00        //P:P1.4  N:P1.5
  21. #define PWM3_2      0x10        //P:P2.4  N:P2.5
  22. #define PWM3_3      0x20        //P:P6.4  N:P6.5

  23. #define PWM4_1      0x00        //P:P1.6  N:P1.7
  24. #define PWM4_2      0x40        //P:P2.6  N:P2.7
  25. #define PWM4_3      0x80        //P:P6.6  N:P6.7
  26. #define PWM4_4      0xC0        //P:P3.4  N:P3.3

  27. #define ENO1P       0x01
  28. #define ENO1N       0x02
  29. #define ENO2P       0x04
  30. #define ENO2N       0x08
  31. #define ENO3P       0x10
  32. #define ENO3N       0x20
  33. #define ENO4P       0x40
  34. #define ENO4N       0x80


  35. //#define PWM_PSCR    3     //设置分频        频率2.499KHz @24MHz          1.249KHz @12MHz
  36. //                                                  //频率计算公式MAIN_Fosc/(PWM_PSCR+1)*(PWM_ARR+1)边沿对齐
  37. //
  38. //#define PWM_ARR  2400    //设置周期值


  39. //#define PWM_PSCR    12     //设置分频        频率0.976KHz @12MHz          实测900Hz
  40. //                                                  //频率计算公式MAIN_Fosc/(PWM_PSCR+1)*(PWM_ARR+1)边沿对齐
  41. //
  42. //#define PWM_ARR  1023    //设置周期值

  43. #define PWM_PSCR    46     //设置分频        频率1KHz @12MHz          实测1.001KHz@12MHz
  44.                                                   //频率计算公式MAIN_Fosc/(PWM_PSCR+1)*(PWM_ARR+1)边沿对齐

  45. #define PWM_ARR  254    //设置周期值

  46. sbit k3=P3^7;
  47. sbit PWA=P1^0;
  48. sbit PWB=P1^1;
  49. u8 key_cont,key_lock;
  50. /*************  本地变量声明    **************/

  51. u16 PWM1_Duty;         //占空比
  52. u8        PWM_Index;        //SPWM查表索引
  53. bit flag_onoff=0;
  54. void UpdatePwm();
  55. ///////////////////////

  56. void Timer0_Init(void)                //2毫秒@12.000MHz
  57. {
  58.         AUXR |= 0x80;                        //定时器时钟1T模式
  59.         TMOD &= 0xF0;                        //设置定时器模式   T0 16位自动重载
  60.         TL0 = 0x40;                                //设置定时初始值
  61.         TH0 = 0xA2;                                //设置定时初始值
  62.         TF0 = 0;                                //清除TF0标志
  63.         TR0 = 1;                                //定时器0开始计时
  64.         ET0=1;
  65.         EA=1;
  66. }

  67. void keyscan()
  68. {
  69.         if(k3)
  70.         {
  71.                 key_lock=0;
  72.                 key_cont=0;               
  73.         }
  74.         else if(key_lock==0)
  75.         {
  76.                 ++key_cont;
  77.                 if(key_cont==10)
  78.                 {
  79.                         key_cont=0;
  80.                         key_lock=1;
  81.                         flag_onoff=!flag_onoff;
  82.                 }        
  83.         }
  84. }

  85. /******************** 主函数 **************************/
  86. void main(void)
  87. {
  88.         Timer0_Init();

  89.     P_SW2 |= 0x80;  //扩展寄存器(XFR)访问使能

  90.     P0M1 = 0x00;   P0M0 = 0x00;   //
  91.     P1M1 = 0x00;   P1M0 = 0x00;   //
  92.     P2M1 = 0x00;   P2M0 = 0x00;   //
  93.     P3M1 = 0x00;   P3M0 = 0x00;   //
  94.     P4M1 = 0x00;   P4M0 = 0x00;   //
  95.     P5M1 = 0x00;   P5M0 = 0x00;   //
  96.     P6M1 = 0x00;   P6M0 = 0x00;   //
  97.     P7M1 = 0x00;   P7M0 = 0x00;   //

  98.         PWA=0;
  99.         PWB=0;
  100. //    PWM1_Duty = 1220;
  101.     PWM1_Duty = 100;

  102.     PWMA_CCER1 = 0x00; //写 CCMRx 前必须先清零 CCxE 关闭通道
  103.     PWMA_CCER2 = 0x00;
  104.     PWMA_CCMR1 = 0x60; //通道模式配置  PWM模式1
  105. //    PWMA_CCMR2 = 0x60;
  106. //    PWMA_CCMR3 = 0x60;
  107. //    PWMA_CCMR4 = 0x60;
  108.     PWMA_CCER1 = 0x05; //配置通道输出使能和极性         OC1通道负极开启比较输出,(OC1通道正极)CC1通道配置为输出低电平有效
  109. //    PWMA_CCER2 = 0x55;

  110.     PWMA_CCMR1 |= 0x08; //开启PWMA_CCR1预装载功能(需要CC1E=1才可写)
  111. //    PWMA_CCMR2 |= 0x08;
  112. //    PWMA_CCMR3 |= 0x08;
  113. //    PWMA_CCMR4 |= 0x08;

  114. //    PWMA_ARRH = 0x09; //设置周期时间  2400
  115. //    PWMA_ARRL = 0x60;

  116.     PWMA_ARRH = (u8)(PWM_ARR >> 8);  //设置周期时间
  117.     PWMA_ARRL = (u8)PWM_ARR;

  118.     PWMA_CCR1H = (u8)(PWM1_Duty >> 8); //设置占空比时间
  119.     PWMA_CCR1L = (u8)(PWM1_Duty);

  120.         PWMA_PSCRH = (u8)(PWM_PSCR>>8);     //设置分频
  121.     PWMA_PSCRL = (u8)(PWM_PSCR);

  122. //    PWMA_DTR = 0x0C;   //设置死区时间        0000 1100    0.5us  @24MHz          (1/MAIN_Fosc)*1000000*12=0.5
  123. //    PWMA_DTR = 0x1F;   //设置死区时间        1.29us        @24MHz
  124.     PWMA_DTR = 0x81;   //设置死区时间        5.4us        @24MHz    10.8us        @12MHz

  125. //    PWMA_DTR = 0xFF;   //设置死区时间        42us        @24MHz

  126.     PWMA_ENO = 0x00;
  127.     PWMA_ENO |= ENO1P; //使能输出
  128.     PWMA_ENO |= ENO1N; //使能输出

  129. //    PWMA_ENO |= ENO2P; //使能输出
  130. //    PWMA_ENO |= ENO2N; //使能输出
  131. //    PWMA_ENO |= ENO3P; //使能输出
  132. //    PWMA_ENO |= ENO3N; //使能输出
  133. //    PWMA_ENO |= ENO4P; //使能输出
  134. //    PWMA_ENO |= ENO4N; //使能输出

  135.     PWMA_PS = 0x00;  //高级 PWM 通道输出脚选择位
  136.     PWMA_PS |= PWM1_1; //选择 PWM1_1 通道
  137. //    PWMA_PS |= PWM2_3; //选择 PWM2_3 通道
  138. //    PWMA_PS |= PWM3_3; //选择 PWM3_3 通道
  139. //    PWMA_PS |= PWM4_3; //选择 PWM4_3 通道

  140.     PWMA_BKR = 0x80; //使能主输出
  141.     PWMA_IER = 0x01; //使能中断
  142.     PWMA_CR1 |= 0x01; //开始计时

  143. //    EA = 1;     //打开总中断         不用PWMA中断函数,可以不打开总中断

  144.     while (1)
  145.     {
  146.                 if(flag_onoff==1)//开灯
  147.                 {
  148.                 //        P_SW2 |= 0x80;  //扩展寄存器(XFR)访问使能
  149.                         
  150.             //        PWMA_CR1 |= 0x01; //开始计时
  151.                         UpdatePwm();
  152.                 }
  153.                 else  //关灯
  154.                 {
  155.                 //        P_SW2 |= 0x80;  //扩展寄存器(XFR)访问使能
  156.         
  157.             //        PWMA_CR1 &= 0xF0; //停止计时
  158.                         
  159.                 //        UpdatePwm();
  160. //                        PWA=0;
  161. //                        PWB=0;               
  162.                 }
  163.     }
  164. }
  165. //========================================================================
  166. // 函数: UpdatePwm(void)
  167. // 描述: 更新PWM占空比.
  168. // 参数: none.
  169. // 返回: none.
  170. // 版本: V1.0, 2012-11-22
  171. //========================================================================
  172. void UpdatePwm(void)
  173. {
  174.         P_SW2 |= 0x80;
  175.         PWMA_CCR1H = (u8)(PWM1_Duty >> 8); //设置占空比时间
  176.     PWMA_CCR1L = (u8)(PWM1_Duty);
  177. //          PWMA_CCR2H = (u8)(PWM2_Duty >> 8); //设置占空比时间
  178. //    PWMA_CCR2L = (u8)(PWM2_Duty);
  179. //          PWMA_CCR3H = (u8)(PWM3_Duty >> 8); //设置占空比时间
  180. //    PWMA_CCR3L = (u8)(PWM3_Duty);
  181. //          PWMA_CCR4H = (u8)(PWM4_Duty >> 8); //设置占空比时间
  182. //    PWMA_CCR4L = (u8)(PWM4_Duty);
  183.         P_SW2 &= 0x7f;
  184. }
  185. /******************** 中断函数 **************************/
  186. //PWMA中断处理程序
  187. //void PWMA_ISR() interrupt 26
  188. //{
  189. //    if(PWMA_SR1 & 0X01)
  190. //    {
  191. //        PWMA_SR1 &=~0X01;
  192. ////        PWM1_Duty = T_SinTable[PWM_Index];
  193. ////        if(++PWM_Index >= 200)        PWM_Index = 0;
  194. //
  195. //        PWMA_CCR1H = (u8)(PWM1_Duty >> 8); //设置占空比时间
  196. //        PWMA_CCR1L = (u8)(PWM1_Duty);
  197. //    }
  198. //    PWMA_SR1 = 0;
  199. //}

  200. /////////////////////
  201. void timer0_ISR() interrupt 1
  202. {
  203.         keyscan();
  204. }
复制代码

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏3 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:1128908 发表于 2024-7-19 20:44 | 只看该作者
  1.         // 假设你有一个函数用于初始化PWM,例如:
  2. void PWM_Init(void)
  3. {
  4.     // 初始化PWM的代码...
  5.     // 设置周期、占空比等
  6. }

  7. // 停止PWM输出的函数
  8. void PWM_Stop(void)
  9. {
  10.     // 找到控制PWM的寄存器,并写入适当的值以停止PWM
  11.     // 例如,如果有一个名为PWM_CTL的寄存器,并且写入0可以停止PWM
  12.     PWM_CTL = 0; // 假设这是停止PWM的正确操作
  13.    
  14.     // 如果需要,禁用GPIO引脚作为PWM输出
  15.     // 例如,如果GPIO_PIN是PWM输出的引脚
  16.     GPIO_PIN_MODE(GPIO_PIN, GPIO_MODE_OUT_PP); // 设置为普通推挽输出或禁用输出
  17.     // 或者,如果你有一个函数来禁用GPIO引脚,可以调用它
  18.     // GPIO_DisableOutput(GPIO_PIN);
  19. }

  20. // 在主函数或其他地方调用这些函数
  21. int main(void)
  22. {
  23.     // 初始化PWM
  24.     PWM_Init();
  25.    
  26.     // ... 其他代码 ...
  27.    
  28.     // 当需要停止PWM时
  29.     PWM_Stop();
  30.    
  31.     // ... 其他代码 ...
  32.    
  33.     return 0;
  34. }
复制代码

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

板凳
ID:1034262 发表于 2024-7-19 22:12 | 只看该作者
简单!
STC8H系列的高级PWM,连续输出0或1有2种方法(以PWM1P为例):

1、使用PWMx_ENO禁止输出PWM,对应IO成为普通IO,禁止PWM输出后,由这个IO直接输出高或低电平。
  PWMA_ENO |= 0x01;   // 允许PWM1P输出
  delay_ms(5);        // P1.0输出PWM 5ms
  P10 = 1;            // P1.0输出高电平
  PWMA_ENO &= ~0x01;  // 关闭PWM输出
  delay_ms(5);        // P1.0输出高电平5ms
               
  PWMA_ENO |= 0x01;   // 允许PWM1P输出
  delay_ms(5);        // P1.0输出PWM 5ms
  P10 = 0;            // P1.0输出低电平
  PWMA_ENO &= ~0x01;  // 关闭PWM输出
  delay_ms(5);        // P1.0输出高电平5ms

2、设置PWMx_CCMRn,强制PWM输出有效(高)电平/无效(低)电平。
  PWMA_CCMR1 = (PWMA_CCMR1 & ~0x70) | 0x60;  // PWM正常输出
  delay_ms(5);                               // PWM输出5ms
  PWMA_CCMR1 = (PWMA_CCMR1 & ~0x70) | 0x40;  // 强制PWM输出无效(低)电平
  delay_ms(5);                               // PWM输出低电平5ms
  PWMA_CCMR1 = (PWMA_CCMR1 & ~0x70) | 0x60;  // PWM正常输出
  delay_ms(5);                               // PWM输出5ms
  PWMA_CCMR1 = (PWMA_CCMR1 & ~0x70) | 0x50;  //强制PWM输出有效(高)电平
  delay_ms(5);                               // PWM输出高电平5ms
回复

使用道具 举报

地板
ID:1110945 发表于 2024-7-20 09:53 | 只看该作者
可以设置某一通道占空比时间=0,//只关某一通道
也可以设置PWMA_ENO   // 关闭某一通道PWM输出
还有刹车信号可以使其全部关闭
回复

使用道具 举报

5#
ID:748084 发表于 2024-8-9 10:33 | 只看该作者
PWMA_ENO    = 0;
回复

使用道具 举报

6#
ID:748084 发表于 2024-8-9 10:34 | 只看该作者
我的关断PWM程序并输出低电平如下,希望对你有帮助。

void disable_pwm()
{
        PWM_Flag = 0;
        PWMA_CR1 = 0; // 清零,停止PCA计数器工作
    PT0 = 0; // 清除定时器0溢出标志
    PT1 = 0; // 清除定时器1溢出标志
//        PWMA_ENO &= ~0x01; // 关闭PWM输出
        PWMA_ENO = 0x00;
        PWMA_BKR = 0x00;   //PWMA的OC OCA禁止输出
        P2M0 = 0x00 ;           // 0xFF ;       
    P2M1 = 0x00;            //0xFF 设ALL为漏极开路;
        P2INTE = 0x00;     //
        P2 = 0;

        delay_ms(1);
}
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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