|
工程硬件平臺: 1,51Core-V1.0(51單片機(jī)最小系統(tǒng)板)
2,差分ADC模塊-CS1237
3,稱重傳感器模塊
4,OLED顯示器0.96寸,4PIN
工程程序版本:51單片機(jī)廚房(藥房)秤方案 V1.0.0.0
(本例程僅提供一種實(shí)現(xiàn)思路,學(xué)會后完全可以使用其他品牌的單片機(jī)替代)
---------------------------------------------------
------------------------------------------------------------------------------------------------------.
硬件:
1,單片機(jī)內(nèi)部時鐘設(shè)置為 5.5296MHZ
2,“差分ADC模塊-CS1237”的電源正確連接到“51單片機(jī)最小系統(tǒng)板“的5V電源上。同時數(shù)字接口如下連接:
OUT = P3^7;//數(shù)據(jù)對應(yīng)IO口
CLK = P3^5;//時鐘對應(yīng)IO口
3,”稱重傳感器模塊“和”差分ADC模塊-CS1237“連接好。接線定義如下:
CS1237模塊的E+ 連接 紅色
CS1237模塊的E- 連接 黑色
CS1237模塊的S+ 連接 綠色
CS1237模塊的S- 連接 白色
(本例程的軟件上有處理,S+和S-不用區(qū)別正負(fù)極,因?yàn)镃S1237的模擬輸入通道是差分輸入)
4,OLED顯示器0.96寸4PIN ,直接查到51最小系統(tǒng)板的P17排母上即可
5,鋰電池供電下的運(yùn)行功耗:19mA 待機(jī)功耗:<2mA
------------------------------------------------------------------------------------------------------
---------------------------------------------------
程序功能:
1, 第一個點(diǎn)校準(zhǔn)功能。需要保證系統(tǒng)供電是一個精確的5V,第一次燒寫完程序后會進(jìn)行第一個點(diǎn)的自動校準(zhǔn)。
此功能也可以通過按 KEY1 按鍵隨時進(jìn)入。
第一個點(diǎn)校準(zhǔn)后,不能直接稱重,還需要第二個點(diǎn)校準(zhǔn)。
2, 第二個點(diǎn)的校準(zhǔn)功能。需要在秤盤上放一個500克的砝碼,等待幾秒,按下 KEY2 按鍵即可。
3, 去皮功能。經(jīng)過兩個點(diǎn)的校準(zhǔn)后便可以正常使用。使用過程中隨時可以去皮重。按下 KEY3 按鍵即可。
4, 電池供電使用。接上一節(jié)普通鋰電池即可使用(也可以是兩節(jié)或三節(jié)普通干電池串聯(lián)),接到5V供電的位置即可。
OLED顯示屏?xí)@示電池的電壓,單位是mV。
5, 程序正常執(zhí)行顯示的是實(shí)時重量。
6, 當(dāng)程序檢測到超過30S重量沒有變化,則自動進(jìn)入低功耗模式,關(guān)閉OLED以達(dá)到省電的目的。若想再次使用必須按下 KEY3 按鍵。
(此時的KEY3按鍵相當(dāng)于產(chǎn)品上面的“開機(jī)”按鍵。當(dāng)然你也可以做一個電源開關(guān),直接關(guān)閉系統(tǒng))
7, 開機(jī)去皮。由于每次開機(jī)時候,傳感器受力情況會發(fā)生微妙變化(比如移動位置,秤盤被壓過,底座沒放平等),所以程序在每次開機(jī)時
會進(jìn)行去皮,軟件上消除此誤差。
8, 按鍵KEY1和KEY2只在校準(zhǔn)時候使用,若廠家做產(chǎn)品,只需要在出場時候校準(zhǔn)使用即可。留給用戶的接口只有KEY3按鍵,兼容去皮和開機(jī)喚醒。
---------------------------------------------------
單片機(jī)源程序如下:
- //內(nèi)部時鐘 5.5296MHZ
- //電池供電可用,實(shí)時顯示重量,單位g
- //KEY1 校準(zhǔn)時第一步空稱 ; KEY2 砝碼校準(zhǔn)500G砝碼 ;KEY3 常規(guī)去皮功能
- #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] //校準(zhǔn)用,皮重
- #define BGA_EEPROM EEROM_20Long[1] //在5V供電下,校準(zhǔn)的內(nèi)部BGA參數(shù)
- #define First_ON EEROM_20Long[2] //第一次開機(jī)標(biāo)志位 如果不是88則表示第一次開機(jī),用于批量生產(chǎn)
- #define Weight_500g EEROM_20Long[3] //500G標(biāo)定時候的ADC數(shù)值
- extern bit Key_1,Key_2,Key_3;//三個按鍵的狀態(tài),全局變量 1表示按下 ,每次用過之后需要手動置零
- extern unsigned int Battery_Now;//計(jì)算出來的當(dāng)前電池電壓
- long EEROM_20Long[20];//用于掉電保存的數(shù)值,每次燒寫過后可能會歸零
- unsigned char Work_Count=0;//放在定時器里面,每50ms進(jìn)行一次顯示,稱重。
- unsigned int Low_Power = 0;//放到定時器里面,進(jìn)行關(guān)機(jī)檢測,30S重量沒有變化后進(jìn)入低功耗模式
- static float Weight_Coe=0.00000;//全局變量,稱重時參考的重量系數(shù)
- static float Tare_Coe=0.00000;//全局變量,皮重的重量,放大1000倍之后的數(shù)值
- static unsigned int Weight_30S_1,Weight_30S_2;//30S讀取一次重量,然后比較,如果兩次相同則進(jìn)入低功耗
- static unsigned char Power_Down_F=0;//單片機(jī)掉電標(biāo)志位,用于掉電重啟后初始化所有設(shè)備
- //獲取電池電壓,50次平均值
- unsigned int Get_Bat(void);
- //讀取CS1237,去皮后的重量,精確到g
- unsigned int Get_Weight(void);
- //根據(jù)校準(zhǔn)的數(shù)值,計(jì)算出稱重系數(shù)
- void Get_Weight_Coe(void);
- void main(void)
- {
- unsigned int Main_Loop=0;//在主函數(shù)里面用的,循環(huán)時候控制循環(huán)次數(shù)的變量
-
- 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;//打開單片機(jī)全局中斷
- Re_20_Long(0XD3B8,EEROM_20Long);//讀取所有的掉電保存數(shù)據(jù)到內(nèi)存里
- Delay1ms(10);
- if(First_ON != 88)//如果檢測到第一次開機(jī)情況,表示需要校準(zhǔn),用于批量生產(chǎn)時候
- {
- LED2 = 0;//燈亮
- First_ON = 88;
- Main_Loop = 10;
- while(Main_Loop--)
- Tare = Read_18Bit_AD();//讀取出CS1237的數(shù)據(jù),5V情況下
- Main_Loop = 10;
- while(Main_Loop--)
- BGA_EEPROM = Get_BGA();//在5V供電情況下,保存BGA參數(shù)
- Wr_20_Long(0XD3B8,EEROM_20Long);//保存數(shù)據(jù)到EEPROM
- LED2 = 1;//燈滅
- }
- else
- Get_Weight_Coe();//依據(jù)EEPROM內(nèi)容,計(jì)算稱重系數(shù)
- Send_Data1(Read_CON());//發(fā)送CS1237配置信息到串口
-
- //---------------------------------------------------------------//
- LED2 = 0;//燈亮
- Main_Loop = 10;//開機(jī)自動讀取一次當(dāng)前皮重。
- while(Main_Loop--)//連續(xù)讀取10次,是因?yàn)镃S1237讀取程序里有軟件濾波器,這樣做更接近真實(shí)值
- Tare_Coe = Read_18Bit_AD();//讀取出皮重的ADC數(shù)據(jù)
- Tare_Coe *= Weight_Coe;
- LED2 = 1;//關(guān)燈
- //--------------------------------------------------------------//
- while(1)
- {
- if(Key_1)//去皮后的值保存到EEPROM里面,必須在5V環(huán)境下 校準(zhǔn)專用
- {
- Key_1 = 0;
- LED2 = 0;//燈亮
- Main_Loop = 10;
- while(Main_Loop--)
- Tare = Read_18Bit_AD();//讀取出CS1237的數(shù)據(jù),5V情況下
- Main_Loop = 10;
- while(Main_Loop--)
- BGA_EEPROM = Get_BGA();//在5V供電情況下,保存BGA參數(shù)
- Wr_20_Long(0XD3B8,EEROM_20Long);//保存數(shù)據(jù)到EEPROM
- LED2 = 1;//關(guān)燈
- }
-
- if(Key_2)//放上一個500g砝碼,用于校準(zhǔn)誤差,必須在5V供電環(huán)境下
- {
- Key_2 = 0;
- LED2 = 0;//燈亮
- Main_Loop = 10;
- while(Main_Loop--)
- Weight_500g = Read_18Bit_AD();//讀取出500G的數(shù)據(jù)
- Weight_Coe = Weight_500g - Tare;//除去皮重的ADC數(shù)值
- Weight_Coe = 500000 / Weight_Coe;//放大1000倍的斜率
- Tare_Coe = Weight_Coe * Tare;//皮重的重量,放大1000倍之后的
- Wr_20_Long(0XD3B8,EEROM_20Long);//保存數(shù)據(jù)到EEPROM
- LED2 = 1;
- }
-
- if(Key_3)//正常的去皮重,不保存到EEPROM里面
- {
- Key_3 = 0;
- LED2 = 0;
- Main_Loop = 10;
- while(Main_Loop--)
- Tare_Coe = Read_18Bit_AD();//讀取出皮重的ADC數(shù)據(jù)
- Tare_Coe *= Weight_Coe;
- LED2 = 1;
- }
-
- //定時器控制的子程序,每150ms調(diào)用一次
- if(Work_Count == 4)
- {
- OLED_ShowNum(7*9,2,Get_Bat(),4,16);//顯示電池電壓
- Weight_30S_1 = Get_Weight();//每一次稱重,都要更新一下用于低功耗的數(shù)據(jù)
- 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進(jìn)入低功耗模式
- OLED_Power_Down();//OLED進(jìn)入低功耗模式
- INT_CLKO |= 0X10;//使能INT2中斷,主要用于喚醒單片機(jī)
- //所有IO口設(shè)置為高阻輸入
- 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;//單片機(jī)進(jìn)入停機(jī)模式
- 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為單位的電壓保留一位小數(shù) 比如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;//計(jì)算出當(dāng)前重量,毛重,1000倍放大的
- dat -= Tare_Coe;//減去皮重的重量
- if(dat<0)
- dat = 0;
- dat2 = dat;
- dat2 /= 100;//準(zhǔn)備四舍五入,因?yàn)榉糯罅?00倍,所以現(xiàn)在保留了小數(shù)點(diǎn)后一位
- if((dat2 % 10) > 5)
- {
- dat2 /= 10;
- dat2 += 1;
- }
- else
- {
- dat2 /= 10;
- }
- return dat2;
- }
- //根據(jù)校準(zhǔn)的數(shù)值,計(jì)算出稱重系數(shù)
- void Get_Weight_Coe(void)
- {
- Weight_Coe = Weight_500g - Tare;//除去皮重的ADC數(shù)值
- Weight_Coe = 500000 / Weight_Coe;//放大1000倍的斜率
- Tare_Coe = Weight_Coe * Tare;//皮重的重量,放大1000倍之后的
- }
- //
- //外部中斷入口,主要用于掉電喚醒
- void EX_Int2(void) interrupt 10 //INT2
- {
- Power_Down_F = 1 ;
- }
- //
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復(fù)制代碼
所有資料51hei提供下載:
電子秤程序.zip
(158.05 KB, 下載次數(shù): 572)
2018-4-21 23:34 上傳
點(diǎn)擊文件名下載附件
|
評分
-
查看全部評分
|