基于51单片机的时钟电子秤称重系统proteus仿真原理图PCB

功能介绍:
0.本系统采用STC89C52作为单片机
1.采用LCD1602液晶显示当前时间和检测重量
2.按键可更改时间和设置超重报警阈值
3.采用HEX711和称重支架传感器获取物体重量信息,传入给单片机后再处理,一旦超重后,蜂鸣器报警
4.时钟芯片采用DS1302

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

PCB:
在这里插入图片描述

主程序:

#include <reg52.h>
#include "main.h"

enum MODE_DF{NORMAL, SET_ALARM}dispMode;
bit setFlag = 0;
unsigned char setIndex=0;
unsigned int alarmWeight = 5000;
unsigned char alarmWeightBuf;
unsigned long initialWeight = 0; //单位g
float objectWeight = 0; //单位g
bit dispFlag; //液晶刷新标志

void main()
{
    dispMode = NORMAL;
    // 定时器初始化
    Timer0_Init();
    DS1302_Init();


    // 开机显示
    LCD_Init();
    LCD_DispStr(0, 0, "Electronic Scale");
    LCD_DispStr(0, 1, "is initializing!");
    DelayS(2);
    initialWeight = HX711_GetInitialWeight();
    LCD_Clear();

    while(1)
    {        
        
        if (dispFlag == 1 && setFlag == 0)
        {
            dispFlag = 0;

            DS1302_ReadTime();
            if (dispMode == NORMAL)
            {
                DispWeight();
                DispTime(setIndex);
            }
            else if (dispMode == SET_ALARM)
            {
                DispAlarm();
            }
        }   
        KeyProcess();
    }
}

void DispWeight()
{
    unsigned char dispRow[16];
    static unsigned char i=0;

    if (i == 5) //计算5次测量的平均值
    {
        objectWeight = objectWeight / 5 - initialWeight;
        if (objectWeight < 0)
        {
            objectWeight = 0;
        }
        
        objectWeight = (objectWeight * 10 / GAPVALUE);
        
        if (objectWeight > alarmWeight)
        {
            BUZZER = 0;
        }
        else
        {
            BUZZER = 1;
        }
        
        sprintf(dispRow, "Weight: %6.3fkg", objectWeight / 1000);
        LCD_DispStr(0, 1, dispRow);
        
        i = 0;
        objectWeight = 0;
    }
    else
    {   
        TR0 = 0;
        objectWeight = objectWeight + HX711_Read();
        TR0 = 1;
        i++;
    }

}

void DispTime(unsigned char setIndex)
{
    unsigned char dispRow[16];
    
    switch (timeBufDec[7])
    {
        case 0: sprintf(dispRow, "%02d/%02d 7 %02d:%02d:%02d", (int)timeBufDec[2], (int)timeBufDec[3], (int)timeBufDec[4], (int)timeBufDec[5], (int)timeBufDec[6]); break;
        case 1: sprintf(dispRow, "%02d/%02d 7 %02d:%02d:%02d", (int)timeBufDec[2], (int)timeBufDec[3], (int)timeBufDec[4], (int)timeBufDec[5], (int)timeBufDec[6]); break;
        case 2: sprintf(dispRow, "%02d/%02d 1 %02d:%02d:%02d", (int)timeBufDec[2], (int)timeBufDec[3], (int)timeBufDec[4], (int)timeBufDec[5], (int)timeBufDec[6]); break;
        case 3: sprintf(dispRow, "%02d/%02d 2 %02d:%02d:%02d", (int)timeBufDec[2], (int)timeBufDec[3], (int)timeBufDec[4], (int)timeBufDec[5], (int)timeBufDec[6]); break;
        case 4: sprintf(dispRow, "%02d/%02d 3 %02d:%02d:%02d", (int)timeBufDec[2], (int)timeBufDec[3], (int)timeBufDec[4], (int)timeBufDec[5], (int)timeBufDec[6]); break;
        case 5: sprintf(dispRow, "%02d/%02d 4 %02d:%02d:%02d", (int)timeBufDec[2], (int)timeBufDec[3], (int)timeBufDec[4], (int)timeBufDec[5], (int)timeBufDec[6]); break;
        case 6: sprintf(dispRow, "%02d/%02d 5 %02d:%02d:%02d", (int)timeBufDec[2], (int)timeBufDec[3], (int)timeBufDec[4], (int)timeBufDec[5], (int)timeBufDec[6]); break;
        case 7: sprintf(dispRow, "%02d/%02d 6 %02d:%02d:%02d", (int)timeBufDec[2], (int)timeBufDec[3], (int)timeBufDec[4], (int)timeBufDec[5], (int)timeBufDec[6]); break;
        default: ;
    }
    LCD_DispStr(0, 0, dispRow);

    switch (setIndex)
    {
        case 1: LCD_LocateXY(1 , 0); break;
        case 2: LCD_LocateXY(4 , 0); break;
        case 3: LCD_LocateXY(6 , 0); break;
        case 4: LCD_LocateXY(9 , 0); break;
        case 5: LCD_LocateXY(12, 0); break;
        case 6: LCD_LocateXY(15, 0); break;
        default: ;
    }
}

void DispAlarm()
{
    unsigned char dispRow[16];

    sprintf(dispRow, "Alarm : %6.3fkg", (float)alarmWeight / 1000);
    LCD_DispStr(0, 0, dispRow);
}

void KeyProcess()
{
    if (!KEY_UP) //按键加
    {
        DelayMs(180);
        if (!KEY_UP)
        {
            if (dispMode == NORMAL && setFlag == 1)
            {
                switch (setIndex)
                {
                case 1:
                {
                    timeBufDec[2]++;
                    if (timeBufDec[2] >= 13)
                    {
                        timeBufDec[2] = 1;
                    }
                    break;
                }
                case 2:
                {
                    timeBufDec[3]++;
                    if (timeBufDec[3] >= YDay(timeBufDec[1], timeBufDec[2]) + 1)
                    {
                        timeBufDec[3] = 1;
                    }
                    break;
                }
                case 3:
                {
                    timeBufDec[7]++;
                    if (timeBufDec[7] > 7)
                    {
                        timeBufDec[7] = 1;
                    }
                    break;
                }
                case 4:
                {
                    timeBufDec[4]++;
                    if (timeBufDec[4] >= 24)
                    {
                        timeBufDec[4] = 0;
                    }
                    break;
                }
                case 5:
                {
                    timeBufDec[5]++;
                    if (timeBufDec[5] >= 60)
                    {
                        timeBufDec[5] = 0;
                    }
                    break;
                }
                case 6:
                {
                    timeBufDec[6]++;
                    if (timeBufDec[6] >= 60)
                    {
                        timeBufDec[6] = 0;
                    }
                    break;
                }
                default:;
                }
                DispTime(setIndex);
            } 

            if (dispMode == SET_ALARM)
            {
                alarmWeight = alarmWeight + 10;
                if (alarmWeight > 5000)
                {
                    alarmWeight = 5000;
                }
            }
        }
        //while (!KEY_UP);
    }

    if (!KEY_DOWN) //按键减
    {
        DelayMs(180);
        if (!KEY_DOWN)
        {
            if (dispMode == NORMAL && setFlag == 1)
            {
                switch (setIndex)
                {
                case 1:
                {
                    timeBufDec[2]--;
                    if (timeBufDec[2] < 1)
                    {
                        timeBufDec[2] = 12;
                    }
                    break;
                }
                case 2:
                {
                    timeBufDec[3]--;
                    if (timeBufDec[3] < 1)
                    {
                        timeBufDec[3] = YDay(timeBufDec[1], timeBufDec[2]);
                    }
                    break;
                }
                case 3:
                {
                    timeBufDec[7]--;
                    if (timeBufDec[7] < 1)
                    {
                        timeBufDec[7] = 7;
                    }
                    break;
                }
                case 4:
                {
                    if (timeBufDec[4] == 0)
                    {
                        timeBufDec[4] = 24;
                    }
                    timeBufDec[4]--;
                    break;
                }
                case 5:
                {
                    if (timeBufDec[5] == 0)
                    {
                        timeBufDec[5] = 60;
                    }
                    timeBufDec[5]--;
                    break;
                }
                case 6:
                {

                    if (timeBufDec[6] == 0)
                    {
                        timeBufDec[6] = 60;
                    }
                    timeBufDec[6]--;
                    break;
                }
                default:;
                }
                DispTime(setIndex);
            } 

            if (dispMode == SET_ALARM)
            {
                alarmWeight = alarmWeight - 10;
                if (alarmWeight <= 0)
                {
                    alarmWeight = 0;
                }
            }
        }
        //while (!KEY_DOWN);
    }
    
    if (!KEY_SET)
    {
        DelayMs(20);
        if (!KEY_SET)
        {
            if (dispMode == NORMAL)
            {
                if (setFlag == 0)
                {
                    setFlag = 1; //进入时间设置
                    setIndex = 1;
                }
                else
                {
                    setIndex++;
                    if (setIndex >= 7)
                    {
                        setFlag = 0; //退出时间设置
                        setIndex = 0;
                    }
                }
                DispTime(setIndex);
            }

        }

仿真演示视频:
https://www.bilibili.com/video/BV16U4y1m7bc/
实物演示视频:
https://www.bilibili.com/video/BV13v4y1A7Wj/

  • 2
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
51单片机谐波检测程序的实现需要按照以下步骤进行: 1.配置定时器:使用定时器实现精确的时间测量。需要设置定时器的计数器初值和计数器溢出中断。 2.配置模拟输入:使用ADC转换模块采集模拟输入信号,需要设置ADC的参考电压、采样时钟和输入通道。 3.进行谐波检测:在定时器溢出中断中对ADC采样结果进行处理,得到输入信号的频率和幅值,进而判断是否存在谐波。 以下是一份简单的51单片机谐波检测程序代码: ```c #include <reg52.h> #define FREQ_THRES 50 #define AMP_THRES 500 unsigned char code freq_table[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; void init_timer(void) { TMOD = 0x01; // 设置定时器1为模式1 TH0 = 0xff; // 定时器计数器初值 TL0 = 0xff; ET0 = 1; // 开启定时器1中断 TR0 = 1; // 启动定时器1 } void init_adc(void) { ADC_CONTR = 0xe0; // 设置ADC转换时钟为最大值 } unsigned int get_adc_value(void) { ADC_CONTR |= 0x08; // 启动ADC转换 while (!(ADC_CONTR & 0x10)); // 等待转换完成 return (ADC_RES << 2) | (ADC_RESL & 0x03); // 返回ADC采样结果 } void timer_isr(void) interrupt 1 { static unsigned int cnt = 0; static unsigned int freq = 0; static unsigned int amp = 0; static unsigned char index = 0; cnt++; if (cnt >= 1000) // 1000个定时器周期为1秒 { cnt = 0; freq = index * 1000 / (TH0<<8|TL0); amp = get_adc_value(); if (freq > FREQ_THRES && amp > AMP_THRES) { P0 = freq_table[index]; } else { P0 = 0xff; // 不满足条件时输出全灭 } index = 0; } else if (cnt % 100 == 0) // 每100个定时器周期记录一次计数器值 { index++; } } void main(void) { init_timer(); init_adc(); while (1); } ``` 对于仿真,可以使用Keil C51集成开发环境中的仿真器进行测试。首先需要在Keil中新建一个工程,将上述代码复制到工程中的main.c文件中,并添加头文件reg52.h。然后进行编译,生成hex文件。最后使用Keil中的仿真器调试工具打开hex文件进行仿真测试。在仿真过程中,可以对单片机的寄存器、内存、IO口等进行实时监测和调试,以便发现程序中可能存在的问题。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值