PIC16F877 定时采集电压 LCD1602显示 Proteus仿真图

功能:定时器间隔50us采集一次AD电压,一共采集30次,并通过LCD1602显示。

软件:MPLAB X IDE v5.35,ISIS 7 Professional

注意事项:系统时钟配置为外部时钟8Mhz,由于间隔50us采集一次,所以AD采集一次时间应该小于50us。可通过调整定时器的数值,间隔不同的时间采集AD。

代码如下:

#include "pic.h"
#define RS  RC1  //command or data
#define RW  RC2  //read write io
#define EN  RC3   //enable

__CONFIG(FOSC_HS & WDTE_OFF & PWRTE_ON & CP_OFF & BOREN_ON & LVP_ON & CPD_OFF);

void LCD1602_Init(void); 
void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);  //display 
void Time_Init(void);
void ADC_Init(char k);
int AD_CollectVolt(void);

char AD_Complete_Flag = 0;    
unsigned int arr[30];  
unsigned int ad_volt = 0;  
unsigned long sum = 0;
unsigned char num = 0,j = 0;
unsigned int Data = 0;
unsigned char volt_num[5];

void main(void)  //Fosc = 8Mhz
{
    PEIE = 1;  
    GIE = 1;  
    TRISC = 0X00;  //OUTPUT
    TRISD = 0X00;  //OUTPUT

    Time_Init();  //50us interrupt
    ADC_Init(0);  //Channel 0 RA0
    LCD1602_Init();
    
    while(1)
    {
        AD_CollectVolt();
        volt_num[0] = ad_volt/1000 + 48;
        volt_num[1] = ad_volt/100%10 + 48;
        volt_num[2] = ad_volt/10%10 + 48;
        volt_num[3] = ad_volt%10 + 48;
        volt_num[4] = '\0';
        LcdShowStr(0, 0, &volt_num);
        LcdShowStr(5, 0, "MV");
    }
}

void interrupt ISR(void)
{
    static unsigned char test = 0;
    if((TMR1IE == 1) && (TMR1IF == 1))  
    {
        TMR1IF = 0;  
        TMR1 = TMR1 + 0xffcd;  
        
        if(GO != 1)  
        {
            Data = ADRESH; 
            Data = Data << 8;  
            Data = Data | ADRESL;   
            arr[num]= Data;
            num ++;
        }
        GO = 1;  
        if(test == 0)  //test 50us time GPIO
        {
            RC4 = 0;
            test = 1;
        }
        else
        {
            RC4 = 1;
            test = 0;
        }

        if(num >= 30)  
        {
            TMR1ON = 0;    
            TMR1IE = 0;
            for(j = 0;j < 30;j ++)
            {
                sum = sum + arr[j];
            }
            sum = sum/30;
            ad_volt = sum*5000/1024;
            sum = 0;
            num = 0;
            AD_Complete_Flag = 1;
        }
    }
}

void LCD_WaitReady(void)
{
    unsigned char sta;
    PORTD = 0xff;
    RS = 0;
    RW = 1;
    do
    {
        EN = 1;
        sta = PORTD;
        EN = 0;
    }
    while(sta&0x80);
}

void Write_Command(unsigned char Command)
{
    LCD_WaitReady();
    PORTD = Command;
    RW = 0;
    RS = 0;
    EN = 1;
    EN = 0;    
}

void Write_Data(unsigned char Data)
{
    LCD_WaitReady();
    PORTD = Data;
    RW = 0;
    RS = 1;
    EN = 1;
    EN = 0;    
}

void LcdSetCursor(unsigned char x, unsigned char y)
{
    unsigned char addr;
    if (y == 0)
    { 
        addr = 0x00 + x;
    }
    else
    {
        addr = 0x40 + x; 
    }
    Write_Command(addr | 0x80); 
}

void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str)
    {
    LcdSetCursor(x, y); 
    while (*str != '\0')
    { 
        Write_Data(*str++); 
    }
}

void LCD1602_Init(void)
{
    Write_Command(0x38);
    Write_Command(0x0c);
    Write_Command(0x06);
    Write_Command(0x01);
}

void Time_Init(void)
{
    TMR1CS = 0;  //FOSC/4
    T1CKPS1 = 0;
    T1CKPS0 = 1;  //1:2      
    TMR1 = 0xffcd;  //50us    
    TMR1IF = 0;  
    TMR1IE = 1;  
}
void ADC_Init(char k)
{
    TRISA = 0XFF;  //input
    ADCON1 = 0X80;
    ADCON0 = 0b00000001;  //FOSC/2
    ADCON0 |= (k << 3);       
}
int AD_CollectVolt(void)  
{
    TMR1ON = 1;
    TMR1IE = 1;
    GO = 1;         
    do  
    {
    }
    while(AD_Complete_Flag == 0);  //delay collect volt complete
    AD_Complete_Flag = 0;
}

硬件图:

在RA1中连接外部3V电源,LCD显示2998mv;

注意:如何验证是否真的50us采集一次,在定时器中断函数里通过IO口电平翻转,然后用示波器来观察;

如上图所示,50us翻转一次,说明是50us采集一次AD值。

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值