HX711称重模块,想必很多人都听说过这个模块,这是一款专门用于测量重量的一个模块,今天在这里总结一下代码和踩过的坑。
代码的话这里借鉴的是官方和CSDN的,具体是哪个博主已经忘记了(侵删),这里只对代码的调用做说明,实现的步骤自行消化。
一、STM32标准库
HX711.c
#include "HX711.h"
#include "delay.h"
//===================
#define MEDIAN_LEN_2 5 //中值滤波的滤波长度,一般取奇数
#define MEDIAN_2 3 //中值在滤波数组中的位置
u32 buffer_2[MEDIAN_LEN_2]; //中值滤波的数据缓存
int medleng_2 = 0; //一组中值滤波数据中,进入滤波缓存的数据个数
u32 xd_2,xd1_2; //数据对比大小中间变量
//==========================
u32 weight; //实际重量值
u32 weight_2; //实际重量值2
u32 pi_weight; //皮重
u32 pi_weight_2; //皮重2
u32 last_weight = 50;
//u32 hx711_xishu=31706; //这是一个修正系数,例如1000g砝码称出来是934g,则HX711_xishu=原数据*1000/934;
//u32 hx711_xishu=47785;
//u32 hx711_xishu=69253;
//u32 hx711_xishu=50921;
//u32 hx711_xishu_2=8174;
u32 hx711_xishu_2=9374;
void HX711_2_GPIO_Init(float TRUTH,float MEASURE)
{
float THAN;
THAN = TRUTH / MEASURE;
GPIO_InitTypeDef GPIO_InitStructure;
HX711_GPIO_APBxClkCmd_2(HX711_GPIO_CLK_2, ENABLE);
GPIO_InitStructure.GPIO_Pin = HX711_SCK_GPIO_PIN_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(HX711_SCK_GPIO_PORT_2, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = HX711_DATA_GPIO_PIN_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(HX711_DATA_GPIO_PORT_2, &GPIO_InitStructure);
hx711_xishu_2 = hx711_xishu_2*THAN;
Get_Tare_2();
}
void HX711_2_Data_Out(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
HX711_GPIO_APBxClkCmd_2(HX711_GPIO_CLK_2, ENABLE);
GPIO_InitStructure.GPIO_Pin = HX711_DATA_GPIO_PIN_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(HX711_DATA_GPIO_PORT_2, &GPIO_InitStructure);
}
void HX711_2_Data_In(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
HX711_GPIO_APBxClkCmd_2(HX711_GPIO_CLK_2, ENABLE);
GPIO_InitStructure.GPIO_Pin = HX711_DATA_GPIO_PIN_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(HX711_DATA_GPIO_PORT_2, &GPIO_InitStructure);
}
u32 Read_HX711_2(void)
{
uint8_t i;
uint32_t value = 0;
/**
数据手册写到,当数据输出管脚 DOUT 为高电平时,表明A/D 转换器还未准备好输出数据,此时串口时
钟输入信号 PD_SCK 应为低电平,所以下面设置引脚状态。
**/
HX711_2_Data_Out();
HX711_DATA_2=1; //初始状态DT引脚为高电平
delay_us(1);
HX711_SCK_2=0; //初始状态SCK引脚为低电平
HX711_2_Data_In();
/**
等待DT引脚变为高电平
**/
while(HX711_DATA_2);
delay_us(1);
/**
当 DOUT 从高电平变低电平后,PD_SCK 应输入 25 至 27 个不等的时钟脉冲
25个时钟脉冲 ---> 通道A 增益128
26个时钟脉冲 ---> 通道B 增益32
27个时钟脉冲 ---> 通道A 增益64
**/
for(i=0; i<24; i++) //24位输出数据从最高位至最低位逐位输出完成
{
HX711_SCK_2=1;
delay_us(1);
HX711_SCK_2=0;
if(HX711_DATA_2 == 0)
{
value = value << 1;
value |= 0x00;
}
if(HX711_DATA_2 == 1)
{
value = value << 1;
value |= 0x01;
}
delay_us(1);
}
//第 25至 27 个时钟脉冲用来选择下一次 A/D 转换的输入通道和增益
HX711_SCK_2=1;;
value = value^0x800000;
delay_us(1);
HX711_SCK_2=0;
delay_us(1);
return value;
}
void Get_Tare_2(void)//获取皮重
{
u32 hx711_dat_2;
u8 i;
for(i=0;i<MEDIAN_LEN_2;i++)
{
hx711_dat_2=Read_HX711_2(); //HX711AD转换数据处理
if(medleng_2 == 0) //缓存的第1个元素,直接放入,不需要排序
{
buffer_2[0] = hx711_dat_2; medleng_2 = 1;
}
else //插入排序算法,按从小到大的顺序排列
{
for(i = 0; i < medleng_2; i ++)
{
if( buffer_2[i] > hx711_dat_2) // 轮询到的当前元素>AD值,则交换它们的值,xd为中间变量存放位置
{
xd_2 = hx711_dat_2; hx711_dat_2 = buffer_2[i]; buffer_2[i] = xd_2;
}
}
buffer_2[medleng_2] = hx711_dat_2; //把轮询出较大的数放入缓存的后面.
medleng_2++;
}
if(medleng_2 >= MEDIAN_LEN_2) //ADC采样的数据个数达到中值滤波要求的数据个数
{
hx711_dat_2 = buffer_2[MEDIAN_2]; //最终重量取中值滤波数组的中间值
medleng_2 = 0;
}
}
pi_weight_2=(u16)(hx711_dat_2*0.01);
}
void Get_Weight_2() //获取被测物体重量
{
u32 hx711_data_2,a_2;
u32 get_2,aa_2;
hx711_data_2=Read_HX711_2(); //HX711数据采集函数
get_2=(u16)(hx711_data_2*0.01); //HX711AD转换数据处理,数据缩小100倍
if(get_2>pi_weight_2)
{
a_2=Read_HX711_2(); //重新采集HX711数据
aa_2=(u16)(a_2*0.01)-pi_weight_2; //测得的重量值减去皮重
weight_2=(u16)((float)aa_2*0.00001*hx711_xishu_2);//重量转换函数,传感器型号不同此函数要适当修改(修改HX711_xishu的大小)
}
else
weight_2=0;
}
unsigned short GET_WEIGHT()//THAN是一个比例,比如你称手机,真实是300g,测量是200g,THAN = 300/200 = 1.5;
{
Get_Weight_2();
if(medleng_2 == 0) //缓存的第1个元素,直接放入,不需要排序
{
buffer_2[0] = weight_2; medleng_2 = 1;
}
else //插入排序算法,按从小到大的顺序排列
{
for(int i = 0; i < medleng_2; i ++)
{
if( buffer_2[i] > weight_2) // 轮询到的当前元素>AD值,则交换它们的值,xd为中间变量存放位置
{
xd_2 = weight_2; weight_2 = buffer_2[i]; buffer_2[i] = xd_2;
}
}
buffer_2[medleng_2] = weight_2; //把轮询出较大的数放入缓存的后面.
medleng_2++;
}
if(medleng_2 >= MEDIAN_LEN_2) //ADC采样的数据个数达到中值滤波要求的数据个数
{
weight_2 = buffer_2[MEDIAN_2]; //最终重量取中值滤波数组的中间值
medleng_2 = 0;
}
return weight_2;
}
HX711.h
#ifndef __HX711_2_H
#define __HX711_2_H
#include "sys.h"
#define HX711_DATA_2 PAin(6)
#define HX711_SCK_2 PAout(7)
// USART GPIO 引脚宏定义
#define HX711_GPIO_CLK_2 RCC_APB2Periph_GPIOA
#define HX711_GPIO_APBxClkCmd_2 RCC_APB2PeriphClockCmd
#define HX711_DATA_GPIO_PORT_2 GPIOA
#define HX711_DATA_GPIO_PIN_2 GPIO_Pin_6
#define HX711_SCK_GPIO_PORT_2 GPIOA
#define HX711_SCK_GPIO_PIN_2 GPIO_Pin_7
void HX711_2_GPIO_Init(float TRUTH,float MEASURE);//初始化,假如你100g的手机,测量值为200,则填入100,200,拿开砝码,重新初始化即可校准
uint32_t Read_HX711_2(void);
void Get_Tare_2(void);//获取皮重
unsigned short GET_WEIGHT(void);//获取重量
#endif
关于STM32代码实现步骤:
1.在工程目录下新建两个文件HX711.c,HX711.h,然后将对应的代码块复制进去(注意:操作这一步的前提就是你原来的工程编译通过)。
2.调用HX711的代码
3.调用初始化函数
4.调用读取函数
5.将数据用串口或者LCD,LED显示出来
STM32的这个代码在STM32F103C8T6,STM32F103ZET6已经实现了。
二.注意事项
事情到这里其实可以结束了,放上相应物体就会有示数了,但是根据我踩的这么多坑来说,这有有你们可能出现的一些问题。
1.引脚不正确
这里不正确的指的是你的连接有问题,或者你的这对引脚干其他活去了,这里的话你就检查那俩引脚的硬件连接。如需改引脚,打开HX711.h,修改下列参数:
这里的时钟,啥的都要注意下要改,
2.称重条装反了
前一步完成后还是没有示数,这个时候就要注意了,你可以用手把称重条从下往上推,这个时候如果出现示数,那就是装反了,用螺丝刀,将螺丝取下,重新装好就可以。这个坑我踩了很多遍。
也可以参考他上面的这个提示朝下的。
如果还是没用,就换一边,有箭头这边的螺丝连接下底盘
三、原理:(以后再写)
四、51代码(有人问了再更新吧)