基于51单片机的电表电量采集模拟系统Proteus仿真原理图PCB

功能介绍:
0.本系统采用STC89C52作为单片机
1.采用LCD1602液晶循环显示当前检测的用电量
2.设计了eeprom可存储各个用户用电量
3.利用8个电位器模拟用户用电情况,便于演示
4.利用CD4051多路开光与一片ADC芯片配合实现了多路信号采集

原理图:
在这里插入图片描述

PCB:
在这里插入图片描述

主程序:

#include "main.h"

bit refreshFlag = 1;

bit isNewFlag; //是否为新芯片 
float xdata Power[8] = 0;
unsigned char setIndex = 0;
unsigned char i = 0;
unsigned char ADC_Value;

char dis0[16]; //定义显示区域临时存储数组
void main(void)
{
    bit ack = 0;
    
    Timer0_Init();
    EEPROM_Init();
    LCD_Init();   //初始化液晶
    DelayMs(200); //延时有助于稳定
    LCD_Clear();  //清屏
    
    ReadEEPROM();
    if (isNewFlag != 0) //新芯片
    {
        EEPROM_WriteByte(ISNEW_ADDRESS, 0);
        
        //给出初始值
        for (i = 0; i <= 7; i++)
        {
            Power[i] = 0;
        }

        WriteEEPROM();
    }

    while (1) //主循环
    {
        
        if (refreshFlag == 1) //1s刷新一次数据
        {
            static unsigned char cnt = 0;

            refreshFlag = 0;
            
            TR0 = 0;

            for (i=0; i<=7; i++)
            {

                CD4051_SelChannel(i); //配置采集通道
                ADC_Value = ReadADC(AIN0_GND); //ADC采集
                DelayMs(10);
                if (ADC_Value > 5) //当采集值大于5时, 开始计算用电量, 为了滤除噪声取5为界限
                {
                    Power[i] = Power[i] + (220 * (float)ADC_Value * 5 / 255) / 3.6; //换算千瓦时
                    EEPROM_WriteByte(BASE_ADDRESS+2*i, (((unsigned int)Power[i] & 0xFF00) >> 8));
                    EEPROM_WriteByte(BASE_ADDRESS+2*i+1, ((unsigned int)Power[i] & 0x00FF));
                    ADC_Value = 0;
                }
                
            }

            DispNormal(cnt);

            cnt++;
            if (cnt > 7)
                cnt = 0;

            TR0 = 1;
            
        }
        CheckKey();

    }
}


void WriteEEPROM(void) //写入用电量
{
	for (i=0; i<=7; i++)
    {
        EEPROM_WriteByte(BASE_ADDRESS+2*i, (((unsigned int)Power[i] & 0xFF00) >> 8));
        EEPROM_WriteByte(BASE_ADDRESS+2*i+1, ((unsigned int)Power[i] & 0x00FF));
    }
}


void ReadEEPROM(void) //读取用电量
{
    isNewFlag = EEPROM_ReadByte(ISNEW_ADDRESS);
    
	for (i=0; i<=7; i++)
    {
        Power[i] = EEPROM_ReadByte(BASE_ADDRESS + 2*i);
        Power[i] = ((unsigned int)Power[i] << 8) | EEPROM_ReadByte(BASE_ADDRESS + 2*i + 1);
    }
}

void DispNormal(unsigned char channel)
{
    sprintf(dis0, " Consumption %02d ", (unsigned int)channel); //打印通道值
    LCD_DispStr(0, 0, dis0);

    sprintf(dis0, " %10.4fkWh ", Power[channel]/1000000); //打印用电量
    LCD_DispStr(0, 1, dis0);                    //显示第二行
}

void CheckKey(void)
{
    if (!KEY_CLEAR) //清零按键按下
    {
        DelayMs(10);
        if (!KEY_CLEAR)
        {
            for (i=0; i<=7; i++)
            {
                Power[i] = 0;
            }
            WriteEEPROM();
        }
        while (!KEY_CLEAR);
    }
    
}

/*------------------------------------------------
                    定时器初始化子程序
------------------------------------------------*/
void Timer0_Init(void)
{
    TMOD |= 0x01; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
	TL0 = 0x00;		//设置定时初值50ms
	TH0 = 0x4C;		//设置定时初值
    EA = 1;  //总中断打开
    ET0 = 1; //定时器中断打开
    TR0 = 1; //定时器开关打开
}

/*------------------------------------------------
                定时器中断子程序
------------------------------------------------*/
void Timer0_Interrupt(void) interrupt 1
{
    static unsigned char time50ms = 0;
    
	TL0 = 0x00;		//设置定时初值50ms
	TH0 = 0x4C;		//设置定时初值

    time50ms++;
    if (time50ms >= 20) // 1s
    {
        time50ms = 0;
        refreshFlag = 1;
    }
    
}

仿真演示视频:
https://www.bilibili.com/video/BV16U4y1m7mV/

实物演示视频:
https://www.bilibili.com/video/BV1WS4y187Cj/

  • 0
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值