工程硬件平台: 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口
3,”称重传感器模块“和”差分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 按键即可。
3, 去皮功能。经过两个点的校准后便可以正常使用。使用过程中随时可以去皮重。按下 KEY3 按键即可。
4, 电池供电使用。接上一节普通锂电池即可使用(也可以是两节或三节普通干电池串联),接到5V供电的位置即可。
OLED显示屏会显示电池的电压,单位是mV。
5, 程序正常执行显示的是实时重量。
6, 当程序检测到超过30S重量没有变化,则自动进入低功耗模式,关闭OLED以达到省电的目的。若想再次使用必须按下 KEY3 按键。
(此时的KEY3按键相当于产品上面的“开机”按键。当然你也可以做一个电源开关,直接关闭系统)
7, 开机去皮。由于每次开机时候,传感器受力情况会发生微妙变化(比如移动位置,秤盘被压过,底座没放平等),所以程序在每次开机时
会进行去皮,软件上消除此误差。
8, 按键KEY1和KEY2只在校准时候使用,若厂家做产品,只需要在出场时候校准使用即可。留给用户的接口只有KEY3按键,兼容去皮和开机唤醒。
---------------------------------------------------
单片机源程序如下:
- //内部时钟 5.5296MHZ
- //电池供电可用,实时显示重量,单位g
- //KEY1 校准时第一步空称 ; KEY2 砝码校准500G砝码 ;KEY3 常规去皮功能
- #include "STC15W.h"
- #include "intrins.h"
- #include "Uart_1.h"
- #include "OLED_IIC.h"
- #include "CS1237.h"
- #include "T4_Key.h"
- #include "ADC.h"
- #include "IAP_EEPROM.h"
- #define Tare EEROM_20Long[0] //校准用,皮重
- #define BGA_EEPROM EEROM_20Long[1] //在5V供电下,校准的内部BGA参数
- #define First_ON EEROM_20Long[2] //第一次开机标志位 如果不是88则表示第一次开机,用于批量生产
- #define Weight_500g EEROM_20Long[3] //500G标定时候的ADC数值
- extern bit Key_1,Key_2,Key_3;//三个按键的状态,全局变量 1表示按下 ,每次用过之后需要手动置零
- extern unsigned int Battery_Now;//计算出来的当前电池电压
- long EEROM_20Long[20];//用于掉电保存的数值,每次烧写过后可能会归零
- unsigned char Work_Count=0;//放在定时器里面,每50ms进行一次显示,称重。
- unsigned int Low_Power = 0;//放到定时器里面,进行关机检测,30S重量没有变化后进入低功耗模式
- static float Weight_Coe=0.00000;//全局变量,称重时参考的重量系数
- static float Tare_Coe=0.00000;//全局变量,皮重的重量,放大1000倍之后的数值
- static unsigned int Weight_30S_1,Weight_30S_2;//30S读取一次重量,然后比较,如果两次相同则进入低功耗
- static unsigned char Power_Down_F=0;//单片机掉电标志位,用于掉电重启后初始化所有设备
- //获取电池电压,50次平均值
- unsigned int Get_Bat(void);
- //读取CS1237,去皮后的重量,精确到g
- unsigned int Get_Weight(void);
- //根据校准的数值,计算出称重系数
- void Get_Weight_Coe(void);
- void main(void)
- {
- unsigned int Main_Loop=0;//在主函数里面用的,循环时候控制循环次数的变量
-
- P0M1=0;P0M0=0;P1M1=0;P1M0=0;
- P2M1=0;P2M0=0;P3M1=0;P3M0=0;
- P4M1=0;P4M0=0;P5M1=0;P5M0=0;//上电初始化所有IO口为普通IO
- Init_Uart1();//初始化串口1,9600bps
- OLED_Init(); //OLED初始化
- Init_T4();//初始化T4,用于按键检测
- Init_CS1237();//初始化CS1237
- Init_ADC();//初始化ADC
- EA = 1;//打开单片机全局中断
- Re_20_Long(0XD3B8,EEROM_20Long);//读取所有的掉电保存数据到内存里
- Delay1ms(10);
- if(First_ON != 88)//如果检测到第一次开机情况,表示需要校准,用于批量生产时候
- {
- LED2 = 0;//灯亮
- First_ON = 88;
- Main_Loop = 10;
- while(Main_Loop--)
- Tare = Read_18Bit_AD();//读取出CS1237的数据,5V情况下
- Main_Loop = 10;
- while(Main_Loop--)
- BGA_EEPROM = Get_BGA();//在5V供电情况下,保存BGA参数
- Wr_20_Long(0XD3B8,EEROM_20Long);//保存数据到EEPROM
- LED2 = 1;//灯灭
- }
- else
- Get_Weight_Coe();//依据EEPROM内容,计算称重系数
- Send_Data1(Read_CON());//发送CS1237配置信息到串口
-
- //---------------------------------------------------------------//
- LED2 = 0;//灯亮
- Main_Loop = 10;//开机自动读取一次当前皮重。
- while(Main_Loop--)//连续读取10次,是因为CS1237读取程序里有软件滤波器,这样做更接近真实值
- Tare_Coe = Read_18Bit_AD();//读取出皮重的ADC数据
- Tare_Coe *= Weight_Coe;
- LED2 = 1;//关灯
- //--------------------------------------------------------------//
- while(1)
- {
- if(Key_1)//去皮后的值保存到EEPROM里面,必须在5V环境下 校准专用
- {
- Key_1 = 0;
- LED2 = 0;//灯亮
- Main_Loop = 10;
- while(Main_Loop--)
- Tare = Read_18Bit_AD();//读取出CS1237的数据,5V情况下
- Main_Loop = 10;
- while(Main_Loop--)
- BGA_EEPROM = Get_BGA();//在5V供电情况下,保存BGA参数
- Wr_20_Long(0XD3B8,EEROM_20Long);//保存数据到EEPROM
- LED2 = 1;//关灯
- }
-
- if(Key_2)//放上一个500g砝码,用于校准误差,必须在5V供电环境下
- {
- Key_2 = 0;
- LED2 = 0;//灯亮
- Main_Loop = 10;
- while(Main_Loop--)
- Weight_500g = Read_18Bit_AD();//读取出500G的数据
- Weight_Coe = Weight_500g - Tare;//除去皮重的ADC数值
- Weight_Coe = 500000 / Weight_Coe;//放大1000倍的斜率
- Tare_Coe = Weight_Coe * Tare;//皮重的重量,放大1000倍之后的
- Wr_20_Long(0XD3B8,EEROM_20Long);//保存数据到EEPROM
- LED2 = 1;
- }
-
- if(Key_3)//正常的去皮重,不保存到EEPROM里面
- {
- Key_3 = 0;
- LED2 = 0;
- Main_Loop = 10;
- while(Main_Loop--)
- Tare_Coe = Read_18Bit_AD();//读取出皮重的ADC数据
- Tare_Coe *= Weight_Coe;
- LED2 = 1;
- }
-
- //定时器控制的子程序,每150ms调用一次
- if(Work_Count == 4)
- {
- OLED_ShowNum(7*9,2,Get_Bat(),4,16);//显示电池电压
- Weight_30S_1 = Get_Weight();//每一次称重,都要更新一下用于低功耗的数据
- OLED_ShowNum(7*8,4,Weight_30S_1,4,16);//OLED显示重量
- Work_Count = 0;
- if(Weight_30S_1 == Weight_30S_2)
- {
- Low_Power ++;
- }
- else
- {
- Weight_30S_2 = Weight_30S_1;
- Low_Power = 0;
- }
- }
- //
- if(Low_Power > 150)
- {
- CS1237_Power_Down();//CS1237进入低功耗模式
- OLED_Power_Down();//OLED进入低功耗模式
- INT_CLKO |= 0X10;//使能INT2中断,主要用于唤醒单片机
- //所有IO口设置为高阻输入
- P0M1=0;P0M0=0;P1M1=0;P1M0=0;
- P2M1=0;P2M0=0;P3M1=0;P3M0=0;
- P4M1=0;P4M0=0;P5M1=0;P5M0=0;
- P0 = 0xff;P1 = 0xff;P2 = 0xff;
- P3 = 0xff;P4 = 0xff;P5 = 0xff;
- Power_Down_F = 0;
- PCON |= 0X02;//单片机进入停机模式
- while(1)
- {
- if(Power_Down_F)//
- IAP_CONTR = 0x20;
- }
- }
- }
- }
- //获取电池电压,50次平均值
- unsigned int Get_Bat(void)
- {
- unsigned char i=50;
- unsigned long dat=0;
- while(i--)
- {
- Get_Vol();//主要是为了获取电池电压
- dat += Battery_Now;
- }
- dat /= 50;
- dat /= 100;//特意忽略电压的最后两位 表示以V为单位的电压保留一位小数 比如3800mV,即3.8V
- dat *= 100;
- return dat;
- }
- //读取CS1237,去皮后的重量,精确到g
- unsigned int Get_Weight(void)
- {
- float dat;
- unsigned long dat2;
- dat = Read_18Bit_AD();
- dat *= Weight_Coe;//计算出当前重量,毛重,1000倍放大的
- dat -= Tare_Coe;//减去皮重的重量
- if(dat<0)
- dat = 0;
- dat2 = dat;
- dat2 /= 100;//准备四舍五入,因为放大了100倍,所以现在保留了小数点后一位
- if((dat2 % 10) > 5)
- {
- dat2 /= 10;
- dat2 += 1;
- }
- else
- {
- dat2 /= 10;
- }
- return dat2;
- }
- //根据校准的数值,计算出称重系数
- void Get_Weight_Coe(void)
- {
- Weight_Coe = Weight_500g - Tare;//除去皮重的ADC数值
- Weight_Coe = 500000 / Weight_Coe;//放大1000倍的斜率
- Tare_Coe = Weight_Coe * Tare;//皮重的重量,放大1000倍之后的
- }
- //
- //外部中断入口,主要用于掉电唤醒
- void EX_Int2(void) interrupt 10 //INT2
- {
- Power_Down_F = 1 ;
- }
- //
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
电子秤程序.zip
(158.05 KB, 下载次数: 572)
|