HyunYong_7782 发表于 2025-10-25 11:27:18

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


// 方案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模块吗?



神农鼎 发表于 2025-10-25 11:50:51


HyunYong_7782 发表于 2025-10-25 11:52:54

按照AI的方案改了一下
发现还是电压高于比较器的参考电压1.19的时候 会检测到P34为高电平(此处应该是低电平)
低于1.19的时候会发送一次脉冲 然后低电平

HyunYong_7782 发表于 2025-10-25 12:03:49

神农鼎 发表于 2025-10-25 11:50


// 主函数
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_ENO   |= 0x40;               // 允许通道4输出到IO (bit6: ENO8P)
                  PWMB_CR1 |= 0x01;                      // 触发一次单脉冲输出

                  PWMB_ENO &= ~0x40;                  // 清除 bit6,使通道4输出禁止
                  P3M1 &= ~0x10;                      // 设置为输出模式
                  P3M0 |=0x10;
                  Pulse = 0;                        // 输出低电平               

                  trigger_lock = 1;                   // 锁住,不再重复触发
                  low_cnt = 0;
                }
            }
            else
            {
                low_cnt = 0; // 已锁定期间不计数
            }
      }
      else // cmp_filtered == 1
      {
            // 电压 > 1.19V
            PWMB_ENO &= ~0x40;                        // 清除 bit6,使通道4输出禁止
            P3M1 &= ~0x10;                              // 设置为输出模式
            P3M0 |=0x10;
            Pulse = 0;                                  // 输出低电平
            trigger_lock = 0;                           // 解锁允许下次触发
      }
    }
}


这样么
我改了一下ENO

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

神农鼎 发表于 2025-10-25 12:46:55


HyunYong_7782 发表于 2025-10-25 13:10:52

神农鼎 发表于 2025-10-25 12:46


两个方案都不行
高于1.19的时候直接强制输出无效电平
也会直接高电平了// 方案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_ENO   |= 0x40;               // 允许通道4输出到IO (bit6: ENO8P)
                  PWMB_CR1 |= 0x01;                      // 触发一次单脉冲输出

                  PWMB_CCMR1 |= 0x40;                         // 强制输出无效电平0%            

                  trigger_lock = 1;                   // 锁住,不再重复触发
                  low_cnt = 0;
                }
            }
            else
            {
                low_cnt = 0; // 已锁定期间不计数
            }
      }
      else // cmp_filtered == 1
      {
            // 电压 > 1.19V
            PWMB_CCMR1 |= 0x40;                         // 强制输出无效电平0%
            trigger_lock = 0;                           // 解锁允许下次触发
      }
    }
}


// 中断服务函数

乘风飞扬 发表于 2025-10-25 14:08:05

HyunYong_7782 发表于 2025-10-25 13:10
两个方案都不行
高于1.19的时候直接强制输出无效电平
也会直接高电平了
将PWMx_ENO对应通道关闭后就可以使用IO口方式输出高低电平

#define ENO5P       0x01
#define ENO6P       0x04
#define ENO7P       0x10
#define ENO8P       0x40

                        if(P34 == 0)
                        {
                              PWMB_ENO &= ~ENO5P; //关闭输出
                              PWMB_ENO &= ~ENO6P; //关闭输出
                              P20 = 0; //输出低电平
                              P21 = 0; //输出低电平
                        }
                        if(P35 == 0)
                        {
                              PWMB_ENO |= ENO5P; //使能输出
                              PWMB_ENO |= ENO6P; //使能输出
                        }

HyunYong_7782 发表于 2025-10-25 14:26:02

乘风飞扬 发表于 2025-10-25 14:08
将PWMx_ENO对应通道关闭后就可以使用IO口方式输出高低电平

好的哥 我试一下

HyunYong_7782 发表于 2025-10-25 18:32:55

乘风飞扬 发表于 2025-10-25 14:08
将PWMx_ENO对应通道关闭后就可以使用IO口方式输出高低电平

// 方案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主频

#define ENO5P       0x01
#define ENO6P       0x04
#define ENO7P       0x10
#define ENO8P       0x40
// 声明
// 数组
// 函数
// 变量
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_ENO   |= 0x40;               // 允许通道4输出到IO (bit6: ENO8P)
                  PWMB_CR1 |= 0x01;                      // 触发一次单脉冲输出

                  PWMB_ENO &= ~ENO8P;               // 关闭输出
                  Pulse = 0;

                  trigger_lock = 1;                   // 锁住,不再重复触发
                  low_cnt = 0;
                }
            }
            else
            {
                low_cnt = 0;                            // 已锁定期间不计数
            }
      }
      else                                          // cmp_filtered == 1
      {
            // 电压 > 1.19V
            PWMB_ENO &= ~ENO8P;                         // 关闭输出
            Pulse = 0;

            trigger_lock = 0;                           // 解锁允许下次触发
      }
    }
}


// 中断服务函数





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

HyunYong_7782 发表于 2025-10-25 18:34:30

"C:\Users\Administrator\Desktop\2a96f1d4430870ed9c85fc98386c9656.jpg""C:\Users\Administrator\Desktop\52da0eed6833e3250b37268fb928bbca.jpg"
这是最新回复的测试结果
页: [1] 2
查看完整版本: PWM脉冲引脚怎么转为普通IO拉低电平