基于PIC 16F877A的呼吸灯的实现+Proteus的仿真

前言

在学习的PWM模块的过程中,见到论坛中关于PIC单片机的呼吸灯的帖子很少,然后就自己试着做了一下这实验。因为最近在学PIC 16F877A的CCP模块,就想着PIC单片机有着集成的硬件PWM模块,那么好的功能,不能浪费了。于是写下这篇帖子希望可以帮助到一些跟我一样的萌新。

一、如何实现呼吸灯

(1)呼吸灯的原理,通俗的说就是利用PWM波的占空比的变化,让其输出的电压的有效值变化使得LED灯的亮度发送变化(灯泡的亮度是由有效值来确定的),然后通过延时让消除由PWM波占空比带来的闪烁影响。(关于如何产生一个PWM波可以看下这篇文章:https://blog.****.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的仿真

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的仿真

(2)电路的搭建

基于PIC 16F877A的呼吸灯的实现+Proteus的仿真


实验效果

实验效果本来用视频来体现是最好的,但是本人不太会上传视频。抱歉。。。。

所有只能用截图来体现了:

基于PIC 16F877A的呼吸灯的实现+Proteus的仿真

基于PIC 16F877A的呼吸灯的实现+Proteus的仿真

基于PIC 16F877A的呼吸灯的实现+Proteus的仿真