天天看點

基于PIC 16F877A的呼吸燈的實作+Proteus的仿真前言一、如何實作呼吸燈二、proteus電路的搭建實驗效果

前言

在學習的PWM子產品的過程中,見到論壇中關于PIC單片機的呼吸燈的文章很少,然後就自己試着做了一下這實驗。因為最近在學PIC 16F877A的CCP子產品,就想着PIC單片機有着內建的硬體PWM子產品,那麼好的功能,不能浪費了。于是寫下這篇文章希望可以幫助到一些跟我一樣的萌新。

一、如何實作呼吸燈

(1)呼吸燈的原理,通俗的說就是利用PWM波的占空比的變化,讓其輸出的電壓的有效值變化使得LED燈的亮度發送變化(燈泡的亮度是由有效值來确定的),然後通過延時讓消除由PWM波占空比帶來的閃爍影響。(關于如何産生一個PWM波可以看下這篇文章:https://blog.csdn.net/cxj7878789/article/details/108165096)

(2)j簡單的介紹下使用的軟體。

程式設計軟體:MPLAC X IDE

仿真軟體:PRTEUS 8.9

(3)j簡單的介紹下使用的寄存器。

1)T2CON寄存器。

在CCP_PWM子產品中要使用到定時器T2,來産生PWM的周期和脈沖寬度.

設定成T2CON=0X04 //初始化定時器T2,預分頻設定為1:1

2)CCP1CON寄存器。

這個寄存器是用來設定PWM波10位分辨率的低2位和開啟PWM模式用的。

設定成  CCP1CON=0X3C。 //初始化CCP_PWM讓10位分辨率的低兩位為11,開啟PWM模式

3)PR2寄存器

這個寄存器是用來設定PWM波的周期的。

設定成 PR2=99。這樣帶入公式中得到的PWM波的周期為:100ns。

4)CCPR1L寄存器。

這個寄存器是用來改變占空比的。(故初始的PWM波的10位分辨率是CCPR1L:CCP1CON<5;4>=0B0000 0000 11)

5)方向寄存器TRISC

這個寄存器是用來設定PORTC口的輸入/輸出的。

可以直接設定成TRISC=0X00;

也可以按照下圖的步驟來設定。(個人習慣我是按照下圖來産生PWM波的)

基于PIC 16F877A的呼吸燈的實作+Proteus的仿真前言一、如何實作呼吸燈二、proteus電路的搭建實驗效果

6)法一:采用軟體延時法的源代碼

#include <xc.h>

void init_pwm();

void delayms(unsigned char x);

void light_control();

unsigned char flag=0;

unsigned int temp=0;

void main(void) {

    TRISD=0X00;

    PORTD=0X00;

    init_pwm();

    while(1)

    {

        light_control();

    }

    return;

}

void delayms(unsigned char x)

{

    unsigned int a,b;

    for(a=x;a>0;a--)

        for(b=110;b>0;b--);

}

void init_pwm()

{

    T2CON=0X04;  //初始化定時器T2,預分頻設定為1:1

    CCP1CON=0X3C;//初始化CCP_PWM讓10位分辨率的低兩位為11,開啟PWM模式

    CCPR1L=0X00; //初始化這個寄存器為0x00,是為在後面的程式中通過改變CCPR1L來改變占空比以改變電壓的有效值,進而改變LED燈的亮度

    PR2=99;

    TRISC=0XFF;

    TMR2IF=0;

    while(!TMR2IF);

    TRISC=0;

}

void light_control()

{

    delayms(1);

    if(flag==0)

    {

        CCPR1L++;

    }

    else

    {

        CCPR1L--;

    }

    temp=CCPR1L;

    if(temp==0X64)

        flag=1;

    if(temp==0X00)

        flag=0;

}

7)法二:采用定時器延時的方法的源代碼。

// PIC16F877A Configuration Bit Settings

// 'C' source line config statements

// CONFIG

#pragma config FOSC = XT        // Oscillator Selection bits (XT oscillator)

#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)

#pragma config PWRTE = ON       // Power-up Timer Enable bit (PWRT enabled)

#pragma config BOREN = ON       // Brown-out Reset Enable bit (BOR enabled)

#pragma config LVP = OFF        // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)

#pragma config CPD = OFF        // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)

#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)

#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

// #pragma config statements should precede project file includes.

// Use project enums instead of #define for ON and OFF.

這上面的是 MPLAB X IDE的配置位,可能因為軟體的不同會出現不同的情況。

#include <xc.h>

void init_pwm();

void delayms(unsigned char x);

void light_control();

unsigned char i=0;

unsigned int num=0;

void main(void) {

    init_pwm();

    while(1)

    {

        if(num==5)

        {

            light_control();

            num=0;

        }

    }

    return;

}

void delayms(unsigned char x)

{

    unsigned int a,b;

    for(a=x;a>0;a--)

        for(b=110;b>0;b--);

}

void init_pwm()

{

    ADCON1=0X07;

    INTCON=0XE0;

    OPTION_REG=0X80;

    TMR0=0X06;

    T2CON=0X04;  //初始化定時器T2,預分頻設定為1:1

    CCP1CON=0X3C;//初始化CCP_PWM讓10位分辨率的低兩位為11,開啟PWM模式

    CCPR1L=0X00; //初始化這個寄存器為0x00,是為在後面的程式中通過改變CCPR1L來改變占空比以改變電壓的有效值,進而改變LED燈的亮度

    PR2=99;

    TRISC=0XFF;

    TMR2IF=0;

    while(!TMR2IF);

    TMR2IF=0;

    TRISC=0;

}

void light_control()

{

    if(i==0)

    CCPR1L++;

    if(i==1)

    CCPR1L--;

    if(CCPR1L==0X63)

//特别注意:在設定這個CCPR1L的上限值時,一定要根據PR2來計算出PWM的周期後在設定,例如:我是用的PR2=99,得到的是PWM的周期為100ns,所有帶入脈沖寬度公式得到是(CCPR1L:CCP1CON<5:4>)=400=0B0001 1001 00 00。

所有CCPR1L=0110 0100=0X64,因為開始設定CCP1CON=0X3C,低兩位為11,是以為了友善設定成,CCPR1L=0x63

(CCPR1L:CCP1CON<5:4>)=0001 1000 11 11=399,誤差不大,可以接受。

    i=1;SU

    if(CCPR1L==0X00)

    i=0;

}

void interrupt T0()

{

    if(T0IF==1)

    {

        T0IF=0;

        num++;

    }

}

二、proteus電路的搭建

(1)元器件的選擇

基于PIC 16F877A的呼吸燈的實作+Proteus的仿真前言一、如何實作呼吸燈二、proteus電路的搭建實驗效果

(2)電路的搭建

基于PIC 16F877A的呼吸燈的實作+Proteus的仿真前言一、如何實作呼吸燈二、proteus電路的搭建實驗效果

實驗效果

實驗效果本來用視訊來展現是最好的,但是本人不太會上傳視訊。抱歉。。。。

所有隻能用截圖來展現了:

基于PIC 16F877A的呼吸燈的實作+Proteus的仿真前言一、如何實作呼吸燈二、proteus電路的搭建實驗效果
基于PIC 16F877A的呼吸燈的實作+Proteus的仿真前言一、如何實作呼吸燈二、proteus電路的搭建實驗效果
基于PIC 16F877A的呼吸燈的實作+Proteus的仿真前言一、如何實作呼吸燈二、proteus電路的搭建實驗效果

繼續閱讀