01 前言
发生了甚么事呢?
事情是这样的,项目需要用到PWM,很快啊,我就想到了我们厉害的STC。
打开STC-ISP开始选型,很快啊,找到手头有的STC8G1K08A符合要求。
注:《手册》为2020-11-05版STC8G说明手册
02 发展
直接复制粘贴例程,一气呵成,编译下载,PWM正常输出例程中的占空比。
使用的例程如下,位于《手册》的552与553页:
//测试工作频率为11.0592MHz #include "reg51.h" #include "intrins.h" sfr CCON = 0xd8; sbit CF = CCON ^ 7; sbit CR = CCON ^ 6; sbit CCF2 = CCON ^ 2; sbit CCF1 = CCON ^ 1; sbit CCF0 = CCON ^ 0; sfr CMOD = 0xd9; sfr CL = 0xe9; sfr CH = 0xf9; sfr CCAPM0 = 0xda; sfr CCAP0L = 0xea; sfr CCAP0H = 0xfa; sfr PCA_PWM0 = 0xf2; sfr CCAPM1 = 0xdb; sfr CCAP1L = 0xeb; sfr CCAP1H = 0xfb; sfr PCA_PWM1 = 0xf3; sfr CCAPM2 = 0xdc; sfr CCAP2L = 0xec; sfr CCAP2H = 0xfc; sfr PCA_PWM2 = 0xf4; sfr P0M1 = 0x93; sfr P0M0 = 0x94; sfr P1M1 = 0x91; sfr P1M0 = 0x92; sfr P2M1 = 0x95; sfr P2M0 = 0x96; sfr P3M1 = 0xb1; sfr P3M0 = 0xb2; sfr P4M1 = 0xb3; sfr P4M0 = 0xb4; sfr P5M1 = 0xc9; sfr P5M0 = 0xca; void main() { P0M0 = 0x00; P0M1 = 0x00; P1M0 = 0x00; P1M1 = 0x00; P2M0 = 0x00; P2M1 = 0x00; P3M0 = 0x00; P3M1 = 0x00; P4M0 = 0x00; P4M1 = 0x00; P5M0 = 0x00; P5M1 = 0x00; CCON = 0x00; CMOD = 0x08; //PCA时钟为系统时钟 CL = 0x00; CH = 0x00; //--6位PWM-- CCAPM0 = 0x42; //PCA模块0为PWM工作模式 PCA_PWM0 = 0x80; //PCA模块0输出6位PWM CCAP0L = 0x20; //PWM占空比为50%[(40H-20H)/40H] CCAP0H = 0x20; //--7位PWM-- CCAPM1 = 0x42; //PCA模块1为PWM工作模式 PCA_PWM1 = 0x40; //PCA模块1输出7位PWM CCAP1L = 0x20; //PWM占空比为75%[(80H-20H)/80H] CCAP1H = 0x20; //--8位PWM-- // CCAPM2 = 0x42; //PCA模块2为PWM工作模式 // PCA_PWM2 = 0x00; //PCA模块2输出8位PWM // CCAP2L = 0x20; //PWM占空比为87.5%[(100H-20H)/100H] // CCAP2H = 0x20; //--10位PWM-- CCAPM2 = 0x42; //PCA模块2为PWM工作模式 PCA_PWM2 = 0xc0; //PCA模块2输出10位PWM CCAP2L = 0x20; //PWM占空比为96.875%[(400H-20H)/400H] CCAP2H = 0x20; CR = 1; //启动PCA计时器 while (1) ; }
这里有一个小细节,PCA_PWMx
的操作方式都是字节操作,并没有位操作。
快进到程序写到PWM操作,到了我喜欢的#define
操作环节,写出了如下代码:
#define _PCA_PWMSetReloadValue(PCAn, valH, valL) \ PCA_PWM##PCAn &= 0xCD; \ //设置寄存器为初始值 PCA_PWM##PCAn |= (valH & 0x03) << 4; \ //设置9,10位 PCA_PWM##PCAn |= (valH & 0x04) >> 1; \ //设置11位 CCAP##PCAn##H = valL; //设置低八位
我乖乖的按照《手册》P545的注意的顺序进行了设置,但是,无论后期怎么调用该宏定义进行更改,输出一直是设定的初始值:高。
我@#¥!@!@#¥要疯了,凭啥?
03 后语
用串口一步一步进行排查,最后将问题定位到了这个宏定义处。
经过观察发现,例程竟然没有用位操作进行PCA_PWMx
的数据更新!
然后想起了某些特殊寄存器不能进行位操作只能进行字节操作,就写出了如下修改后的程序:
#define _PCA_PWMSetReloadValue(PCAn, valH, valL) \ x = PCA_PWM##PCAn; \ x &= 0xCD; \ x |= (valH & 0x03) << 4; \ x |= (valH & 0x04) >> 1; \ PCA_PWM##PCAn = x; \ CCAP##PCAn##H = valL;
对变量进行位操作后再直接字节赋值就可以正常进行调制了,,,
我无fa可说啊xdm,,
贴一个最后成功调制输出50%与75%占空比的波形:
我希望,我们强大的STC,耗子尾汁,好好反思。以后不要再犯这样的马虎,小马虎,啊,嗯… 开发者要以和为贵,要讲武德,不要搞缺印漏印。谢谢朋友们!