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%占空比的波形:

日狗,yyds

我希望,我们强大的STC,耗子尾汁,好好反思。以后不要再犯这样的马虎,小马虎,啊,嗯… 开发者要以和为贵,要讲武德,不要搞缺印漏印。谢谢朋友们!