HX711—称重模块

news2024/11/15 2:09:04

1、简介

        HX711 采用了海芯科技集成电路专利技术, 是一款专为高精度电子秤而设计的 24 位 A/D 转 换器芯片。

2、原理图

PCB参考设计原理图 

3、模块驱动代码(固件库)

数据读取代码分析

HX711信号读取时序

  1. 初始化

    • 将 PD_SCK(Power Down / Serial Clock)引脚设置为低电平。
    • 将 DOUT 引脚设置为输入模式。
  2. 等待 DOUT 变为高电平

    • 等待 DOUT 引脚变为高电平,这表明HX711准备好发送数据。
  3. 读取24位数据

    • 每个 PD_SCK 的上升沿,HX711 会在 DOUT 引脚上输出一位数据。
    • 每个 PD_SCK 的下降沿,数据线保持稳定,此时可以读取 DOUT 上的数据。
  4. 读取第25位(符号位)

    • 在读取完24位数据之后,通过 PD_SCK 的一次上升沿读取第25位数据(符号位)。
uint32_t HX711_ReadData(void)                          //读数据
{
	uint8_t i;
	uint32_t value = 0;    						//接收HX711采集的AD值
	
	HX711_W_DOUT(1); 									//初始DOUT为高电平
	HX711_W_PD_SCK(0); 							  //初始PD_SCK为低电平
	Delay_us(1);
	HX711_R_DOUT();                   //DOUT转换为输入
	
	while(HX711_R_DOUT());           //等待DOUT引脚变为高电平
	Delay_us(1);
	for(i=0;i<24;i++)                 //按照HX711时序接收数据
	{
		HX711_W_PD_SCK(1);              // PD_SCK置高,发送脉冲 
		value = value << 1;              //下降沿来时变量左移一位,右侧补零,
		Delay_us(1);
		HX711_W_PD_SCK(0);               // PD_SCK置低
		if(HX711_R_DOUT())               //读取一位数据,如果高电平,加一,低电平不变。
			value++;
	  Delay_us(1);
	}
	HX711_W_PD_SCK(1);               //最后一个脉冲,增益为128
	value = value^0x800000;          //第25个脉冲转换数据,24位AD转换,最高位为符号位,其余为有效位
	Delay_us(1);
	HX711_W_PD_SCK(0);
	Delay_us(1);
	return value;
}

 4、驱动代码

HX711.c

#include "stm32f10x.h"                  // Device header
#include "HX711.h"
#include "Delay.h"
#include "OLED.h"
#include "Serial.h"
	
float	BiaoDing=384.7;       			//标定系数,根据自己的传感器调节
uint32_t pi_weight,weight;
uint32_t buffer[MEDIAN_LEN];   	        //中值滤波的数据缓存
int medleng = 0;          	            
uint32_t   num;					                  //数据对比大小中间变量
uint8_t Pi_flag=0;

void HX711_GPIO_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      //时钟线推挽输出
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  //数据线浮空输入     
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
}

void HX711_W_PD_SCK(uint8_t BitValue)                  //写时钟线
{	
	GPIO_WriteBit(GPIOA, GPIO_Pin_1, (BitAction)BitValue);
}

void HX711_W_DOUT(uint8_t BitValue)                    //写数据线,开始时,需要拉高DOUT电平
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	GPIO_WriteBit(GPIOA, GPIO_Pin_2, (BitAction)BitValue);
}

uint8_t HX711_R_DOUT(void)                             //读数据
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
  return GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_2);
}


void HX711_Reset(void)                                 // 传感器复位,去皮
{
	HX711_W_PD_SCK(1);                                   //拉高,延时60us
	Delay_us(60);
}

uint32_t HX711_ReadData(void)                          //读数据
{
	uint8_t i;
	uint32_t value = 0;    						//接收HX711采集的AD值
	
	HX711_W_DOUT(1); 									//初始DOUT为高电平
	HX711_W_PD_SCK(0); 							  //初始PD_SCK为低电平
	Delay_us(1);
	HX711_R_DOUT();                   //DOUT转换为输入
	
	while(HX711_R_DOUT());           //等待DOUT引脚变为高电平
	Delay_us(1);
	for(i=0;i<24;i++)                 //按照HX711时序接收数据
	{
		HX711_W_PD_SCK(1);              // PD_SCK置高,发送脉冲 
		value = value << 1;              //下降沿来时变量左移一位,右侧补零,
		Delay_us(1);
		HX711_W_PD_SCK(0);               // PD_SCK置低
		if(HX711_R_DOUT())               //读取一位数据,如果高电平,加一,低电平不变。
			value++;
	  Delay_us(1);
	}
	HX711_W_PD_SCK(1);               //最后一个脉冲,增益为128
	value = value^0x800000;          //第25个脉冲转换数据,24位AD转换,最高位为符号位,其余为有效位
	Delay_us(1);
	HX711_W_PD_SCK(0);
	Delay_us(1);
	return value;
}


uint32_t Get_Pi(void)                           //皮重函数  每次去皮需要再次重置一下
{                                               //中值滤波参数,冒泡排序法
	uint32_t   buffer[MEDIAN_LEN];              //储存数组
	uint32_t HX711_dat,pi_weight,num;           				
	uint8_t i,medleng = 0;
	for(i=0;i<MEDIAN_LEN;i++)
	{
		HX711_dat=HX711_ReadData();	        	   
		if(medleng == 0)                           //第1个元素,直接放入,不需要排序
		{ 
			buffer[0] = HX711_dat;
			medleng = 1; 
		}
		else                            	           //中值滤波,取中间值,冒泡排序法
		{  
			for(i = 0; i < medleng; i ++)  
			{
				if( buffer[i] > HX711_dat) 	          
				{ 
					num = HX711_dat; HX711_dat = buffer[i]; buffer[i] = num;
				}
			}
			buffer[medleng] = HX711_dat;          	
			medleng++;
		}		
		if(medleng >= MEDIAN_LEN) 		           
		{
			HX711_dat = buffer[MEDIAN];	            //取排序好的中间值,
			medleng = 0; 
		}
	}
	pi_weight=HX711_dat;      
	return pi_weight;
}

uint32_t Get_Weight(uint32_t pi_weight)	               //称重函数
{
	uint32_t get_weight;
	uint32_t weight;
	
	get_weight=HX711_ReadData();		            //HX711数据采集函数
	if(get_weight>pi_weight)
	{
		get_weight=HX711_ReadData();			                  //重新采集HX711数据					 														   
		weight=(uint32_t)(((float)(get_weight-pi_weight))/BiaoDing);//修改标定系数,根据传感器不同
		if(weight==11164458)weight=0;     //干扰值校准为0
	}
	else 				
		weight=0;
	return weight;
}


void Show_weight(void)
{
	  weight=Get_Weight(pi_weight);
		if(medleng == 0)                         //中值滤波,取中间值,冒泡排序法
		{ 
			buffer[0] = weight; medleng = 1; 
		}
		else                            	       
		{  
			for(int i = 0; i < medleng; i ++)  
			{
				if( buffer[i] > weight) 	           
				{ 
					num = weight; weight = buffer[i]; buffer[i] = num;
				}
			}
			buffer[medleng] = weight; 	            
			medleng++;
		}		
		if(medleng >= MEDIAN_LEN) 		             
		{
			weight = buffer[MEDIAN];	                //取中间值
			medleng = 0; 
			OLED_ShowNum(1,6,weight,4);

			Delay_ms(500);
		}

}

HX711.h 

#ifndef __HX711_H
#define __HX711_H


#define MEDIAN_LEN       5  			              //中值滤波的滤波长度,一般取奇数
#define MEDIAN           3  			              //中值在滤波数组中的位置

extern uint32_t buffer[];
extern int medleng;
extern uint32_t num,weight;
extern uint32_t pi_weight;


void HX711_GPIO_Init(void);
void HX711_W_PD_SCK(uint8_t BitValue);
void HX711_W_DOUT(uint8_t BitValue);
void HX711_Reset(void);
uint8_t HX711_R_DOUT(void);
uint32_t HX711_ReadData(void);
uint32_t Get_Pi(void);
uint32_t Get_Weight(uint32_t pi_weight);
void Show_weight(void);

#endif

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Serial.h"
#include <stdio.h>
#include "HX711.h"


int main(void)
{
	OLED_Init();
	Serial_Init();
	HX711_GPIO_Init();    //初始化HX711
	OLED_ShowChinese(1,1,4);
	OLED_ShowChinese(1,2,5);
	OLED_ShowString(1, 10, "g");
	OLED_ShowString(1, 5, ":");
	pi_weight=Get_Pi();  //获取一次皮重
	
	while (1)
	{
     Show_weight();    //获取并显示重量·
		 
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2096475.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C练手题--A snail enters a bar! 【7 kyu】

一、原题 链接&#xff1a;Training on A snail enters a bar! | Codewars Problem Description: A snail is crawling along a rubber band that has an initial length of x units. The snail moves at a constant speed of y units per minute. As the snail crawls from t…

upload-labs靶场通关(附靶场环境)

链接: https://pan.baidu.com/s/1GQP5zthh598A4Mp-WQM4vA 提取码: zovn 环境搭建 步骤一&#xff1a;将环境附件下载到phpstudy_pro\WWW下面修改名字为upload 步骤二&#xff1a;询问绑定地址 第一关 less-1 步骤一&#xff1a;上传一句话木马 步骤二&#xff1a;更改文件名…

昇腾 编程范式 - 矢量编程流水任务设计

昇腾 编程范式 - 矢量编程流水任务设计 flyfish 编程范式简单来说就是不同编程风格或方式的“套路”。按着套路走就可以。 矢量算子编程范式把算子的实现流程分为3个基本任务:CopyOut&#xff0c;Compute&#xff0c;copyout CopyIn负责数据搬入操作&#xff0c; Compute负责…

spring入门(一)spring简介

一、spring简介 Spring技术是JavaEE开发必备技能&#xff0c;企业开发技术选型命中率>90% spring能够简化开发&#xff0c;降低企业级开发的复杂性。框架整合&#xff0c;高效整合其他技术&#xff0c;提高企业级应用开发与运行效率。 主要学习&…

Leetcode3244. 新增道路查询后的最短距离 II

Every day a Leetcode 题目来源&#xff1a;3244. 新增道路查询后的最短距离 II 解法1&#xff1a;贪心 由于题目保证添加的边&#xff08;捷径&#xff09;不会交叉&#xff0c;从贪心的角度看&#xff0c;遇到捷径就走捷径是最优的。所有被跳过的城市都不可能再出现在最短…

从人机环境系统的角度看,自下而上和自上而下两种认知方式如何有机地结合使用?...

从具体的“态”到抽象的“势”&#xff0c;从感觉到认知是自下而上的&#xff0c;例如 GPT&#xff1b;反之&#xff0c;则是自上而下的&#xff0c;比如有经验的人。理性偏自下而上&#xff0c;神性&#xff08;感觉&#xff09;则自上而下。其中&#xff0c;“态”和“势”是…

[000-01-008].Seata案例应用

业务说明&#xff1a;这里我们创建三个服务&#xff0c;一个订单服务&#xff0c;一个库存服务&#xff0c;一个账户服务。当用户下单时&#xff0c;会在订单服务中创建一个订单&#xff0c;然后通过远程调用库存服务来扣减下单商品的库存&#xff1b;再通过远程调用账户服务来…

如何用命令行工作流做定制化 AI 文献回顾?

&#xff08;注&#xff1a;本文为小报童精选文章。已订阅小报童或加入知识星球「玉树芝兰」用户请勿重复付费&#xff09; 千万不要把 AI 生成的结果&#xff0c;直接端出去给你的导师&#xff0c;甚至是投稿到出版社。 需求 我最近在 B 站发布了一个视频&#xff0c;叫做《AI…

Redis:Redis性能影响因素

这里写自定义目录标题 一、CPU对Redis的影响二、磁盘对Redis的影响三、网络对Redis的影响四、Swap对Redis的影响 一、CPU对Redis的影响 二、磁盘对Redis的影响 性能建议&#xff1a; 如果是热点场景&#xff0c;建议大家关闭rdb和aof。在SATA和SAS普通盘上&#xff0c;append…

【微服务】springboot 自定义注解+反射+aop实现动态修改请求参数

目录 一、前言 二、动态修改接口请求参数的场景 2.1 动态修改请求参场景汇总 2.1.1 数据格式标准化 2.1.2 安全需要 2.1.3 参数校验与默认值设定 2.1.4 数据隐私保护 2.1.5 适配不同客户端 2.1.6 统计与监控 2.1.7 高级功能特性 三、springboot 使用过滤器和拦截器动…

Mysql8 主从复制主从切换(超详细)

文章目录 1 主从复制1.1 实施前提1.2 主节点配置(在192.168.25.91操作)1.3 从节点配置(在192.168.25.92操作)1.4 创建用于主从同步的用户1.5 开启主从同步1.5 主从同步验证 2 主从切换2.1 实施前提2.2 主节点设置只读(在192.168.25.91操作)2.3 检查主从数据是否同步完毕(在192.…

Vue的冷门内置指令:优化与性能提升的利器

在Vue.js的广阔生态中&#xff0c;开发者们常常聚焦于那些耳熟能详的内置指令&#xff0c;如v-for用于循环渲染列表&#xff0c;v-if和v-else-if用于条件渲染等。然而&#xff0c;Vue还提供了一系列较为冷门但功能强大的内置指令&#xff0c;它们在某些特定场景下能够显著提升应…

ER模型介绍

7.1.概述&#xff1a; 1.ER模型也叫做实体关系模型&#xff0c;是用来描述现实生活中客观存在的事物、事物的属性&#xff0c;以及事物之间关系的一种数据模型。2.在开发基于数据库的信息系统的设计阶段&#xff0c;通常使用ER模型来描述信息需要和信息特性&#xff0c;帮助我…

云平台之Zabbix 监控网站

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:Linux运维老纪的首页…

NMPC非线性模型预测控制经验分享与代码实例

NMPC非线性模型预测控制经验分享与代码实例 原本做完本科毕设之后就应该动笔写这一部分&#xff0c;但是做的过程中慢慢意识到自己懂的只是一点点。最近重新接触一些优化相关的问题&#xff0c;希望能够做出我认知之下比较好的解答。本人知识有限&#xff0c;难免写的有问题&am…

ClickHousez中如何定时清理过期数据库?

一、脚本清理 要在ClickHouse中自动删除过期的数据库&#xff0c;你可以使用ClickHouse的SQL命令结合外部脚本&#xff08;如Shell脚本&#xff09;和计划任务&#xff08;如cron&#xff09;来实现。下面是一个示例&#xff0c;展示如何创建一个Shell脚本来检查数据库的创建时…

1、.Net UI框架:Avalonia UI - .Net宣传系列文章

Avalonia UI是一个开源的跨平台UI框架&#xff0c;它允许开发者使用C#和XAML来创建应用程序&#xff0c;这些应用程序可以在多个平台上运行&#xff0c;包括Windows、macOS、Linux、Android和iOS。Avalonia UI的设计目标是提供一个现代化、可移植的UI框架&#xff0c;它具有类似…

C++之搜索二叉树(上)

目录 搜索二叉树的概念 搜索二叉树的操作 递归版本 二叉树的插入 二叉树的查找 二叉树的删除 非递归版本 二叉树的递归插入 二叉树的递归查找 二叉树的递归删除 在之前我们已经学习过了二叉树这一数据结构&#xff0c;本期我们将学习一种新的数据结构------搜索二…

Ubuntu服务器时间和本地时间不一致怎么解决——Linux的Local Time和RTC time

最近一直在搞大模型的相关工作&#xff0c;所以一直在用Linux服务器&#xff0c;前面的文章里也提到了&#xff0c;我用的是一台Dell PowerEdge R730xd。 但在使用中发现&#xff0c;IDRAC中的日志时间和本地时间存在时差&#xff0c;大概相关8小时。 对于技术人员&#xff0c…

UE5学习笔记19-服务器的更新频率,根骨骼旋转节点

一、服务器向客户端发送数据的频率 在Config中的DefaultEngine.ini文件添加 [/Script/OnlineSubsystemUtils.IpNetDriver] NetServerMaxTickRate60; 二、角色类中&#xff0c;角色蓝图类中在细节面板收缩net可以在界面中找到下面两个变量 NetUpdateFrequency 66.f; //净更…