📄 yh_t3_new.c
字号:
/********************************
说明:
1.该程序适用于高精度的场合
2.关于如何借鉴保加利亚程序的原则:
首先,如果能完全看懂,则将原汇编程序改写为C程序;
其次,如果大部分能看懂,则仍模仿汇编程序的
结构和流程,改写。那些不懂的细节可以自己编写
或者干脆暂时省略,以后出了问题再补充。
最后,如果大部分看不懂,则自己创造,自己编写,
同时借鉴汇编程序中可以看得懂的部分,以后出了
问题再完善和补充。
*********************************/
/********************************
注意事项:
1.对AT24C02进行多次写操作时,中间必须相隔5ms
2.乘法运算时,乘数必须和积的数据类型相统一。
注意:不同的数据类型进行运算时,极易出现隐蔽性的差错。
要么定义为相同的数据类型,要么使用强制转换。
另外,涉及到乘法运算时,存在着运算过程中,某个被乘数
的变量的内容被“非法”修改的现象。
如果碰上这种情况,重新赋值就可以了。
通过单步调试来发现这个隐形杀手。
3.我们使用的晶振是11.0592M,不是12M,所以定时是不准确
的,存在误差。
4.DATA的128个字节不能全部占用,因为堆栈也需要占用DATA
的空间。因此可以将占用空间最大的数组存放在IDATA,
其余变量都默认存放在DATA即可。
5.制约响应速度的原因有两个:排序数组的长度和5460的
输出速率。
6.CS5460A的偏置校准数据一旦写入偏置校准寄存器,要断电
之后该寄存器的数据才消失。当然如果,每次运行程序都
写入偏置校准数据,可能也不需要断电。
7.单位转换中的克与英镑的转换存在bug,当秤的精度变大
时会出现问题。示数的最高位与小数点的位置可能不正确
8.AT24C02的页面写操作存在不能超越当前page(8个字节);
顺序写操作则没有这种限制。
9.分度值的改变牵连很广,包括:重量值的计算,精度,
数值的符号的产生,长期稳定旗标。
10.
*********************************/
/********************************
功能上的欠缺:
1.还是校准完成后马上可以称重,比较人性化,但是代码
可能会大量增加,因为,称重那部分很可能要重复。
以后再尝试。
也不一定,不妨尝试一下,我感觉应该也没有多少难度,
代码也不会增加多少。
建议方法:将菜单部分设计成一个庞大的函数。
通过在称重循环结尾处查询组合键是否按下
调用菜单函数。设定完成后通过break跳出
菜单的循环,继续称重。
当然读取24c02部分可能会重复。也
可能不会。现炒现卖。
暂时不用。
2.应该添加防震功能。
3.传说中的LCD亮度调节,就是背光亮度的调节,只要在硬件
上调整相应的电阻就可以了。
至于软件调节肯定要使用专门的液晶或者增加相关的硬件
电路。
4.低电压报警模块应该并不难,但是,如果想要显示电压的
数值则比较困难。要研究耀华T3的电路和软件才能解决。
5.目前没有hold功能,因为按键不够!
6.
7.
8.我所使用的背光模块是一种手动背光,必须进行菜单设置。
今后可能要考虑自动背光以及真正的手动按键控制背光。
9.
***************************************************/
/*************************************************
目前存在的问题
问题一:现在的背光电路有一个不爽的地方,开机就亮!
建议方法:背光电路之前加一个三极管作为反相器
就可以了。
问题二:如果没有单位转换,小数点位置的变换会很简单,
有单位转换,可能很麻烦。
问题三:
问题四:
问题五:T2作为波特率发生器,仿真失败;有可能是keil
本身的模拟串口存在问题,不支持T2。如果进行
实际的线路连接可能会成功。
暂时使用T1作为串口波特率发生器;使用T0和T2
实现延时5分钟的功能。
问题六:
问题七:串口模块中,由于目前的示数的正负旗标:f_minus
的局限性,当示数为0时,串口输出的数据会出现
+0和-0两种情况。不过影响也不大,暂时不管它。
**************************************************/
/***************************
思路一:菜单所包含的内容暂时有以下几个:
分度值选择、小数点的位置、波特率、背光开关
、量程选择、校准、校准砝码。
先模仿T3,归零范围选择和零点跟踪选择以后再说。
思路二:
思路三:新建LCD编码数组的过程中可能修改了某些数据,
也不会出错,但是看着不爽。如果见到就改回来。
思路四:原来使用的sort函数中后来被去掉的部分应该有一定
的防震功能。考虑一下是否恢复。
在某个时间段之内的短暂的AD变化不去取样。
建议方法:保加利亚程序中,在排序部分,那种间隔取值的
方法研究一下。这种方法,在相同的排序数组长度
的情况下,牺牲一部分时间,即LCD的变化速率
翻倍,如果数组的长度是25,则称对瞬间冲力的忽略
时间可达1~2秒。
只要忽略时间达到2秒,防震功能就马马虎虎了。
暂时不用,以后再说,因为我的RAM和ROM的空间
都很有限。
思路五:
思路六:在菜单这部分,考虑使用位域,因为变量的值都
比较小,即使使用最小的uchar也有点浪费。
或者使用枚举
思路七:尽量减少变量,尽量减少全局变量。宁可增加子函数
中的局部变量也要减少全局变量和主函数中的变量。
思路八:
思路九:
思路十:考虑延时自动关机功能。也不复杂,只要在
时间到了之时,对OFF脚(P1.4)置零就能达到
关机的目的。
思路11:考虑分段校准。表头项目成功生产后再考虑提高。
思路12:
思路13:
思路14:
思路15:通过对比汇编产生的代码的多少,进行深层次的
优化。
******************************/
#include <reg52.h>
#include <intrins.h>
//----------------------
//以下是自定义的数据类型
#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)
//这条指令可以不要,因为1621上电默认的就是选择片内的RC256振荡器
#define SYSTEN 0x01//0X02 //Turn on system oscillator(打开系统的振荡器)
#define SYSDIS 0x00//0X00 //Turn off both system oscillator and LCD bias generator(全关)
#define LCDON 0x03//0X06 //Turn on LCD
#define LCDOFF 0x02 //关闭LCD
#define BUZON 0x09//打开蜂鸣器
#define BUZOFF 0x08//关闭声音
#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个大写字母对应的HT1621的编码,为了方便查询,数组定义为27个字节,其中,首字节为特殊符号“=”的编码。
//以下是26个字母在数组中对应的下标。
//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};
//定义一个HT1621显示数据缓冲区,初始化全部为0x00。
uchar dis_zone[6]={0x00,0x00,0x00,0x00,0x00,0x00};
sbit dt_1621=P2^4; //LCD显示的数据。
sbit cs_1621=P2^5; //使能。
sbit wr_1621=P2^6; //写信号。
sbit BL=P1^6;//背光引脚,为1,背光亮;
//为0,背光灭
//------------------------------------
//以下是CS5460的变量定义和函数声明
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;
//-----------------------------------
//以下是串口的函数声明
/*********************************
串口帧信息格式:一帧10位,
其中第1位:起始位“0”
第10位:停止位“1”
中间8位:数据位
注意:一帧虽然在时序上有十位,包含起始位和停止位。
但是,向sbuf赋值的实际上只有中间的8位数据位。
********************************/
/********************************
LCD显示的重量信息100.00Kg
串口发送的数据:”00.001 “,注意:最后的空格表示正号。
LCD显示的重量信息-35.000Kg
串口发送的数据:”000.53-“,注意:最后的"-"表示负号。
包含小数点和符号,共7位数据。并且二者的顺序恰好相反
另外:重量数字中高位为零不显示的情况,传送时按0发送
凑够位数。
*******************************/
void send_byte(uchar txd);
/******************************
//常用的ASCII码: 0 :48
=:61
. :46
-:45
g :103
K :75
空格” “:32
******************************/
//------------------------------------
//以下是定时器(计数器)的管脚定义和函数声明
/************************************
为了实现延时5分钟, T0作为16位定时器
T1作为16位计数器
************************************/
sbit CLK_COUNTER0=P3^4;
void delay_5min(void);
//------------------------------------
//以下是AT24c02的相关变量和函数
uchar code READ=0xa1; // 器件地址以及读取操作
uchar code WRITE=0xa0; // 器件地址以及写入操作
sbit SDA=P2^1; // IIC数据
sbit SCL=P2^2; // IIC时钟
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];
/*****************************
数组buf_24c02_rd[]中相应位置的数据含义:
0——分度值
1——小数点位置
2——波特率
3——背光
*****************************/
uchar idata buf_24c02_4B[4];//用来存储从24c02中读取的数据,
//随后就用来存储将要向24c02中写入的数据
//目的:1.在菜单状态下,显示当前的设定
//2.在称重状态下,获取设定信息
// 用于显示和计算。
//下面数组的用途:
//第一个:量程;第二个:校准砝码的重量
ulong idata buf_24c02_2L[2];
//--------------------------------------------
//电池电压检测部分的变量定义和函数声明。
sbit PD=P1^5;
void alarm_low(void);
//--------------------------------------------
//下面的数据是针对3公斤传感器(1.5Kg校准,没有偏置校准)
//电流通道增益PGA=50
//这种情况下,AD值太大,因此将从5460读出的数据
//在原来的基础上缩小为原来的1/4
//校准的AD平均值增量是:76477
#define N_5460 500 //表示5460的转换周期
//注意:下述带参数的宏定义中的x表示量程的AD平均值增量
#define ZERO_POS(x) ((x)/5) //表示零点范围上限:+20%
//#define ZERO_NEG(x) ((-1)*((x)/25)) //表示零点范围下限:-4%,这两个百分比都是以校准的AD平均值增量为分母的。
#define ZERO_NEG(x) (((-x)/25)) //表示零点范围下限:-4%,这两个百分比都是以校准的AD平均值增量为分母的。
#define MANU_ZERO_POS(x) ((x)/50) //表示手动归零范围上限:+2%
//#define MANU_ZERO_NEG(x) ((-1)*((x)/50)) //表示手动归零范围下限:-2%,这两个百分比都是以校准的AD平均值增量为分母的。
#define MANU_ZERO_NEG(x) ((-x)/50) //表示手动归零范围下限:-2%,这两个百分比都是以校准的AD平均值增量为分母的。
#define AUTO_ZERO_POS(x) ((x)/200) //表示自动归零范围上限:+0.5%
//#define AUTO_ZERO_NEG(x) ((-1)*((x)/200)) //表示自动归零范围下限:-0.5%,这两个百分比都是以校准的AD平均值增量为分母的。
#define AUTO_ZERO_NEG(x) ((-x)/200) //表示自动归零范围下限:-0.5%,这两个百分比都是以校准的AD平均值增量为分母的。
#define TARE_HIGH(x) (x) //表示去皮的上限:量程的50%
#define TARE_LOW 5 //表示去皮的下限
#define E 5 //表示通常我们所说的一个E。
#define E1(x) ((x)*E)
#define OVER_LOAD(x) ((x)+E*9+(long)(buf_24c02_AD[0]))//表示秤量程AD值上限,比量程AD高约9个E。
//#define OFFSET 0x00fba48e //表示5460的偏置校准数据
//#define JZ_ZERO_LOW 10000 //表示5460AD校准,空载时的下限
//#define JZ_ZERO_HIGH 20000 //表示5460AD校准,空载时的上限
//#define JZ_LOAD_LOW 90000 //表示5460AD校准,加砝码后的下限
//#define JZ_LOAD_HIGH 100000 //表示5460AD校准,加砝码后的上限
//#define ZERO_POS 15295 //表示零点范围上限:+20%
//#define ZERO_NEG -3059 //表示零点范围下限:-4%,这两个百分比都是以校准的AD平均值增量为分母的。
//#define MANU_ZERO_POS 1530//表示手动归零范围上限:+2%
//#define MANU_ZERO_NEG -1530//表示手动归零范围下限:-2%,这两个百分比都是以校准的AD平均值增量为分母的。
//#define AUTO_ZERO_POS 382//表示自动归零范围上限:+0.5%
//#define AUTO_ZERO_NEG -382//表示自动归零范围下限:-0.5%,这两个百分比都是以校准的AD平均值增量为分母的。
//#define TARE_HIGH 38239//表示去皮的上限:量程的50%
//#define TARE_LOW 5 //表示去皮的下限
//#define OVER_LOAD 100000 //表示秤量程AD值上限,比量程AD高约9个E。
//这个宏定义今后可以省略。
//#define E 5 //表示通常我们所说的一个E。
//#define N 15000 //表示精度,即我自己平时所说的几万分之一或几千分之一。
/*****************************************************
//下面的数据是针对3公斤传感器(1Kg校准,没有偏置校准)
//电流通道增益PGA=50
//这种情况下,AD值太大,因此将从5460读出的数据
//在原来的基础上缩小为原来的1/4
//校准的AD平均值增量是:
#define N_5460 375 //表示5460的转换周期
//#define OFFSET 0x00fba48e //表示5460的偏置校准数据
#define JZ_ZERO_LOW 10000 //表示5460AD校准,空载时的下限
#define JZ_ZERO_HIGH 20000 //表示5460AD校准,空载时的上限
#define JZ_LOAD_LOW 60000 //表示5460AD校准,加砝码后的下限
#define JZ_LOAD_HIGH 70000 //表示5460AD校准,加砝码后的上限
#define ZERO_POS 15295 //表示零点范围上限:+20%
#define ZERO_NEG -3059 //表示零点范围下限:-4%,这两个百分比都是以校准的AD平均值增量为分母的。
#define MANU_ZERO_POS 1530//表示手动归零范围上限:+2%
#define MANU_ZERO_NEG -1530//表示手动归零范围下限:-2%,这两个百分比都是以校准的AD平均值增量为分母的。
#define AUTO_ZERO_POS 382//表示自动归零范围上限:+0.5%
#define AUTO_ZERO_NEG -382//表示自动归零范围下限:-0.5%,这两个百分比都是以校准的AD平均值增量为分母的。
#define TARE_HIGH 38239//表示去皮的上限:量程的50%
#define TARE_LOW 5 //表示去皮的下限
#define OVER_LOAD 100000 //表示秤量程AD值上限,比量程AD高约9个E。
//这个宏定义今后可以省略。
#define E 5 //表示通常我们所说的一个E。
#define N 10000 //表示精度,即我自己平时所说的几万分之一或几千分之一。
************************************************************************/
/*****************************************
错误号说明:(注意:针对错误号使用搜索,不行!)
Err 1: 零点偏离了指定范围
Err 2: 单位转换
Err 3: 菜单
Err 4: 超载
Err 5: 校准时空载的AD平均值超出了范围
Err 6: 校准时,放置校准砝码后的AD平均值超出了范围
Err 7: 菜单中的分度值或者称重时分度值选择
Err 8: 菜单中的波特率或者称重时波特率选择
*******************************************/
/******************************************
秤的状态符号说明如下:
F1:表征稳定
F2:表征HOLD锁定
F5:表征去皮状态
F6:表征示数归零
电池符号:表示电量不足
F4:暂时表示f_x1
F3:暂时表示重量累加
******************************************/
//以下是全局变量和数据处理过程中使用到的函数
bit bdata f_stab_weight=0;//表征称重结果示数的稳定
//为1,示数稳定;
//为0,示数不稳
bit bdata f_stab=0; //表征结果的稳定(相邻两个AD),
//为0,表示稳定;
//为1,表示不稳定
bit bdata f_stab2=0; //表征结果的稳定(间隔的两个AD),
//为0,表示稳定;
//为1,表示不稳定
bit bdata f_hold=0;//表征是否开启了锁定功能
//为0,表示没有锁定示数;
//为1,表示已经锁定了称重示数
bit bdata f_tare=0;//表征去皮状态,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -