基于hx711的51单片机电子秤设计

嵌入式设计应用

127人已加入

描述

  电子秤是采用现代传感器技术、电子技术和计算机技术一体化的电子称量装置,满足并解决现实生活中提出的“快速、准确、连续、自动”称量要求,同时有效地消除人为误差,使之更符合法制计量管理和工业生产过程控制的应用要求。

硬件设计

51单片机

  称重传感器感应被测重力,输出微弱的毫伏级电压信号。该电压信号经过电子秤专用模拟/数字(A/D)转换器芯片hx711对传感器信号进行调理转换。HX711 采用了海芯科技集成电路专利技术,是一款专为高精度电子秤而设计的24 位A/D 转换器芯片,内置增益控制,精度高,性能稳定。HX711芯片通过2线串行方式与单片机通信。单片机读取被测数据,进行计算转换,再液晶屏上显示出来。

  矩阵键盘主要用于计算金额。当被测物体重量得到后,用户可以通过矩阵键盘输入单价,电子秤自动计算总金额并在液晶屏显示。电源系统给单片机、HX711电路及传感器供电。

  电子秤专用24位AD转换芯片HX711电路

51单片机
51单片机

  单片机STC89C52电路

51单片机
51单片机

  液晶屏电路

51单片机

  矩阵键盘电路

51单片机

  矩阵键盘可以显示0-9数字、小数点和五个功能键。键盘行扫描信号为ROW1—ROW4,列扫描信号为COL1—COL4。行信号为输入信号,低电平有效;列信号为输出信号。当没有键按下时,即使行扫描输入低电平信号,列信号仍为高电平;当行扫描为低电平并且有键按下时,相应的列输出低电平。该低电平信号可以定位至按下键的位置。

  声光报警电路

51单片机

  当测量重量超过量程时,beep和alert给出低电平信号,驱动蜂鸣器鸣响,报警灯亮。

  电源电路

51单片机

  电源采用USB接口供电,电源电压5V。同时,USB接口通过内含PL2303芯片的转换电路对单片机进行程序编写。

软件设计

  主程序使用了定时器,用来实现每0.5秒称重一次的功能,流程图如下:

51单片机       51单片机

  时钟中断程序流程图                                 键盘扫描程序流程图               

51单片机

  主程序流程图

主程序编写

  下面介绍main.c主程序编写,其他程序略。

  (1) 头文件和一些宏定义

  #include 《reg52.h》

  #include 《intrins.h》

  #include 《string.h》

  #include “lcd.h”

  #include “hx711.h”

  #include “keyboard.h”

  //定义量程系数

  #define RATIO 2114/1623

  (2) 管脚、常量、变量定义

  //定义标识

  volatile bit FlagTest = 0;

  //定时测试标志,每0.5秒置位,测完清0

  volatile bit FlagKeyPress = 0; //有键按下标志,处理完毕清0

  volatile bit FlagSetPrice = 0; //价格设置状态标志,设置好为1

  //管脚定义 sbit LedA = P2^2;

  sbit beep = P1^0;

  sbit alert = P1^1;

  //显示用变量 int Counter;

  uchar idata str1[6] = “000000”;

  int i, iTemp; //称重用变量

  unsigned long idata FullScale; //满量程AD值/1000

  unsigned long AdVal; //AD采样值

  unsigned long weight; //重量值,单位g

  unsigned long idata price; //单价,长整型值,单位为分

  unsigned long idata money; //总价,长整型值,单位为分

  //键盘处理变量

  uchar keycode; uchar DotPos;

  //小数点标志及位置

  (4) 各子程序

  //整型转字符串的函数,转换范围0--65536 void int2str(int x, char* str)

  {

  int i=1;

  int tmp=10;

  while(x/tmp!=0)

  {

  i++;

  tmp*=10;

  }

  tmp=x;

  str[i]=‘’;

  while(i》1)

  {

  str[--i]=‘0’+(tmp%10);

  tmp/=10;

  }

  str[0]=tmp+‘0’;

  }

  //重新找回零点,每次测量前调用

  void To_Zero() {

  FullScale=ReadCount()/1000;

  price=0;

  }

  //显示单价,单位为元,四位整数,两位小数

  void Display_Price()

  {

  unsigned int i,j;

  display_GB2312_string(5,44,“ ”);

  i = price/100; //得到整数部分

  j = price - i*100;//得到小数部分

  int2str(i,str1); //显示整数部分

  if (i》=1000)

  {

  display_GB2312_string(5,44,str1);

  }

  else if (i》=100)

  {

  display_GB2312_string(5,52,str1);

  }

  else if (i》=10)

  {

  display_GB2312_string(5,60,str1);

  }

  else

  {

  display_GB2312_string(5,68,str1);

  }

  //显示小数点

  display_GB2312_string(5,76,“。”);

  //显示小数部分

  int2str(j,str1);

  if (j《10)

  {

  display_GB2312_string(5,84,“0”);

  display_GB2312_string(5,92,str1);

  }

  else

  {

  display_GB2312_string(5,84,str1);

  }

  }

  //显示重量,单位kg,两位整数,三位小数

  void Display_Weight()

  {

  unsigned int i,j;

  display_GB2312_string(3,60,“ ”); //weight单位是g

  i = weight/1000; //得到整数部分

  j = weight - i*1000;//得到小数部分

  int2str(i,str1);

  if (i》=10)

  {

  display_GB2312_string(3,60,str1);

  }

  else

  {

  display_GB2312_string(3,68,str1);

  }

  display_GB2312_string(3,76,“。”);

  int2str(j,str1);

  if (j《10) else if (j《100)

  {

  display_GB2312_string(3,84,“0”);

  display_GB2312_string(3,92,str1);

  }

  else

  {

  display_GB2312_string(3,84,str1);

  }

  }

  //显示总价,单位为元,四位整数,两位小数

  void Display_Money()

  {

  unsigned int i,j;

  display_GB2312_string(7,44,“ ”);

  if (money》999999) //超出显示量程

  {

  display_GB2312_string(7,44,“-------”);

  return;

  }

  display_GB2312_string(7,44,str1);

  }

  else if (i》=100)

  {

  display_GB2312_string(7,52,str1);

  }

  else if (i》=10)

  {

  display_GB2312_string(7,60,str1);

  }

  else

  {

  display_GB2312_string(7,68,str1);

  }

  //显示小数点

  display_GB2312_string(7,76,“。”); //显示小数部分

  int2str(j,str1);

  if (j《10)

  {

  display_GB2312_string(7,84,“0”);

  display_GB2312_string(7,92,str1);

  }

  else

  {

  display_GB2312_string(7,84,str1);

  }

  }

  //数据初始化

  void Data_Init()

  {

  price = 0;

  DotPos = 0;

  beep = 1;

  alert = 1;

  }

  //管脚配置 void Port_Init()

  {

  }

  //定时器0初始化

  void Timer0_Init()

  {

  ET0 = 1; //允许定时器0中断 TMOD = 1;

  //定时器工作方式选择 TL0 = 0x06;

  TH0 = 0xf8; //定时器赋予初值

  TR0 = 1; //启动定时器

  }

  //定时器0中断

  void Timer0_ISR (void) interrupt 1 using 0

  {

  TL0 = 0x06;

  TH0 = 0xf8; //定时器赋予初值

  //每0.5秒钟刷新重量

  Counter ++;

  if (Counter 》= 200)

  {

  FlagTest = 1;

  Counter = 0;

  }

  }

  //===============main program===================//

  void main(void)

  {

  Rom_CS=1;

  initial_lcd();

  EA = 0;

  Data_Init();

  Port_Init();

  Timer0_Init(); //初始化完成,开中断

  EA = 1; //背光

  LedA = 1;

  clear_screen(); //clear all dots

  display_GB2312_string(1,1,“电子秤初始化。。。。”);

  To_Zero();

  display_GB2312_string(1,1,“电子秤初始化成功”);

  display_GB2312_string(3,1,“重量: kg”);

  display_GB2312_string(5,1,“单价: 元”);

  display_GB2312_string(7,1,“金额: 元”);

  Display_Price();

  while(1)

  {

  //每0.5秒称重一次

  if (FlagTest==1)

  {

  //称重,得到重量值weight,单位为g

  AdVal=ReadCount();

  weight=FullScale-AdVal/1000;

  if (weight》0x8000) weight=0;

  weight=10000*weight/FullScale;

  weight=weight*RATIO; //如果超量程,则报警

  if (weight 》= 10000)

  {

  beep = 0;

  alert = 0;

  display_GB2312_string(3,60,“------”);

  display_GB2312_string(7,44,“--------”);

  }

  //如果不超量程

  else

  {

  beep = 1;

  alert = 1; //显示重量值

  Display_Weight();

  //如果单价设定好了,则计算价格

  if (FlagSetPrice == 1)

  {

  money = weight*price/1000; //money单位为分

  //显示总金额

  Display_Money();

  }

  else

  {

  display_GB2312_string(7,44,“ ”);

  }

  //清测试标志

  FlagTest = 0;

  }

  }

  //获取按键

  keycode = Getkeyboard(); //有效键值0-15

  if ((keycode《16)&&(FlagKeyPress==0))

  {

  FlagKeyPress = 1;

  KeyPress(keycode);

  FlagKeyPress = 0;

  }

  delay(20);

  }

  }

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分