天天看點

單片機應用——PWM輸出(一)

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

單片機應用——PWM輸出(一)

具體源程式如下所示

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左右