写在前面
这篇博客介绍下如果使用STC12C5A60S2这款单片机上两路自带的PWM模块输出占空比不同的方波。
先上代码:
/*------------------------------------------------------------------*/
/* --- STC MCU Limited ---------------------------------------------*/
/* --- STC12C5Axx Series MCU PCA module output PWM wave Demo -------*/
/* --- Mobile: (86)13922805190 -------------------------------------*/
/* --- Fax: 86-0513-55012956,55012947,55012969 ---------------------*/
/* --- Tel: 86-0513-55012928,55012929,55012966----------------------*/
/* --- Web: www.STCMCU.com -----------------------------------------*/
/* --- Web: www.GXWMCU.com -----------------------------------------*/
/* If you want to use the program or the program referenced in the */
/* article, please specify in which data and procedures from STC */
/*------------------------------------------------------------------*/
/*********************************************************************
* 呼吸灯 *
实现现象:上电之后,P1.3 P1.4 每5MS占空比增加1%,加到100%之后开始递减到0%
P1.3与P1.4的波形互补(相反)
注意事项:
*********************************************************************/
#include "reg51.h"
#include "intrins.h"
#define FOSC 11059200L
typedef unsigned char BYTE;
typedef unsigned int WORD;
//寄存器地址声明,因为没有包含STC12C5A60S2的头文件
/*Declare SFR associated with the PCA */
sfr CCON = 0xD8; //PCA control register
sbit CCF0 = CCON^0; //PCA module-0 interrupt flag
sbit CCF1 = CCON^1; //PCA module-1 interrupt flag
sbit CR = CCON^6; //PCA timer run control bit
sbit CF = CCON^7; //PCA timer overflow flag
sfr CMOD = 0xD9; //PCA mode register
sfr CL = 0xE9; //PCA base timer LOW
sfr CH = 0xF9; //PCA base timer HIGH
sfr CCAPM0 = 0xDA; //PCA module-0 mode register
sfr CCAP0L = 0xEA; //PCA module-0 capture register LOW
sfr CCAP0H = 0xFA; //PCA module-0 capture register HIGH
sfr CCAPM1 = 0xDB; //PCA module-1 mode register
sfr CCAP1L = 0xEB; //PCA module-1 capture register LOW
sfr CCAP1H = 0xFB; //PCA module-1 capture register HIGH
sfr PCAPWM0 = 0xf2;
sfr PCAPWM1 = 0xf3;
//***********************************端口声明************************************//
sbit led1 = P1^0;
sbit led4 = P1^3;
unsigned char num=0x00;
unsigned char num1=0xfe;
unsigned int delay1;
bit flag,flag1,flag2;
//*******************************************************************************/
//* 函数名 :pwm_set(unsigned char x,unsigned char y)
//* 函数功能 :重设占空比
//* 输入 : num,num1
//* 输出 : 无
//*******************************************************************************/
void pwm_set(unsigned char x,unsigned char y){
CCAP0H=x; //设置比较值
CCAP0L=x;
CCAP1H=y;
CCAP1L=y;
}
/*******************************************************************************
* 函数名 : delay1ms()
* 函数功能 :延时1ms
* 输入 : 无
* 输出 : 无
*******************************************************************************/
bit delay1ms()
{
unsigned int x,y;
for(x=1; x>0; x--)
for(y=920; y>0; y--);
return 1;
}
/*******************************************************************************
* 函数名 : pwm_init()
* 函数功能 :初始化PWM模块
* 输入 : 无
* 输出 : 无
*******************************************************************************/
void pwm_init(){
CCON = 0; //Initial PCA control register
//PCA timer stop running
//Clear CF flag
//Clear all module interrupt flag
CL = 0; //Reset PCA base timer
CH = 0;
CMOD = 0x02; //Set PCA timer clock source as Fosc/2
//Disable PCA timer overflow interrupt
CCAP0H = CCAP0L = 0x00; //PWM0 port output 0% duty cycle square wave
CCAPM0 = 0x42; //PCA module-0 work in 8-bit PWM mode and no PCA interrupt
CCAP1H = CCAP1L = 0xff; //PWM1 port output 0% duty cycle square wave
CCAPM1 = 0x42; //PCA module-1 work in 8-bit PWM mode and no PCA interrupt
CR = 1; //PCA timer start run
}
/*******************************************************************************
* 函数名 : tmr0_init()
* 函数功能 :初始化定时器0
* 输入 : 无
* 输出 : 无
*******************************************************************************/
void tmr0_init(){
EA = 0;
TF0 = 0;
TMOD = 0X01;
TH0 = 0XEE; //5MS
TL0 = 0X00;
ET0 = 1;
EA = 1;
TR0 = 1;
}
/*******************************************************************************
* 函数名 : isr_timer0 ()
* 函数功能 :定时器0中断服务函数
* 输入 : 无
* 输出 : 无
*******************************************************************************/
void isr_timer0 () interrupt 1 using 0{
TH0 = 0XEE; //5MS
TL0 = 0X00;
if(!flag){
if(++num > 0xfe) flag = 1;
}
else{
if(--num < 0x01) flag = 0;
}
if(!flag1){
if(++num1 > 0xfe) flag1 = 1;
}
else{
if(--num1 < 0x01) flag1 = 0;
}
}
/************************************主函数****************************************/
void main()
{
pwm_init();
tmr0_init();
while (1){
pwm_set(num,num1);
}
}
代码用的是STC给出的官方示例代码,不过STC的给的代码是占空比固定的。于是再开启定时器0让占空比每5ms改变一次,在主函数中不断把递增的值重新赋值给PWM0和1的比较/捕获寄存器,PWM在开启之后计数器CL会不断的递增,一旦跟CCAP0L或CCAP1L相等,就会让相应的PWM输出口输出高电平,在脉宽调节模式里面,CH暂时没发现作用(推断),CCAP0H和CCAP1H分别是用来调节PWM0和PWM1这两路输出占空比的,当CL的值从FF变为00之后,CCAP0H/CCAP1H会把值赋给CCAP0L/CCAP1L,这样实现无干扰更新占空比。其他模式可以参考芯片手册,这里只介绍PWM模式下的用法。