STM32+CUBE+HX711模块中断读取

简单介绍:

双路HX711+STM32+CUBE+FREERTOS使用记录-CSDN博客

这里甩出代码

CUBE引脚配置:

头文件:

/**
 * @Author:      本人不帅
 *
 */
#ifndef HX711
#define HX711
#include "stdint.h"
#include "main.h"
#include "cmsis_os.h"
typedef struct {
    GPIO_TypeDef*  SCK_GPIO_Port;//时钟IO端口
    GPIO_TypeDef* DT_GPIO_Port;//数据IO端口

    uint16_t SCK_Pin;//时钟引脚号
    uint16_t DT_Pin;//数据引脚号
	
    int32_t hx711count;//读出的数据
	float gain;//增益,用于调整单位
    float weight_offset;//偏置,用于清零
    float weight_real;//实际力的大小
} HX711_t;
extern HX711_t HX711_A;
void HX711_TaskStart(void);//FREERTOS线程启动函数,不用的话可以删掉,把初始化放到别的地方
void HX711_EXIT_CALLBACK(HX711_t* hx711);//数据引脚对应的中断回调
void ResetWeight(void);//重量清零函数
#endif
#ifdef __cplusplus
}
#endif

 源文件:

#include "HX711_dev.h"
#include "gpio.h"
HX711_t HX711_A;
void HX711_Init(HX711_t* hx711,GPIO_TypeDef* GPIO_Port_DT, uint16_t GPIO_Pin_DT,GPIO_TypeDef* GPIO_Port_SCK, uint16_t GPIO_Pin_SCK) {
    hx711->DT_GPIO_Port = GPIO_Port_DT;
    hx711->DT_Pin = GPIO_Pin_DT;
    hx711->SCK_GPIO_Port = GPIO_Port_SCK;
    hx711->SCK_Pin = GPIO_Pin_SCK;

    hx711->hx711count = 0;
    hx711->weight_offset = 0;
    hx711->weight_real = 0;
    HAL_GPIO_WritePin(GPIO_Port_SCK, GPIO_Pin_SCK, GPIO_PIN_RESET);
}

void HX711_Daemon_Task(void)
{

    HX711_Init(&HX711_A,GPIOB, GPIO_PIN_12,GPIOB, GPIO_PIN_13);
    HX711_A.weight_offset = -100;
    HX711_A.gain = 0.0007f;
    for(;;) {
        //可以在这写一些任务处理函数,没有的话可以删掉Task相关函数
        osDelay(10);
    }
}
int i = 0;
uint32_t Count = 0;
void HX711_EXIT_CALLBACK(HX711_t* hx711) {
    HAL_NVIC_DisableIRQ(EXTI15_10_IRQn);//关闭中断
    GPIO_InitTypeDef GPIO_InitStruct = {0};//把数据引脚设为输入模式
    GPIO_InitStruct.Pin = hx711->DT_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(hx711->DT_GPIO_Port, &GPIO_InitStruct);
    if(HAL_GPIO_ReadPin(hx711->DT_GPIO_Port, hx711->DT_Pin) == RESET) {//再次读取引脚电平,确保电平正确

        Count = 0;
        i=0;

        for(i = 0; i <24; i++)//24个数据bit
        {
            HAL_GPIO_WritePin(hx711->SCK_GPIO_Port, hx711->SCK_Pin, GPIO_PIN_SET);

            if(HAL_GPIO_ReadPin(hx711->DT_GPIO_Port, hx711->DT_Pin))
            {
                Count ++;
            }
            Count = Count << 1;
            HAL_GPIO_WritePin(hx711->SCK_GPIO_Port, hx711->SCK_Pin, GPIO_PIN_RESET);
        }

        HAL_GPIO_WritePin(hx711->SCK_GPIO_Port, hx711->SCK_Pin, GPIO_PIN_SET);//第25个脉冲:增益128
		
		hx711->hx711count = (int32_t)(Count<<8);//24位补码左移8位刚好是int32
        hx711->weight_real = ((float)hx711->hx711count/2511886.43f/0.5f*9.8f - hx711->weight_offset)*hx711->gain;
//上面这几个参数感拿测力计测的,觉有点抽象,如果有好的确定方法欢迎在评论区留言。


        HAL_GPIO_WritePin(hx711->SCK_GPIO_Port, hx711->SCK_Pin, GPIO_PIN_RESET);
    }
    GPIO_InitTypeDef GPIO_InitStruct1 = {0};//把数据引脚设为下降沿中断模式
    GPIO_InitStruct1.Pin = hx711->DT_Pin;
    GPIO_InitStruct1.Mode = GPIO_MODE_IT_FALLING;
    GPIO_InitStruct1.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(hx711->DT_GPIO_Port, &GPIO_InitStruct1);
    HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);//使能中断
}
void ResetWeight(void) {
    HX711_A.weight_offset += HX711_A.weight_real;//数据归零
}
/************************ RTOS *******************/
void HX711_TaskStart(void)
{
    xTaskCreate((TaskFunction_t)HX711_Daemon_Task,"",128,NULL,6,NULL);
}

函数引用:

 重写外部中断回调:

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
    if(GPIO_Pin == HX711_A.DT_Pin) {
        HX711_EXIT_CALLBACK(&HX711_A);
    }else{
		ResetWeight();//外部中断归零重量
		}
}

在void MX_FREERTOS_Init(void)里引用把线程启动函数:

HX711_TaskStart(void);

编译运行。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
HX711是一种高精度,高分辨率的24位模拟数字转换器(ADC),常用于电子秤和称重传感器等应用中。在STM32C8T6单片机中,可以通过模拟IIC协议来控制HX711芯片。 以下是基于STM32C8T6的模拟IIC控制HX711的实现步骤: 1. 硬件连接:将STM32C8T6的SCL引脚连接到HX711的SCK引脚,将STM32C8T6的SDA引脚连接到HX711的DT引脚。 2. 初始化IIC:通过GPIO配置STM32C8T6的SCL和SDA引脚,并初始化IIC协议。 3. 写入数据:IIC发送START信号后,发送HX711的设备地址和写入命令,然后依次发送数据。 4. 读取数据:IIC发送START信号后,发送HX711的设备地址和读取命令,然后接收数据。 5. 解析数据:将接收到的数据按照HX711的规则解析成24位数据并返回。 以下是代码示例: ```c #include "stm32f10x.h" #define HX711_ADDR 0x80 // HX711设备地址 #define CMD_WRITE 0x40 // 写入命令 #define CMD_READ 0x80 // 读取命令 void IIC_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // 使能GPIOB时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; // SCL和SDA引脚 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; // 开漏输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_SetBits(GPIOB, GPIO_Pin_6 | GPIO_Pin_7); // 初始化为高电平 } void IIC_Start(void) { GPIO_SetBits(GPIOB, GPIO_Pin_7); // SDA初始化为高电平 GPIO_SetBits(GPIOB, GPIO_Pin_6); // SCL初始化为高电平 GPIO_ResetBits(GPIOB, GPIO_Pin_7); // SDA下降沿 GPIO_ResetBits(GPIOB, GPIO_Pin_6); // SCL下降沿 } void IIC_Stop(void) { GPIO_ResetBits(GPIOB, GPIO_Pin_6); // SCL下降沿 GPIO_ResetBits(GPIOB, GPIO_Pin_7); // SDA下降沿 GPIO_SetBits(GPIOB, GPIO_Pin_6); // SCL初始化为高电平 GPIO_SetBits(GPIOB, GPIO_Pin_7); // SDA初始化为高电平 } void IIC_SendByte(uint8_t byte) { uint8_t i; for (i = 0; i < 8; i++) { if (byte & 0x80) { GPIO_SetBits(GPIOB, GPIO_Pin_7); // 发送高电平 } else { GPIO_ResetBits(GPIOB, GPIO_Pin_7); // 发送低电平 } GPIO_SetBits(GPIOB, GPIO_Pin_6); // SCL上升沿 GPIO_ResetBits(GPIOB, GPIO_Pin_6); // SCL下降沿 byte <<= 1; } GPIO_SetBits(GPIOB, GPIO_Pin_7); // 释放SDA GPIO_SetBits(GPIOB, GPIO_Pin_6); // SCL上升沿 GPIO_ResetBits(GPIOB, GPIO_Pin_6); // SCL下降沿 } uint8_t IIC_RecvByte(void) { uint8_t i; uint8_t byte = 0; GPIO_SetBits(GPIOB, GPIO_Pin_7); // SDA初始化为高电平 for (i = 0; i < 8; i++) { byte <<= 1; GPIO_SetBits(GPIOB, GPIO_Pin_6); // SCL上升沿 if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_7)) { byte |= 0x01; } GPIO_ResetBits(GPIOB, GPIO_Pin_6); // SCL下降沿 } return byte; } uint32_t HX711_ReadWeight(void) { uint8_t i; uint32_t weight = 0; uint8_t buf[3]; IIC_Start(); IIC_SendByte(HX711_ADDR | CMD_WRITE); IIC_SendByte(0x00); IIC_Stop(); delay_us(1); IIC_Start(); IIC_SendByte(HX711_ADDR | CMD_READ); for (i = 0; i < 3; i++) { buf[i] = IIC_RecvByte(); } IIC_Stop(); weight = (uint32_t)buf[2] | ((uint32_t)buf[1] << 8) | ((uint32_t)buf[0] << 16); return weight; } int main(void) { IIC_Init(); while (1) { uint32_t weight = HX711_ReadWeight(); // 处理称重数据 } } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

本人不帅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值