hx711驅(qū)動(dòng)代碼
已有 3711 次閱讀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; //通道選擇,默認(rèn)為A通道,128增益
// 采用濾波器測量的方式
#define N 12 //定義濾波時(shí),存放采樣值的隊(duì)列的長度。使用循環(huán)隊(duì)列。
static uint32_t BUF[N]; //定義作為隊(duì)列的全局?jǐn)?shù)組。
static uint32_t SUM=0; //定義存放采樣值之和的全局變量。
static uint8_t i=0; //定義指向隊(duì)列當(dāng)前位置的數(shù)組下標(biāo)變量。
/* Private functions ---------------------------------------------------------*/
void Delay(uint16_t nCount);
void HX711_Clk(void);
void Init_HX711(void);
union LongData R_AD0;
//-----------------------------------------------------
//函數(shù)名稱:延時(shí)程序
//功 能: 延時(shí)
//說 明:
//-----------------------------------------------------
void Delay(uint16_t nCount)
{
/* Decrement nCount value */
while (nCount != 0)
{
nCount--;
}
}
//-----------------------------------------------------
//函數(shù)名稱:HX711_Clk
//功 能: 為HX711 輸出一個(gè)時(shí)鐘
//說 明:
//-----------------------------------------------------
void HX711_Clk(void)
{
GPIO_WriteHigh(HX711_PORT, HX711_SCK);
Delay(16);; //SCLK 高電平或低電平脈寬 最小為200ns ,最大為50us,但高電平超過 60μs,芯片進(jìn)入待機(jī)模式 串口時(shí)鐘SCLK工作頻率最大1.1M
GPIO_WriteLow(HX711_PORT, HX711_SCK);
Delay(16);; ////SCLK 高電平或低電平脈寬 最小為200ns
}
/*-----------------------------------------------------------------------------
Name : F_Read_AD_Byte
Function: 讀3字節(jié)AD值
-----------------------------------------------------------------------------*/
uint32_t Read_AD(void)
{
R_AD0.word = 0; //用于保存從 HX711 讀取的 AD 值, 預(yù)賦值 0
// 如下可修改為設(shè)置為中斷方式 to do ... 等高電平到電平中斷發(fā)生
// 當(dāng)數(shù)據(jù)輸出管腳 DOUT 為高電平時(shí),表明A/D 轉(zhuǎn)換器還未準(zhǔn)備好輸出數(shù)據(jù),此時(shí)串口時(shí)鐘輸入信號 PD_SCK 應(yīng)為低電平。當(dāng) DOUT 從高
//電平變低電平后,PD_SCK 應(yīng)輸入 25 至 27 個(gè)不等的時(shí)鐘脈沖(圖二)。其中第一個(gè)時(shí)鐘脈沖的上升沿將讀出輸出 24 位數(shù)據(jù)的最高位(MSB),
// EXTI_DeInit(); // 禁止中斷;(防止讀寫時(shí)誤觸發(fā))
GPIO_Init(HX711_PORT, (GPIO_Pin_TypeDef)HX711_DATA, GPIO_MODE_IN_FL_NO_IT);; //再次確定data管腳為輸入
while(GPIO_ReadInputPin(HX711_PORT, HX711_DATA)); //讀 AD 值之前再次確認(rèn)數(shù)據(jù)線是否為低電平
GPIO_WriteLow(HX711_PORT, HX711_SCK); //此語句可確保在讀 AD 值之前 SCLK 為低電平
for(int k = 0; k < 24; k++) //發(fā)送24個(gè)CLK,接收數(shù)據(jù)
{
R_AD0.word <<= 1;
HX711_Clk(); //上升沿接收數(shù)據(jù),下降沿更新數(shù)據(jù)
if(GPIO_ReadInputPin(HX711_PORT, HX711_DATA)) //如果hx輸出的數(shù)據(jù)是1
{
R_AD0.word += 1; //若數(shù)據(jù)線上數(shù)據(jù)為 1,則返回值加 1
}
}
HX711_Clk(); //第25個(gè)時(shí)鐘
R_AD0.word = (R_AD0.word)^0x800000; //輸出數(shù)據(jù)編碼 二進(jìn)制補(bǔ)碼格式 min = 800000; max = 7FFFFF
//如果一個(gè)數(shù)據(jù)轉(zhuǎn)換周期內(nèi)對ADC進(jìn)行兩次或以上的讀寫操作,則需要發(fā)送46個(gè)CLK,而不是27個(gè)CLK
//(即:發(fā)送24個(gè)CLK讀取數(shù)據(jù),然后再發(fā)送22個(gè)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);
//數(shù)據(jù)以中斷模式接收 見HX711_Read(void) 的的中斷描述
//EXTI_SetExtIntSensitivity(HX711_EXTI, EXTI_SENSITIVITY_FALL_LOW); // 中斷下降沿觸發(fā)
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,芯片從復(fù)位或斷電狀態(tài)進(jìn)入正常工作狀態(tài)后,通道A和增益128會被自動(dòng)作為第一次AD的選擇。
while(GPIO_ReadInputPin(HX711_PORT, HX711_DATA)); //等待一個(gè)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,芯片進(jìn)入待機(jī)模式 串口時(shí)鐘SCLK工作頻率最大1.1M
}
/*-----------------------------------------------------------------------------
* Name : *HX711_Read
* Function: 按控制代碼讀取AD結(jié)果
* 參數(shù)dCode:0x11=通道選擇A 增益128 0x12
0x12= 通道選擇B 增益32
0x13=通道選擇A 增益64
* 注意:前面兩個(gè)數(shù)據(jù)可能是錯(cuò)誤
-----------------------------------------------------------------------------*/
uint32_t *HX711_Read(uint8_t dCode)
{
uint32_t *data = 0;
Read_AD(); //共25個(gè)時(shí)鐘,不讀取數(shù)據(jù),第1次數(shù)據(jù)舍棄
if (dCode == HX711_IOCTRL_A_128) // 默認(rèn)A通道,128增益
{
}
if (dCode == HX711_IOCTRL_B_32)
{
HX711_Clk(); //第26個(gè)時(shí)鐘,選擇通道B,增益32
}
if (dCode == HX711_IOCTRL_A_64)
{
HX711_Clk(); //第26個(gè)時(shí)鐘
HX711_Clk(); //第27個(gè)時(shí)鐘,選擇通道A,增益64
}
*data =Read_AD(); //共25個(gè)時(shí)鐘,讀取數(shù)據(jù)
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) //滑動(dòng)均值濾波法的函數(shù)。
{
unsigned long temp=0,max=0,min=0;
int j=0;
temp = Read_AD();
/*下面一句不使用SUM+=temp-BUF[i]的形式,是為了避免temp-BUF[i]的運(yùn)算,以免產(chǎn)生
負(fù)數(shù),引起誤差。*/
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);
這兩句來替代,因?yàn)椋@樣會改變SUM的值,越減越小,到最后,會出現(xiàn)負(fù)數(shù)了。*/
return (SUM-max-min)/(N-2);
}
/**
* @}
*/
/******************* (C) COPYRIGHT 2016 by eageo *****END OF FILE****/