天天看点

基于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电路的搭建实验效果