单片机论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 8626|回复: 20
收起左侧

带详细注释的51单片机CS1237电子秤源程序

  [复制链接]
BorealOwl 发表于 2018-4-21 23:35 | 显示全部楼层 |阅读模式
工程硬件平台:    1,51Core-V1.0(51单片机最小系统板)
                2,差分ADC模块-CS1237
                3,称重传感器模块
                4,OLED显示器0.96寸,4PIN

工程程序版本:51单片机厨房(药房)秤方案 V1.0.0.0
(本例程仅提供一种实现思路,学会后完全可以使用其他品牌的单片机替代)
---------------------------------------------------
------------------------------------------------------------------------------------------------------.

硬件:

1,单片机内部时钟设置为 5.5296MHZ

2,“差分ADC模块-CS1237”的电源正确连接到“51单片机最小系统板“的5V电源上。同时数字接口如下连接:
    OUT = P3^7;//数据对应IO口
    CLK = P3^5;//时钟对应IO口

www.cp71.la_【官方首页】-点la3,”称重传感器模块“和”差分ADC模块-CS1237“连接好。接线定义如下:
    CS1237模块的E+ 连接 红色
    CS1237模块的E- 连接 黑色
    CS1237模块的S+ 连接 绿色
    CS1237模块的S- 连接 白色
(本例程的软件上有处理,S+和S-不用区别正负极,因为CS1237的模拟输入通道是差分输入)

4,OLED显示器0.96寸4PIN ,直接查到51最小系统板的P17排母上即可

5,锂电池供电下的运行功耗:19mA    待机功耗:<2mA

------------------------------------------------------------------------------------------------------



---------------------------------------------------

程序功能:
1,    第一个点校准功能。需要保证系统供电是一个精确的5V,第一次烧写完程序后会进行第一个点的自动校准。
    此功能也可以通过按 KEY1 按键随时进入。
    第一个点校准后,不能直接称重,还需要第二个点校准。
   
2,    第二个点的校准功能。需要在秤盘上放一个500克的砝码,等待几秒,按下 KEY2 按键即可。

www.cp71.la_【官方首页】-点la3,    去皮功能。经过两个点的校准后便可以正常使用。使用过程中随时可以去皮重。按下 KEY3 按键即可。

4,    电池供电使用。接上一节普通锂电池即可使用(也可以是两节或三节普通干电池串联),接到5V供电的位置即可。
www.cp71.la_【官方首页】-点la    OLED显示屏会显示电池的电压,单位是mV。
   
5,    程序正常执行显示的是实时重量。

6,    当程序检测到超过30S重量没有变化,则自动进入低功耗模式,关闭OLED以达到省电的目的。若想再次使用必须按下 KEY3 按键。
www.cp71.la_【官方首页】-点la    (此时的KEY3按键相当于产品上面的“开机”按键。当然你也可以做一个电源开关,直接关闭系统)

7,    开机去皮。由于每次开机时候,传感器受力情况会发生微妙变化(比如移动位置,秤盘被压过,底座没放平等),所以程序在每次开机时
www.cp71.la_【官方首页】-点la    会进行去皮,软件上消除此误差。

8,    按键KEY1和KEY2只在校准时候使用,若厂家做产品,只需要在出场时候校准使用即可。留给用户的接口只有KEY3按键,兼容去皮和开机唤醒。

---------------------------------------------------
单片机源程序如下:
  1. //内部时钟 5.5296MHZ
  2. //电池供电可用,实时显示重量,单位g
  3. //KEY1 校准时第一步空称 ;  KEY2 砝码校准500G砝码 ;KEY3 常规去皮功能
  4. #include "STC15W.h"
  5. #include "intrins.h"
  6. #include "Uart_1.h"
  7. #include "OLED_IIC.h"
  8. #include "CS1237.h"
  9. #include "T4_Key.h"
  10. #include "ADC.h"
  11. #include "IAP_EEPROM.h"


  12. #define  Tare         EEROM_20Long[0]  //校准用,皮重
  13. #define  BGA_EEPROM   EEROM_20Long[1]  //在5V供电下,校准的内部BGA参数
  14. #define  First_ON     EEROM_20Long[2]  //第一次开机标志位 如果不是88则表示第一次开机,用于批量生产
  15. #define  Weight_500g  EEROM_20Long[3]  //500G标定时候的ADC数值


  16. extern bit Key_1,Key_2,Key_3;//三个按键的状态,全局变量 1表示按下 ,每次用过之后需要手动置零
  17. extern unsigned int Battery_Now;//计算出来的当前电池电压
  18. long EEROM_20Long[20];//用于掉电保存的数值,每次烧写过后可能会归零
  19. unsigned char Work_Count=0;//放在定时器里面,每50ms进行一次显示,称重。
  20. unsigned int Low_Power = 0;//放到定时器里面,进行关机检测,30S重量没有变化后进入低功耗模式
  21. static float Weight_Coe=0.00000;//全局变量,称重时参考的重量系数
  22. static float Tare_Coe=0.00000;//全局变量,皮重的重量,放大1000倍之后的数值
  23. static unsigned int Weight_30S_1,Weight_30S_2;//30S读取一次重量,然后比较,如果两次相同则进入低功耗
  24. static unsigned char Power_Down_F=0;//单片机掉电标志位,用于掉电重启后初始化所有设备

  25. //获取电池电压,50次平均值
  26. unsigned int Get_Bat(void);
  27. //读取CS1237,去皮后的重量,精确到g
  28. unsigned int  Get_Weight(void);
  29. //根据校准的数值,计算出称重系数
  30. void Get_Weight_Coe(void);

  31. void main(void)
  32. {
  33.         unsigned int Main_Loop=0;//在主函数里面用的,循环时候控制循环次数的变量
  34.         
  35.         P0M1=0;P0M0=0;P1M1=0;P1M0=0;
  36.         P2M1=0;P2M0=0;P3M1=0;P3M0=0;
  37.         P4M1=0;P4M0=0;P5M1=0;P5M0=0;//上电初始化所有IO口为普通IO
  38.         Init_Uart1();//初始化串口1,9600bps
  39.         OLED_Init();  //OLED初始化
  40.         Init_T4();//初始化T4,用于按键检测
  41.         Init_CS1237();//初始化CS1237
  42.         Init_ADC();//初始化ADC
  43.         EA = 1;//打开单片机全局中断
  44.         Re_20_Long(0XD3B8,EEROM_20Long);//读取所有的掉电保存数据到内存里
  45.         Delay1ms(10);
  46.         if(First_ON != 88)//如果检测到第一次开机情况,表示需要校准,用于批量生产时候
  47.         {
  48.                 LED2 = 0;//灯亮
  49.                 First_ON = 88;
  50.                 Main_Loop = 10;
  51.                 while(Main_Loop--)
  52.                         Tare = Read_18Bit_AD();//读取出CS1237的数据,5V情况下
  53.                 Main_Loop = 10;
  54.                 while(Main_Loop--)
  55.                         BGA_EEPROM = Get_BGA();//在5V供电情况下,保存BGA参数
  56.                 Wr_20_Long(0XD3B8,EEROM_20Long);//保存数据到EEPROM
  57.                 LED2 = 1;//灯灭
  58.         }
  59.         else
  60.                 Get_Weight_Coe();//依据EEPROM内容,计算称重系数
  61.         Send_Data1(Read_CON());//发送CS1237配置信息到串口
  62.         
  63.         //---------------------------------------------------------------//
  64.         LED2 = 0;//灯亮
  65.         Main_Loop = 10;//开机自动读取一次当前皮重。
  66.         while(Main_Loop--)//连续读取10次,是因为CS1237读取程序里有软件滤波器,这样做更接近真实值
  67.                 Tare_Coe = Read_18Bit_AD();//读取出皮重的ADC数据
  68.         Tare_Coe *= Weight_Coe;
  69.         LED2 = 1;//关灯
  70.         //--------------------------------------------------------------//               
  71.         while(1)
  72.         {
  73.                 if(Key_1)//去皮后的值保存到EEPROM里面,必须在5V环境下 校准专用
  74.                 {
  75.                         Key_1 = 0;
  76.                         LED2 = 0;//灯亮
  77.                         Main_Loop = 10;
  78.                         while(Main_Loop--)
  79.                                 Tare = Read_18Bit_AD();//读取出CS1237的数据,5V情况下
  80.                         Main_Loop = 10;
  81.                         while(Main_Loop--)
  82.                                 BGA_EEPROM = Get_BGA();//在5V供电情况下,保存BGA参数
  83.                         Wr_20_Long(0XD3B8,EEROM_20Long);//保存数据到EEPROM
  84.                         LED2 = 1;//关灯
  85.                 }
  86.                
  87.                 if(Key_2)//放上一个500g砝码,用于校准误差,必须在5V供电环境下
  88.                 {
  89.                         Key_2 = 0;
  90.                         LED2 = 0;//灯亮
  91.                         Main_Loop = 10;
  92.                         while(Main_Loop--)
  93.                                 Weight_500g = Read_18Bit_AD();//读取出500G的数据
  94.                         Weight_Coe = Weight_500g -  Tare;//除去皮重的ADC数值
  95.                         Weight_Coe = 500000 / Weight_Coe;//放大1000倍的斜率
  96.                         Tare_Coe = Weight_Coe * Tare;//皮重的重量,放大1000倍之后的
  97.                         Wr_20_Long(0XD3B8,EEROM_20Long);//保存数据到EEPROM
  98.                         LED2 = 1;
  99.                 }
  100.                
  101.                 if(Key_3)//正常的去皮重,不保存到EEPROM里面
  102.                 {
  103.                         Key_3 = 0;
  104.                         LED2 = 0;
  105.                         Main_Loop = 10;
  106.                         while(Main_Loop--)
  107.                                 Tare_Coe = Read_18Bit_AD();//读取出皮重的ADC数据
  108.                         Tare_Coe *= Weight_Coe;
  109.                         LED2 = 1;
  110.                 }
  111.                
  112.                 //定时器控制的子程序,每150ms调用一次
  113.                 if(Work_Count == 4)
  114.                 {
  115.                         OLED_ShowNum(7*9,2,Get_Bat(),4,16);//显示电池电压
  116.                         Weight_30S_1 = Get_Weight();//每一次称重,都要更新一下用于低功耗的数据
  117.                         OLED_ShowNum(7*8,4,Weight_30S_1,4,16);//OLED显示重量
  118.                         Work_Count = 0;
  119.                         if(Weight_30S_1 == Weight_30S_2)
  120.                         {
  121.                                 Low_Power ++;
  122.                         }
  123.                         else
  124.                         {
  125.                                 Weight_30S_2 = Weight_30S_1;
  126.                                 Low_Power = 0;
  127.                         }
  128.                 }
  129.                 //
  130.                 if(Low_Power > 150)
  131.                 {
  132.                         CS1237_Power_Down();//CS1237进入低功耗模式
  133.                         OLED_Power_Down();//OLED进入低功耗模式
  134.                         INT_CLKO |= 0X10;//使能INT2中断,主要用于唤醒单片机
  135.                         //所有IO口设置为高阻输入
  136.                         P0M1=0;P0M0=0;P1M1=0;P1M0=0;
  137.                         P2M1=0;P2M0=0;P3M1=0;P3M0=0;
  138.                         P4M1=0;P4M0=0;P5M1=0;P5M0=0;
  139.                         P0 = 0xff;P1 = 0xff;P2 = 0xff;
  140.                         P3 = 0xff;P4 = 0xff;P5 = 0xff;
  141.                         Power_Down_F = 0;
  142.                         PCON |= 0X02;//单片机进入停机模式
  143.                         while(1)
  144.                         {
  145.                                 if(Power_Down_F)//
  146.                                         IAP_CONTR = 0x20;
  147.                         }
  148.                 }
  149.         }
  150. }
  151. //获取电池电压,50次平均值
  152. unsigned int Get_Bat(void)
  153. {
  154.         unsigned char i=50;
  155.         unsigned long  dat=0;
  156.         while(i--)
  157.         {
  158.                 Get_Vol();//主要是为了获取电池电压
  159.                 dat += Battery_Now;
  160.         }
  161.         dat /= 50;
  162.         dat /= 100;//特意忽略电压的最后两位 表示以V为单位的电压保留一位小数 比如3800mV,即3.8V
  163.         dat *= 100;
  164.         return dat;
  165. }
  166. //读取CS1237,去皮后的重量,精确到g
  167. unsigned int Get_Weight(void)
  168. {
  169.         float dat;
  170.         unsigned long dat2;
  171.         dat = Read_18Bit_AD();
  172.         dat *= Weight_Coe;//计算出当前重量,毛重,1000倍放大的
  173.         dat -= Tare_Coe;//减去皮重的重量
  174.         if(dat<0)
  175.                 dat = 0;
  176.         dat2 = dat;
  177.         dat2 /= 100;//准备四舍五入,因为放大了100倍,所以现在保留了小数点后一位
  178.         if((dat2 % 10) > 5)
  179.         {
  180.                 dat2 /= 10;
  181.                 dat2 += 1;
  182.         }
  183.         else
  184.         {
  185.                 dat2 /= 10;
  186.         }
  187.         return dat2;
  188. }
  189. //根据校准的数值,计算出称重系数
  190. void Get_Weight_Coe(void)
  191. {
  192.         Weight_Coe = Weight_500g -  Tare;//除去皮重的ADC数值
  193.         Weight_Coe = 500000 / Weight_Coe;//放大1000倍的斜率
  194.         Tare_Coe = Weight_Coe * Tare;//皮重的重量,放大1000倍之后的
  195. }
  196. //
  197. //外部中断入口,主要用于掉电唤醒
  198. void EX_Int2(void) interrupt 10       //INT2
  199. {
  200. Power_Down_F = 1 ;
  201. }


  202. //






  203. ……………………

  204. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
0.jpg

所有资料51hei提供下载:
电子秤程序.zip (158.05 KB, 下载次数: 231)

评分

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

查看全部评分

回复

使用道具 举报

goalpeak 发表于 2019-9-20 15:05 | 显示全部楼层
CS1237是深圳芯海科技专用ADC芯片,在128倍放大倍数情况下,AD精度可以到18位左右,VS参考电压本身芯片可以提供,硬件可以选择,可以做厨房秤和人体秤,以及其他高精度场合,软件处理最好加上滑动滤波操作,从12年开始就使用芯海科技的ADC,希望有这方面爱好的便宜一起研究讨论
回复

使用道具 举报

ancient-gree 发表于 2018-6-17 14:09 | 显示全部楼层
感谢大佬分享
回复

使用道具 举报

zytraw 发表于 2018-11-14 08:19 | 显示全部楼层

感谢分享!!谢谢
回复

使用道具 举报

1585551473 发表于 2018-11-14 21:27 | 显示全部楼层
感谢分享!!谢谢
回复

使用道具 举报

wjh_004 发表于 2019-1-4 13:32 | 显示全部楼层
很详细,很精辟的 一个贴
回复

使用道具 举报

cwt 发表于 2019-1-18 16:16 | 显示全部楼层
感谢大佬的分享
回复

使用道具 举报

cwt 发表于 2019-1-18 16:17 | 显示全部楼层
谢谢了
回复

使用道具 举报

梦园心田 发表于 2019-1-22 00:50 来自手机 | 显示全部楼层
可以帮我移植52到这个单片机上吗,可以有报酬
回复

使用道具 举报

ak5136728 发表于 2019-4-10 10:41 | 显示全部楼层
谢谢楼主分享资料
回复

使用道具 举报

smile小宝 发表于 2019-5-24 22:13 | 显示全部楼层
正好想学习一下,谢谢分享
回复

使用道具 举报

284183304 发表于 2019-6-12 22:49 | 显示全部楼层
www.cp71.la_【官方首页】-点la做一个小项目正好用上,谢谢楼主分享资料。
回复

使用道具 举报

lyl_420819 发表于 2019-7-27 20:06 | 显示全部楼层
谢楼主分享。
回复

使用道具 举报

jswxsw 发表于 2019-8-5 16:54 | 显示全部楼层
谢谢楼主分享
回复

使用道具 举报

hwasun 发表于 2019-9-15 11:22 | 显示全部楼层
谢谢楼主分享!
回复

使用道具 举报

mssfabc 发表于 2019-9-20 09:55 | 显示全部楼层
感谢分享
回复

使用道具 举报

goalpeak 发表于 2019-9-20 15:00 | 显示全部楼层
梦园心田 发表于 2019-1-22 00:50
可以帮我移植52到这个单片机上吗,可以有报酬

我可以帮你,我专业做电子秤的
回复

使用道具 举报

18#
无效楼层,该帖已经被删除
pengyongnet 发表于 2019-11-17 19:23 来自手机 | 显示全部楼层
可以帮我一下吗移植到stc89c52r
回复

使用道具 举报

郑同学 发表于 2019-11-17 22:24 | 显示全部楼层
感谢大佬的分享 哦
回复

使用道具 举报

猪仔耙地 发表于 2019-11-19 09:31 | 显示全部楼层
学习了,谢谢
回复

使用道具 举报

lyl_420819 发表于 2020-2-14 16:38 | 显示全部楼层
雪中送碳,太感谢了。www.cp71.la_【官方首页】-点la谢楼主分享。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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