stc8a--pca--pwm--10wei--22.1184mhz--2fenpin

23 篇文章 0 订阅

/*
说明:
本代码,用的是P70,P71,P72,P73四个产生PCA的PWM。
选择10位PWM模式
晶振频率22.1184Mhz,选择2分频,则PWM的频率都是10.85Khz左右

如果想用其他的端口,以及分频系数,将对应的端口宏定义的注释掉;同时认真阅读对应的函数,设置进去。
设置步骤:
1、PCAPWM_Init中切换端口代码;
2、分频系数设置。我们这里必须确定是10位PCA的PWM。
当晶振22.1184M,PCA是10位,
分频系数 时基us 周期 频率
1 0.045us 10240.045=46.3us 21.6k
2 0.09us 1024
0.09=92.16us 10.85khz
4 5.4khz
8 2.7k
16 0.723us 1024*0.723 =740.74us 1.35k

计算过程如下:
PCA的时钟来源是22.1184Mhz的二分频,则是11.0592Mhz,倒数就是PCA计数器的时间基准t0=1/11.0592M=0.09us
最大是10位,则PCA计时的最大值是2^10 *0.09us=92.16us,
0-1-2-…2^10—0–1,每次加1需要0.09us,则周期是92.16us;
所以频率是周期的倒数,1/92.16us=10.85khz

由于是10位的PWM,这里设置PWM的时候比较复杂,单片机将低八位之外的高两位,放在PCAPWMn的B5和B4位中;
更新占空比的时候,需要先关闭对应通道的PCAPWM,然后更新比较值,
更新比较值的时候,需要将高两位的B5和B4清0,然后将比较值的高两位提取出来赋值进去
之后,将比较值的低八位,放到对应的寄存器中。然后重新打开PCAPWM。
这里比较麻烦。

如果设置是8位的PCAPWM,就不用这么麻烦了。但是8位的PWM,最多等级是2^8=256,细分不够
变化不够光滑。既然有10位,那就用十位就好了。

*/
在这里插入图片描述
在这里插入图片描述

pcapwm.h

#ifndef __PCAPWM_H
#define __PCAPWM_H		

#include "STC8a8k.h"

//PCA端口切换设置
//#define PCAPORTP1    0x00     //P1.7-P1.4  ECI=P1.2
//#define PCAPORTP2    0x10     //P2.3-P2.6  ECI=P2.2
#define PCAPORTP7    0x20     //P7.0-P73  ECI=P7.4
//#define PCAPORTP3    0x30     //P3.0-P3.3  ECI=P3.5
//PWM位数设置
//#define PCAPWM6Bit    0x80     //6位PWM
//#define PCAPWM7Bit    0x40    
//#define PCAPWM8Bit    0x00 
#define PCAPWM10Bit   0xC0   
//PCA的时钟来源
//空闲模式继续PCA计数,禁止PCA计数器溢出中断
// CMOD--B7--B6--B5--B4   B3--B2--B1--B0
//CMOD--CIDL-k---k---k----CPS[2:0]----ECF
//#define PCACLK1    0x08  //系统时钟
#define PCACLK2    0x02  //系统时钟/2
//#define PCACLK4    0x0A  //系统时钟/4
//#define PCACLK6    0x0C   //系统时钟/6
//#define PCACLK8    0x0E   //系统时钟/8
//#define PCACLK12   0x00   //系统时钟/12
//#define PCACLKTIM0 0x04  //定时器0的溢出脉冲
//#define PCACLKECI  0x06  //ECI引脚的外部输入时钟
//PCA模式
#define PCAPWMModeEnable 0x42  //PCA用作PWM模式
#define PCAPWMModeDisable 0x40  //PCA用作PWM模式

void PCAPWM_Init();
void PCAPWM_OutEnable(bit ena);//0是不是能输出,1:输出PWM
void PCA_Pwm0_10BitSet(float Duty);//Duty=0---1之间,如果等于0,输出低电平,没PWM。
void PCA_Pwm1_10BitSet(float Duty);
void PCA_Pwm2_10BitSet(float Duty);
void PCA_Pwm3_10BitSet(float Duty);

#endif  

/*
说明:
本代码,用的是P70,P71,P72,P73四个产生PCA的PWM。
选择10位PWM模式
晶振频率22.1184Mhz,选择2分频,则PWM的频率都是10.85Khz左右

如果想用其他的端口,以及分频系数,将对应的端口宏定义的注释掉;同时认真阅读对应的函数,设置进去。
设置步骤:
1、PCAPWM_Init中切换端口代码;
2、分频系数设置。我们这里必须确定是10位PCA的PWM。
当晶振22.1184M,PCA是10位,
分频系数	时基us	周期	            频率
1			0.045us  1024*0.045=46.3us  21.6k
2			0.09us   1024*0.09=92.16us  10.85khz
4                                 5.4khz
8                                 2.7k
16     0.723us  1024*0.723 =740.74us   1.35k

计算过程如下:
PCA的时钟来源是22.1184Mhz的二分频,则是11.0592Mhz,倒数就是PCA计数器的时间基准t0=1/11.0592M=0.09us
最大是10位,则PCA计时的最大值是2^10 *0.09us=92.16us,
0-1-2-...2^10---0--1,每次加1需要0.09us,则周期是92.16us;
所以频率是周期的倒数,1/92.16us=10.85khz

由于是10位的PWM,这里设置PWM的时候比较复杂,单片机将低八位之外的高两位,放在PCAPWMn的B5和B4位中;
更新占空比的时候,需要先关闭对应通道的PCAPWM,然后更新比较值,
更新比较值的时候,需要将高两位的B5和B4清0,然后将比较值的高两位提取出来赋值进去
之后,将比较值的低八位,放到对应的寄存器中。然后重新打开PCAPWM。
这里比较麻烦。

如果设置是8位的PCAPWM,就不用这么麻烦了。但是8位的PWM,最多等级是2^8=256,细分不够
变化不够光滑。既然有10位,那就用十位就好了。

*/

pcapwm.c

#include "pcapwm.h"
#include "delay.h"
#include <uart.h>
#include "stdio.h"

///
void PCAPWM_Init()
{

	//管脚切换,参考stc官方例程
	P_SW1=PCAPORTP7;//切换到P7口
	CCON=0x00;
	CMOD=PCACLK2;//2分频 22.1182M/2=11.0592Mhz
	CL=0x00;//从0开始计数
	CH=0x00;
	
	CCAPM0=PCAPWMModeDisable;//PCA0做PWM模式
	PCA_PWM0=PCAPWM10Bit;//10位模式
	CCAP0L=0x20;
  CCAP0H=0x20;
  
		
	CCAPM1=PCAPWMModeDisable;//PCA0做PWM模式
	PCA_PWM1=PCAPWM10Bit;//10位模式
	CCAP1L=0x20;
  CCAP1H=0x20;
	
	CCAPM2=PCAPWMModeDisable;//PCA0做PWM模式
	PCA_PWM2=PCAPWM10Bit;//10位模式
	CCAP2L=0x20;
  CCAP2H=0x20;
	
	CCAPM3=PCAPWMModeDisable;//PCA0做PWM模式
	PCA_PWM3=PCAPWM10Bit;//10位模式
	CCAP3L=0x20;
  CCAP3H=0x20;
	
	PCAPWM_OutEnable(1);
}

void PCA_Pwm0_10BitSet(float Duty)
{
	unsigned int DutyNum=0;
	if(Duty==0)	
	{
		CCAPM0= PCAPWMModeDisable;
		P70=0;//这里设置输出口等于低电平,不然默认高电平
		return;
	}
	DutyNum=1024-Duty*1024;
	CCAPM0= PCAPWMModeDisable;//重新设置PWM的时候,需要先关闭PWM
	PCA_PWM0 &=~(3<<4);//清0重新装高2位XCCCAPNH  B5 B4
	PCA_PWM0  |=(DutyNum>>4)&0x30;//设置新的高2位
	CCAP0H=DutyNum;//重载低8位
	CCAPM0=PCAPWMModeEnable;//设置完成之后,打开PWM
}

void PCA_Pwm1_10BitSet(float Duty)
{
	unsigned int DutyNum=0;
	if(Duty==0)	
	{
		CCAPM1= PCAPWMModeDisable;
		P71=0;//这里设置输出口等于低电平,不然默认高电平
		return;
	}
	DutyNum=1024-Duty*1024;
	CCAPM1= PCAPWMModeDisable;//重新设置PWM的时候,需要先关闭PWM
	PCA_PWM1 &=~(3<<4);//清0重新装高2位XCCCAPNH  B5 B4
	PCA_PWM1  |=(DutyNum>>4)&0x30;//设置新的高2位
	CCAP1H=DutyNum;//重载低8位
	CCAPM1=PCAPWMModeEnable;//设置完成之后,打开PWM
}

void PCA_Pwm2_10BitSet(float Duty)
{
	unsigned int DutyNum=0;
	if(Duty==0)	
	{
		CCAPM2= PCAPWMModeDisable;
		P72=0;//这里设置输出口等于低电平,不然默认高电平
		return;
	}
	DutyNum=1024-Duty*1024;
	CCAPM2= PCAPWMModeDisable;//重新设置PWM的时候,需要先关闭PWM
	PCA_PWM2 &=~(3<<4);//清0重新装高2位XCCCAPNH  B5 B4
	PCA_PWM2  |=(DutyNum>>4)&0x30;//设置新的高2位
	CCAP2H=DutyNum;//重载低8位
	CCAPM2=PCAPWMModeEnable;//设置完成之后,打开PWM
}

void PCA_Pwm3_10BitSet(float Duty)
{
	unsigned int DutyNum=0;
	if(Duty==0)	
	{
		CCAPM3= PCAPWMModeDisable;
		P73=0;//这里设置输出口等于低电平,不然默认高电平
		return;
	}
	DutyNum=1024-Duty*1024;
	CCAPM3= PCAPWMModeDisable;//重新设置PWM的时候,需要先关闭PWM
	PCA_PWM3 &=~(3<<4);//清0重新装高2位XCCCAPNH  B5 B4
	PCA_PWM3  |=(DutyNum>>4)&0x30;//设置新的高2位
	CCAP3H=DutyNum;//重载低8位
	CCAPM3=PCAPWMModeEnable;//设置完成之后,打开PWM
}
//********************************************
//0是不是能输出,1:输出PWM
void PCAPWM_OutEnable(bit ena)
{

	 if(ena==0)//关闭PWM模块
	  CR=0;
	 else
		CR=1;
}

main.c

#include "stc8a8k.h"
#include "delay.h"
#include "pcapwm.h"
#include "stdio.h"
#include <uart.h>


//*************************************************主函数
void main()
{
	float aa=0.1;
	int duty0;
	PCAPWM_Init();

  UartInit();
		delay_tms(5000);//两秒后开始

	printf("aaa\r\n");
	delay_tms(100);//两秒后开始
	duty0=10;
	
	while(1)
	{
		PCA_Pwm0_10BitSet(0.1);
		PCA_Pwm1_10BitSet(0.2);
		PCA_Pwm2_10BitSet(0.3);
		PCA_Pwm3_10BitSet(0.4);
		delay_tms(100);
		 PCA_Pwm0_10BitSet(0);
		 PCA_Pwm1_10BitSet(0);
		 PCA_Pwm2_10BitSet(0);
		 PCA_Pwm3_10BitSet(0);
			delay_tms(100);
			PCA_Pwm0_10BitSet(0.5);
		PCA_Pwm1_10BitSet(0.6);
		PCA_Pwm2_10BitSet(0.7);
		PCA_Pwm3_10BitSet(0.8);
		delay_tms(100);
		 PCA_Pwm0_10BitSet(0);
		 PCA_Pwm1_10BitSet(0);
		 PCA_Pwm2_10BitSet(0);
		 PCA_Pwm3_10BitSet(0);
			delay_tms(100);
		
	}
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值