基于51单片机的hx711模块,实现称重
一些变量定义:(为什么定义在xdata ,因为我的data区空间不够,够的话直接定义就好)
u32 xdata HX711_Buffer = 0; //读取重量AD的变量
u32 Weight_Maopi= 0; //毛重
s32 xdata Weight_ADvalue= 0; //重量AD值
s32 xdata Weight_Shiwu= 0; //实际重量,这是一个有符号的数
s32 xdata weight_value = 0; //实际重量,送显示使用的中间变量
u32 xdata zeroValue ; //校准时0点的AD变量
u32 xdata fullScaleValue ; //校准时标准砝码的AD变量
u32 xdata calibrationValue; //0点AD-标准砝码AD 差值
u32 Calvalue_1000 ; //最终用于计算的标准砝码AD
u32 Calvalue_zero ; //最终用于计算的0点AD
bit Calib0_flag = 0; //读取到了0点标志
bit Calib1000_flag = 0;
hx711驱动程序(网上一搜一大把):
记得配置DAT(上拉输入)和SCK(推挽输出)引脚
u32 HX711_Read(void) //增益128
{
unsigned long count;
unsigned char i;
HX711_SCK = 0; //拉低时钟引脚
count=0;
Delay__hx711_us();
while(HX711_DOUT); //读取数据引脚状态,等待AD芯片准备好,为低电平时是准备好了
for(i=0;i<24;i++) //时钟周期500Khz
{
HX711_SCK = 1;
count=count<<1;
Delay__hx711_us();
HX711_SCK = 0;
if(HX711_DOUT)
count++;
Delay__hx711_us();
}
HX711_SCK = 1;
count=count^0x800000;//第25个脉冲下降沿来时,转换数据
Delay__hx711_us();
HX711_SCK = 0;
return(count);
}
最基本的驱动已经完成了,接下来是称重和校准处理
去皮函数:
//获取毛皮重量
//****************************************************
void Get_Maopi(void)
{
Weight_Maopi = HX711_Read();
}
称重函数:
/****************************************************
称重函数
****************************************************/
void Get_Weight(void)
{
u8 m;
HX711_Buffer = HX711_Read();
Weight_ADvalue = Weight_Maopi - HX711_Buffer; //获取实物的AD采样数值。Weight_Maopi在上电的时候采集一次,是一个固定的值, HX711_Buffer一直在采集,不固定
Weight_Shiwu =(Weight_ADvalue *100 /SysPara.Gapvalue); //计算实物的实际重量
//上边 标定时系数扩大了10倍 AD值扩大100倍 最终的结果重量扩大十倍
//秤盘上有东西,按置零去皮,再把东西拿走之后,显示负值
m = Weight_Shiwu%10; //扩大十倍后计算重量的个位数,进行四舍五入
if(Weight_Shiwu - 5 > 0) //重量是正数时,个位数大于等于5,则将重量缩小10倍后加1
{
if(m >= 5) Weight_Shiwu = Weight_Shiwu/10 + 1;
else Weight_Shiwu = Weight_Shiwu/10;
}
else if(Weight_Shiwu + 5 <= 0) //重量是负数时,个位数大于等于5,则将重量缩小10倍后减1
{
if(m >= 5) Weight_Shiwu = Weight_Shiwu/10 - 1;
else Weight_Shiwu = Weight_Shiwu/10;
}
else
{
Weight_Shiwu = 0;
}
/***注释:重量值扩大了十倍,精确度为1g。判断区间时不是单纯的大于0或小于0,应为大于5或小于-5,
也就是实际重量在-0.5---+0.5之间时为0,否则0会显示不稳****/
}
以上代码我包含了标准砝码校准的参数和获得重量后的四舍五入处理,假如要求不高:
HX711_Buffer = HX711_Read();
Weight_ADvalue = Weight_Maopi - HX711_Buffer; //获取实物的AD采样数值。Weight_Maopi在上电的时候采集一次,是一个固定的值, HX711_Buffer一直在采集,不固定
Weight_Shiwu =(Weight_ADvalue /SysPara.Gapvalue);
这些就能获得实际重量了。
SysPara.Gapvalue 是一个需要保存到eeprom中系数,如果不需要,可以定义为常值Gapvalue=xx。
这个系数根据自己的传感器计算。
标准砝码校准过程:
首先用户需要通过某按键进入校准状态
获取0点的AD值:
void hx711_calibrate_zero()
{
u8 i ;
u32 sum;
u32 max = 0, min = 0xffffff;
// 读取零点值
zeroValue = HX711_Read();
sum = 0;
if(zeroValue > 0x7C5000) //4g---0x7C5081 这是4g时的AD值
{
for(i = 0; i<10; i++)
{
zeroValue = HX711_Read();
if(zeroValue > 0x7C5000) //大于4g时的AD值 认为空秤
{
if( max < zeroValue ) max = zeroValue;
if( min > zeroValue ) min = zeroValue;
sum += zeroValue;
}
}
sum = sum - max - min;
sum = sum/8;
Calvalue_zero = sum; //多次读取之后去掉一个最大值一个最小值,求平均
Calib0_flag = 1; // 获取到0点的标志置1
}
}
根据这个标志,可以跳转进入下一状态,读取标准砝码的AD值,我使用1000g的砝码:
void hx711_calibrate_full()
{
u8 i;
u32 sum ;
u32 max = 0, min = 0xffffff; //(u32 要是0xffffffff,但因为重量值最大是0x007cxxxx 因此可写6个f,但不能写4个,值不对)
// // 在传感器上放置已知重量的物体,读取满量程值
fullScaleValue = HX711_Read();
sum = 0;
if(fullScaleValue < 0x775000 && fullScaleValue > 0x755000 ) //防止读空秤 给定一个大概范围,等着读1000g的AD
{
for(i = 0; i<30; i++)
{
fullScaleValue = HX711_Read();
if( max < fullScaleValue ) max = fullScaleValue;
if( min > fullScaleValue ) min = fullScaleValue;
sum += fullScaleValue;
}
sum = sum - max - min;
sum = sum/28;
Calvalue_1000 = sum;
Calib1000_flag = 1;
}
}
Calib1000_flag = 1;后,已经获取到1000g的AD了,就可以计算系数了:
void count_gapvalue()
{
calibrationValue = Calvalue_zero - Calvalue_1000;
calibrationValue = calibrationValue / 100; // 校准重量为 1000g , /100---扩大10倍
SysPara.Gapvalue = calibrationValue; //得出系数后存入eeprom
}
这里应该除以1000,但是除以100等于将系数扩大了10倍,提高重量精度,方便后续四舍五入处理
就是这里:
Weight_Shiwu =(Weight_ADvalue *100 /SysPara.Gapvalue); //计算实物的实际重量
//上边 标定时系数扩大了10倍 AD值扩大100倍 最终的结果重量扩大十倍
最终重量扩大了10倍,进行四舍五入处理就可以通过判断个位进行。
特别说明:以上都是用0点去减有重量时的AD,或者去皮减重量,因为我的HX711模块接传感器的那两根线接反了,导致0点时的AD值最大,有重量后AD值变小,也就是说,如果用正常的测得的重量减去皮重,我这没有数值,不是放上东西有数值,而是把传感器向上抬起才有数值。当然,我所处理的重量是有符号的,表现出来就是放上东西显示负的重量,所以要用毛皮减去测得重量。