降低单片机运行频率(调整时钟分频系数): 此方法比较简单: 但存在问题如下:程序运行时间会增加,比如读取传感器的数据会影响其他步骤的运行 以应广单片机PMS171B为例 //==========================================//// IO设置//案例为://设置了IO脚的不同输入输出状态//比如PA.0为输出高/低,PB.6为输入上拉/下拉等//==========================================/#include "extern.h"void IO_init(void){ //注:无PA.1,PA.2脚位 //未使用端口需有防漏电设置,如加内部上拉 PAPH = 0b1111_1110; //上拉控制寄存器,控制上拉高相应的引脚(1:启用,0:停用) PAC = 0b0000_1001; //数据控制寄存器(1:输出模式,0:输入模式) PA = 0b0000_0001; //数据寄存器 .delay 10000;}void FPPA0 (void){ .ADJUST_IC SYSCLK=IHRC/2, IHRC=16MHz, VDD=5.0V;//单片机时钟为8MHZ IO_init(); while (1) { LED=0; .delay 100; LED=1; .delay 100; }}void Interrupt (void){ pushaf; if (Intrq.T16) { // T16 Trig // User can add code Intrq.T16 = 0; //... } popaf;}定义PA.3为输出口 .ADJUST_IC SYSCLK=IHRC/2, IHRC=16MHz, VDD=5.0V;时钟分频为2 单片机时钟为SYSCLK =8Mhz 功耗和输出波形如下图所示 调整分频系数为16 单片机时钟为SYSCLK =1Mhz .ADJUST_IC SYSCLK=IHRC/16, IHRC=16MHz, VDD=5.0V;功耗和输出波形如下图所示 间歇性工作和触发工作 此方法和降低运行频率如出一辙,不同的是此方法不是全程降低运行频率 例如:在定时中断触发和其他方式触发时,提升单片机的频率,高速运行,在处理完成上述事件后,降低单片机的运行频率,等待下一次的触发事件。 //===========================================//// 休眠//主要介绍了省电模式和掉电模式//省电模式介绍了用计数器唤醒和IO唤醒,// 例中介绍了T16唤醒后且num自加超过100后退出休眠,即针对不是IO脚电平变化的唤醒条件的唤醒// IO唤醒的唤醒条件可参考掉电模式,其他不变//掉电模式介绍了IO唤醒// 例中介绍了IO脚电平变化后唤醒,即针对IO脚电平变化的唤醒条件的唤醒//===========================================//#include "extern.h"byte CLKMD_BK;//=======省电模式=========byte num;word reload_T16;void Save_power(void){ //======User can add code===== //进入省电模式前动作,如关灯、关计数器等 //关闭不需要唤醒的引脚的数字使能,例中只给了PA的设置 $ PADIER 0x00; //============================ CLKMD_BK = CLKMD; //保存休眠前的时钟 num = 0; while(1) { $ CLKMD ILRC/1,En_IHRC,En_ILRC; //系统时钟选择,是否启用IHRC,是否启用ILRC,(En_IHRC和En_ILRC不写为停用,写为启用) //系统时钟可选择IHRC/4, IHRC/16, IHRC/2, IHRC/8, ILRC/16, EOSC/4, IHRC/32, EOSC/2, IHRC/64, EOSC/1, EOSC/8, ILRC/4, ILRC/1 //选择系统时钟为ILRC/1,启用ILRC和IHRC;(注:两个RC振荡器至少有一个开启,否则会出现宕机) CLKMD.En_IHRC = 0; //关闭高频IHRC,若上条语句没使用低频时钟,此句必须去掉 nop; //========设置T16定时,详情请参考T16========= $ T16M ILRC,/1,bit8; reload_T16 = 0; stt16 reload_T16; stopexe; //进入省电模式,T16计时溢出时唤醒 $ CLKMD ILRC/1,En_IHRC,En_ILRC; //打开高频使能,准备切换高频进入唤醒条件判断 $ CLKMD IHRC/64,EN_IHRC,EN_ILRC;//选择系统时钟为IHRC/64,启用ILRC和IHRC nop; //=======编写唤醒条件========= //例如num自加超过100后唤醒,该方法针对不是IO脚电平变化的唤醒条件 num++; if(num > 20) //假如发生唤醒而且满足唤醒条件,就返回正常工作 { //否则停留在省电模式,继续休眠 num=0; break; } } CLKMD = CLKMD_BK; //恢复休眠前的时钟 //======User can add code===== //唤醒后打开需要的动作,比如开灯、定时器等 //打开需要数字使能的引脚,例中只给了PA.0的设置 $ PADIER 0x01; //============================ }void IO_init(void){ //注:无PA.1,PA.2脚位 //未使用端口需有防漏电设置,如加内部上拉 PAPH = 0b1111_0110; //上拉控制寄存器,控制上拉高相应的引脚(1:启用,0:停用) PAC = 0b0000_1001; //数据控制寄存器(1:输出模式,0:输入模式) PA = 0b0000_0001; //数据寄存器 .delay 10000;}void FPPA0 (void){ .ADJUST_IC SYSCLK=IHRC/2, IHRC=16MHz, VDD=5V; IO_init(); while (1) { num++; if(num > 200) //假如发生唤醒而且满足唤醒条件,就返回正常工作 { //否则停留在省电模式,继续休眠 num=0; Save_power(); //省电模式休眠 } .delay 10000; }}void Interrupt (void){ pushaf; if (Intrq.T16) { // T16 Trig // User can add code Intrq.T16 = 0; //... } popaf;}
|