基于stm32f103c8t6的HX711称重传感器快速上手

 HX711芯片

简介:

         HX711 采用了海芯科技集成电路专利技术, 是一款专为高精度电子秤而设计的 24 位 A/D 转 换器芯片。与同类型其它芯片相比,该芯片集 成了包括稳压电源、片内时钟振荡器等其它同类型芯片所需要的外围电路,具有集成度高、 响应速度快、抗干扰性强等优点。降低了电子秤的整机成本,提高了整机的性能和可靠性。 该芯片与后端 MCU 芯片的接口和编程非常 简单,所有控制信号由管脚驱动,无需对芯片 内部的寄存器编程。输入选择开关可任意选取 通道 A 或通道 B,与其内部的低噪声可编程放 大器相连。通道 A 的可编程增益为 128 或 64,对应的满额度差分输入信号幅值分别为±20mV 或±40mV。通道 B 则为固定的 32 增益,用于系 统参数检测。芯片内提供的稳压电源可以直接 向外部传感器和芯片内的 A/D 转换器提供电源,系统板上无需另外的模拟电源。芯片内的时钟振荡器不需要任何外接器件。上电自动复位功能简化了开机的初始化过程。

特点:

• 两路可选择差分输入        

• 片内低噪声可编程放大器,可选增益为 32,64 和 128 • 片内稳压电路可直接向外部传感器和芯片内 A/D 转换器提供电源

• 片内时钟振荡器无需任何外接器件,必要时 也可使用外接晶振或时钟

• 上电自动复位电路

• 简单的数字控制和串口通讯:所有控制由管 脚输入,芯片内寄存器无需编程

• 可选择 10Hz 或 80Hz 的输出数据速率

• 同步抑制 50Hz 和 60Hz 的电源干扰

• 耗电量(含稳压电源电路): 典型工作电流:< 1.6mA, 断电电流:< 1µA

• 工作电压范围:2.6 ~ 5.5V

• 工作温度范围:-40 ~ +85℃

• 16 管脚的 SOP-16 封装 

  本次内容讲解使用的主控芯片为stm32f1038t6,使用的是最小系统板,结构图如下:

        我们主要目的是让大家快速上手使用该称重传感器,所以上述内容只作为教学开篇使用,具体内容还需大家自行深入学习。结合HX711芯片使用(这边建议大家直接购买功能板,如上图所示),只需要外接功能板的VCC(亲测5V/3.3V都可使用,毕竟电压范围是2.7-5.5V,上面框图有标注)、GND以及数据线DOUT和时钟线SCK到核心板自行设置的对应引脚。另一边的E+、E-、A+、A-、B+、B-则是连接我们对应的称重传感器。使用的是实验中常见的桥式压力传感器,称重范围(5kg、10kg等等)大家可以根据自身需求购买,在这里就不多赘述了。 见下图:

该传感器会带有四根线,颜色普遍为红黑白绿(如有例外大家自行询问商家如何连接即可),这四根线则需要连接上述的E+、E-、A+、A-即可使用,不用连接B+、B-(如果如下图连接存在不显示称重重量或为负数,可尝试将白绿两线调换位置。如果还不行,当我没说!!!偷偷跳楼即可!!!),连接顺序见下图:

 程序代码:

接下来就是大家最期待的代码部分:

(为了方便大家  CV,直接为大家准备好 .C 和.H 以及main的整体代码!!!)

hx711.c文件:

代码注意事项:

1.代码亲测能用的,遇到问题别着急!!!

2.引脚配置要与hx711.h内定义相对应,换就要全部换!!!

3.如不懂hx711工作原理,自行查看芯片手册。(建议小破站搜索!!!)

#include "HX711.h"    //调用hx711头文件
#include "delay.h"    //调用delay延时头文件

void HX711_GPIO_Init(void)      //初始化hx711  
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	HX711_GPIO_APBxClkCmd(HX711_GPIO_CLK, ENABLE);    //使能对应时钟

	GPIO_InitStructure.GPIO_Pin = HX711_SCK_GPIO_PIN;	//配置SCK引脚
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;    //配置输出模式-推完输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;    //配置速度频率
	GPIO_Init(HX711_SCK_GPIO_PORT, &GPIO_InitStructure);    //初始化配置
	
	GPIO_InitStructure.GPIO_Pin = HX711_DATA_GPIO_PIN;    //配置DOUT引脚
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;    //配置输入模式-浮空输入
	GPIO_Init(HX711_DATA_GPIO_PORT, &GPIO_InitStructure);    //初始化配置
}

void HX711_Data_Out(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	HX711_GPIO_APBxClkCmd(HX711_GPIO_CLK, ENABLE);

	GPIO_InitStructure.GPIO_Pin = HX711_DATA_GPIO_PIN;	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(HX711_DATA_GPIO_PORT, &GPIO_InitStructure);
}

void HX711_Data_In(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	HX711_GPIO_APBxClkCmd(HX711_GPIO_CLK, ENABLE);

	GPIO_InitStructure.GPIO_Pin = HX711_DATA_GPIO_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(HX711_DATA_GPIO_PORT, &GPIO_InitStructure);
	
}

u32 Read_HX711(void)
{
	uint8_t i;
	uint32_t value = 0;
	
	/**
	数据手册写到,当数据输出管脚 DOUT 为高电平时,表明A/D 转换器还未准备好输出数据,此时串口时
	钟输入信号 PD_SCK 应为低电平,所以下面设置引脚状态。
	**/
	HX711_Data_Out();
	HX711_DATA=1; //初始状态DT引脚为高电平
	delay_us(1);
	HX711_SCK=0; //初始状态SCK引脚为低电平
	HX711_Data_In();
	/**
	等待DT引脚变为高电平
	**/
	while(HX711_DATA);
	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=1;
		delay_us(1);
		HX711_SCK=0;
		if(HX711_DATA == 0)
		{
			value = value << 1;
			value |= 0x00;
		}
		if(HX711_DATA == 1)
		{
			value = value << 1;
			value |= 0x01;
		}
		delay_us(1);
	}
	
	//第 25至 27 个时钟脉冲用来选择下一次 A/D 转换的输入通道和增益
	HX711_SCK=1;; 
	value = value^0x800000; 
	delay_us(1); 
	HX711_SCK=0; 
	delay_us(1);  
	return value; 	
}


//最后记得空行!!!

 hx711.h文件:

代码注意事项:

1.这里采用的引脚是A11、A12分别连接的是Dout和Sck,如要修改记得将全部引脚号修改!!!

2.看好修改的引脚对应的APB总线,避免无效修改(改就要全部改好)。

#ifndef __HX711_H
#define __HX711_H
#include "sys.h"

#define  HX711_DATA  PAin(11)       //这里使用的DOUT引脚是A11
#define  HX711_SCK   PAout(12)      //这里使用的SCK引脚是A12  


// USART GPIO 引脚宏定义
#define  HX711_GPIO_CLK            RCC_APB2Periph_GPIOA
#define  HX711_GPIO_APBxClkCmd     RCC_APB2PeriphClockCmd
	
#define  HX711_DATA_GPIO_PORT      GPIOA
#define  HX711_DATA_GPIO_PIN       GPIO_Pin_11	
#define  HX711_SCK_GPIO_PORT       GPIOA   
#define  HX711_SCK_GPIO_PIN        GPIO_Pin_12



void HX711_GPIO_Init(void);
uint32_t Read_HX711(void);

#endif

//最后记得空行!!!

 main文件:

代码注意事项:

1.使用了0.96寸OLED显示屏用作重量的显示(如不需要或尺寸不同请自行更换OLED相关代码);

2.使用了核心板串口1进行数据通信,可以连接核心板的PA9(TX)、PA10(RX)到电脑,使用串口助手查看数据输出;(如不需要,请将与usart相关的的代码全部删除,包括头文件、初始化、printf等)

3.称重传感器使用中,称重不准不是代码问题,是由于每款传感器存在差异,代码中修改修正系数可以解决问题——例如1000g砝码称出来重量是934g,则将代码中的HX711_xishu修改为原数据(指的是代码中的47785)*1000/934。假如我们称100g砝码,显示重量为98g,就用 47785*100/98得到新的修正系数为48760(这里取整了,带小数也是可以的)。建议大家多调试几次,采用不同重量砝码!!!

4.中值滤波方法简单有效,如有更好办法,可以自行尝试!

#include "sys.h"        
#include "delay.h"
#include "oled_iic.h"
#include "HX711.h"
#include "usart.h"
#include "stdio.h"


#define MEDIAN_LEN  5  			//中值滤波的滤波长度,一般取奇数
#define MEDIAN      3  			//中值在滤波数组中的位置
u32   buffer[MEDIAN_LEN];   	//中值滤波的数据缓存
int   medleng = 0;          	//一组中值滤波数据中,进入滤波缓存的数据个数
u32   xd,xd1;					//数据对比大小中间变量

u32	weight;		      //实际重量值
u32	pi_weight;		        //皮重
//u32	hx711_xishu=31706;		//这是一个修正系数,例如1000g砝码称出来是934g,则HX711_xishu=原数据*1000/934;
u32	hx711_xishu=47785;
void Get_Tare(void)//获取皮重
{
	u32 hx711_dat;
	u8 i;
	for(i=0;i<MEDIAN_LEN;i++)
	{
		hx711_dat=Read_HX711();	        	//HX711AD转换数据处理
		if(medleng == 0)                    //缓存的第1个元素,直接放入,不需要排序
		{ 
			buffer[0] = hx711_dat; medleng = 1; 
		}
		else                            	//插入排序算法,按从小到大的顺序排列 
		{  
			for(i = 0; i < medleng; i ++)  
			{
				if( buffer[i] > hx711_dat) 	// 轮询到的当前元素>AD值,则交换它们的值,xd为中间变量存放位置
				{ 
					xd = hx711_dat; hx711_dat = buffer[i]; buffer[i] = xd;
				}
			}
			buffer[medleng] = hx711_dat; 	//把轮询出较大的数放入缓存的后面.
			medleng++;
		}		
		if(medleng >= MEDIAN_LEN) 		    //ADC采样的数据个数达到中值滤波要求的数据个数
		{
			hx711_dat = buffer[MEDIAN];	    //最终重量取中值滤波数组的中间值
			medleng = 0; 
		}
	}
	pi_weight=(u16)(hx711_dat*0.01);
}

void Get_Weight()	  //获取被测物体重量
{
	u32 hx711_data,a;
	u32 get,aa;	
	hx711_data=Read_HX711();		   //HX711数据采集函数
	get=(u16)(hx711_data*0.01);   //HX711AD转换数据处理,数据缩小100倍
	if(get>pi_weight)
	{
		a=Read_HX711();			   //重新采集HX711数据					 														   
		aa=(u16)(a*0.01)-pi_weight;			     //测得的重量值减去皮重
		weight=(u16)((float)aa*0.00001*hx711_xishu);//重量转换函数,传感器型号不同此函数要适当修改(修改HX711_xishu的大小)	
	}
	else				
		weight=0;
}


int main(void)
{		
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
	delay_init();
	HX711_GPIO_Init();
	uart_init(115200);
	Get_Tare();
	OLED_Init();
	OLED_Clear();
	OLED_ShowCH(20,4,"重量:   0g");
	while(1)
	{		
		Get_Weight();
		if(medleng == 0)                    //缓存的第1个元素,直接放入,不需要排序
		{ 
			buffer[0] = weight; medleng = 1; 
		}
		else                            	//插入排序算法,按从小到大的顺序排列 
		{  
			for(int i = 0; i < medleng; i ++)  
			{
				if( buffer[i] > weight) 	// 轮询到的当前元素>AD值,则交换它们的值,xd为中间变量存放位置
				{ 
					xd = weight; weight = buffer[i]; buffer[i] = xd;
				}
			}
			buffer[medleng] = weight; 	//把轮询出较大的数放入缓存的后面.
			medleng++;
		}		
		if(medleng >= MEDIAN_LEN) 		    //ADC采样的数据个数达到中值滤波要求的数据个数
		{
			weight = buffer[MEDIAN];	    //最终重量取中值滤波数组的中间值
			medleng = 0; 
			OLED_ShowNum(60,4,weight,4,0);
			printf("weight:%d g\r\n",weight);
			delay_ms(500);
		}
	}
}

//最后记得空行!!!

有遇到其他问题可关注私信!!! 

更新自制PCB板,开源广场:

失重-智能迷你秤 - 嘉立创EDA开源硬件平台 (oshwhub.com)

更新代码提取:

链接:https://pan.baidu.com/s/1KPyF-2T3ezOItrAhBjPTbQ 
提取码:ztyy

  • 46
    点赞
  • 232
    收藏
    觉得还不错? 一键收藏
  • 44
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 44
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值