hx711驱动代码
已有 3644 次阅读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****/