立即注册 登录
返回首页

uid:232188的个人空间

日志

hx711驱动代码

已有 3558 次阅读2017-9-10 10:05

/**
  ******************************************************************************
  * @file    Project/hx711.c
  * @author  aben lee
  * email: aben.lee@foxmail.com qq: 619412201
  * @version V2.1.0
  * @date    18-November-2011
  * @brief   Main program body
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "hx711.h"
#include "ulitity.h"
   
/** @addtogroup Template_Project
  * @{
  */

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
uint8_t HxChGain = HX711_IOCTRL_A_128;                    //通道选择,默认为A通道,128增益
// 采用滤波器测量的方式
#define N 12                //定义滤波时,存放采样值的队列的长度。使用循环队列。
static uint32_t BUF[N];            //定义作为队列的全局数组。
static uint32_t SUM=0;                //定义存放采样值之和的全局变量。
static uint8_t i=0;                //定义指向队列当前位置的数组下标变量。

/* Private functions ---------------------------------------------------------*/
void Delay(uint16_t nCount);
void HX711_Clk(void);
void Init_HX711(void);


union LongData R_AD0;


//-----------------------------------------------------
//函数名称:延时程序 
//功     能: 延时
//说     明:
//-----------------------------------------------------
void Delay(uint16_t nCount)
{
  /* Decrement nCount value */
  while (nCount != 0)
  {  
    nCount--;
  }
}

//-----------------------------------------------------
//函数名称:HX711_Clk 
//功     能: 为HX711 输出一个时钟
//说     明:
//-----------------------------------------------------
void HX711_Clk(void)
{
     GPIO_WriteHigh(HX711_PORT, HX711_SCK); 
    Delay(16);;    //SCLK 高电平或低电平脉宽 最小为200ns ,最大为50us,但高电平超过 60μs,芯片进入待机模式  串口时钟SCLK工作频率最大1.1M
    GPIO_WriteLow(HX711_PORT, HX711_SCK);
        Delay(16);;   ////SCLK 高电平或低电平脉宽 最小为200ns
}

/*-----------------------------------------------------------------------------
Name    : F_Read_AD_Byte
Function: 读3字节AD值
-----------------------------------------------------------------------------*/
uint32_t Read_AD(void)
{
    R_AD0.word = 0;                 //用于保存从 HX711 读取的 AD 值, 预赋值 0
       
        // 如下可修改为设置为中断方式  to do ... 等高电平到电平中断发生
        // 当数据输出管脚 DOUT 为高电平时,表明A/D 转换器还未准备好输出数据,此时串口时钟输入信号 PD_SCK 应为低电平。当 DOUT 从高
        //电平变低电平后,PD_SCK 应输入 25 至 27 个不等的时钟脉冲(图二)。其中第一个时钟脉冲的上升沿将读出输出 24 位数据的最高位(MSB),
      //  EXTI_DeInit();            // 禁止中断;(防止读写时误触发)
         
        GPIO_Init(HX711_PORT, (GPIO_Pin_TypeDef)HX711_DATA, GPIO_MODE_IN_FL_NO_IT);;     //再次确定data管脚为输入

    while(GPIO_ReadInputPin(HX711_PORT, HX711_DATA));     //读 AD 值之前再次确认数据线是否为低电平
       
        GPIO_WriteLow(HX711_PORT, HX711_SCK);                 //此语句可确保在读 AD 值之前 SCLK 为低电平
   
    for(int k = 0; k < 24; k++)                //发送24个CLK,接收数据
    {
        R_AD0.word <<= 1;
        HX711_Clk();                            //上升沿接收数据,下降沿更新数据
       
                if(GPIO_ReadInputPin(HX711_PORT, HX711_DATA))    //如果hx输出的数据是1
        {
            R_AD0.word += 1; //若数据线上数据为 1,则返回值加 1
        }
    }
   
        HX711_Clk();   //第25个时钟   
       
        R_AD0.word = (R_AD0.word)^0x800000;      //输出数据编码 二进制补码格式 min = 800000;  max = 7FFFFF
       
    //如果一个数据转换周期内对ADC进行两次或以上的读写操作,则需要发送46个CLK,而不是27个CLK
    //(即:发送24个CLK读取数据,然后再发送22个CLK)
    //EXTI_SetExtIntSensitivity(HX711_EXTI, EXTI_SENSITIVITY_FALL_LOW); //重新开启MCU_DAT管脚的外部中断
       
        return(R_AD0.word); 
}

/* Public functions ----------------------------------------------------------*/

uint8_t HX711_Init(void)
{
  GPIO_Init(HX711_PORT, (GPIO_Pin_TypeDef)HX711_SCK, GPIO_MODE_OUT_PP_LOW_FAST);
 
  GPIO_Init(HX711_PORT, (GPIO_Pin_TypeDef)HX711_DATA, GPIO_MODE_IN_FL_NO_IT);
 
  //数据以中断模式接收 见HX711_Read(void) 的的中断描述
  //EXTI_SetExtIntSensitivity(HX711_EXTI, EXTI_SENSITIVITY_FALL_LOW);    // 中断下降沿触发

  return 1; 
}

bool HX711_Deinit(void)
{
  HX711_PowerDown();
  return TRUE;
}

void HX711_PowerUp(void)
{
  HX711_PowerDown();
  GPIO_WriteLow(HX711_PORT, HX711_SCK);
  Delay(10);   //SCK重新回到低电平 最小宽度为200ns,芯片从复位或断电状态进入正常工作状态后,通道A和增益128会被自动作为第一次AD的选择。
 
  while(GPIO_ReadInputPin(HX711_PORT, HX711_DATA));     //等待一个AD值,表示AD工作正常;
  while(!GPIO_ReadInputPin(HX711_PORT, HX711_DATA));
}

void HX711_PowerDown(void)
{
    GPIO_WriteHigh(HX711_PORT, HX711_SCK); 
    Delay(2000);    //SCLK 高电平或低电平脉宽 最小为200ns ,最大为50us,但高电平超过 60μs,芯片进入待机模式  串口时钟SCLK工作频率最大1.1M  
}

/*-----------------------------------------------------------------------------
* Name    : *HX711_Read
* Function: 按控制代码读取AD结果
*   参数dCode:0x11=通道选择A 增益128 0x12   
            0x12= 通道选择B 增益32
            0x13=通道选择A 增益64

* 注意:前面两个数据可能是错误
-----------------------------------------------------------------------------*/
uint32_t *HX711_Read(uint8_t dCode)
{
  uint32_t *data = 0;
  Read_AD();    //共25个时钟,不读取数据,第1次数据舍弃
 
  if (dCode == HX711_IOCTRL_A_128)    // 默认A通道,128增益
  {
  }

  if (dCode == HX711_IOCTRL_B_32)
  {   
    HX711_Clk();  //第26个时钟,选择通道B,增益32
  }
  if (dCode == HX711_IOCTRL_A_64)
  {   
    HX711_Clk();  //第26个时钟
    HX711_Clk();  //第27个时钟,选择通道A,增益64
   }
 
  *data =Read_AD();    //共25个时钟,读取数据
 return data;
}

/*
int AcqData(uint32_t *pData, uint32_t N, unsigned int cmd)
{
  Init_HX711();
  Delay(20);
 
  switch(cmd)
  {
    case HX_IOCTRL_PowerUp :
      HX_PowerUp();   
      break;
    case HX_IOCTRL_PowerDown :
      HX_PowerDown();
      break;
    case HX_IOCTRL_A_128  :
      pData = HX_Read(HX_IOCTRL_A_128);
      break; 
    case  HX_IOCTRL_B_32  :
      pData = HX_Read(HX_IOCTRL_B_32);
      break;
    case HX_IOCTRL_A_64  :
      pData = HX_Read(HX_IOCTRL_A_64);
      break;
    default:
      pData = HX_Read(HX_IOCTRL_A_128);
      break;
  }
 return N;
}
*/

void BUFInit(void)
{
    int j=0; 

    for(j=0;j<N;j++)
    {
        BUF[j] = Read_AD();
        SUM+=BUF[j];
    }
}

uint32_t  MassAD_Filter(void)            //滑动均值滤波法的函数。
{
    unsigned long temp=0,max=0,min=0;
    int j=0;
       
    temp = Read_AD();

    /*下面一句不使用SUM+=temp-BUF[i]的形式,是为了避免temp-BUF[i]的运算,以免产生
    负数,引起误差。*/

    SUM = SUM+temp-BUF[i];
    BUF[i]=temp;
    i++;
    if(i == N)
        i=0;
   
    max=BUF[0];
    min=BUF[0];
    for(j=0;j<N;j++)
    {
        if(max<BUF[j])    max=BUF[j];
        if(min>BUF[j])    min=BUF[j];
    }
   
    /*下面一句中的(SUM-max-min)/(N-2),不能用SUM=SUM-max-min; SUM/(N-2);
    这两句来替代,因为,这样会改变SUM的值,越减越小,到最后,会出现负数了。*/

    return (SUM-max-min)/(N-2);   
}


/**
  * @}
  */

/******************* (C) COPYRIGHT 2016 by eageo *****END OF FILE****/

路过

鸡蛋

鲜花

握手

雷人

评论 (0 个评论)

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

返回顶部