STM32F103ZET6应用之-HX711重力传感器与hc_sr04超声波模块联合应用

简单介绍一下重力转感器HX711和超声波hc_sr04。

HX711:

 hc_sr04:

HX711和hc_sr04的实现本质上也是数模转换的应用,通过传感器采集到被测物体的重量并将其转换成电压信号。啰嗦几句,由于模拟信号是连续、微弱的,而stm能处理数字信号是一段一段的,所以我们一般会对这种前端信号在处理电路中进行线性放大,然后才将放大后的模拟电压信号经A/D转换电路转换成数字量被送入到STM32中,如果要用数码管显示,直接STM32控制译码显示器就行,从而显示出被测物体的重量。一般淘宝卖的都把把传感器、信号的前级处理和A/D转换部分集合到一块小pcb板里了。转换后的数字信号送给控制器处理,由控制器也就是我们的STM32完成对该数字量的处理,驱动显示模块完成人机间的信息交换。

 连线图:

重力传感器:

VCC-->3.3V

DOUT-->PB1

SCK-->PB0

GND-->GND

hc_sr04超声波模块:

VCC-->3.3V

TRIG-->PB11

ECHO-->PB10

GND-->GND

STM32代码:

工程可以在串口输出实验的基础上添加

HX711.h头文件

#ifndef __HX711_H
#define __HX711_H

#include "sys.h"

#define HX711_SCK PBout(0)// PB0
#define HX711_DOUT PBin(1)// PB1


extern void Init_HX711pin(void);
extern u32 HX711_Read(void);
extern void Get_Maopi(void);
extern void Get_Weight(void);
extern int HX711_Work(void);

extern u32 HX711_Buffer;
extern u32 Weight_Maopi;
extern s32 Weight_Shiwu;
extern u8 Flag_Error;

#endif

HX711.c

void Init_HX711pin(void):初始化函数主要用于初始化IO口PB0和PB1

u32 HX711_Read(void):驱动函数,用于读取传感器传输过来的电信号

void Get_Maopi(void):确定初始值(毛皮),即放空的时候的数值

#include "HX711.h"
#include "delay.h"

u32 HX711_Buffer;
u32 Weight_Maopi;
s32 Weight_Shiwu;
s32 Surplus_Tile;
u8 Flag_Error = 0;



//校准参数
//因为不同的传感器特性曲线不是很一致,因此,每一个传感器需要矫正这里这个参数才能使测量值很准确。
//当发现测试出来的重量偏大时,增加该数值。
//如果测试出来的重量偏小时,减小改数值。
//该值可以为小数
#define GapValue 106.5
#define One_Tile 233.5

void Init_HX711pin(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	 //使能PF端口时钟

	//HX711_SCK
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;				 // 端口配置
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
	GPIO_Init(GPIOB, &GPIO_InitStructure);					 //根据设定参数初始化GPIOB
	
	//HX711_DOUT
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//输入上拉
    GPIO_Init(GPIOB, &GPIO_InitStructure);  
	
	GPIO_SetBits(GPIOB,GPIO_Pin_0);					//初始化设置为0
}



//****************************************************
//读取HX711
//****************************************************
u32 HX711_Read(void)	//增益128
{
	unsigned long count; 
	unsigned char i; 
  	HX711_DOUT=1; 
	delay_us(1);
  	HX711_SCK=0; 
  	count=0; 
  	while(HX711_DOUT); 
  	for(i=0;i<24;i++)
	{ 
	  	HX711_SCK=1; 
	  	count=count<<1; 
		delay_us(1);
		HX711_SCK=0; 
	  	if(HX711_DOUT)
			count++; 
		delay_us(1);
	} 
 	HX711_SCK=1; 
    count=count^0x800000;//第25个脉冲下降沿来时,转换数据
	delay_us(1);
	HX711_SCK=0;  
	return(count);
}

//****************************************************
//获取毛皮重量
//****************************************************
void Get_Maopi(void)
{
	Weight_Maopi = HX711_Read();	
} 

//****************************************************
//称重
//****************************************************
void Get_Weight(void)
{
	HX711_Buffer = HX711_Read();
	if(HX711_Buffer > Weight_Maopi)			
	{
		Weight_Shiwu = HX711_Buffer;
		Weight_Shiwu = Weight_Shiwu - Weight_Maopi;				//获取实物的AD采样数值。
	
		Weight_Shiwu = (s32)((float)Weight_Shiwu/GapValue); 	//计算实物的实际重量
																		//因为不同的传感器特性曲线不一样,因此,每一个传感器需要矫正这里的GapValue这个除数。
																		//当发现测试出来的重量偏大时,增加该数值。
																		//如果测试出来的重量偏小时,减小改数值。
	}

	
}


hc_sr04.h

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

//超声波硬件接口定义
#define HCSR04_PORT     GPIOB
#define HCSR04_CLK      RCC_APB2Periph_GPIOB
#define HCSR04_TRIG     GPIO_Pin_11
#define HCSR04_ECHO     GPIO_Pin_10
#define TRIG_Send  PBout(11)
#define ECHO_Reci  PBin(10)

void Hcsr04Init(void);
void hc_sr04_Work(void);
float Hcsr04GetLength(void );				    
#endif

hc_sr04.c

void hcsr04_NVIC():定时器4中断设置;

void Hcsr04Init(void) :IO口初始化 及其他初始化

static void OpenTimerForHc() :打开定时器4

static void CloseTimerForHc() :闭定时器4

void TIM4_IRQHandler(void)  :定时器4中断服务函

u32 GetEchoTimer(void):获取定时器4计数器值,通过定时器4计数器值推算距离

#include "hc_sr04.h"
#include "sys.h" 
#include "delay.h"
#include "led.h"
#include "usart.h"

//超声波计数
u16 msHcCount = 0;

//定时器4中断设置
void hcsr04_NVIC()
{
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断优先级分组函数 2位抢占优先级,2 位响应优先级
			
	NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;           //使能外部中断通道          
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级 2 级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;        //从优先级 2 级   
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;          //外部中断通道使能
	NVIC_Init(&NVIC_InitStructure);													//初始化 NVIC
}

//IO口初始化 及其他初始化
void Hcsr04Init(void)
{  
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;   
    GPIO_InitTypeDef GPIO_InitStructure;
	
    RCC_APB2PeriphClockCmd(HCSR04_CLK, ENABLE);//复用时钟使能
   
    GPIO_InitStructure.GPIO_Pin =HCSR04_TRIG;      
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//HCSR04_TRIG推挽输出
    GPIO_Init(HCSR04_PORT, &GPIO_InitStructure);
    GPIO_ResetBits(HCSR04_PORT,HCSR04_TRIG);
     
    GPIO_InitStructure.GPIO_Pin =   HCSR04_ECHO;     
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//HCSR04_ECHO浮空输入
    GPIO_Init(HCSR04_PORT, &GPIO_InitStructure);  
    GPIO_ResetBits(HCSR04_PORT,HCSR04_ECHO);    
			
          
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);// TIM4 时钟使能   
    TIM_TimeBaseStructure.TIM_Period = (1000-1); 								//设置自动重装载寄存器周期的值arr
    TIM_TimeBaseStructure.TIM_Prescaler =(72-1); 								//设置时钟频率除数的预分频值psc
    TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; 			//设置时钟分割
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM4 向上计数
    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);     				//初始化 TIM4     
        
    TIM_ClearFlag(TIM4, TIM_FLAG_Update); 			//清除中断标志位 
    TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);		//允许更新中断
    hcsr04_NVIC();                       				//定时器4设置
    TIM_Cmd(TIM4,DISABLE);   										//使能 TIM4 外设  
}


//打开定时器4
static void OpenTimerForHc()  
{
   TIM_SetCounter(TIM4,0);//TIM4归 0
   msHcCount = 0;
   TIM_Cmd(TIM4, ENABLE); 
}

//关闭定时器4
static void CloseTimerForHc()    
{
   TIM_Cmd(TIM4, DISABLE); 
}

//定时器4中断服务函数
void TIM4_IRQHandler(void)  
{
   if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)//TIM4更新中断发生
   {
       TIM_ClearITPendingBit(TIM4, TIM_IT_Update); //TIM4清中断标志位
       msHcCount++;
   }
}
 

//获取定时器4计数器值
u32 GetEchoTimer(void)
{
   u32 t = 0;
   t = msHcCount*1000;//中断一次1/1000s,计算一共有多少个微秒
   t += TIM_GetCounter(TIM4);//当前定时器的计数值
   TIM4->CNT = 0;  
	//TIMx_CNT 寄存器,该寄存器是定时器的计数器,该寄存器存储了当前定时器的计数值
   delay_ms(50);
   return t;
}
 
//通过定时器4计数器值推算距离
float Hcsr04GetLength(void)
{
   u32 t = 0;
   int i = 0;
   float lengthTemp = 0;
   float sum = 0;
   while(i!=5)
   {
      TRIG_Send = 1;      
      delay_us(20);
      TRIG_Send = 0;
      while(ECHO_Reci == 0);      
		 
      OpenTimerForHc();        
      i = i + 1;
      while(ECHO_Reci == 1);
      CloseTimerForHc();        
      t = GetEchoTimer();        
      lengthTemp = ((float)t/58.0);
		 //cm 343M/s 0.0343厘米/微秒 等价于 1/0.0343微秒/厘米 约等于29微秒/厘米 一厘米两个来回58微秒
      sum = lengthTemp + sum ; 
    }
    lengthTemp = sum/5.0;
		
    return lengthTemp;
}
/*下面我简单做了个报警距离太近报警的代码,连线的话用LED的正极连PB3就行,不用的话可以注释掉,用的话得把下面的led代码块加上
*/
void hc_sr04_Work(void){
	int number;
	printf("A");
	number=Hcsr04GetLength();
	if(number<30)
	{
		GPIO_SetBits(GPIOB,GPIO_Pin_3);
	}
	else
	{
		GPIO_ResetBits(GPIOB,GPIO_Pin_3);	
	}
}

led.h

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

void IO_Init(void);//初始化
		 				    
#endif

led.c:

void IO_Init(void):初始化pb5的io口

void IO_Init(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB);	 //使能PB端口时钟
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
	//A组·使用的
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;				 //PB.3 端口配置      警报信号
    GPIO_Init(GPIOB, &GPIO_InitStructure);					   
    //GPIO_SetBits(GPIOB,GPIO_Pin_3);						       //PB.3 输出高
}
 

main.c主函数

#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "HX711.h"
#include "hc_sr04.h"
 

 int main(void)
 {		
	int HX;
	//int led0pwmval=1;
 int a=1;
// 	u16 t;  
//	u16 len;	
//	u16 times=0;
	Init_HX711pin();	
	delay_init();	    	 //延时函数初始化	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
	uart_init(115200);	 //串口初始化为115200
 	IO_Init();			     //IO端口初始化
	delay_ms(1000);
	 
	Get_Maopi();				//称毛皮重量
	delay_ms(1000);
	Get_Maopi();				//重新获取毛皮重量
	Hcsr04Init();
	printf("aaaaa");                //当串口输出aaaaa时初始化完成
	while(1)
	{ 
		printf("a");
		hc_sr04_Work();
		HX=HX711_Work();
		a=Hcsr04GetLength();
		printf("距离:%d\r\n",a);
		printf("重力:%d\r\n",HX);
        delay(1);
	}
		
		
}
 
		

  • 6
    点赞
  • 72
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
要使用STM32F103ZET6控制HC-SR04超声波传感器,你需要了解以下几个方面: 1. HC-SR04超声波传感器的工作原理:HC-SR04超声波传感器通过发送超声波脉冲,然后接收回波来测量距离。 2. STM32F103ZET6的GPIO控制:STM32F103ZET6的GPIO控制是通过设置寄存器来实现的,需要了解如何配置GPIO的输入输出模式、上下拉电阻、速度等。 3. 定时器控制:HC-SR04超声波传感器需要定时器来控制发送超声波脉冲的时间和接收回波的时间。 下面是控制HC-SR04超声波传感器的基本步骤: 1. 配置STM32F103ZET6的GPIO为输出模式,用于控制HC-SR04超声波传感器的Trig引脚。 2. 配置STM32F103ZET6的GPIO为输入模式,用于接收HC-SR04超声波传感器的Echo引脚。 3. 配置STM32F103ZET6的定时器,用于控制超声波脉冲的时间和接收回波的时间。 4. 在主程序中通过GPIO控制Trig引脚,发送超声波脉冲。 5. 启动定时器,开始计时。 6. 等待Echo引脚变为高电平,表示接收到了回波,停止定时器。 7. 根据定时器的计数值计算出距离。 下面是一个简单的代码示例,供你参考: ```c #include "stm32f10x.h" #define TRIG_PIN GPIO_Pin_0 #define ECHO_PIN GPIO_Pin_1 #define TRIG_PORT GPIOB #define ECHO_PORT GPIOB #define TIMx TIM2 void HC_SR04_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); GPIO_InitStructure.GPIO_Pin = TRIG_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(TRIG_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = ECHO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(ECHO_PORT, &GPIO_InitStructure); TIM_TimeBaseInitStructure.TIM_Period = 0xFFFF; TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1; TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIMx, &TIM_TimeBaseInitStructure); TIM_Cmd(TIMx, ENABLE); } float HC_SR04_GetDist(void) { GPIO_ResetBits(TRIG_PORT, TRIG_PIN); delay_us(2); GPIO_SetBits(TRIG_PORT, TRIG_PIN); delay_us(10); GPIO_ResetBits(TRIG_PORT, TRIG_PIN); while(GPIO_ReadInputDataBit(ECHO_PORT, ECHO_PIN) == RESET); TIM_SetCounter(TIMx, 0); while(GPIO_ReadInputDataBit(ECHO_PORT, ECHO_PIN) == SET); uint16_t cnt = TIM_GetCounter(TIMx); return cnt / 58.0; } int main(void) { HC_SR04_Init(); while(1) { float dist = HC_SR04_GetDist(); printf("Distance: %.2f cm\r\n", dist); delay_ms(1000); } } ``` 注意,上述代码中的delay_us()和delay_ms()函数需要自己实现

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值