找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1583|回复: 0
打印 上一主题 下一主题
收起左侧

基于51单片机电子秤PCB与源代码

[复制链接]
跳转到指定楼层
楼主
Altium Designer画的PCB图如下:(51hei附件中可下载工程文件)


单片机源程序如下:
  1. /*************************************************
  2. /********************************************************************
  3. ***********主题:基于51单片机电子称c程序设计       
  4. ***********功能: 可以输出量程为5kg物体的重量并且结合键盘单价的输入计算
  5. ***********      出价格,还具有去皮、休眠、切换量程等功能,输出的重量和
  6. ***********      总额采用四舍五入
  7. *********************************************************************/

  8. #include "Main.h"
  9. bit   g_DecimalPointflag = 0, KeycanFlag = 0, RangeFlag = 0, TotalFlag = 0;          //小数点按下标志位,数字按键按下标志位,量程切换标志位
  10. sbit  Beep  = P1^3;                                             //蜂鸣器报警
  11. sbit  Led   = P1^4;                                            //报警LED
  12. sbit  RATE   = P2^5;                                        //转换速率调节
  13. UINT_16 g_HighPrice = 0;                            //输入单价存储整数部分变量
  14. UINT_8  g_LowPrice = 0;                                        //输入单价存储小数点后部分变量
  15. UINT_8  Count1 = 0, Count2 = 0, DecimalPointCount = 0;                  //Count1限定输入单价整数部分的次数(限定为5位数,超过自动清零),Count限定为两位小数,超过自动清零
  16. FLOAT_32 g_Price = 0.0;                             //物品单价(整数与小数之和)
  17. UINT_32 g_TotalPrices = 0;                          //物品总额
  18. FLOAT_32 g_TempPrices = 0.0;                   //总额中间变量(防止总额过大超出液晶屏显示,超出时警告)
  19. UINT_8 code table1[] = {"欢迎你"};
  20. UINT_8 code table2[] = {"重量G:     g"};
  21. UINT_8 code table3[] = {"单价$:"};
  22. UINT_8 code table4[] = {"总额$:"};
  23. UINT_8 code table5[] = {"Err!"};
  24. UINT_8 code table6[] = {"          "};                         //清屏的某一行
  25. UINT_8 code table7[] = {"重量G:0.000Kg"};
  26. UINT_8 code table8[] = {"0.000"};                            //用空格会引起闪烁感
  27. UINT_8 WeightTable[6];                                         //存储质量的字符串
  28. UINT_8 TotalPricesTable[11];                         //存储总额字符串
  29.                                          
  30. void Init(void);                                                   //初始化函数
  31. void Clean_Price(void);                                           //清除函数
  32. void Display_Int2str(UINT_32 DecNum, UINT_8 Str[], UINT_8 DDRAM);                 //输入十进制显示字符函数
  33. void Init_Weighttab(UINT_8 *String1, UINT_8 *String2);                                         //初始化字符串数组

  34. void main()                                                                                       
  35. {         
  36.         INT_8 j = 0, k = 0, count = 0;
  37.     UINT_8 Key = 0, Num = 0;                //Key存储按键的键值,Num存储按下的是那个数字
  38.         UINT_32 tmp = 0;                  
  39.         Init();
  40.         while (1)
  41.         {
  42.                 WDT_FeedDog();                           //喂狗
  43.                 if (KeycanFlag == 0)                                        //价格还没输入时可以显示(防止价格输入一半DDRAM地址改变,造成价格不可连续输入)
  44.                 {          
  45.                         if (TimeCount >= 50)                            //定时时间超过250ms执行AD采集
  46.                         {
  47.                                 //        Offset = AD_Hx711();                                                                 //8527820-8475960 =51860
  48.                                 //        Display_Int2str(Offset, WeightTable, 0x93);
  49.                                  WeightTemp = AD_Weight(AD_Hx711());                                   //把AD值转化为以克为单位的质量(含小数)
  50.                                 if (WeightTemp > 4000)                                                            //超出量程4000g报警
  51.                                 {       
  52.                                         for (k = 0; k < 4; k++)
  53.                                         {
  54.                                                 LcdDdram_Display(1,3,table5);                  //输出错误字符串                                  
  55.                                         }
  56.                                         Beep = 0;                          //蜂鸣器鸣叫
  57.                                         Led  = 0;                          //Led亮
  58.                                 }       
  59.                                 else
  60.                                 {                                                                                                             
  61.                                         Beep = 1;                                                                           //重量少于最大量程关闭蜂鸣器
  62.                                         Led  = 1;       
  63.                                         tmp = (UINT_32)(WeightTemp);        //        tmp = (UINT_32)(WeightTemp + 0.5);                   //将质量四舍五入,例如1000.50 》1001
  64.                                         if(RangeFlag == 0)                                                  //量程单位为g
  65.                                         {               
  66.                                                 Init_Weighttab(WeightTable,table6);        //初始化字符数组为空格,防止上次字符位数比这次大,没有清除
  67.                                                 k = 0;                                                                 //例如上次显示1234,这次12,残留34
  68.                                             Weight = tmp;                                                 //中间质量变量赋给质量
  69.                                                 while (tmp != 0)                                                                                
  70.                                                 {
  71.                                                         WeightTable[k++] = 0x30 + tmp % 10;                         //提取十进制最后一位转换为字符
  72.                                                     tmp /= 10;               
  73.                                                 }       
  74.                                                 if (k == 0)                                        //质量为0时
  75.                                                 {       
  76.                                                         WeightTable[k++] = '0';                  
  77.                                                 }       
  78.                                                 Write_Cmd(0x93);                                                                        
  79.                                                 count = k;
  80.                                                 while (k > 0)                       
  81.                                             {       
  82.                                                         Write_Data(WeightTable[k-1]);          //质量倒序输出,因为之前是倒序输入,高位地址为高位,由高位到低位       
  83.                                                         k--;                                                                  
  84.                                                 }        
  85.                                                 for (k = count; k < 5; k++ )                  //把上次残留的字符清掉
  86.                                                 {
  87.                                                          Write_Data(WeightTable[k]);
  88.                                                 }
  89.                                         }
  90.                                         else
  91.                                         {
  92.                                                 Init_Weighttab(WeightTable,table8);                         //清空字符串数组
  93.                                                 k = 0;
  94.                                                 Weight = tmp / 1000.0;                                    //质量/g 1000 =  /kg
  95.                                                   while (tmp != 0)                                                        
  96.                                                 {
  97.                                                         WeightTable[k++] = 0x30 + tmp % 10;                        
  98.                                                     tmp /= 10;               
  99.                                                         if (k == 3)                                                            //i=3时就是获得3位小数时插入小数点   
  100.                                                         {                                                       
  101.                                                                 WeightTable[k] = '.';                        
  102.                                                                 k += 1;       
  103.                                                         }
  104.                                                 }
  105.                                                 if (k == 4)                                //刚好3个小数补0 0.123                
  106.                                                 {
  107.                                                         WeightTable[k] = '0';               
  108.                                                         k++;                           //和上面统一,k比实际大1,下面再减回
  109.                                                 }
  110.                                                 if (k < 3)                                                   //当不够两位小数时,例如1实际代表的是0.01
  111.                                                 {               
  112.                                                         WeightTable[4] = 0x30;                                //在最高位插入0
  113.                                                         WeightTable[3] = '.';                                //在最次高位插入.
  114.                                                         for (j = k; j < 3; j++)
  115.                                                         {
  116.                                                                 WeightTable[j] = 0x30;                 //如果只有0位时插入一个插入两个0         0.00
  117.                                                         }                                                                         //如果只有1位时插入一个插入1个0         0.0
  118.                                                         k = 5;                                                        //0.001刚好5个数
  119.                                                 }       
  120.                                                 Write_Cmd(0x93);                                 //重定位液晶DDRAM地址                                                 
  121.                                                 while (k > 0)                              
  122.                                             {       
  123.                                                         Write_Data(WeightTable[k-1]);          //总额结算,倒序输出,因为之前是倒序输入,高位地址为高位
  124.                                                         k--;                                                                  
  125.                                                 }
  126.        
  127.                                         }
  128.                                
  129.                                 }                                 
  130.                                 TimeCount = 0;
  131.                                 Write_Cmd(0x8b);                                                         //显示完体重就定位价格显示地址
  132.                         }                  
  133.             }       
  134.        
  135.                 if (TimeIRQflag == 1)                 //5ms定时中断 ,5ms是为了可以利用来去抖延时而不失效率,由扫描态转入确认态至少5ms
  136.             {
  137.                         TimeIRQflag = 0;               
  138.                         Key = KeyRead();                //键盘扫描,获取键值                                                                           按键的意义:        1     2     3     量程切换
  139.                         switch (Key)                                                                                                                                                 //                    4          5                6          去皮
  140.                         {                                                                                                                                                                        //                        7          8                9          清除
  141.                                 case KEY1  :         if (TotalFlag== 0) { Write_Data(0x31);  Num = 1; } break;                //                        .     0          开关          结算
  142.                                 case KEY2  :         if (TotalFlag== 0) { Write_Data(0x32);  Num = 2; } break;                       
  143.                                 case KEY3  :         if (TotalFlag== 0) { Write_Data(0x33);  Num = 3; } break;
  144.                                 case KEY4  :                                   
  145.                                 {
  146.                                          RangeFlag = !RangeFlag ;
  147.                                          Clean_Price();
  148.                                          if (RangeFlag == 0)                                   //量程切换模式,0为g为单位,1为Kg为单位
  149.                                          {
  150.                                                  LcdDdram_Display(1,0,table2);            //把字符串Kg 变成 g ,残留1个g
  151.                                                 Write_Data(' ');                                           //清掉残留的g
  152.                                          }
  153.                                          else
  154.                                          {
  155.                                                  LcdDdram_Display(1,0,table7);                  //把字符串g 变成 Kg       
  156.                                          }
  157.                                          Write_Cmd(0x8b);
  158.                                 }         
  159.                                 break;               
  160.                                 case KEY5  :         if (TotalFlag== 0) { Write_Data(0x34);  Num = 4;}  break;
  161.                                 case KEY6  :         if (TotalFlag== 0) { Write_Data(0x35);  Num = 5;}  break;
  162.                                 case KEY7  :         if (TotalFlag== 0) { Write_Data(0x36);  Num = 6;}  break;
  163.                                 case KEY8  :         AD_Offset();                                                                                      break;               
  164.                                 case KEY9  :         if (TotalFlag== 0) { Write_Data(0x37);  Num = 7;}  break;
  165.                                 case KEY10 :         if (TotalFlag== 0) { Write_Data(0x38);  Num = 8;}  break;
  166.                                 case KEY11 :         if (TotalFlag== 0) { Write_Data(0x39);  Num = 9;}  break;
  167.                                 case KEY12 :         Clean_Price();                          break;                                                           
  168.                                 case KEY13 :         
  169.                                 {                       
  170.                                                                 if (DecimalPointCount == 0 && KeycanFlag == 0)
  171.                                                                 {       
  172.                                                                          Write_Data(0x30);
  173.                                                                          Write_Data(0x2e);                                  //显示‘.’
  174.                                                                 }
  175.                                                                 if (DecimalPointCount == 0 && KeycanFlag == 1)
  176.                                                                 {
  177.                                                                          Write_Data(0x2e);
  178.                                                                 }
  179.                                                                 if (DecimalPointCount > 200)
  180.                                                                 {       
  181.                                                                         DecimalPointCount = 0;                       
  182.                                                                 }
  183.                                                                 DecimalPointCount++;
  184.                                                                 g_DecimalPointflag = 1;                 //小数点按下
  185.                                                                 KeycanFlag = 1;
  186.                                 }
  187.                                 break;               
  188.                                 case KEY14 :        if (TotalFlag== 0) { Write_Data(0x30);  Num = 0; }  break;                  
  189.                                 case KEY15 :        PCON_PD();                    break;                                 
  190.                                 case KEY16 :         
  191.                             {               
  192.                                         TotalFlag = 1;                                         //总额显示之后不能输入价格
  193.                                         if (Count1 == 1)                          
  194.                                         {
  195.                                                 Count1 = 0;                                  //小数点后面只有1位数的时候*10
  196.                                                 g_LowPrice *= 10;                  //变大10倍,防止出现例如输入1.2的时候,小数部分为0.02
  197.                                         }                       
  198.                                         g_Price = g_HighPrice + g_LowPrice / 100.0;                        //单价 = 整数 + 小数
  199.                                         g_TempPrices = g_Price * Weight * 100;                                 //总额中间变量 = 价格 * 重量 * 100(保留两位小数点)
  200.                                         if (g_TempPrices >999999999)                                                 //超出屏幕显示(10位,1位为小数点)报警
  201.                                         {
  202.                                                 LcdDdram_Display(3,3,table5);                                          //超出量程报错       
  203.                                                 break;
  204.                                         }                                                                                                           //(int)(a+0.5)为四舍五入
  205.                                         g_TotalPrices = (UINT_32)(g_TempPrices+0.5);                   //把浮点型转换为整型,2.10*1*100 = 209.99 (优化出错)!!!!       
  206.                                         Display_Int2str(g_TotalPrices, TotalPricesTable, 0x9b);                 //显示总额
  207.                                 }                                                    
  208.                                 break;       
  209.                                 default  :       break;       
  210.                         }                                                                                                                                                       
  211.                        
  212.                         if (Key == KEY1 || Key == KEY2 || Key == KEY3 || Key == KEY5 || Key == KEY6             //有数字按键按下时
  213.                                  || Key == KEY7 || Key == KEY9 || Key == KEY10 || Key == KEY11 || Key == KEY14)
  214.                         {
  215.                             KeycanFlag = 1;
  216.                            if (g_DecimalPointflag != 1)                                 //数字按下时小数点还没按下输入的是整数部分
  217.                            {
  218.                                              Count2++;
  219.                                           if (Count2 >= 5)                                        //不可以输入超过5位数
  220.                                           {
  221.                                                    Clean_Price();                                     //超过自动清零
  222.                                           }
  223.                                           g_HighPrice = g_HighPrice * 10 + Num;                          //连续输入整数部分时,前一位*10再+后一位  
  224.                            }
  225.                            else                                                                                 //有小数点按下了
  226.                            {
  227.                                              Count1++;
  228.                                           if (Count1 >= 3)                                         //小数部分不可以输入超过2位数
  229.                                           {
  230.                                                    Clean_Price();                                          //超过自动清零
  231.                                           }
  232.                                              g_LowPrice = g_LowPrice * 10 + Num;       
  233.                                          
  234.                            }

  235.                         }
  236.                                
  237.                 }         
  238.         }                 
  239. }
  240.           
  241. /********************************************************************
  242. 函数名称: Init()               
  243. 功能简介: 初始化定时器,液晶初始化
  244. 入口参数: 无
  245. 返回值  :无
  246. *********************************************************************/
  247. void Init(void)
  248. {       
  249.         RATE = 0;                                                            //初始化Hx711转换速率为10Hz(RATE = 0时AD转换速率为10Hz,RATE = 1为80Hz)
  250.         Time_Init();                                        //定时器0中断初始化
  251.         LCD_Init();                                                        //12864液晶初始化
  252.         LcdDdram_Display(0,0,table1);                //第1行显示数据table1内容        (万家福超市欢迎你)
  253.         LcdDdram_Display(1,0,table2);                //第2行显示数据table2内容         (重量G:     g)
  254.         LcdDdram_Display(2,0,table3);            //第3行显示数据table3内容         (单价$:)
  255.         LcdDdram_Display(3,0,table4);            //第4行显示数据table4内容         (总额$:)
  256.         AD_Offset();                                            //采集零偏的平均值               
  257. }

  258. /********************************************************************
  259. 函数名称: void Clean_Price(void)               
  260. 功能简介: 清除函数,把单价、总额变量等清0
  261. 入口参数: 无
  262. 返回值  :无
  263. *********************************************************************/
  264. void Clean_Price(void)
  265. {
  266.          LcdDdram_Display(2,3,table6);                  //清除单价显示
  267.          LcdDdram_Display(3,3,table6);                  //清除总额显示
  268.          g_HighPrice = 0;                                          //清除价格
  269.          g_LowPrice = 0;
  270.          Count1 = 0;
  271.          Count2        = 0;
  272.          KeycanFlag = 0;                                          //清除禁止AD采集标志位
  273.          TotalFlag  = 0;
  274.          DecimalPointCount  = 0;
  275.          g_DecimalPointflag = 0;                          //小数点
  276.          Write_Cmd(0x8b);                                          //DDRAM地址指针调整
  277. }

  278. /********************************************************************
  279. 函数名称: void Display_Int2str(UINT_32 DecNum, UINT_8 Str[], UINT_8 DDRAM)               
  280. 功能简介: 把十进制数转换为字符串输出,保留两位小数点
  281.                   此段代码是把十进制的“总额”倒序转换为字符串存放在数组TotalPricesTable【】里面,
  282.                   总额TotalPrices的LSB位存放在字符数组的最低位,这样做的原因有两点:
  283.               可以确定小数点存放在数组那个位置(由保留小数点位数(i)确定,从最低位数0起到第i位插入小数点)
  284.                   如果设定12864液晶为地址自动减1模式时为小端字节,例如把654321倒序输出就会变成214365
  285. 入口参数: UINT_32 DecNum, UINT_8 Str[], UINT_8 DDRAM
  286. 返回值  :无
  287. *********************************************************************/
  288. void Display_Int2str(UINT_32 DecNum, UINT_8 Str[], UINT_8 DDRAM)
  289. {
  290.         INT_8 i = 0, j = 0;
  291.         while (DecNum != 0)                                                         //十进制数不为0时               
  292.         {
  293.                 Str[i++] = 0x30 + DecNum % 10;                         //提取十进制最后一位转换为字符
  294.             DecNum /= 10;               
  295.                 if (i == 2)                                                        //倒序存储到Str数组里去,例如1234,存放为4321
  296.                 {                                                       
  297.                         Str[i] = '.';                                         //i=2时就是获得两位小数时插入小数点
  298.                         i+=1;       
  299.                 }
  300.         }
  301.         if (i == 3)                                                //Str只有两位数时,在最前面插入‘0’
  302.         {
  303.                 Str[i] = '0';
  304.                 i++;
  305.         }
  306.         Write_Cmd(DDRAM);                                 //重定位液晶DDRAM地址
  307.         if (i < 2)                                                   //当不够两位小数时,例如1实际代表的是0.01
  308.         {               
  309.                 Str[3] = 0x30;                                //在最高位插入0
  310.                 Str[2] = '.';                                //在最次高位插入.
  311.                 for (j = i; j < 2; j++)
  312.                 {
  313.                         Str[j] = 0x30;                 //如果只有0位时插入一个插入两个0         0.00
  314.                 }                                                                         //如果只有1位时插入一个插入1个0         0.0
  315.                 i = 4;                                       //字符数组TotalPricesTable长度
  316.         }                                                                 
  317.         while (i >= 1)                       //i设定大于1不大于0是因为前面的i在不符合循环条件时自动加1,比实际字符数组长度多1位
  318.     {       
  319.                 Write_Data(Str[i-1]);          //总额结算,倒序输出,因为之前是倒序输入,高位地址为高位
  320.                 i--;                                                                  
  321.         }        
  322. }

  323. /********************************************************************
  324. 函数名称: Init_Weighttab()               
  325. 功能简介: 初始化字符数组
  326. 入口参数: UINT_8 *String1, UINT_8 *String2
  327. 返回值  :无
  328. *********************************************************************/
  329. void Init_Weighttab(UINT_8 *String1, UINT_8 *String2 )
  330. {
  331.         UINT_8 i;
  332.         for (i = 0; i < 5 ;i++)
  333.         {
  334.                  *String1++ = *String2;         
  335.         }
  336. }          
  337.                                                     
复制代码

Keil代码PCB 2个文件下载:
电子秤.7z (664.39 KB, 下载次数: 28)


评分

参与人数 1黑币 +20 收起 理由
admin + 20 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表