单片机应用——PWM输出(一)

按下三路按键,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> /* ========================================================================= * 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_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; pwmdcycle = 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) { pwmduty1 = 0xf; //占空比为就是不执行 pwmflg.pwm1en = 0; } //PB4状态检测 if((PORTBbits.PB4 == 1)&&(pwmflg.pwm2en == 0)) { delayms(50); //估计在10ms左右 if(PORTBbits.PB4 == 1) { pwmduty2 = 2; //占空比为25% pwmflg.pwm2en = 1; } else { pwmduty2 = 0xf; //占空比为就是不执行 } } else if(PORTBbits.PB4 == 0) { pwmduty2 = 0xf; //占空比为就是不执行 pwmflg.pwm2en = 0; } //PB5状态检测 if((PORTBbits.PB5 == 1)&&(pwmflg.pwm3en == 0)) { delayms(50); //估计在10ms左右 if(PORTBbits.PB5 == 1) { pwmduty3 = 2; //占空比为30% pwmflg.pwm3en = 1; } else { pwmduty3 = 0xf; //占空比为就是不执行 } } else if(PORTBbits.PB5 == 0) { pwmduty3 = 0xf; //占空比为就是不执行 pwmflg.pwm3en = 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左右 } else { sleepcent = 0; } } }


posted @ 2021-10-28 16:00  steven_lg  阅读(755)  评论(0编辑  收藏  举报