找回密码
 立即注册
查看: 117|回复: 12

PWM脉冲引脚怎么转为普通IO拉低电平

[复制链接]
  • 打卡等级:偶尔看看III
  • 打卡总天数:34
  • 最近打卡:2025-10-30 10:47:29
已绑定手机

20

主题

67

回帖

209

积分

中级会员

积分
209
发表于 7 天前 | 显示全部楼层 |阅读模式

// 方案003
/*
配置说明:
比较器电平:
0表示 正输入 小于 负输入
1表示 正输入 大于 负输入

*/


// 头文件
#include "STC8Hxxx.h"


// 引脚定义
sbit OUT_INT0 = P3^2;   // 外部中断0输入引脚
sbit Pulse = P3^4;      // PWM脉冲输出引脚
sbit CMP   = P3^7;      // 比较器正输入端


// 宏定义
#define MAIN_Fosc 35000000L     // 35MHz主频


// 声明
// 数组
// 函数
// 变量
bit cmp_filtered = 1;           // 当前比较器稳定状态
bit trigger_lock = 0;           // 锁存标志:0=允许触发,1=已触发等待解锁

u8 stable_cnt = 0;


// 函数模块
// 比较器初始化
void CMP_Init(void)
{
    CMPEXCFG = 0x00;
    CMPEXCFG |= 0x00;   // P3.7 为 CMP+ 输入脚
    CMPEXCFG |= 0x04;   // 内部 1.19V 参考为 CMP?
    P_SW2 &= 0x7F;      // 禁止XFR访问

    CMPCR2 = 0x00;
    CMPCR2 &= ~0x80;    // 输出不反向
    CMPCR2 &= ~0x40;    // 使能0.1us滤波
    CMPCR2 |= 0x10;     // 输出结果经过16个去抖时钟稳定输出

    CMPCR1 = 0x00;
    CMPCR1 |= 0x02;     // 输出使能
    CMPCR1 |= 0x80;     // 比较器模块使能
}

// PWMB脉冲配置
void PWMB_config(void)
{
    PWMB_PSCR   = 11;                   // 预分频寄存器, Fpwm = SYSclk / ((PSCR+1)*(ARR+1))
    PWMB_DTR    = 0;                    // 死区时间配置
    PWMB_ARR    = 29165;                 // 自动重装载寄存器,控制PWM周期

    PWMB_CCER1  = 0;
    PWMB_CCER2  = 0;
    PWMB_SR1    = 0;
    PWMB_SR2    = 0;
    PWMB_ENO    = 0;
    PWMB_PS     = 0;
    PWMB_IER    = 0;
    PWMB_CR1    = 0;

    PWMB_CCR4   = 14582;                 // 比较匹配值: 输出脉宽 = 2000 - 1750 = 250
    PWMB_CCMR4  = (7 << 4) + 8;         // 通道4 PWM模式2 + 允许CCR预装载

    PWMB_CCER2 |= 0x50;                 // 使能通道4输出, 高电平有效 (CH4P=0, CH4E=1)
   
    PWMB_PS    |= (1 << 6);             // 选择P3.4作为PWM输出引脚(bit7:6 = 01)
    PWMB_ENO   |= 0x40;                 // 允许通道4输出到IO (bit6: ENO8P)

    PWMB_BKR    = 0x80;                 // 主输出使能(MOE=1)
    PWMB_CR1   |= 0x08;                 // 单脉冲模式(OPM=1)
}


// 主函数
void main(void)
{
    P_SW2 |= 0x80;      // 允许XFR访问

    // 引脚初始化
    P3M0 = (P3M0 & ~0x84) | 0x10; P3M1 = (P3M1 & ~0x10) | 0x84;     // P32 37 高阻输入  P34 推挽输出

    Pulse = 0;

    // 函数初始化
    CMP_Init();
    PWMB_config();
   
    // 主循环
    while (1)
    {
        bit now_cmp = CMPCR1 & 0x01;  // 读取比较器结果(1=V+>V?,0=V+<V?)

        //------------------ 去抖判断 ------------------
        if (now_cmp == cmp_filtered)
        {
            stable_cnt = 0;  // 状态稳定,不计数
        }
        else if (++stable_cnt > 3)
        {
            cmp_filtered = now_cmp;   // 确认状态改变
            stable_cnt = 0;
        }

        //------------------ 主逻辑 ------------------
        if (cmp_filtered == 0)
        {
            // 电压 < 1.19V
            static unsigned char low_cnt = 0;

            if (!trigger_lock)
            {
                // 连续三次低电平确认后触发一次
                if (++low_cnt >= 3)
                {
                    PWMB_CCER2 |= 0x10;         // 重新启用CH2输出
                    PWMB_CR1 |= 0x01;           // 触发一次单脉冲输出

                    PWMB_CCER2 &= ~0x10;        // 关闭CH2输出
                    Pulse = 0;                  // 输出脚保持低电平

                    trigger_lock = 1;           // 锁住,不再重复触发
                    low_cnt = 0;
                }
            }
            else
            {
                low_cnt = 0; // 已锁定期间不计数
            }
        }
        else // cmp_filtered == 1
        {
            // 电压 > 1.19V
            PWMB_CCER2 &= ~0x10;                // 关闭CH2输出
            PWMB_ENO   |= 0x00;
            Pulse = 0;                          // 输出脚保持低电平
            trigger_lock = 0;                   // 解锁允许下次触发
        }
    }
}


// 中断服务函数




现在发现一个问题

当我cmp_filtered = 0的时候 打完一个脉冲 Pulse 就是低电平了 这是我需要的
而当cmp_filtered = 1的时候 应该也是强制拉低的状态 但是现在拉不低 是还需要配置哪个寄存器才能让Pulse 引脚脱离PWMB模块吗?



回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:225
  • 最近打卡:2025-11-01 08:22:10

792

主题

1万

回帖

2万

积分

管理员

积分
20133
发表于 7 天前 | 显示全部楼层
截图202510251150264707.jpg
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:34
  • 最近打卡:2025-10-30 10:47:29
已绑定手机

20

主题

67

回帖

209

积分

中级会员

积分
209
发表于 7 天前 | 显示全部楼层
按照AI的方案改了一下
发现还是电压高于比较器的参考电压1.19的时候 会检测到P34为高电平(此处应该是低电平)
低于1.19的时候会发送一次脉冲 然后低电平
截图202510251151341985.jpg
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:34
  • 最近打卡:2025-10-30 10:47:29
已绑定手机

20

主题

67

回帖

209

积分

中级会员

积分
209
发表于 7 天前 | 显示全部楼层
  1. // 主函数
  2. void main(void)
  3. {
  4.     P_SW2 |= 0x80;      // 允许XFR访问
  5.     // 引脚初始化
  6.     P3M0 = (P3M0 & ~0x84) | 0x10; P3M1 = (P3M1 & ~0x10) | 0x84;     // P32 37 高阻输入  P34 推挽输出
  7.     Pulse = 0;
  8.     // 函数初始化
  9.     CMP_Init();
  10.     PWMB_config();
  11.    
  12.     // 主循环
  13.     while (1)
  14.     {
  15.         bit now_cmp = CMPCR1 & 0x01;  // 读取比较器结果(1=V+>V?,0=V+<V?)
  16.         //------------------ 去抖判断 ------------------
  17.         if (now_cmp == cmp_filtered)
  18.         {
  19.             stable_cnt = 0;  // 状态稳定,不计数
  20.         }
  21.         else if (++stable_cnt > 3)
  22.         {
  23.             cmp_filtered = now_cmp;   // 确认状态改变
  24.             stable_cnt = 0;
  25.         }
  26.         //------------------ 主逻辑 ------------------
  27.         if (cmp_filtered == 0)
  28.         {
  29.             // 电压 < 1.19V
  30.             static unsigned char low_cnt = 0;
  31.             if (!trigger_lock)
  32.             {
  33.                 // 连续三次低电平确认后触发一次
  34.                 if (++low_cnt >= 3)
  35.                 {
  36.                     PWMB_ENO   |= 0x40;                 // 允许通道4输出到IO (bit6: ENO8P)
  37.                     PWMB_CR1 |= 0x01;                        // 触发一次单脉冲输出
  38.                     PWMB_ENO &= ~0x40;                  // 清除 bit6,使通道4输出禁止
  39.                     P3M1 &= ~0x10;                      // 设置为输出模式
  40.                     P3M0 |=  0x10;
  41.                     Pulse = 0;                          // 输出低电平               
  42.                     trigger_lock = 1;                   // 锁住,不再重复触发
  43.                     low_cnt = 0;
  44.                 }
  45.             }
  46.             else
  47.             {
  48.                 low_cnt = 0; // 已锁定期间不计数
  49.             }
  50.         }
  51.         else // cmp_filtered == 1
  52.         {
  53.             // 电压 > 1.19V
  54.             PWMB_ENO &= ~0x40;                          // 清除 bit6,使通道4输出禁止
  55.             P3M1 &= ~0x10;                              // 设置为输出模式
  56.             P3M0 |=  0x10;
  57.             Pulse = 0;                                  // 输出低电平
  58.             trigger_lock = 0;                           // 解锁允许下次触发
  59.         }
  60.     }
  61. }
复制代码



这样么
我改了一下ENO

但还是当高于1.19的时候输出高电平
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:225
  • 最近打卡:2025-11-01 08:22:10

792

主题

1万

回帖

2万

积分

管理员

积分
20133
发表于 7 天前 | 显示全部楼层
截图202510251246444216.jpg
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:34
  • 最近打卡:2025-10-30 10:47:29
已绑定手机

20

主题

67

回帖

209

积分

中级会员

积分
209
发表于 7 天前 | 显示全部楼层

两个方案都不行
高于1.19的时候直接强制输出无效电平
也会直接高电平了
  1. // 方案003
  2. /*
  3. 配置说明:
  4. 比较器电平:
  5. 0表示 正输入 小于 负输入
  6. 1表示 正输入 大于 负输入
  7. */
  8. // 头文件
  9. #include "STC8Hxxx.h"
  10. // 引脚定义
  11. sbit OUT_INT0 = P3^2;   // 外部中断0输入引脚
  12. sbit Pulse = P3^4;      // PWM脉冲输出引脚
  13. sbit CMP   = P3^7;      // 比较器正输入端
  14. // 宏定义
  15. #define MAIN_Fosc 35000000L     // 35MHz主频
  16. // 声明
  17. // 数组
  18. // 函数
  19. // 变量
  20. bit cmp_filtered = 1;           // 当前比较器稳定状态
  21. bit trigger_lock = 0;           // 锁存标志:0=允许触发,1=已触发等待解锁
  22. u8 stable_cnt = 0;
  23. // 函数模块
  24. // 比较器初始化
  25. void CMP_Init(void)
  26. {
  27.     CMPEXCFG = 0x00;
  28.     CMPEXCFG |= 0x00;   // P3.7 为 CMP+ 输入脚
  29.     CMPEXCFG |= 0x04;   // 内部 1.19V 参考为 CMP?
  30.     P_SW2 &= 0x7F;      // 禁止XFR访问
  31.     CMPCR2 = 0x00;
  32.     CMPCR2 &= ~0x80;    // 输出不反向
  33.     CMPCR2 &= ~0x40;    // 使能0.1us滤波
  34.     CMPCR2 |= 0x10;     // 输出结果经过16个去抖时钟稳定输出
  35.     CMPCR1 = 0x00;
  36.     CMPCR1 |= 0x02;     // 输出使能
  37.     CMPCR1 |= 0x80;     // 比较器模块使能
  38. }
  39. // PWMB脉冲配置
  40. void PWMB_config(void)
  41. {
  42.     PWMB_PSCR   = 11;                   // 预分频寄存器, Fpwm = SYSclk / ((PSCR+1)*(ARR+1))
  43.     PWMB_DTR    = 0;                    // 死区时间配置
  44.     PWMB_ARR    = 29165;                 // 自动重装载寄存器,控制PWM周期
  45.     PWMB_CCER1  = 0;
  46.     PWMB_CCER2  = 0;
  47.     PWMB_SR1    = 0;
  48.     PWMB_SR2    = 0;
  49.     PWMB_ENO    = 0;
  50.     PWMB_PS     = 0;
  51.     PWMB_IER    = 0;
  52.     PWMB_CR1    = 0;
  53.     PWMB_CCR4   = 14582;                 // 比较匹配值: 输出脉宽 = 2000 - 1750 = 250
  54.     PWMB_CCMR4  = (7 << 4) + 8;         // 通道4 PWM模式2 + 允许CCR预装载
  55.     PWMB_CCER2 |= 0x50;                 // 使能通道4输出, 高电平有效 (CH4P=0, CH4E=1)
  56.    
  57.     PWMB_PS    |= (1 << 6);             // 选择P3.4作为PWM输出引脚(bit7:6 = 01)
  58.     PWMB_ENO   |= 0x40;                 // 允许通道4输出到IO (bit6: ENO8P)
  59.     PWMB_BKR    = 0x80;                 // 主输出使能(MOE=1)
  60.     PWMB_CR1   |= 0x08;                 // 单脉冲模式(OPM=1)
  61. }
  62. // 主函数
  63. void main(void)
  64. {
  65.     P_SW2 |= 0x80;      // 允许XFR访问
  66.     // 引脚初始化
  67.     P3M0 = (P3M0 & ~0x84) | 0x10; P3M1 = (P3M1 & ~0x10) | 0x84;     // P32 37 高阻输入  P34 推挽输出
  68.     Pulse = 0;
  69.     // 函数初始化
  70.     CMP_Init();
  71.     PWMB_config();
  72.    
  73.     // 主循环
  74.     while (1)
  75.     {
  76.         bit now_cmp = CMPCR1 & 0x01;  // 读取比较器结果(1=V+>V?,0=V+<V?)
  77.         //------------------ 去抖判断 ------------------
  78.         if (now_cmp == cmp_filtered)
  79.         {
  80.             stable_cnt = 0;  // 状态稳定,不计数
  81.         }
  82.         else if (++stable_cnt > 3)
  83.         {
  84.             cmp_filtered = now_cmp;   // 确认状态改变
  85.             stable_cnt = 0;
  86.         }
  87.         //------------------ 主逻辑 ------------------
  88.         if (cmp_filtered == 0)
  89.         {
  90.             // 电压 < 1.19V
  91.             static unsigned char low_cnt = 0;
  92.             if (!trigger_lock)
  93.             {
  94.                 // 连续三次低电平确认后触发一次
  95.                 if (++low_cnt >= 3)
  96.                 {
  97.                     PWMB_ENO   |= 0x40;                 // 允许通道4输出到IO (bit6: ENO8P)
  98.                     PWMB_CR1 |= 0x01;                        // 触发一次单脉冲输出
  99.                     PWMB_CCMR1 |= 0x40;                         // 强制输出无效电平0%              
  100.                     trigger_lock = 1;                   // 锁住,不再重复触发
  101.                     low_cnt = 0;
  102.                 }
  103.             }
  104.             else
  105.             {
  106.                 low_cnt = 0; // 已锁定期间不计数
  107.             }
  108.         }
  109.         else // cmp_filtered == 1
  110.         {
  111.             // 电压 > 1.19V
  112.             PWMB_CCMR1 |= 0x40;                         // 强制输出无效电平0%
  113.             trigger_lock = 0;                           // 解锁允许下次触发
  114.         }
  115.     }
  116. }
  117. // 中断服务函数
复制代码
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:544
  • 最近打卡:2025-10-31 09:14:02
已绑定手机

48

主题

2300

回帖

8120

积分

论坛元老

积分
8120
发表于 7 天前 | 显示全部楼层
HyunYon*** 发表于 2025-10-25 13:10
两个方案都不行
高于1.19的时候直接强制输出无效电平
也会直接高电平了

将PWMx_ENO对应通道关闭后就可以使用IO口方式输出高低电平
  1. #define ENO5P       0x01
  2. #define ENO6P       0x04
  3. #define ENO7P       0x10
  4. #define ENO8P       0x40
  5.                         if(P34 == 0)
  6.                         {
  7.                                 PWMB_ENO &= ~ENO5P; //关闭输出
  8.                                 PWMB_ENO &= ~ENO6P; //关闭输出
  9.                                 P20 = 0; //输出低电平
  10.                                 P21 = 0; //输出低电平
  11.                         }
  12.                         if(P35 == 0)
  13.                         {
  14.                                 PWMB_ENO |= ENO5P; //使能输出
  15.                                 PWMB_ENO |= ENO6P; //使能输出
  16.                         }
复制代码
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:34
  • 最近打卡:2025-10-30 10:47:29
已绑定手机

20

主题

67

回帖

209

积分

中级会员

积分
209
发表于 7 天前 | 显示全部楼层
乘风*** 发表于 2025-10-25 14:08
将PWMx_ENO对应通道关闭后就可以使用IO口方式输出高低电平

好的哥 我试一下
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:34
  • 最近打卡:2025-10-30 10:47:29
已绑定手机

20

主题

67

回帖

209

积分

中级会员

积分
209
发表于 7 天前 | 显示全部楼层
乘风*** 发表于 2025-10-25 14:08
将PWMx_ENO对应通道关闭后就可以使用IO口方式输出高低电平
  1. // 方案003
  2. /*
  3. 配置说明:
  4. 比较器电平:
  5. 0表示 正输入 小于 负输入
  6. 1表示 正输入 大于 负输入
  7. */
  8. // 头文件
  9. #include "STC8Hxxx.h"
  10. // 引脚定义
  11. sbit OUT_INT0 = P3^2;   // 外部中断0输入引脚
  12. sbit Pulse = P3^4;      // PWM脉冲输出引脚
  13. sbit CMP   = P3^7;      // 比较器正输入端
  14. // 宏定义
  15. #define MAIN_Fosc 35000000L     // 35MHz主频
  16. #define ENO5P       0x01
  17. #define ENO6P       0x04
  18. #define ENO7P       0x10
  19. #define ENO8P       0x40
  20. // 声明
  21. // 数组
  22. // 函数
  23. // 变量
  24. bit cmp_filtered = 1;           // 当前比较器稳定状态
  25. bit trigger_lock = 0;           // 锁存标志:0=允许触发,1=已触发等待解锁
  26. u8 stable_cnt = 0;
  27. // 函数模块
  28. // 比较器初始化
  29. void CMP_Init(void)
  30. {
  31.     CMPEXCFG = 0x00;
  32.     CMPEXCFG |= 0x00;   // P3.7 为 CMP+ 输入脚
  33.     CMPEXCFG |= 0x04;   // 内部 1.19V 参考为 CMP?
  34.     P_SW2 &= 0x7F;      // 禁止XFR访问
  35.     CMPCR2 = 0x00;
  36.     CMPCR2 &= ~0x80;    // 输出不反向
  37.     CMPCR2 &= ~0x40;    // 使能0.1us滤波
  38.     CMPCR2 |= 0x10;     // 输出结果经过16个去抖时钟稳定输出
  39.     CMPCR1 = 0x00;
  40.     CMPCR1 |= 0x02;     // 输出使能
  41.     CMPCR1 |= 0x80;     // 比较器模块使能
  42. }
  43. // PWMB脉冲配置
  44. void PWMB_config(void)
  45. {
  46.     PWMB_PSCR   = 11;                   // 预分频寄存器, Fpwm = SYSclk / ((PSCR+1)*(ARR+1))
  47.     PWMB_DTR    = 0;                    // 死区时间配置
  48.     PWMB_ARR    = 29165;                // 自动重装载寄存器,控制PWM周期
  49.     PWMB_CCER1  = 0;
  50.     PWMB_CCER2  = 0;
  51.     PWMB_SR1    = 0;
  52.     PWMB_SR2    = 0;
  53.     PWMB_ENO    = 0;
  54.     PWMB_PS     = 0;
  55.     PWMB_IER    = 0;
  56.     PWMB_CR1    = 0;
  57.     PWMB_CCR4   = 14582;                // 比较匹配值: 输出脉宽 = 2000 - 1750 = 250
  58.     PWMB_CCMR4  = (7 << 4) + 8;         // 通道4 PWM模式2 + 允许CCR预装载
  59.     PWMB_CCER2 |= 0x50;                 // 使能通道4输出, 高电平有效 (CH4P=0, CH4E=1)
  60.    
  61.     PWMB_PS    |= (1 << 6);             // 选择P3.4作为PWM输出引脚(bit7:6 = 01)
  62.     PWMB_ENO   |= 0x40;                 // 允许通道4输出到IO (bit6: ENO8P)
  63.     PWMB_BKR    = 0x80;                 // 主输出使能(MOE=1)
  64.     PWMB_CR1   |= 0x08;                 // 单脉冲模式(OPM=1)
  65. }
  66. // 主函数
  67. void main(void)
  68. {
  69.     P_SW2 |= 0x80;      // 允许XFR访问
  70.     // 引脚初始化
  71.     P3M0 = (P3M0 & ~0x84) | 0x10; P3M1 = (P3M1 & ~0x10) | 0x84;         // P32 37 高阻输入  P34 推挽输出
  72.     Pulse = 0;
  73.     // 函数初始化
  74.     CMP_Init();
  75.     PWMB_config();
  76.    
  77.     // 主循环
  78.     while (1)
  79.     {
  80.         bit now_cmp = CMPCR1 & 0x01;                    // 读取比较器结果(1=V+>V?,0=V+<V?)
  81.         //------------------ 去抖判断 ------------------
  82.         if (now_cmp == cmp_filtered)
  83.         {
  84.             stable_cnt = 0;                             // 状态稳定,不计数
  85.         }
  86.         else if (++stable_cnt > 3)
  87.         {
  88.             cmp_filtered = now_cmp;                     // 确认状态改变
  89.             stable_cnt = 0;
  90.         }
  91.         //------------------ 主逻辑 ------------------
  92.         if (cmp_filtered == 0)
  93.         {
  94.             // 电压 < 1.19V
  95.             static unsigned char low_cnt = 0;
  96.             if (!trigger_lock)
  97.             {
  98.                 // 连续三次低电平确认后触发一次
  99.                 if (++low_cnt >= 3)
  100.                 {
  101.                     PWMB_ENO   |= 0x40;                 // 允许通道4输出到IO (bit6: ENO8P)
  102.                     PWMB_CR1 |= 0x01;                        // 触发一次单脉冲输出
  103.                     PWMB_ENO &= ~ENO8P;                 // 关闭输出
  104.                     Pulse = 0;
  105.                     trigger_lock = 1;                   // 锁住,不再重复触发
  106.                     low_cnt = 0;
  107.                 }
  108.             }
  109.             else
  110.             {
  111.                 low_cnt = 0;                            // 已锁定期间不计数
  112.             }
  113.         }
  114.         else                                            // cmp_filtered == 1
  115.         {
  116.             // 电压 > 1.19V
  117.             PWMB_ENO &= ~ENO8P;                         // 关闭输出
  118.             Pulse = 0;
  119.             trigger_lock = 0;                           // 解锁允许下次触发
  120.         }
  121.     }
  122. }
  123. // 中断服务函数
复制代码




我现在是这样写的
但是实际检测的时候发现高于1.19的时候还是高电平
而且我判断有可能低1.19的时候有可能拉低电平也没有起作用 而仅仅只是因为脉冲刚好在低电平结束 所以持续低于的状态
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:34
  • 最近打卡:2025-10-30 10:47:29
已绑定手机

20

主题

67

回帖

209

积分

中级会员

积分
209
发表于 7 天前 | 显示全部楼层

这是最新回复的测试结果
回复

使用道具 举报 送花

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

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-11-1 22:13 , Processed in 0.128347 second(s), 101 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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