?? yh_t3_new.c
字號(hào):
/********************************
說明:
1.該程序適用于高精度的場(chǎng)合
2.關(guān)于如何借鑒保加利亞程序的原則:
首先,如果能完全看懂,則將原匯編程序改寫為C程序;
其次,如果大部分能看懂,則仍模仿匯編程序的
結(jié)構(gòu)和流程,改寫。那些不懂的細(xì)節(jié)可以自己編寫
或者干脆暫時(shí)省略,以后出了問題再補(bǔ)充。
最后,如果大部分看不懂,則自己創(chuàng)造,自己編寫,
同時(shí)借鑒匯編程序中可以看得懂的部分,以后出了
問題再完善和補(bǔ)充。
*********************************/
/********************************
注意事項(xiàng):
1.對(duì)AT24C02進(jìn)行多次寫操作時(shí),中間必須相隔5ms
2.乘法運(yùn)算時(shí),乘數(shù)必須和積的數(shù)據(jù)類型相統(tǒng)一。
注意:不同的數(shù)據(jù)類型進(jìn)行運(yùn)算時(shí),極易出現(xiàn)隱蔽性的差錯(cuò)。
要么定義為相同的數(shù)據(jù)類型,要么使用強(qiáng)制轉(zhuǎn)換。
另外,涉及到乘法運(yùn)算時(shí),存在著運(yùn)算過程中,某個(gè)被乘數(shù)
的變量的內(nèi)容被“非法”修改的現(xiàn)象。
如果碰上這種情況,重新賦值就可以了。
通過單步調(diào)試來發(fā)現(xiàn)這個(gè)隱形殺手。
3.我們使用的晶振是11.0592M,不是12M,所以定時(shí)是不準(zhǔn)確
的,存在誤差。
4.DATA的128個(gè)字節(jié)不能全部占用,因?yàn)槎褩R残枰加肈ATA
的空間。因此可以將占用空間最大的數(shù)組存放在IDATA,
其余變量都默認(rèn)存放在DATA即可。
5.制約響應(yīng)速度的原因有兩個(gè):排序數(shù)組的長度和5460的
輸出速率。
6.CS5460A的偏置校準(zhǔn)數(shù)據(jù)一旦寫入偏置校準(zhǔn)寄存器,要斷電
之后該寄存器的數(shù)據(jù)才消失。當(dāng)然如果,每次運(yùn)行程序都
寫入偏置校準(zhǔn)數(shù)據(jù),可能也不需要斷電。
7.單位轉(zhuǎn)換中的克與英鎊的轉(zhuǎn)換存在bug,當(dāng)秤的精度變大
時(shí)會(huì)出現(xiàn)問題。示數(shù)的最高位與小數(shù)點(diǎn)的位置可能不正確
8.AT24C02的頁面寫操作存在不能超越當(dāng)前page(8個(gè)字節(jié));
順序?qū)懖僮鲃t沒有這種限制。
9.分度值的改變牽連很廣,包括:重量值的計(jì)算,精度,
數(shù)值的符號(hào)的產(chǎn)生,長期穩(wěn)定旗標(biāo)。
10.
*********************************/
/********************************
功能上的欠缺:
1.還是校準(zhǔn)完成后馬上可以稱重,比較人性化,但是代碼
可能會(huì)大量增加,因?yàn)椋Q重那部分很可能要重復(fù)。
以后再嘗試。
也不一定,不妨嘗試一下,我感覺應(yīng)該也沒有多少難度,
代碼也不會(huì)增加多少。
建議方法:將菜單部分設(shè)計(jì)成一個(gè)龐大的函數(shù)。
通過在稱重循環(huán)結(jié)尾處查詢組合鍵是否按下
調(diào)用菜單函數(shù)。設(shè)定完成后通過break跳出
菜單的循環(huán),繼續(xù)稱重。
當(dāng)然讀取24c02部分可能會(huì)重復(fù)。也
可能不會(huì)?,F(xiàn)炒現(xiàn)賣。
暫時(shí)不用。
2.應(yīng)該添加防震功能。
3.傳說中的LCD亮度調(diào)節(jié),就是背光亮度的調(diào)節(jié),只要在硬件
上調(diào)整相應(yīng)的電阻就可以了。
至于軟件調(diào)節(jié)肯定要使用專門的液晶或者增加相關(guān)的硬件
電路。
4.低電壓報(bào)警模塊應(yīng)該并不難,但是,如果想要顯示電壓的
數(shù)值則比較困難。要研究耀華T3的電路和軟件才能解決。
5.目前沒有hold功能,因?yàn)榘存I不夠!
6.
7.
8.我所使用的背光模塊是一種手動(dòng)背光,必須進(jìn)行菜單設(shè)置。
今后可能要考慮自動(dòng)背光以及真正的手動(dòng)按鍵控制背光。
9.
***************************************************/
/*************************************************
目前存在的問題
問題一:現(xiàn)在的背光電路有一個(gè)不爽的地方,開機(jī)就亮!
建議方法:背光電路之前加一個(gè)三極管作為反相器
就可以了。
問題二:如果沒有單位轉(zhuǎn)換,小數(shù)點(diǎn)位置的變換會(huì)很簡(jiǎn)單,
有單位轉(zhuǎn)換,可能很麻煩。
問題三:
問題四:
問題五:T2作為波特率發(fā)生器,仿真失敗;有可能是keil
本身的模擬串口存在問題,不支持T2。如果進(jìn)行
實(shí)際的線路連接可能會(huì)成功。
暫時(shí)使用T1作為串口波特率發(fā)生器;使用T0和T2
實(shí)現(xiàn)延時(shí)5分鐘的功能。
問題六:
問題七:串口模塊中,由于目前的示數(shù)的正負(fù)旗標(biāo):f_minus
的局限性,當(dāng)示數(shù)為0時(shí),串口輸出的數(shù)據(jù)會(huì)出現(xiàn)
+0和-0兩種情況。不過影響也不大,暫時(shí)不管它。
**************************************************/
/***************************
思路一:菜單所包含的內(nèi)容暫時(shí)有以下幾個(gè):
分度值選擇、小數(shù)點(diǎn)的位置、波特率、背光開關(guān)
、量程選擇、校準(zhǔn)、校準(zhǔn)砝碼。
先模仿T3,歸零范圍選擇和零點(diǎn)跟蹤選擇以后再說。
思路二:
思路三:新建LCD編碼數(shù)組的過程中可能修改了某些數(shù)據(jù),
也不會(huì)出錯(cuò),但是看著不爽。如果見到就改回來。
思路四:原來使用的sort函數(shù)中后來被去掉的部分應(yīng)該有一定
的防震功能??紤]一下是否恢復(fù)。
在某個(gè)時(shí)間段之內(nèi)的短暫的AD變化不去取樣。
建議方法:保加利亞程序中,在排序部分,那種間隔取值的
方法研究一下。這種方法,在相同的排序數(shù)組長度
的情況下,犧牲一部分時(shí)間,即LCD的變化速率
翻倍,如果數(shù)組的長度是25,則稱對(duì)瞬間沖力的忽略
時(shí)間可達(dá)1~2秒。
只要忽略時(shí)間達(dá)到2秒,防震功能就馬馬虎虎了。
暫時(shí)不用,以后再說,因?yàn)槲业腞AM和ROM的空間
都很有限。
思路五:
思路六:在菜單這部分,考慮使用位域,因?yàn)樽兞康闹刀? 比較小,即使使用最小的uchar也有點(diǎn)浪費(fèi)。
或者使用枚舉
思路七:盡量減少變量,盡量減少全局變量。寧可增加子函數(shù)
中的局部變量也要減少全局變量和主函數(shù)中的變量。
思路八:
思路九:
思路十:考慮延時(shí)自動(dòng)關(guān)機(jī)功能。也不復(fù)雜,只要在
時(shí)間到了之時(shí),對(duì)OFF腳(P1.4)置零就能達(dá)到
關(guān)機(jī)的目的。
思路11:考慮分段校準(zhǔn)。表頭項(xiàng)目成功生產(chǎn)后再考慮提高。
思路12:
思路13:
思路14:
思路15:通過對(duì)比匯編產(chǎn)生的代碼的多少,進(jìn)行深層次的
優(yōu)化。
******************************/
#include <reg52.h>
#include <intrins.h>
//----------------------
//以下是自定義的數(shù)據(jù)類型
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
struct AFEI
{
ulong ad;
uchar times;
};
//---------------------------------------------------------------------------------------------------------
//以下是HT1621模塊的定義和聲明
#define BIAS_COM 0x29//0X52 //LCD 1/3偏壓(bias) , 4公共口(com)。
//#define RC256 0x18//0X30 //System clock source選擇on-chip RC oscillator(256k)
//這條指令可以不要,因?yàn)?621上電默認(rèn)的就是選擇片內(nèi)的RC256振蕩器
#define SYSTEN 0x01//0X02 //Turn on system oscillator(打開系統(tǒng)的振蕩器)
#define SYSDIS 0x00//0X00 //Turn off both system oscillator and LCD bias generator(全關(guān))
#define LCDON 0x03//0X06 //Turn on LCD
#define LCDOFF 0x02 //關(guān)閉LCD
#define BUZON 0x09//打開蜂鳴器
#define BUZOFF 0x08//關(guān)閉聲音
#define F_2K 0x60//聲音頻率為2K
#define F_4K 0x40//聲音頻率為4K
uchar code ID_CMD=0x04;
uchar code ID_WR=0x05;
void wr_id(uchar id);
void wr_addr(uchar addr);
void wr_byte_1621(uchar dat_or_cmd);
void cmd_1621(uchar cmd);
void reset_1621(void);
void off_on_lcd(void);
void display_1621(void);
void alarm(uint time);
void delay_nms(uint n);
void delay_nus(char n);
//以上是HT1621的字型編碼表,包括0-9,A、C、E、F、全部不顯示、全部顯示。
//uchar code discode[16]={0xbe,0x06,0x7c,0x5e,0xc6,0xda,0xfa,0x0e,0xfe,0xde,0xee,0xb8,0xf8,0xe8,0x00,0xff};
uchar code discode_num[10]={0xbe,0x06,0x7c,0x5e,0xc6,0xda,0xfa,0x0e,0xfe,0xde};
//以下是26個(gè)大寫字母對(duì)應(yīng)的HT1621的編碼,為了方便查詢,數(shù)組定義為27個(gè)字節(jié),其中,首字節(jié)為特殊符號(hào)“=”的編碼。
//以下是26個(gè)字母在數(shù)組中對(duì)應(yīng)的下標(biāo)。
//A-1,B-2,C-3,D-4,E-5,F-6,G-7,H-8,I-9,J-10,K-11,L-12,M-13,N-14;
//O-15,P-16,Q-17,R-18,S-19,T-20,U-21,V-22,W-23,X-23,Y-25,Z-26;
uchar code discode_cap[27]={0x50,0xee,0x00,0xb8,0x00,0xf8,0xe8,0x00,0xe6,0x00,0x00,0x00,0xb0,0x00,0x00,0xbe,0xec,0x00,0x00,0xda,0x00,0xb6,0x00,0x00,0x00,0x00,0x00};
uchar code discode_low[27]={0x50,0x00,0xf2,0x70,0x76,0x00,0x00,0xde,0xe2,0x00,0x00,0x00,0x00,0x00,0x62,0x72,0xec,0xce,0x60,0x00,0xf0,0x32,0x00,0x00,0x00,0xd6,0x00};
//定義一個(gè)HT1621顯示數(shù)據(jù)緩沖區(qū),初始化全部為0x00。
uchar dis_zone[6]={0x00,0x00,0x00,0x00,0x00,0x00};
sbit dt_1621=P2^4; //LCD顯示的數(shù)據(jù)。
sbit cs_1621=P2^5; //使能。
sbit wr_1621=P2^6; //寫信號(hào)。
sbit BL=P1^6;//背光引腳,為1,背光亮;
//為0,背光滅
//------------------------------------
//以下是CS5460的變量定義和函數(shù)聲明
sbit reset_5460=P1^0;
sbit sdo_5460=P1^1;
sbit sclk_5460=P1^2;
sbit sdi_5460=P1^3;
void cmd_5460(uchar cmd);
ulong read_5460(void);
void write_5460(ulong dat);
ulong buf_5460;
//-----------------------------------
//以下是串口的函數(shù)聲明
/*********************************
串口幀信息格式:一幀10位,
其中第1位:起始位“0”
第10位:停止位“1”
中間8位:數(shù)據(jù)位
注意:一幀雖然在時(shí)序上有十位,包含起始位和停止位。
但是,向sbuf賦值的實(shí)際上只有中間的8位數(shù)據(jù)位。
********************************/
/********************************
LCD顯示的重量信息100.00Kg
串口發(fā)送的數(shù)據(jù):”00.001 “,注意:最后的空格表示正號(hào)。
LCD顯示的重量信息-35.000Kg
串口發(fā)送的數(shù)據(jù):”000.53-“,注意:最后的"-"表示負(fù)號(hào)。
包含小數(shù)點(diǎn)和符號(hào),共7位數(shù)據(jù)。并且二者的順序恰好相反
另外:重量數(shù)字中高位為零不顯示的情況,傳送時(shí)按0發(fā)送
湊夠位數(shù)。
*******************************/
void send_byte(uchar txd);
/******************************
//常用的ASCII碼: 0 :48
=:61
. :46
-:45
g :103
K :75
空格” “:32
******************************/
//------------------------------------
//以下是定時(shí)器(計(jì)數(shù)器)的管腳定義和函數(shù)聲明
/************************************
為了實(shí)現(xiàn)延時(shí)5分鐘, T0作為16位定時(shí)器
T1作為16位計(jì)數(shù)器
************************************/
sbit CLK_COUNTER0=P3^4;
void delay_5min(void);
//------------------------------------
//以下是AT24c02的相關(guān)變量和函數(shù)
uchar code READ=0xa1; // 器件地址以及讀取操作
uchar code WRITE=0xa0; // 器件地址以及寫入操作
sbit SDA=P2^1; // IIC數(shù)據(jù)
sbit SCL=P2^2; // IIC時(shí)鐘
void start(void);
void stop(void);
void ack(void);
void not_ack(void);
void write(uchar data_wr);
//void wr_byte(uchar addr_sla,uchar addr_wr,uchar data_byte);
void wr_nbyte(uchar addr,void *p_arr,uchar n);
//void wr_page(uchar addr_wr);
uchar rd_cur(void);
void rd_seq(uchar addr_rd,void *p_bufrd,uchar n);
//ulong rd_long(uchar addr_rd);
ulong idata buf_24c02_AD[2];
/*****************************
數(shù)組buf_24c02_rd[]中相應(yīng)位置的數(shù)據(jù)含義:
0——分度值
1——小數(shù)點(diǎn)位置
2——波特率
3——背光
*****************************/
uchar idata buf_24c02_4B[4];//用來存儲(chǔ)從24c02中讀取的數(shù)據(jù),
//隨后就用來存儲(chǔ)將要向24c02中寫入的數(shù)據(jù)
//目的:1.在菜單狀態(tài)下,顯示當(dāng)前的設(shè)定
//2.在稱重狀態(tài)下,獲取設(shè)定信息
// 用于顯示和計(jì)算。
//下面數(shù)組的用途:
//第一個(gè):量程;第二個(gè):校準(zhǔn)砝碼的重量
ulong idata buf_24c02_2L[2];
//--------------------------------------------
//電池電壓檢測(cè)部分的變量定義和函數(shù)聲明。
sbit PD=P1^5;
void alarm_low(void);
//--------------------------------------------
//下面的數(shù)據(jù)是針對(duì)3公斤傳感器(1.5Kg校準(zhǔn),沒有偏置校準(zhǔn))
//電流通道增益PGA=50
//這種情況下,AD值太大,因此將從5460讀出的數(shù)據(jù)
//在原來的基礎(chǔ)上縮小為原來的1/4
//校準(zhǔn)的AD平均值增量是:76477
#define N_5460 500 //表示5460的轉(zhuǎn)換周期
//注意:下述帶參數(shù)的宏定義中的x表示量程的AD平均值增量
#define ZERO_POS(x) ((x)/5) //表示零點(diǎn)范圍上限:+20%
//#define ZERO_NEG(x) ((-1)*((x)/25)) //表示零點(diǎn)范圍下限:-4%,這兩個(gè)百分比都是以校準(zhǔn)的AD平均值增量為分母的。
#define ZERO_NEG(x) (((-x)/25)) //表示零點(diǎn)范圍下限:-4%,這兩個(gè)百分比都是以校準(zhǔn)的AD平均值增量為分母的。
#define MANU_ZERO_POS(x) ((x)/50) //表示手動(dòng)歸零范圍上限:+2%
//#define MANU_ZERO_NEG(x) ((-1)*((x)/50)) //表示手動(dòng)歸零范圍下限:-2%,這兩個(gè)百分比都是以校準(zhǔn)的AD平均值增量為分母的。
#define MANU_ZERO_NEG(x) ((-x)/50) //表示手動(dòng)歸零范圍下限:-2%,這兩個(gè)百分比都是以校準(zhǔn)的AD平均值增量為分母的。
#define AUTO_ZERO_POS(x) ((x)/200) //表示自動(dòng)歸零范圍上限:+0.5%
//#define AUTO_ZERO_NEG(x) ((-1)*((x)/200)) //表示自動(dòng)歸零范圍下限:-0.5%,這兩個(gè)百分比都是以校準(zhǔn)的AD平均值增量為分母的。
#define AUTO_ZERO_NEG(x) ((-x)/200) //表示自動(dòng)歸零范圍下限:-0.5%,這兩個(gè)百分比都是以校準(zhǔn)的AD平均值增量為分母的。
#define TARE_HIGH(x) (x) //表示去皮的上限:量程的50%
#define TARE_LOW 5 //表示去皮的下限
#define E 5 //表示通常我們所說的一個(gè)E。
#define E1(x) ((x)*E)
#define OVER_LOAD(x) ((x)+E*9+(long)(buf_24c02_AD[0]))//表示秤量程AD值上限,比量程AD高約9個(gè)E。
//#define OFFSET 0x00fba48e //表示5460的偏置校準(zhǔn)數(shù)據(jù)
//#define JZ_ZERO_LOW 10000 //表示5460AD校準(zhǔn),空載時(shí)的下限
//#define JZ_ZERO_HIGH 20000 //表示5460AD校準(zhǔn),空載時(shí)的上限
//#define JZ_LOAD_LOW 90000 //表示5460AD校準(zhǔn),加砝碼后的下限
//#define JZ_LOAD_HIGH 100000 //表示5460AD校準(zhǔn),加砝碼后的上限
//#define ZERO_POS 15295 //表示零點(diǎn)范圍上限:+20%
//#define ZERO_NEG -3059 //表示零點(diǎn)范圍下限:-4%,這兩個(gè)百分比都是以校準(zhǔn)的AD平均值增量為分母的。
//#define MANU_ZERO_POS 1530//表示手動(dòng)歸零范圍上限:+2%
//#define MANU_ZERO_NEG -1530//表示手動(dòng)歸零范圍下限:-2%,這兩個(gè)百分比都是以校準(zhǔn)的AD平均值增量為分母的。
//#define AUTO_ZERO_POS 382//表示自動(dòng)歸零范圍上限:+0.5%
//#define AUTO_ZERO_NEG -382//表示自動(dòng)歸零范圍下限:-0.5%,這兩個(gè)百分比都是以校準(zhǔn)的AD平均值增量為分母的。
//#define TARE_HIGH 38239//表示去皮的上限:量程的50%
//#define TARE_LOW 5 //表示去皮的下限
//#define OVER_LOAD 100000 //表示秤量程AD值上限,比量程AD高約9個(gè)E。
//這個(gè)宏定義今后可以省略。
//#define E 5 //表示通常我們所說的一個(gè)E。
//#define N 15000 //表示精度,即我自己平時(shí)所說的幾萬分之一或幾千分之一。
/*****************************************************
//下面的數(shù)據(jù)是針對(duì)3公斤傳感器(1Kg校準(zhǔn),沒有偏置校準(zhǔn))
//電流通道增益PGA=50
//這種情況下,AD值太大,因此將從5460讀出的數(shù)據(jù)
//在原來的基礎(chǔ)上縮小為原來的1/4
//校準(zhǔn)的AD平均值增量是:
#define N_5460 375 //表示5460的轉(zhuǎn)換周期
//#define OFFSET 0x00fba48e //表示5460的偏置校準(zhǔn)數(shù)據(jù)
#define JZ_ZERO_LOW 10000 //表示5460AD校準(zhǔn),空載時(shí)的下限
#define JZ_ZERO_HIGH 20000 //表示5460AD校準(zhǔn),空載時(shí)的上限
#define JZ_LOAD_LOW 60000 //表示5460AD校準(zhǔn),加砝碼后的下限
#define JZ_LOAD_HIGH 70000 //表示5460AD校準(zhǔn),加砝碼后的上限
#define ZERO_POS 15295 //表示零點(diǎn)范圍上限:+20%
#define ZERO_NEG -3059 //表示零點(diǎn)范圍下限:-4%,這兩個(gè)百分比都是以校準(zhǔn)的AD平均值增量為分母的。
#define MANU_ZERO_POS 1530//表示手動(dòng)歸零范圍上限:+2%
#define MANU_ZERO_NEG -1530//表示手動(dòng)歸零范圍下限:-2%,這兩個(gè)百分比都是以校準(zhǔn)的AD平均值增量為分母的。
#define AUTO_ZERO_POS 382//表示自動(dòng)歸零范圍上限:+0.5%
#define AUTO_ZERO_NEG -382//表示自動(dòng)歸零范圍下限:-0.5%,這兩個(gè)百分比都是以校準(zhǔn)的AD平均值增量為分母的。
#define TARE_HIGH 38239//表示去皮的上限:量程的50%
#define TARE_LOW 5 //表示去皮的下限
#define OVER_LOAD 100000 //表示秤量程AD值上限,比量程AD高約9個(gè)E。
//這個(gè)宏定義今后可以省略。
#define E 5 //表示通常我們所說的一個(gè)E。
#define N 10000 //表示精度,即我自己平時(shí)所說的幾萬分之一或幾千分之一。
************************************************************************/
/*****************************************
錯(cuò)誤號(hào)說明:(注意:針對(duì)錯(cuò)誤號(hào)使用搜索,不行!)
Err 1: 零點(diǎn)偏離了指定范圍
Err 2: 單位轉(zhuǎn)換
Err 3: 菜單
Err 4: 超載
Err 5: 校準(zhǔn)時(shí)空載的AD平均值超出了范圍
Err 6: 校準(zhǔn)時(shí),放置校準(zhǔn)砝碼后的AD平均值超出了范圍
Err 7: 菜單中的分度值或者稱重時(shí)分度值選擇
Err 8: 菜單中的波特率或者稱重時(shí)波特率選擇
*******************************************/
/******************************************
秤的狀態(tài)符號(hào)說明如下:
F1:表征穩(wěn)定
F2:表征HOLD鎖定
F5:表征去皮狀態(tài)
F6:表征示數(shù)歸零
電池符號(hào):表示電量不足
F4:暫時(shí)表示f_x1
F3:暫時(shí)表示重量累加
******************************************/
//以下是全局變量和數(shù)據(jù)處理過程中使用到的函數(shù)
bit bdata f_stab_weight=0;//表征稱重結(jié)果示數(shù)的穩(wěn)定
//為1,示數(shù)穩(wěn)定;
//為0,示數(shù)不穩(wěn)
bit bdata f_stab=0; //表征結(jié)果的穩(wěn)定(相鄰兩個(gè)AD),
//為0,表示穩(wěn)定;
//為1,表示不穩(wěn)定
bit bdata f_stab2=0; //表征結(jié)果的穩(wěn)定(間隔的兩個(gè)AD),
//為0,表示穩(wěn)定;
//為1,表示不穩(wěn)定
bit bdata f_hold=0;//表征是否開啟了鎖定功能
//為0,表示沒有鎖定示數(shù);
//為1,表示已經(jīng)鎖定了稱重示數(shù)
bit bdata f_tare=0;//表征去皮狀態(tài),
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -