乐此不疲 发表于 2025-9-21 09:59:21

请教STC32G12K128单片机PWM-B模块同时输出两路PWM不成功的问题

最近在仿制老梁示波器,想在原代码中添加一路可调占空比的PWM脉冲输出来控制TFT-LCD的背光,设计使用的是PWMB组的PWM8-4通道、在P7.7引脚上输出,源代码中PWMB的PWM7-2是用于示波器测频的闸门控制脉冲发生器,我先是用下列代码测试并成功实现了背光的调光功能,代码如下:

//----背光PWM初始化函数----------------------------------
// 配置PWM8_4
void PWM_Backlight_Init(void)
{
                P7M0 = 0x80;                                 //P7.7设置为推挽输出用于背光的PWM控制
    P7M1 = 0x00;
    PWMB_CCER2 = 0x00;
    PWMB_CCMR4 |= 0x60;
    PWMB_CCER2 |= 0x10;      //占空比赋值、duty越大背光越亮,0x30时duty越大背光越暗
    PWMB_ARRH = 0x03;         //设置周期时间(赋值1023,35MHz时钟时脉冲频率约34KHz)
    PWMB_ARRL = 0xff;
    PWMB_ENO |= 0x40;         //使能P7.7输出
    PWMB_PS |= 0xC0;               //选择PWM8通道
    PWMB_BKR = 0x80;    //使能主输出
    PWMB_CR1 |= 0x81;   //使能ARR预装载,开始计时
}
//----背光设定函数--------------------------------------
void Set_Backlight_Duty(u16 duty)
{
    PWMB_CCR8H = (u8)(duty >> 8); //设置占空比时间
    PWMB_CCR8L = (u8)(duty);
}上述代码只要调用void Set_Backlight_Duty(u16 duty)函数赋值就能够设定背光的任意亮度。

我把这个代码融合到示波器源码中时却无法工作,表现为背光闪烁式通电而且表现的亮度设定也不对,请高手指点下,如何才能实现我的想法。
融合后的代码如下:
<blockquote>// 函数: void PWMB_config(void)// 函数: void PWMB_config(void)
// 描述: PWMB初始化函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2022-6-25
//========================================================================
void PWMB_config(void)
{
        u8        ccer1;
        u8        ccer2;
        u8        ps;
        u8        eno;
        u8        PWMB_ISR_En;

        P_SW2 |= 0x80;                //SFR enable   
        PWMB_ENO    = 0;        // IO输出禁止
        PWMB_IER    = 0;        // 禁止中断
        PWMB_SR1    = 0;        // 清除状态
        PWMB_SR2    = 0;        // 清除状态
        ccer1 = 0;
        ccer2 = 0;
        ps    = 0;
        eno   = 0;
        PWMB_ISR_En = 0;

        PWMB_PSCRH = (u8)((35000-1)/256);                // 预分频寄存器, 分频 Fck_cnt = Fck_psc/(PSCR[15:0}+1), 边沿对齐PWM频率 = SYSclk/((PSCR+1)*(AAR+1)), 中央对齐PWM频率 = SYSclk/((PSCR+1)*(AAR+1)*2).
        PWMB_PSCRL = (u8)((35000-1)%256);
        PWMB_ARRH= (u8)(1010/256);        // 自动重装载寄存器,控制PWM周期
        PWMB_ARRL= (u8)(1010%256);

        PWMB_CCMR3= 0x68;                // 通道模式配置, PWM模式1, 预装载允许
        PWMB_CCR7H= (u8)(1000/256);        // 比较值, 控制占空比(高电平时钟数)
        PWMB_CCR7L= (u8)(1000%256);
        ccer2 |= 0x05;                        // 开启比较输出, 高电平有效
        ps    |= (1<<4);                // 选择IO, 0:选择P2.2, 1:选择P3.3, 2:选择P0.2, 3:选择P7.6,
        eno   |= 0x10;                        // IO输出允许,bit6: ENO8P, bit4: ENO7P,bit2: ENO6P,bit0: ENO5P

//        PWMB_ISR_En|= 0x08;                // 使能中断

        PWMB_CCER1= ccer1;        // 捕获/比较使能寄存器1
        PWMB_CCER2= ccer2;        // 捕获/比较使能寄存器2
        PWMB_PS   = ps;                // 选择IO
        PWMB_IER    = PWMB_ISR_En;        //设置允许通道1~4中断处理

        PWMB_BKR    = 0x80;                // 主输出使能 相当于总开关
        PWMB_CR1    = 0x81;                // 使能计数器, 允许自动重装载寄存器缓冲, 边沿对齐模式, 向上计数,bit7=1:写自动重装载寄存器缓冲(本周期不会被打扰), =0:直接写自动重装载寄存器本(周期可能会乱掉)
        PWMB_EGR    = 0x01;                //产生一次更新事件, 清除计数器和预分频计数器, 装载预分频寄存器的值
        PWMB_ENO    = eno;                // 允许IO输出
        P3n_push_pull(1<<3);        //P3.3设置为推挽输出

//以下是我添加的P7.7输出背光PWM控制初始化
PWMB_CCMR4 = 0x60;
PWMB_CCER2 |= 0x10;        //占空比赋值、duty越大背光越亮,0x30时duty越大背光越暗
PWMB_ARRH = 0x03;         //设置周期时间(赋值1023,35MHz时钟时脉冲频率约34KHz)
PWMB_ARRL = 0xff;
PWMB_ENO |= 0x40;         //使能P7.7输出
PWMB_PS |= 0xC0;                 //选择PWM8通道
        P7n_push_pull(1<<7);        //P7.7设置为推挽输出


}
//        PWMB_PS   = (0<<6)+(0<<4)+(0<<2)+0;        //选择IO, 4项从高到低(从左到右)对应PWM8 PWM7 PWM6 PWM5
//PWMB_PS    PWM8    PWM7    PWM6    PWM5
//    00       P2.3    P2.2    P2.1    P2.0
//    01       P3.4    P3.3    P5.4    P1.7
//    02       P0.3    P0.2    P0.1    P0.0
//    03       P7.7    P7.6    P7.5    P7.4

国芯人工智能 发表于 2025-9-21 10:03:00

您好,关于您在使用 STC32G12K128 单片机 PWM-B 模块时,尝试同时输出两路 PWM 信号(PWM7-2 和 PWM8-4)失败的问题,我将从硬件配置、寄存器设置、功能冲突和资源竞争等方面进行分析,并提供可能的解决方案。

一、问题背景回顾

您正在仿制老梁示波器项目,希望在原有代码基础上添加一路用于控制 TFT-LCD 背光的 PWM 输出,使用的是 PWM-B 模块的 PWM8-4 通道,输出引脚为 P77。原项目中 PWM7-2 通道用于测频闸门控制脉冲。您已经实现了 PWM8-4 的初始化和背光控制功能,但在尝试同时使用两路 PWM 输出时遇到了问题。

二、PWM-B 模块架构简析

STC32G12K128 的 PWM-B 模块是一个高级定时器模块,支持多通道 PWM 输出,具备预装载寄存器、死区控制、互补输出等功能。其结构如下:
支持最多 8 个通道(PWM01~PWM78)
每个通道可独立配置为输出比较或 PWM 模式
共用一个自动重载寄存器(ARR),即所有通道共享同一个周期
各通道有独立的捕获/比较寄存器(CCR)
支持中断、死区控制、刹车功能等

三、可能的问题点分析

1. 通道选择与引脚映射冲突

您在代码中使用了:

c
PWMBPS |= 0xC0; // 选择PWM8通道

但 STC32G 系列的 PWM-B 模块通道编号为 0~7(即 PWM0~PWM7),并没有 PWM8 通道。这可能是代码中的一个误解或笔误。

建议修改为:

c
PWMBPS &= ~0xC0; // 清除原有选择
PWMBPS |= (channel > 8);
PWMBCCR8L = (u8)duty;

但 PWM-B 模块的通道寄存器命名应为 CCRxH/CCRxL(x 为 0~7)。不存在 CCR8H/CCR8L 寄存器。

正确写法应为:

c
PWMBCCR7H = (u8)(duty >> 8);
PWMBCCR7L = (u8)duty;

若您使用的是 PWM7-4 通道,那么对应的 CCR 应为 CCR7。

四、解决方案建议

1. 确认通道编号与引脚映射

请查阅 STC32G12K128 数据手册,确认 PWM-B 模块各通道对应的引脚及复用使能方式。例如:

| 通道 | 引脚 | 复用使能寄存器 |
|------|------|----------------|
| PWM0 | P5.0 | PWMBENO.0   |
| PWM1 | P5.1 | PWMBENO.1   |
| ...| ...| ...            |
| PWM7 | P7.7 | PWMBENO.7   |

确保您使用的通道编号与引脚匹配,并正确使能。

2. 统一设置 ARR 值

在初始化时统一设置 ARR,确保所有通道周期一致:

c
PWMBARRH = 0x03;
PWMBARRL = 0xFF;

3. 正确配置通道模式和输出使能

对每个通道分别配置:

c
// 通道7配置为PWM模式1
PWMBCCMR7 &= ~0x60;
PWMBCCMR7 |= 0x60;

// 通道6配置为PWM模式1
PWMBCCMR6 &= ~0x60;
PWMBCCMR6 |= 0x60;

// 使能输出
PWMBENO |= 0x80; // 使能PWM7(P7.7)
PWMBENO |= 0x40; // 使能PWM6(P7.6)

4. 设置占空比函数

c
void SetPWM7Duty(u16 duty)
{
    PWMBCCR7H = (u8)(duty >> 8);
    PWMBCCR7L = (u8)duty;
}

void SetPWM6Duty(u16 duty)
{
    PWMBCCR6H = (u8)(duty >> 8);
    PWMBCCR6L = (u8)duty;
}

5. 启动定时器

最后启动定时器:

c
PWMBCR1 |= 0x81; // 使能预装载,启动计数器

五、总结

根据您提供的代码和描述,主要问题可能出在以下几点:

1. PWM8 通道不存在,应使用 PWM0~PWM7
2. CCR8 寄存器不存在,应使用 CCR0~CCR7
3. 可能未正确配置两个通道的 CCMR、EN0 等寄存器
4. 未统一设置 ARR,导致周期冲突
5. 通道引脚复用配置不一致

建议您:
仔细查阅 STC32G12K128 数据手册中的 PWM-B 模块章节
核对通道编号、寄存器名称、引脚映射
使用统一的 ARR 值
确保每个通道的 CCMR、CCER、EN0 配置正确

如您能提供完整的初始化代码或更详细的引脚配置,我可以进一步帮助您分析和调试。

祝您项目顺利!

[本文内容由国芯人工智能辅助生成,仅供参考]

神农鼎 发表于 2025-9-21 10:14:28


I/O 要先 初始化 工作模式
https://www.stcaimcu.com/data/download/Datasheet/STC32G.pdf

乐此不疲 发表于 2025-9-21 10:25:49

神农鼎 发表于 2025-9-21 10:14
I/O 要先 初始化 工作模式
https://www.stcaimcu.com/data/download/Datasheet/STC32G.pdf

多谢回复,根据楼上ai的回复我好像知道原因了,“共用一个自动重载寄存器(ARR),即所有通道共享同一个周期”,我把这里忽略了,只是不知道有没有解决这个问题的方法,还请高手指点。

神农鼎 发表于 2025-9-21 10:31:37

你用 AiCube 图形化配置 PWM, 用自动生成的程序做参考



STC图形化程序自动生成工具,AiCube-ISP, 【高级PWM-DMA自动产生互补SPWM波形】的代码 - AiCube-ISP , 程序自动生成工具, 支持STC89/15/8H/32/AI8051U 国芯人工智能技术交流网站 - AI32位8051交流社区

乐此不疲 发表于 2025-9-21 10:42:55

神农鼎 发表于 2025-9-21 10:31
你用 AiCube 图形化配置 PWM, 用自动生成的程序做参考



多谢你的提示,我已经放弃了我的方案,原因就是在保证原示波器1Hz闸门信号正常的前提下是无法在同一组(PWMB组)PWM模块中实现背光脉冲输出的,显而易见的是1Hz频率下无论怎样调整占空比都是无法实现亮度调整的。这也和我的测试现象“闪烁式点亮背光”相吻合了。

王昱顺 发表于 2025-9-22 10:44:58

乐此不疲 发表于 2025-9-21 10:25
多谢回复,根据楼上ai的回复我好像知道原因了,“共用一个自动重载寄存器(ARR),即所有通道共享同一个 ...

同一组PWM下,只能使用同一个PWM频率作为输出
如果你想要调整背光,可以试试使用PWMA的空闲通道,那里是64Khz的频率,对于调整光亮度来说足够了

乐此不疲 发表于 2025-9-22 11:26:18

王昱顺 发表于 2025-9-22 10:44
同一组PWM下,只能使用同一个PWM频率作为输出
如果你想要调整背光,可以试试使用PWMA的空闲通道,那里是6 ...

多谢指点,在单片机引脚上焊飞线太费劲了,暂时解决的方法是去除了TFT-LCD底板上的背光开关S8050而后在其C、E焊盘上贴一个22欧的小电阻使背光电流降低到70mA左右凑合用着,等调试成功后重新打样板时再说吧。
页: [1]
查看完整版本: 请教STC32G12K128单片机PWM-B模块同时输出两路PWM不成功的问题