按下三路按鍵,MCU喚醒且三路PWM有輸出(占空比30%),松開按鍵PWM無輸出,且MCU進入休眠狀态(低功耗狀态)。按鍵1按下,PWM1輸出,按鍵2按鍵3按下,PWM2/PWM3輸出

具體源程式如下所示
8位單片機項目合作請聯系我:18665321219
/* =========================================================================
* Project: GPIO_Setting
* File: main.c
* Description: Set GPIO of PORTB
* 1. PORTB I/O state
* - PB4 set input mode and enable pull-high resistor
* - PB2 set output mode
* - PB1 set input mode and enable pull-low resistor
* - PB0 set open-drain output mode
*
* Author: JasonLee
* Version: V1.1
* Date: 2018/09/07
=========================================================================*/
#include <ny8.h>
#include "ny8_constant.h"
#include <stdint.h>
#define UPDATE_REG(x) __asm__("MOVR _" #x ",F")
struct pwmflg
{
uint8_t pwm1en : 1;
uint8_t pwm2en : 1;
uint8_t pwm3en : 1;
}pwmflg;
uint8_t sleepcent;
uint8_t pwmdcycle; //計數1000為一個周期
uint8_t pwmduty1;
uint8_t pwmduty2;
uint8_t pwmduty3;
uint8_t pwmduty1s;
uint8_t pwmduty2s;
uint8_t pwmduty3s;
void peripinit(void)
// ;Initial GPIO
// ; PORTB I/O state
// ; PB0、PB1、PB2 set output mode and enable pull-high resister
// ;BPHCON = (uint8_t) ~( C_PB1_PHB | C_PB0_PHB | C_PB2_PHB ); // Enable PB0、PB1、PB2 Pull-High Resistor,others disable
BPLCON = (uint8_t) ~( C_PB3_PLB ); //Enable PB3 Pull-low Resistor,others disable
IOSTB = (uint8_t) ((~( C_PB1_Input | C_PB2_Input | C_PB0_Input )) | C_PB3_Input | C_PB4_Input | C_PB5_Input); // Set PB0、PB1、PB2 to output mode,Set PB3、PB4、PB5 to output mode
PORTB = 0x00; //初始化為0
BWUCON = C_PB5_Wakeup | C_PB4_Wakeup | C_PB3_Wakeup; //使能PB5、PB4、PB3按鍵喚醒
INTE = INTE | C_INT_PBKey; //使能按鍵喚醒中斷
//;Initial time1
// ; instrclk i_hrc 4/4M div = 1 計數8次溢出即可
// ;
TMRH = 0X20
TMR1 = 0x70; //到0下溢出中斷,計數100 //20M/2/100 = 100K
T1CR1 = C_TMR1_Reload | C_TMR1_En; //自動重載
T1CR2 = C_TMR1_ClkSrc_Inst | C_PS1_Dis ; //指令時鐘
INTE = INTE | C_INT_TMR1; //使能定時器中斷
INTF = 0; //清除中斷标志
OSCCR = C_FHOSC_Sel; //喚醒後進入正常模式
}
//盡量減小中斷代碼時長
void isr_hw(void) __interrupt(0)
if(INTFbits.T1IF)
pwmdcycle++;
if(pwmdcycle == 0x3) //周期10
PORTBbits.PB2 = 0;
PORTBbits.PB1 = 0;
PORTBbits.PB0 = 0;
pwmduty1s = pwmduty1; //按鍵按下時指派0x3,按鍵松開指派0xf(不可能執行)
pwmduty2s = pwmduty2; //
pwmduty3s = pwmduty3;
pwmdcycle = 0;
if(pwmdcycle == pwmduty1s) //占空比3
PORTBbits.PB0 = 1;
if(pwmdcycle == pwmduty2s) //占空比3
PORTBbits.PB1 = 1;
if(pwmdcycle == pwmduty3s) //占空比3
PORTBbits.PB2 = 1;
INTFbits.T1IF = 0; //寫在if語句防止意外清除标志位
if(INTFbits.PBIF) //清除按鍵中斷标志
INTFbits.PBIF = 0;
void delayms(uint8_t ms) //CLK_20M/IN_2T = 10M,MS = 100,延時61ms
uint8_t i = 0xff;
while(ms--)
while(i--);
void main(void) //main()函數周期11us
pwmflg.pwm1en = 0;
pwmflg.pwm2en = 0;
pwmflg.pwm3en = 0;
pwmduty1s = 0;
pwmduty2s = 0;
pwmduty3s = 0;
pwmduty1 = 0xf;
pwmduty2 = 0xf;
pwmduty3 = 0xf;
sleepcent = 0;
DISI();
peripinit();
ENI();
while(1)
CLRWDT();
//PB3狀态檢測
if((PORTBbits.PB3 == 1)&&(pwmflg.pwm1en == 0))
delayms(50); //估計在10ms左右
if(PORTBbits.PB3 == 1)
pwmduty1 = 2; //占空比為25%
pwmflg.pwm1en = 1;
else
pwmduty1 = 0xf; //占空比為就是不執行
else if(PORTBbits.PB3 == 0)
//PB4狀态檢測
if((PORTBbits.PB4 == 1)&&(pwmflg.pwm2en == 0))
if(PORTBbits.PB4 == 1)
pwmduty2 = 2; //占空比為25%
pwmflg.pwm2en = 1;
pwmduty2 = 0xf; //占空比為就是不執行
else if(PORTBbits.PB4 == 0)
//PB5狀态檢測
if((PORTBbits.PB5 == 1)&&(pwmflg.pwm3en == 0))
if(PORTBbits.PB5 == 1)
pwmduty3 = 2; //占空比為30%
pwmflg.pwm3en = 1;
pwmduty3 = 0xf; //占空比為就是不執行
else if(PORTBbits.PB5 == 0)
//休眠檢測
if(((PORTB & 0x38) == 0x00) && ((PORTB & 0x07) == 0x00)) //PB5、PB4、PB3輸入低(無效),PB0、PB1、PB2輸出低(無效)
sleepcent++; //累加100次
if(sleepcent == 100)
PCON = PCON & (~ C_WDT_En);//關閉看門狗定時器
SLEEP();//進入睡眠模式
DISI();//關閉中斷,喚醒後直接執行下一條指令
PCON = PCON | C_WDT_En;//開啟看門狗定時器
ENI();//開啟中斷
//delayms(100); //估計在10ms左右