找回密码
 立即注册
查看: 159|回复: 7

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

[复制链接]
  • 打卡等级:以坛为家II
  • 打卡总天数:593
  • 最近打卡:2025-10-15 11:02:35

49

主题

189

回帖

2477

积分

金牌会员

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

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

我把这个代码融合到示波器源码中时却无法工作,表现为背光闪烁式通电而且表现的亮度设定也不对,请高手指点下,如何才能实现我的想法。
融合后的代码如下:
  1. <blockquote>// 函数: void PWMB_config(void)
复制代码
  1. // 函数: void PWMB_config(void)
  2. // 描述: PWMB初始化函数.
  3. // 参数: none.
  4. // 返回: none.
  5. // 版本: V1.0, 2022-6-25
  6. //========================================================================
  7. void PWMB_config(void)
  8. {
  9.         u8        ccer1;
  10.         u8        ccer2;
  11.         u8        ps;
  12.         u8        eno;
  13.         u8        PWMB_ISR_En;
  14.         P_SW2 |= 0x80;                //SFR enable   
  15.         PWMB_ENO    = 0;        // IO输出禁止
  16.         PWMB_IER    = 0;        // 禁止中断
  17.         PWMB_SR1    = 0;        // 清除状态
  18.         PWMB_SR2    = 0;        // 清除状态
  19.         ccer1 = 0;
  20.         ccer2 = 0;
  21.         ps    = 0;
  22.         eno   = 0;
  23.         PWMB_ISR_En = 0;
  24.         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).
  25.         PWMB_PSCRL = (u8)((35000-1)%256);
  26.         PWMB_ARRH  = (u8)(1010/256);        // 自动重装载寄存器,  控制PWM周期
  27.         PWMB_ARRL  = (u8)(1010%256);
  28.         PWMB_CCMR3  = 0x68;                // 通道模式配置, PWM模式1, 预装载允许
  29.         PWMB_CCR7H  = (u8)(1000/256);        // 比较值, 控制占空比(高电平时钟数)
  30.         PWMB_CCR7L  = (u8)(1000%256);
  31.         ccer2 |= 0x05;                        // 开启比较输出, 高电平有效
  32.         ps    |= (1<<4);                // 选择IO, 0:选择P2.2, 1:选择P3.3, 2:选择P0.2, 3:选择P7.6,
  33.         eno   |= 0x10;                        // IO输出允许,  bit6: ENO8P, bit4: ENO7P,  bit2: ENO6P,  bit0: ENO5P
  34. //        PWMB_ISR_En|= 0x08;                // 使能中断
  35.         PWMB_CCER1  = ccer1;        // 捕获/比较使能寄存器1
  36.         PWMB_CCER2  = ccer2;        // 捕获/比较使能寄存器2
  37.         PWMB_PS     = ps;                // 选择IO
  38.         PWMB_IER    = PWMB_ISR_En;        //设置允许通道1~4中断处理
  39.         PWMB_BKR    = 0x80;                // 主输出使能 相当于总开关
  40.         PWMB_CR1    = 0x81;                // 使能计数器, 允许自动重装载寄存器缓冲, 边沿对齐模式, 向上计数,  bit7=1:写自动重装载寄存器缓冲(本周期不会被打扰), =0:直接写自动重装载寄存器本(周期可能会乱掉)
  41.         PWMB_EGR    = 0x01;                //产生一次更新事件, 清除计数器和预分频计数器, 装载预分频寄存器的值
  42.         PWMB_ENO    = eno;                // 允许IO输出
  43.         P3n_push_pull(1<<3);        //P3.3设置为推挽输出
  44. //以下是我添加的P7.7输出背光PWM控制初始化
  45.   PWMB_CCMR4 = 0x60;
  46.   PWMB_CCER2 |= 0x10;        //占空比赋值、duty越大背光越亮,0x30时duty越大背光越暗
  47.   PWMB_ARRH = 0x03;         //设置周期时间(赋值1023,35MHz时钟时脉冲频率约34KHz)
  48.   PWMB_ARRL = 0xff;
  49.   PWMB_ENO |= 0x40;         //使能P7.7输出
  50.   PWMB_PS |= 0xC0;                 //选择PWM8通道
  51.         P7n_push_pull(1<<7);        //P7.7设置为推挽输出
  52. }
  53. //        PWMB_PS   = (0<<6)+(0<<4)+(0<<2)+0;        //选择IO, 4项从高到低(从左到右)对应PWM8 PWM7 PWM6 PWM5
  54. //  PWMB_PS    PWM8    PWM7    PWM6    PWM5
  55. //    00       P2.3    P2.2    P2.1    P2.0
  56. //    01       P3.4    P3.3    P5.4    P1.7
  57. //    02       P0.3    P0.2    P0.1    P0.0
  58. //    03       P7.7    P7.6    P7.5    P7.4
复制代码


回复

使用道具 举报 送花

3

主题

1880

回帖

608

积分

等待验证会员

积分
608
发表于 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. 通道选择与引脚映射冲突

您在代码中使用了:
  1. c
  2. PWMBPS |= 0xC0; // 选择PWM8通道
复制代码

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

建议修改为:
  1. c
  2. PWMBPS &= ~0xC0; // 清除原有选择
  3. PWMBPS |= (channel > 8);
  4. PWMBCCR8L = (u8)duty;
复制代码

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

正确写法应为:
  1. c
  2. PWMBCCR7H = (u8)(duty >> 8);
  3. 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,确保所有通道周期一致:
  1. c
  2. PWMBARRH = 0x03;
  3. PWMBARRL = 0xFF;
复制代码

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

对每个通道分别配置:
  1. c
  2. // 通道7配置为PWM模式1
  3. PWMBCCMR7 &= ~0x60;
  4. PWMBCCMR7 |= 0x60;
  5. // 通道6配置为PWM模式1
  6. PWMBCCMR6 &= ~0x60;
  7. PWMBCCMR6 |= 0x60;
  8. // 使能输出
  9. PWMBENO |= 0x80; // 使能PWM7(P7.7)
  10. PWMBENO |= 0x40; // 使能PWM6(P7.6)
复制代码

4. 设置占空比函数
  1. c
  2. void SetPWM7Duty(u16 duty)
  3. {
  4.     PWMBCCR7H = (u8)(duty >> 8);
  5.     PWMBCCR7L = (u8)duty;
  6. }
  7. void SetPWM6Duty(u16 duty)
  8. {
  9.     PWMBCCR6H = (u8)(duty >> 8);
  10.     PWMBCCR6L = (u8)duty;
  11. }
复制代码

5. 启动定时器

最后启动定时器:
  1. c
  2. PWMBCR1 |= 0x81; // 使能预装载,启动计数器
复制代码

五、总结

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

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

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

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

祝您项目顺利!

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

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:208
  • 最近打卡:2025-10-15 11:03:15

787

主题

1万

回帖

1万

积分

管理员

积分
19768
发表于 2025-9-21 10:14:28 | 显示全部楼层
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:593
  • 最近打卡:2025-10-15 11:02:35

49

主题

189

回帖

2477

积分

金牌会员

积分
2477
发表于 2025-9-21 10:25:49 | 显示全部楼层
神*** 发表于 2025-9-21 10:14
I/O 要先 初始化 工作模式
https://www.stcaimcu.com/data/download/Datasheet/STC32G.pdf

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

点评

同一组PWM下,只能使用同一个PWM频率作为输出 如果你想要调整背光,可以试试使用PWMA的空闲通道,那里是64Khz的频率,对于调整光亮度来说足够了  详情 回复 发表于 2025-9-22 10:44
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:208
  • 最近打卡:2025-10-15 11:03:15

787

主题

1万

回帖

1万

积分

管理员

积分
19768
发表于 2025-9-21 10:31:37 | 显示全部楼层
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:593
  • 最近打卡:2025-10-15 11:02:35

49

主题

189

回帖

2477

积分

金牌会员

积分
2477
发表于 2025-9-21 10:42:55 | 显示全部楼层
神*** 发表于 2025-9-21 10:31
你用 AiCube 图形化配置 PWM, 用自动生成的程序做参考

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

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:591
  • 最近打卡:2025-10-15 09:49:21
已绑定手机
已实名认证

116

主题

2889

回帖

7364

积分

版主

积分
7364
发表于 2025-9-22 10:44:58 | 显示全部楼层
乐此*** 发表于 2025-9-21 10:25
多谢回复,根据楼上ai的回复我好像知道原因了,“共用一个自动重载寄存器(ARR),即所有通道共享同一个 ...

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

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:593
  • 最近打卡:2025-10-15 11:02:35

49

主题

189

回帖

2477

积分

金牌会员

积分
2477
发表于 2025-9-22 11:26:18 | 显示全部楼层
王*** 发表于 2025-9-22 10:44
同一组PWM下,只能使用同一个PWM频率作为输出
如果你想要调整背光,可以试试使用PWMA的空闲通道,那里是6 ...

多谢指点,在单片机引脚上焊飞线太费劲了,暂时解决的方法是去除了TFT-LCD底板上的背光开关S8050而后在其C、E焊盘上贴一个22欧的小电阻使背光电流降低到70mA左右凑合用着,等调试成功后重新打样板时再说吧。
回复

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-10-16 07:57 , Processed in 0.151824 second(s), 104 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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