2014-12-20 20:45:07 lixiangminghate 阅读数 5906
  • 机器学习案例实战第六课-PCA与Xgboost视频教学

    购买课程后,可扫码进入学习群,获取唐宇迪老师答疑 用实例演示机器学习中的Xgboost算法和PCA原理。本视频课程首先讲解两个案例,基于文本分类的股价预测与PCA降维应用在鸢尾花数据集上。简介Xgboost算法原理,并安装xgboost实例演示如何进行操作。 会员卡优惠购买:http://edu.csdn.net/lecturer/1079

    3111 人正在学习 去看看 唐宇迪

    STC12C5系列单片机属于增强性单片机,有多强呢?带有SPI接口,PCA模块,定时器输出,16K+的片上ROM,越来越妖孽了!前面见识了定时器输出功能,现在来领教一下STC12C5A60S单片机的PCA捕捉比较模块,后面有心情再看看SPI模块。

    按我个人理解捕捉比较的意思应该是捕捉外部引脚上的跳变,与预设的值比较,然后做相应的动作。下文按这个理解展开。老规矩,寄存器功能介绍省略了,懒得抄手册了。

    虽然说寄存器设置的说明不介绍,不过表格还是得给一张,这样条理比较清晰,如下:

   

1)PCA模块PWM的应用,感觉设置寄存器最少的一个:

PWM(脉宽调制,改变输出方波的占空比)估计拥有最广泛的应用空间(恕我眼见浅),据说常有人用PWM做心跳灯向妹子表白,不知道有没有成功;还有改变直流电机的输出转速。。。 

怎么理解PWM这个功能呢?刚去了趟WC突然想到了:在一个有0xFF个刻度的跑表上,CH是秒表,CCAPnH是表面上的一个绊脚石,当CH遇到绊脚石,直接给跪了,一直跪到下一轮0x00,继续站起来行走。如果CCAPnH没被移动,CH还在同一个地方周而复始的摔倒(人说不要再同一个地方摔倒)。然后计算从0x00-0xFF这段时间里,CH站着走路占了这段时间的百分之几,给跪占了剩下的多少(路遇倒地不扶也就算了还做应用题)!

#include <STC\STC12C5A.H>

enum sState
{
    sInit=0,sPca,sClk,sPwm,sClkOut,
};

#define CCF1_INT 0x02
#define CCF0_INT 0x01

#define ResetPCA() \
do{ \
    CCON = 0; \
    CL = 0; \
    CH = 0; \
    CMOD = 0x00; \
    CCAPM0 = 0x00; \
    CCAPM1 = 0x00; \
}while(0); \

#define StartPCA() \
do{ \
    CR = 1; \
}while(0); \

#define StopPCA() \
do{ \
    CR = 0; \
}while(0); \

#define SetModnCmp(n) \
do{ \ 
    CCAPM##n |= PCA0_ECOM; \
    CCAPM##n |= PCA0_MAT; \    
}while(0); \

#define SetModnTog(n) \
do{ \
    CCAPM##n |= PCA0_TOG; \
}while(0); \

#define SetCapnMod(n,mod) \
do{ \
    CCAPM##n |= mod; \
}while(0); \

#define SetCCAPn(n,hi,lo) \
do{ \
    CCAP##n##H = hi; \
    CCAP##n##L = lo; \    
}while(0); \
//ECCFn 使能CCFn中断。使能寄存器CCON的比较/捕获标志CCFn,用来产生中断。
#define EnPcaModnInt(n) \
do{ \
    CCAPM##n |= PCA0_ECCF; \    
}while(0); \

//PCA0_ECOM 允许比较器功能控制位
//PCA0_PWM 脉宽调制模式。当PWMn=1时,CEXn脚用作脉宽调制输出
#define SetPwmMod(n) \
do{ \
    CCAPM##n |= PCA0_ECOM|PCA0_PWM; \    
}while(0); \

unsigned int CCAPnHVal = 0x80,CCAPnLVal = 0x80; 

void delay()
{
    int i=0,j=0;
    for(i=0;i<1000;i++)
    {
        for(j=0;j<110;j++);
    }
}

int main()
{
    unsigned char sState = sInit;
    ResetPCA();
    //pwm有比较功能 但没用到匹配...真特立独行
    //只要设置CCAPMn的PWM位和比较位
    SetPwmMod(0);
    
    //设置占空比,有点类似定时器Mod2,TH自动装载到TL
    //此处是CCAPnH自动装载到CCAPnL(8位);CH装载到CL(8位)
    //CH-CL低于    CCAPnH-CCAPnL输出0,其他输出1
    while(1)
    {
        StopPCA();
        SetCCAPn(0,CCAPnHVal,CCAPnLVal);
        if(CCAPnHVal == 0xF0)
            CCAPnLVal = CCAPnHVal = 0x00;
        else
            CCAPnLVal = CCAPnHVal = CCAPnLVal+0x10;
        //启动pca模块
        StartPCA();
        delay();
    }
}

PWM0的输出引脚是P1.3在我的开发板上正好连了一个红色LED,忽明忽亮的,眼都刺瞎了!用示波器测试时的确输出可变的波形。(无图无真相随我BB)

本来想用中断控制pwm占空比,不过没成功,没法调试好麻烦,只能用这种粗线条的延时了。

2) 在看PCA捕捉功能之前,先看下51MCU的计数器功能,PCA的捕捉功能应该是加强版计数器:

2a) 51的定时器对系统时钟计数,计满诺干个时钟脉冲后,产生溢出;计数器对外部输入信号计数,计满诺干负跳变后,产生溢出。传说,计算流水线上的工件数会用到计数器功能。想象一下点钞机里的票票经过光感时,使计数器不断的加一,想想是不是有点小激动?醒醒了,拿钱不是自己的。还是看下面的代码了

#include <reg51.h>

#define MakeByte(target, Hi,Lo) \  
do{ \  
    target |= (((Hi)<<4)|(Lo)); \   
}while(0); \  
  
#define SetTH(n,val) \  
do{ \  
    TH##n = val; \  
}while(0); \  
  
#define SetTL(n,val)  \  
do{ \  
    TL##n = val; \  
}while(0); \  
  
#define EnableET(n) \  
do{ \  
    ET##n = 0x01; \  
    IE |= 0x80; \  
}while(0); \

#define StartClk(val) \
do{ \
	TCON |= val; \
}while(0); \

sbit P10=P1^0;

int main()
{
	//T0工作在方式2 计数器模式
	MakeByte(TMOD,0x00,0x06);
	SetTH(0,0xFF);
	SetTL(0,0xFF);
		
	EnableET(0);
	//启动定时器
	StartClk(0x10);
	while(1);
}  

void IsrT0() interrupt 1 
{
    //TH自动装入0xFF,再计满一个负跳变又能进入isr
    P10 = ~P10;	
}
程序对P3.4引脚采样,遇到负跳变计数器加1,因为设置计数溢出是0xFF,因此只要有负跳变就产生中断,对P1.0引脚取反。因为文章是关于PCA的,所以不能安排MCU计数器模块抢了镜头~

蓝色波形是信号发生器的输出,黄色波形是P1.0的输出。因为2个负跳变产生一个完整的波形,因此P1.0方波周期正好对应2个信号发生器的周期。

2b) 回到文章的主角PCA模块,当PCA模块工作在捕获模式时,对外部输入CEXn(P13/P14)的跳变进行采样。当采样到有效跳变时,PCA硬件将PCA计数器阵列寄存器(CH和CL)的值装载到捕获寄存器(CCAPnH和CCAPnL)中。如果CCON中的CCFn位和CCAPMn中的ECCFn位被置位,将产生中断。

#include <STC\STC12C5A.H>

enum sState
{
	sInit=0,sPca,sClk,sPwm,sClkOut,
};

#define CCF1_INT 0x02
#define CCF0_INT 0x01

#define ResetPCA() \
do{ \
	CCON = 0; \
	CL = 0; \
	CH = 0; \
	CMOD = 0x00; \
	CCAPM0 = 0x00; \
	CCAPM1 = 0x00; \
}while(0); \

#define StartPCA() \
do{ \
	CR = 1; \
}while(0); \

#define StopPCA() \
do{ \
	CR = 0; \
}while(0); \

#define SetModnCmp(n) \
do{ \ 
	CCAPM##n |= PCA0_ECOM; \
	CCAPM##n |= PCA0_MAT; \	
}while(0); \

#define SetModnTog(n) \
do{ \
	CCAPM##n |= PCA0_TOG; \
}while(0); \

#define SetCapnMod(n,mod) \
do{ \
	CCAPM##n |= mod; \
}while(0); \

#define SetCCAPn(n,hi,lo) \
do{ \
	CCAP##n##H = hi; \
	CCAP##n##L = lo; \	
}while(0); \
//ECCFn 使能CCFn中断。使能寄存器CCON的比较/捕获标志CCFn,用来产生中断。
#define EnPcaModnInt(n) \
do{ \
	CCAPM##n |= PCA0_ECCF; \	
}while(0); \

//PCA0_ECOM 允许比较器功能控制位
//PCA0_PWM 脉宽调制模式。当PWMn=1时,CEXn脚用作脉宽调制输出
#define SetPwmMod(n) \
do{ \
	CCAPM##n |= PCA0_ECOM|PCA0_PWM; \	
}while(0); \

//当PCA模块工作在捕获模式时,对外部输入CEXn的跳变进行采样。
//当采样到有效跳变时,PCA硬件将PCA计数器阵列寄存器(CH和CL)的值装载到捕获寄存器(CCAPnH和CCAPnL)中。
//如果CCON中的CCFn位和CCAPMn中的ECCFn位被置位,将产生中断。
//当P1.3出现下降沿时产生中断 对P1.5取反

void delay()
{
    int i=0,j=0;
    for(i=0;i<200;i++)
    {
        for(j=0;j<110;j++);
    }
}

int main()
{
	unsigned char sState = sInit;
	ResetPCA();
	EA = 1;
	//捕捉模式,捕捉到跳变沿时触发中断
	//CH-CL不用与CCAPnH-CCAPnL比较,因此不用使能ECOMn
	//也不需要设置PCA计数器阵列寄存器(CH和CL)以及捕获寄存器(CCAPnH和CCAPnL)
	SetCapnMod(0,PCA0_CAPN);
	//开启PCA中断
	EnPcaModnInt(0);
	//启动pca模块
	StartPCA();
	while(1)
	{
		P12 = ~P12;	
		delay();
	}	
}

void PCA_ISR(void) interrupt 7
{
	switch(CCON&0x03)
	{
	//模块0触发中断
	case CCF0_INT:
		//清除模块中断标志位
		CCON &=	(0x00<<CCF0_INT);
		P15 = ~P15;
		break;
	//模块1触发中断
	case CCF1_INT:
		CCON &=	(0x00<<CCF1_INT);
		break;
	default:
		break;
	}
}
程序烧写到MCU后,用跳线帽连接P12和P13,使得P13对P12的输出经行采样。下面是示波器的输出:

蓝色波形是P12引脚的输出,黄色波形是P15引脚的输出。图中(我的低端示波器)可以很明显的看出P13上采样到一个负跳表,P15发生一次翻转。

这个功能跟计数器每次计满一个脉冲就触发中断类似,不过感觉没有计数器那么灵活,它可以计数256个跳变,不过PCA捕捉可以同时捕捉双边沿,可用于脉宽测量;


STC MCU PCA模块还有其他功能,不过感觉有点无聊,就不一一展示了,不过代码还是要贴上来已做备忘:

#include <STC\STC12C5A.H>

enum sState
{
	sInit=0,sPca,sClk,sPwm,sClkOut,
};

#define CCF1_INT 0x02
#define CCF0_INT 0x01

#define ResetPCA() \
do{ \
	CCON = 0; \
	CL = 0; \
	CH = 0; \
	CMOD = 0x00; \
	CCAPM0 = 0x00; \
	CCAPM1 = 0x00; \
}while(0); \

#define StartPCA() \
do{ \
	CR = 1; \
}while(0); \

#define SetModnCmp(n) \
do{ \ 
	CCAPM##n |= PCA0_ECOM; \
	CCAPM##n |= PCA0_MAT; \	
}while(0); \

#define SetModnTog(n) \
do{ \
	CCAPM##n |= PCA0_TOG; \
}while(0); \

#define SetCapnMod(n,mod) \
do{ \
	CCAPM##n |= mod; \
}while(0); \

#define SetCCAPn(n,hi,lo) \
do{ \
	CCAP##n##H = hi; \
	CCAP##n##L = lo; \	
}while(0); \
//
#define EnPcaModnInt(n) \
do{ \
	CCAPM##n |= PCA0_ECCF; \	
}while(0); \

#define SetPwmMod(n) \
do{ \
	CCAPM##n |= PCA0_ECOM|PCA0_PWM; \	
}while(0); \

int main()
{
	unsigned char sState = sInit;

	ResetPCA();
	EA = 1;
	while(1)
	{
		switch(sState)
		{
		case sInit:
			//输入提示
			break;
		default: 
			
			sState = sInit;
			break;
		case sPca:
			ResetPCA();
			//捕捉模式,捕捉到跳变沿时触发中断
			//CH-CL不用与CCAPnH-CCAPnL比较,因此不用使能ECOMn
			//也不需要设置PCA计数器阵列寄存器(CH和CL)以及捕获寄存器(CCAPnH和CCAPnL)
			SetCapnMod(0,PCA0_CAPN|PCA0_CAPP);
			//开启PCA中断
			EnPcaModnInt(0);
			sState = sInit;
			break;
		case sClk:
                        //软件定时器功能
                        ResetPCA();
			//定时器功能
			//CH-CL增加计数值,然后与CCAPnH和CCAPnL比较,相等触发中断
			//有比较功能 设置比较和匹配控制位
			SetModnCmp(0);
			//设置 CCAPnH和CCAPnL,当CH-CL计数值==CCAPnH-CCAPnL中的预制值
			//发生中断
			SetCCAPn(0,0x80,0x00);
			//开启PCA中断
			EnPcaModnInt(0);
			sState = sInit;
			break;
		case sPwm:
			ResetPCA();
			//pwm有比较功能 但没用到匹配...真特立独行
			//只要设置CCAPMn的PWM位和比较位
			SetPwmMod(0);
			//设置占空比,有点类似定时器Mod2,TH自动装载到TL
			//此处是CCAPnH自动装载到此处是CCAPnL(8位);CH装载到CL(8位)
			//CH-CL低于	CCAPnH-CCAPnL输出0,其他输出1
			SetCCAPn(0,0x80,0x80);
			sState = sInit;
			break;
		case sClkOut:
                        //高速输出功能
                        ResetPCA();
			//当PCA计数器的CH-CL与CCAPnH-CCAPnL中的预制值相等时
			//CCPn发生翻转,这个功能也用到比较-匹配
			SetModnCmp(0);
			SetModnTog(0);
			EnPcaModnInt(0);
			sState = sInit;
			break;  				 
		}
		//启动pca模块
		StartPCA();	
	}
}

void PCA_ISR(void) interrupt 7
{
	switch(CCON&0x03)
	{
	//模块0触发中断
	case CCF0_INT:
		//清除模块中断标志位
		CCON &=	(0x00<<CCF0_INT);
		break;
	//模块1触发中断
	case CCF1_INT:
		CCON &=	(0x00<<CCF1_INT);
		break;
	default:
		break;
	}
}


2019-12-21 14:36:06 Liu1644 阅读数 14
  • 机器学习案例实战第六课-PCA与Xgboost视频教学

    购买课程后,可扫码进入学习群,获取唐宇迪老师答疑 用实例演示机器学习中的Xgboost算法和PCA原理。本视频课程首先讲解两个案例,基于文本分类的股价预测与PCA降维应用在鸢尾花数据集上。简介Xgboost算法原理,并安装xgboost实例演示如何进行操作。 会员卡优惠购买:http://edu.csdn.net/lecturer/1079

    3111 人正在学习 去看看 唐宇迪

这里写自定义目录标题

单片机PCA和PWM的关系

PCA指的是单片机的一个功能模块,然后PWM指的是脉冲宽度调制,是一种技术。

使用单片机的PCA模块可以实现PWM功能,比如要输出一个固定的频率,那么单片机只要开机时,把PCA的相关寄存器配置一下,频率就出来了,就是后台运行了,单片机就可以去做其他的事情,想连续发脉冲时,不中断其他运行中的程序。多路发出也可以,频率也可以不同,关键看单片机的功能。

PCA指的试可编程计数器阵列,就是说的PWM模块了,有这个的,就一定有PWM功能,不只是PWM,还有好多其他功能,比如捕捉(测脉宽)、高速输出、频率输出等。

这里的意思是。传统51的定时器是没有PWM功能的,但是PHILIP的增强型51,它的定时器有这功能,所以单独提出说明了,即定时器自己就能输出PWM。
有PCA的意思是,在定时器的基础上,实现了一些其它的功能,实现这个工能的东西是PCA。
有PCA的单片机,PWM、捕捉、高速输出、频率输出等都可以用模块完成;没有PCA、有PWM的单片机,PWM是靠定时器自己就能自动做了,但其他的功能要靠程序去做。都没有的,自然就都要靠程序去实现,要中断。

2019-09-06 16:48:16 weixin_43444989 阅读数 98
  • 机器学习案例实战第六课-PCA与Xgboost视频教学

    购买课程后,可扫码进入学习群,获取唐宇迪老师答疑 用实例演示机器学习中的Xgboost算法和PCA原理。本视频课程首先讲解两个案例,基于文本分类的股价预测与PCA降维应用在鸢尾花数据集上。简介Xgboost算法原理,并安装xgboost实例演示如何进行操作。 会员卡优惠购买:http://edu.csdn.net/lecturer/1079

    3111 人正在学习 去看看 唐宇迪

目录

定时器配置及PCA相关寄存器配置源代码: 

代码解析:

效果图:


STC15F2K60S2(IAP15也可以)中PWM产生的原理图(PWM产生功能是集成在PCA功能模块中的): 

产生PWM是使用计数-->比较-->输出的模式 

定时器配置及PCA相关寄存器配置源代码: 

void Timer0_init(void)//1us作为PCA计数器的计数单位
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x02;		//设置定时器模式
	TL0 = 0xF5;		//设置定时初值
	TH0 = 0xF5;		//设置定时重载值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
}

void PWM_EN()
{
	CCAP0L = 0x80;//PCA0比较寄存器,使占空比达到1:1
	CCAP1L = 0x80;//PCA1比较寄存器
	CCAP0H = 0x80;//设定PCA0比较寄存器重载值后八位
	CCAP1H = 0x80;//设定PCA1比较寄存器重载值后八位
	CL = 0;//PCA计数器清零
	CH = 0;//PCA计数器清零
	
	CMOD = 0x84;  // 空闲模式下PCA计数器停止工作;定时器0溢出做PCA模块的时钟源 
	CCON= 0x00;
	CCAPM0 = 0x42;//使能PWM0和比较器
	CCAPM1 = 0x42;//使能PWM1和比较器
	PCA_PWM0 = 0x00;//PCA0八位PWM模式,EPC0L(和比较寄存器组成9位数字)置零
	PCA_PWM1 = 0x00;//PCA1八位PWM模式
	CCON= 0x40;//使能PAC计数器
}

 上面代码实现的是CCP0和CCP1管脚输出占空比位为1:1的PWM波:

代码解析:

 

这里的时钟源采用的是定时器0产生的脉冲,并且不启用PCA计数器的中断

可通过字节操作使能计数器

在这里使能比较器和脉冲宽度调制功能

 

计数器和比较器的寄存器

 

 

效果图:

 频率为3.9332KHZ,这个频率和输入的时钟源的频率有关。

 也就是计数器溢出一次产生一个周期的PWM波

2015-03-22 18:50:22 sparkstrike 阅读数 1654
  • 机器学习案例实战第六课-PCA与Xgboost视频教学

    购买课程后,可扫码进入学习群,获取唐宇迪老师答疑 用实例演示机器学习中的Xgboost算法和PCA原理。本视频课程首先讲解两个案例,基于文本分类的股价预测与PCA降维应用在鸢尾花数据集上。简介Xgboost算法原理,并安装xgboost实例演示如何进行操作。 会员卡优惠购买:http://edu.csdn.net/lecturer/1079

    3111 人正在学习 去看看 唐宇迪

STC12C5A60S2 PCA相关寄存器介绍

STC12C5A60S2有两个PCA模块共用一个16位计数器(对应2个寄存器低8位CL和高8位CH),两个模块有各自的16位捕捉/比较器(对应2个寄存器低8位CCAPnL和高8位CCAPnH)。计数器的技术源可以是1/8系统时钟、1/2系统时钟、定时器0溢出或ECI脚输入。
STC12C5A60S2 PCA相关寄存器

STC12C5A60S2 PWM驱动舵机

PCA做PWM时计数器是8位的,16位的计数器和比较器只用到低8位(比较器的高八位也用到,下面会讲到),硬件将计数器的值和捕捉/比较寄存器比较,匹配时将改变PWM引脚电平。以PWM0为例,计数器为CL,比较器为CCAP0L
计数器CL中的值< 比较器CCAP0L中的值是,相应的引脚输出电平;
计数器CL中的值>=比较器CCAP0L中的值是,相应的引脚输出电平。
当计数器CL的值从0xFF到0X00溢出是,比较器的高八位CCPA0H的值将载入CCPA0L,这样就实现了无干扰的更新PWM。
因为舵机的驱动信号要50HZ,所以PCA计数器时钟频率应该是1/(50*256)=78us,不可能改变单片机的晶振频率,所以只能用定时器0的溢出做计数源,对计数源的设置在PCA模式寄存器CMOD的B3-B2位
STC12C5A60S2 PCA 计数源设置寄存器
22.1184dMHZ的晶振下STC12C5A60S2的定时器初始化函数为:

void Timer0Init(void){      //78微秒@22.1184MHz,8位自动重载模式
    ET0 = 1;
    AUXR &= 0x7F;       //定时器时钟12T模式
    TMOD &= 0xF0;       //设置定时器模式
    TMOD |= 0x02;       //设置定时器模式
    TL0 = 0x70;     //设置定时初值
    TH0 = 0x70;     //设置定时重载值
    TF0 = 0;        //清除TF0标志
    TR0 = 1;        //定时器0开始计时
}

注意:PCA用定时器做时钟源0的时候只需要定时器的溢出就行,并不需要开始中断,而且事实上,定时器0的中断还能再用。
通过控制信号PWM中高电平的脉宽来控制舵机的角度,脉宽从5ms到15ms分别对应舵机的角度范围的上下限。详细的舵机控制原理请戳舵机的原理和控制-新浪微博 50HZ的PWM高电平20ms一共被分成256份,取到5ms-15ms的只有26份,也就是说8位PWM驱动舵机只能产出25个档位。现在要做的就是确定比较器值和舵机角度的对应关系,舵机电路的误差为是这个值的范围有一定的偏移。
一下为初始化PWM并驱动舵机到某一角度的函数

    CMOD = 0x84; //1000,0100,PCA脉冲时钟源为定时器0
    CCAP1H = CCAP1L = 0xec;//设置比较器和比较器重载寄存器的值
    CCAPM1 = 0x42;//0100,0010//b6
    CR = 1;//开启PCA
2016-04-03 14:01:42 weifengdq 阅读数 892
  • 机器学习案例实战第六课-PCA与Xgboost视频教学

    购买课程后,可扫码进入学习群,获取唐宇迪老师答疑 用实例演示机器学习中的Xgboost算法和PCA原理。本视频课程首先讲解两个案例,基于文本分类的股价预测与PCA降维应用在鸢尾花数据集上。简介Xgboost算法原理,并安装xgboost实例演示如何进行操作。 会员卡优惠购买:http://edu.csdn.net/lecturer/1079

    3111 人正在学习 去看看 唐宇迪

STC15系列部分单片机集成了3路可编程计数阵列(CCP/PCA)模块(CCP0、1、2引脚),可用于软件定时器、外部脉冲的捕获、高速脉冲输出以及脉宽调制(PWM)输出。

慕司板的PWM应用于蜂鸣器、液晶屏亮度调节、直流电机调速,如下图(注意P19的跳线帽插到上面):
I01

程序中需要把CCP的3个引脚切换到第三通道:
I02

切换的代码在PCA_PWM_Init()函数中,直接用官方例程:

//    ACC = P_SW1;
//    ACC &= ~(CCP_S0 | CCP_S1);      //CCP_S0=0 CCP_S1=0
//    P_SW1 = ACC;                    //(P1.2/ECI, P1.1/CCP0, P1.0/CCP1, P3.7/CCP2)

//   ACC = P_SW1;
//   ACC &= ~(CCP_S0 | CCP_S1);      //CCP_S0=1 CCP_S1=0
//   ACC |= CCP_S0;                  //(P3.4/ECI_2, P3.5/CCP0_2, P3.6/CCP1_2, P3.7/CCP2_2)
//   P_SW1 = ACC;  

      ACC = P_SW1;
      ACC &= ~(CCP_S0 | CCP_S1);      //CCP_S0=0 CCP_S1=1
      ACC |= CCP_S1;              //(P2.4/ECI_3, P2.5/CCP0_3, P2.6/CCP1_3, P2.7/CCP2_3)
      P_SW1 = ACC;

PCA的时钟源通过CMOD寄存器来设置:
I04

如我们的系统时钟为33.1776MHz,CMOD=0x02;则PCA时钟源为33.1776/12=2.7648M,如果为8位PWM(即占空比分辨率为1/256),则输出PWM的频率为2.7648M/256=10.8KHz.

8位PWM设置在PCA_PWMx(x:0、1、2)寄存器中(PCA_PWM0=0x00):
I05

至于PWM的占空比,设置CCAPxH和CCAPxL寄存器即可:

PCA_PWM0 = 0x00;                //PCA模块0工作于8位PWM
CCAP0H = CCAP0L = 0x20;         //PWM0的占空比为87.5% ((100H-20H)/100H)

设置为PWM模式,还需设置CCAPMx(x:0、1、2)寄存器,这里我们只需CCAPM0=0x42即可:
I07

程序实现了液晶屏的亮度渐变(连接到CCP1_3通道上),把P19的跳线帽插到上面,即可看到液晶屏亮度变化。

完整工程参见资源汇总帖.

原作于 2014年10月
CSDN发表于2016年4月
weifengdq

没有更多推荐了,返回首页