关于STC8A8K64D4芯片PCA_PWM功能的一些见解(输出1kHz sin波形)

关于STC8A8K64D4芯片PCA_PWM功能的一些见解(输出1kHz sin波形)

二齐

STC8A8K64D4芯片是目前STC公司产出的8A系列最新的8位单片机MCU。其中囊括了STC8A8K64S4A12芯片的全部功能,改进了关于PWM,比较器,I/O中断等硬件功能。新增的库函数比较好用。但是对于PCA应用,以我个人的状态来说,库函数应用比较不理想,下面文章仅对寄存器使用进行说明。

**一、**PCA硬件结构
官方说明书中的PCA结构图
其中PCA计数器时钟主要来源于系统时钟和T0定时器,外部中断时钟入口暂时没用。16位计数器的计数位数取决于定义的PWM位数。
如果定义为8位PWM,则仅使用CL8位数据,CH数据不更新;如果定位为10位PWM,则使用CL8位,CH2位满足10位定时的要求,其他类似。CCON主要控制的是PCA计时器启停(CR位)和中断状态标志。CMOD主要决定中断状态和引脚选择状态。
**二、**寄存器结构
在这里插入图片描述
在这里插入图片描述
如上图所示,PCA模块共4个,分别作用于不同的输出管脚。我们首先定义CCON和CMOD寄存器(当然了,在这之前请先定义系统时钟、GPIO管脚状态)。完成后对使用的PCA管脚进行设置。我这里使用的是PCA0管脚。
在这里插入图片描述
CCAPMn寄存器主要控制PCA工作模式,我们如果要产生1k正弦波,需要对占空比进行实时更新,来达到调整输出电压的效果,因此需要使用中断(中断问题后续讲解)。
在这里插入图片描述
如上图,再次对PCA_PWM寄存器进行设置,这里重点设置PWM位数,其中的拓展数据值先不写。
完成后即可对CR位进行置1操作,启动寄存器。

**三。**关于中断
PCA工作在PWM模式下的中断操作很神奇。目前我的处理方式为,先对sin正弦波进行取值,可在网络上搜索相关内容。取值完成后,当PCA0产生中断后,先将CCAPH的存储值写入CCAPL,再将sin正弦波的取点值写入CCAPH,进行更新。
当设置为上升沿中断时,效果是可以的。(8位模式下,输出正弦波频率为PCA时钟频率/256/点数),下降沿中断可能存在问题。因为在对PCA计数值进行比较时,当CL小于CCAPL时输出低电平,高于CCAPL时,输出高电平,此时产生上升沿,这时对CCAP进行更新,有一定的时间完成,但是如果进行下降沿中断,那么在CL溢出时,产生下降沿中断,进入中断服务程序后,同时也会进行更新CCAP,我们再进行操作可能引起问题(目前没出现问题),可能是隐患。当设定边沿中断时,上升沿、下降沿都会产生中断,频率翻倍。

总结如下:PCA使用时,会调用系统时钟,系统时钟存在一定误差,因此可能和预想设定的频率有一定差异,建议多测试,找到最好的结果。如果大家有什么好的意见,请及时交流,共同进步。
代码附下:

#include  "config.h"
#include  "STC8A_GPIO.h"

u8 code T_sin[]={
0x80,0x88,0x90,0x99,0xa1,0xa9,0xb1,0xb9,
0xc0,0xc7,0xce,0xd5,0xdb,0xe0,0xe6,0xeb,
0xef,0xf3,0xf6,0xf9,0xfb,0xfd,0xfe,0xfe,
0xfe,0xfe,0xfd,0xfb,0xf9,0xf6,0xf3,0xef,
0xeb,0xe6,0xe0,0xdb,0xd5,0xce,0xc7,0xc0,
0xb9,0xb1,0xa9,0xa1,0x99,0x90,0x88,0x80,
0x77,0x6f,0x66,0x5e,0x56,0x4e,0x46,0x3f,
0x38,0x31,0x2a,0x24,0x1f,0x19,0x14,0x10,
0x0c,0x09,0x06,0x04,0x02,0x01,0x01,0x01,
0x01,0x02,0x04,0x06,0x09,0x0c,0x10,0x14,
0x19,0x1f,0x24,0x2a,0x31,0x38,0x3f,0x46,
0x4e,0x56,0x5e,0x66,0x6f,0x77,
};
u8 i;
int main()
{
  P1_MODE_IO_PU(GPIO_Pin_7);

  CCON   = 0x00;
  CMOD   = 0x08; //ϵͳʱÖÓ
  CL     = 0x00;
  CH     = 0x00;
  CCAPM0    = 0x63;
  PCA_PWM0  = (0x00<<6);
  CCAP0L    = 0x00;
  CCAP0H    = 0x80;
  CR        = 1;
  EA        = 1;
  while(1);
}


void PCA_interrupt(void) interrupt PCA_VECTOR
{
  if(CCF0)
  {
    CCF0 = 0;
    CCAP0L    = CCAP0H;
    CCAP0H    = T_sin[i];
    i++;
    if(i==94) i=0;
  }
    if(CF)CF = 0;
}
  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值