STC PWMA通道2占空比无法改变?已经解决!理论理解错
这几天又跟着冲哥和布丁橘长学习了PWM发现一个怪现象:STC32G12K128的通道2,好像占空比不能改变?
看看下面这个呼吸灯:
#include <STC32G.H>
#include "config.h"
#define PWM_PSC (120-1) //120分频
#define PWM_PERIOD 1000 //周期10毫秒
void PWMA_Config(void); //PWMA初始化设置函数
void Update_duty(); //更新占空比函数
u16 duty; //占空比变量
bit updateduty; //占空比更新标志
bit blinkflag; //呼吸灯状态标志
void main(void)
{
EAXFR = 1; // 使能访问 XFR
CKCON = 0x00; // 设置外部数据总线速度为最快
WTST = 0x00; // 设置程序代码等待参数,等待时间为0个时钟,CPU执行程序速度最快
P0M1 = 0x00;P0M0 = 0x00; //设置P0口为准双向口模式 //00:准双向口 01:推挽输出 10:高阻输入 11:开漏输出
P1M1 = 0x00;P1M0 = 0x00; //设置P1口为准双向口模式 //00:准双向口 01:推挽输出 10:高阻输入 11:开漏输出
P2M1 = 0x00;P2M0 = 0x00; //设置P2口为准双向口模式 //00:准双向口 01:推挽输出 10:高阻输入 11:开漏输出
P3M1 = 0x00;P3M0 = 0x00; //设置P3口为准双向口模式 //00:准双向口 01:推挽输出 10:高阻输入 11:开漏输出
P4M1 = 0x00;P4M0 = 0x00; //设置P4口为准双向口模式 //00:准双向口 01:推挽输出 10:高阻输入 11:开漏输出
P5M1 = 0x00;P5M0 = 0x00; //设置P5口为准双向口模式 //00:准双向口 01:推挽输出 10:高阻输入 11:开漏输出
P6M1 = 0x00;P6M0 = 0x00; //设置P6口为准双向口模式 //00:准双向口 01:推挽输出 10:高阻输入 11:开漏输出
P7M1 = 0x00;P7M0 = 0x00; //设置P7口为准双向口模式 //00:准双向口 01:推挽输出 10:高阻输入 11:开漏输出
PWMA_Config(); //PWMA初始化设置
Update_duty(); //更新占空比
EA = 1; //使能EA总中断
duty = PWM_PERIOD; //初始占空比100%,LED熄灭
while (1)
{
Update_duty(); //循环执行占空比更新函数
}
}
void PWM_ISR() interrupt 26
{
if(PWMA_SR1 & 0x01) //PWM中断后,查询中断标志位,更新中断标志是否置1
{
PWMA_SR1 &= ~0x01; //清零更新中断标志位
if(blinkflag == 0) duty -= 10; //由暗到亮过程:duty-10
else if(blinkflag == 1) duty += 10; //有亮到暗过程:duty+10
if(duty >= 1000) blinkflag = 0; //防溢出周期1000
else if(duty <= 0) blinkflag = 1; //防溢出
updateduty = 1; //占空比更新标志置1
}
}
void PWMA_Config(void)
{
//PWMA_PS = 0x01; //PWM1P引脚切换到P2.0
PWMA_PS = 0x00; //通道1PWM1P引脚切换到P1.0,1N脚P1.1,通道2输出脚
//默认PWM2P脚P1.2,PWM2N脚P1.3
PWMA_PSCRH = (u16)(PWM_PSC >> 8);
PWMA_PSCRL = (u16)(PWM_PSC); //119+1=120预分频
PWMA_CCER1 = 0x00; //写 CCMRx 前必须先清零 CCERx 关闭通道cc1
PWMA_CCER2 = 0x00; //写 CCMRx 前必须先清零 CCERx 关闭通道cc3
PWMA_CCMR1 = 0x60; // 设置 CC1 为 PWMA 输出模式,PWM模式1
PWMA_CCMR2 = 0x60; // 设置 CC2 为 PWMA 输出模式,PWM模式1
//PWMA_CCER1 |= 0x01; // 使能 CC1 通道,01就只有单路输出P1.0
PWMA_CCER1 |= 0x05; // 使能 OC1 通道,开启输出比较通道,双路互补输出
PWMA_CCER2 |= 0x05; // 使能 OC2 通道,开启输出比较通道,双路互补输出
//PWMA_CCER1 |= 0x08; //加这句是启输出比较通道,把双路互补输出改双路同向输出
PWMA_CCER2 |= 0x08; //加这句是启输出比较通道,把双路互补输出改双路同向输出
//方便看到LED亮
PWMA_CCR1H = (u16)(PWM_PERIOD >> 8); // 设置初始占空比100%,LED熄灭
PWMA_CCR1L = (u16)(PWM_PERIOD);
PWMA_CCR2H = (u16)(PWM_PERIOD >> 8); // 设置初始占空比100%,LED熄灭
PWMA_CCR2L = (u16)(PWM_PERIOD);
PWMA_ARRH = (u16)(PWM_PERIOD >> 8); // 设置PWM周期
PWMA_ARRL = (u16)(PWM_PERIOD);
PWMA_ENO |= 0X01; //使能PWM1p通道输出(P1.0)
PWMA_ENO |= 0X02; //使能PWM1n通道输出(P1.1)
PWMA_ENO |= 0X10; //使能PWM2p通道输出(P1.2)
PWMA_ENO |= 0X20; //使能PWM2n通道输出(P1.3)
PWMA_BKR = 0x80; // 使能主输出
PWMA_IER = 0x01; // 使能更新中断
PWMA_CR1 = 0x01; // 启动PWM定时器,向上计数模式
}
void Update_duty() //更新占空比函数
{
PWMA_CCR1H = (u8)(duty >> 8);
PWMA_CCR1L = duty; //更新CC1通道占空比
PWMA_CCR2H = (u8)(duty >> 8);
PWMA_CCR2L = duty;
//更新CC2通道占空比
updateduty = 0; //占空比更新标志清零
}
上面黑体字的2句,好像完全不起作用,导致接在通道2的2个LED,不能象接着通道1上的2个LED一样可以呼吸
应该是原理上有没看到的地方?哪位大侠,帮手看看?
你的PWMA_CCER给错了,你用的ccer2是控制oc3和oc4的,需要使用 PWMA_CCER1 |= 0x50; //打开oc2通道使能 王昱顺 发表于 2025-11-1 14:20
你的PWMA_CCER给错了,你用的ccer2是控制oc3和oc4的,需要使用 PWMA_CCER1 |= 0x50; //打开oc2通道使能 ...
感谢您!
我改了这里:
PWMA_CCER1 |= 0x50; //打开oc2通道使能 ...
本来以为是第3和4个LED灯(P1.2P1.3)是呼吸灯的,结果不是,是多了一个第6个LED灯成了呼吸灯,但是也不对啊
PWMA_CCER1 = 0x00; //写 CCMRx 前必须先清零 CCERx 关闭通道cc1
PWMA_CCER2 = 0x00; //写 CCMRx 前必须先清零 CCERx 关闭通道cc3
PWMA_CCMR1 = 0x60; // 设置 CC1 为 PWMA 输出模式,PWM模式1
PWMA_CCMR2 = 0x60; // 设置 CC3 为 PWMA 输出模式,PWM模式1
这里PWMA_CCMR2 = 0x60;肯定也是理解错误的产物,但是把他们删除了,第6个LED灯灭了,第3和4个LED灯(P1.2P1.3)也没有反应.....手册也没看明白!
void PWMA_Config(void)
{
//PWMA_PS = 0x01; //PWM1P引脚切换到P2.0
PWMA_PS = 0x00; //通道1PWM1P引脚切换到P1.0,1N脚P1.1,通道2输出脚
//默认PWM2P脚P1.2,PWM2N脚P1.3
PWMA_PSCRH = (u16)(PWM_PSC >> 8);
PWMA_PSCRL = (u16)(PWM_PSC); //119+1=120预分频
PWMA_CCR1H = (u16)(PWM_PERIOD >> 8); // 设置初始占空比100%,LED熄灭
PWMA_CCR1L = (u16)(PWM_PERIOD);
PWMA_ARRH = (u16)(PWM_PERIOD >> 8); // 设置PWM周期
PWMA_ARRL = (u16)(PWM_PERIOD);
PWMA_CCER1 = 0x00; //写 CCMRx 前必须先清零 CCERx 关闭通道cc1
PWMA_CCER2 = 0x00; //写 CCMRx 前必须先清零 CCERx 关闭通道cc3
PWMA_CCMR1 = 0x60; // 设置 CC1 为 PWMA 输出模式,PWM模式1
PWMA_CCMR2 = 0x60; // 设置 CC3 为 PWMA 输出模式,PWM模式1
//PWMA_CCER1 |= 0x01; // 使能 CC1 通道,01就只有单路输出P1.0
PWMA_CCER1 |= 0x05; // 使能 OC1 通道,开启输出比较通道,双路互补输出
PWMA_CCER1 |= 0x50; // //打开oc2通道使能,开启输出比较通道,双路互补输出
//PWMA_CCER1 |= 0x08; //加这句是启输出比较通道,把双路互补输出改双路同向输出
//PWMA_CCER2 |= 0x08; //加这句是启输出比较通道,把双路互补输出改双路同向输出
//方便看到LED亮
PWMA_ENO |= 0X0F; //使能PWM2n通道输出(P1.0---P1.3)
PWMA_BKR = 0x80; // 使能主输出
PWMA_IER = 0x01; // 使能更新中断
PWMA_CR1 = 0x01; // 启动PWM定时器,向上计数模式
}
2句黑色的肯定是错的,通道1是可以正常运行的,按道理我们加了:
PWMA_CCER1 |= 0x50; // //打开oc2通道使能,开启输出比较通道,双路互补输出
PWMA_ENO |= 0X0F; //使能PWM2n通道输出(P1.0---P1.3)
再加上默认:
PWMA_PS = 0x00; //通道1PWM1P引脚切换到P1.0,1N脚P1.1,通道2输出脚
//默认PWM2P脚P1.2,PWM2N脚P1.3
应该P0---P3这4个LED都是呼吸灯啊?我不知道哪里没有设置对。。。。。。。。。。。
先改回去通道3:
void PWMA_Config(void)
{
//PWMA_PS = 0x01; //PWM1P引脚切换到P2.0
PWMA_PS = 0x00; //通道1PWM1P引脚切换到P1.0,1N脚P1.1,通道2输出脚
//默认PWM2P脚P1.2,PWM2N脚P1.3
PWMA_PSCRH = (u16)(PWM_PSC >> 8);
PWMA_PSCRL = (u16)(PWM_PSC); //119+1=120预分频
PWMA_CCR1H = (u16)(PWM_PERIOD >> 8); // 设置初始占空比100%,LED熄灭
PWMA_CCR1L = (u16)(PWM_PERIOD);
PWMA_ARRH = (u16)(PWM_PERIOD >> 8); // 设置PWM周期
PWMA_ARRL = (u16)(PWM_PERIOD);
PWMA_CCER1 = 0x00; //写 CCMRx 前必须先清零 CCERx 关闭通道cc1
PWMA_CCER2 = 0x00; //写 CCMRx 前必须先清零 CCERx 关闭通道cc3
PWMA_CCMR1 = 0x60; // 设置 CC1 为 PWMA 输出模式,PWM模式1
PWMA_CCMR3 = 0x60; // 设置 CC3 为 PWMA 输出模式,PWM模式1
//PWMA_CCER1 |= 0x01; // 使能 CC1 通道,01就只有单路输出P1.0
PWMA_CCER1 |= 0x05; // 使能 OC1 通道,开启输出比较通道,双路互补输出
PWMA_CCER2 |= 0x05; // //打开oc3通道使能,开启输出比较通道,双路互补输出
//PWMA_CCER1 |= 0x08; //加这句是启输出比较通道,把双路互补输出改双路同向输出
PWMA_CCER2 |= 0x08; //加这句是启输出比较通道,把双路互补输出改双路同向输出
//方便看到LED亮
PWMA_ENO |= 0X33; //使能PWM2n通道输出(P1.0---P1.3)
PWMA_BKR = 0x80; // 使能主输出
PWMA_IER = 0x01; // 使能更新中断
PWMA_CR1 = 0x01; // 启动PWM定时器,向上计数模式
}
这样就是P10P11的LED正常呼吸灯,P12P13就长亮,不会呼吸.....但灯的位置是对的
void PWMA_Config(void)
{
//PWMA_PS = 0x01; //PWM1P引脚切换到P2.0
PWMA_PS = 0x00; //通道1PWM1P引脚切换到P1.0,1N脚P1.1,通道2输出脚
//默认PWM2P脚P1.2,PWM2N脚P1.3
PWMA_PSCRH = (u16)(PWM_PSC >> 8);
PWMA_PSCRL = (u16)(PWM_PSC); //119+1=120预分频
PWMA_CCR1H = (u16)(PWM_PERIOD >> 8); // 设置初始占空比100%,LED熄灭
PWMA_CCR1L = (u16)(PWM_PERIOD);
PWMA_CCR3H = (u8)(duty >> 8);
PWMA_CCR3L = duty;
PWMA_ARRH = (u16)(PWM_PERIOD >> 8); // 设置PWM周期
PWMA_ARRL = (u16)(PWM_PERIOD);
PWMA_CCER1 = 0x00; //写 CCMRx 前必须先清零 CCERx 关闭通道cc1
PWMA_CCER2 = 0x00; //写 CCMRx 前必须先清零 CCERx 关闭通道cc3
PWMA_CCMR1 = 0x60; // 设置 CC1 为 PWMA 输出模式,PWM模式1
PWMA_CCMR3 = 0x60; // 设置 CC3 为 PWMA 输出模式,PWM模式1
//PWMA_CCER1 |= 0x01; // 使能 CC1 通道,01就只有单路输出P1.0
PWMA_CCER1 |= 0x05; // 使能 OC1 通道,开启输出比较通道,双路互补输出
PWMA_CCER2 |= 0x05; // //打开oc3通道使能,开启输出比较通道,双路互补输出
//PWMA_CCER1 |= 0x08; //加这句是启输出比较通道,把双路互补输出改双路同向输出
//PWMA_CCER2 |= 0x08; //加这句是启输出比较通道,把双路互补输出改双路同向输出
//方便看到LED亮
PWMA_ENO |= 0X33; //使能PWM2n通道输出(P1.0---P1.3)
PWMA_BKR = 0x80; // 使能主输出
PWMA_IER = 0x01; // 使能更新中断
PWMA_CR1 = 0x01; // 启动PWM定时器,向上计数模式
}
void Update_duty() //更新占空比函数
{
PWMA_CCR1H = (u8)(duty >> 8);
PWMA_CCR1L = duty; //更新CC1通道占空比
PWMA_CCR3H = (u8)(duty >> 8);
PWMA_CCR3L = duty;
//更新CC2通道占空比
updateduty = 0; //占空比更新标志清零
}
好像这样就可以,但我只能用通道1和通道3
实际应该是用通道1+通道2更加方便的,但是我不会设置通道2 ...........,哪位大侠指导一下?万分感谢!
但是实际是有问题的:
PWMA_PS = 0x00;
现在发现通道2和通道3的默认脚位错乱了:
我现在是用通道3,应该默认脚位是P1.4P1.5
但实际上LED是在P1.2P1.3上工作
//PWMA_PS = 0x01; //PWM1P引脚切换到P2.0
PWMA_PS = 0x00; //通道1PWM1P引脚切换到P1.0,1N脚P1.1,通道2输出脚
//默认PWM2P脚P1.2,PWM2N脚P1.3
其实我折腾了一天,都是想用通道2 ,但是怎么都不能让通道2正常工作,我读手册的水平太低,只能按照以前摸索过的通道1+通道3来搞
但是一认真,就发现通道3的默认脚位不是P1.2和P1.3,再加上一直没搞懂通道2的设置,真不知道是怎么回事?
哪位大侠,指点一下,万分感谢。。。。。。。。。。。。
页:
[1]