电子模块|压力传感器模块HX711---硬件介绍与C51&&STM32驱动
- 实物照片
- 模块简介
- 模块特点
- 软件驱动
- C51软件代码
- STM32软件代码
实物照片
模块简介
HX711是一款专为高精度称重传感器而设计的24位A/D转换器芯片。与同类型其它芯片相比,该芯片集成了包括稳压电源、片内时钟振荡器等其它同类型芯片所需要的外围电路,具有集成度高、响应速度快、抗干扰性强等优点。降低了电子秤的整机成本,提高了整机的性能和可靠性。该芯片与后端MCU芯片的接口和编程非常简单,所有控制信号由管脚驱动,无需对芯片内部的寄存器编程。输入选择开关可任意选取通道A或通道B,与其内部的低噪声可编程放大器相连。通道A的可编程增益为128或64,对应的满额度差分输入信号幅值分别为±20mV或±40mV。通道B则为固定的32增益,用于系统参数检测。芯片内提供的稳压电源可以直接向外部传感器和芯片内的A/D转换器提供电源,系统板上无需另外的模拟电源。芯片内的时钟振荡器不需要任何外接器件。上电自动复位功能简化了开机的初始化过程。
模块特点
- 两路可选择差分输入
- 片内低噪声可编程放大器,可选增益为64 和128
- 片内稳压电路可直接向外部传感器和芯片内A/D 转换器提供电源
- 片内时钟振荡器无需任何外接器件,必要时也可使用外接晶振或时钟
- 上电自动复位电路
- 简单的数字控制和串口通讯:所有控制由管脚输入,芯片内寄存器无需编程
- 可选择10Hz 或80Hz 的输出数据速率
- 同步抑制50Hz 和60Hz 的电源干扰
- 耗电量(含稳压电源电路):典型工作电流:<1.7mA, 断电电流:<1μA
- 工作电压范围:2.6 ~ 5.5V
- 工作温度范围:-20 ~ +85℃
- 16 管脚的SOP-16 封装
软件驱动
串口通讯线由管脚PD_SCK和DOUT组成,用来输出数据,选择输入通道和增益。当数据输出管脚DOUT为高电平时,表明A/D转换器还未准备好输出数据,此时串口时钟输入信号PD_SCK应为低电平。当DOUT从高电平变低电平后,PD_SCK应输入25至27个不等的时钟脉冲。其中第一个时钟脉冲的上升沿将读出输出24位数据的最高位(MSB),直至第24个时钟脉冲完成,24位输出数据从最高位至最低位逐位输出完成。第25至27个时钟脉冲用来选择下一次A/D转换的输入通道和增益。
PD_SCK的输入时钟脉冲数不应少于25或多于27,否则会造成串口通讯错误。当A/D转换器的输入通道或增益改变时,A/D转换器需要4个数据输出周期才能稳定。DOUT在4个数据输出周期后才会从高电平变低电平,输出有效数据。
数据输出,输入通道和增益选择时序图
通过测得的AD值,转为重力原理如下:
假设重力为 A Kg,(x<5Kg),测量出来的 AD 值为 y
传感器输出,发送给 AD 模块儿的电压为 A Kg * 4.3mV / 5Kg = 0.86A mV
经过 128 倍增益后为 128 * 0.86A = 110.08AmV
转换为 24bit 数字信号为 110.08A mV * 224 / 4.3V = 429496.7296A
所以 y = 429496.7296A
因此得出 A = y / 429496.7296
所以得出程序中计算公式
Weight_Shiwu = (unsigned long)((float)Weight_Shiwu/429.5)
C51软件代码
sbit ADDO = P1^5;
sbit ADSK = P0^0;
unsigned long ReadCount(void)
{
unsigned long Count;
unsigned char i;
ADSK=0;
//使能AD(PD_SCK 置低)
Count=0;
while(ADDO);
//AD转换未结束则等待,否则开始读取
for (i=0;i<24;i++)
{
ADSK=1;
//PD_SCK 置高(发送脉冲)
Count=Count<<1; //下降沿来时变量Count左移一位,右侧补零
ADSK=0;
//PD_SCK 置低
if(ADDO) Count++;
}
ADSK=1;
Count=Count^0x800000;//第25个脉冲下降沿来时,转换数据
ADSK=0;
return(Count);
}
STM32软件代码
#define DWT_CYCCNT *(volatile unsigned int *)0xE0001004
#define DWT_CR *(volatile unsigned int *)0xE0001000
#define DEM_CR *(volatile unsigned int *)0xE000EDFC
#define DBGMCU_CR *(volatile unsigned int *)0xE0042004
#define DEM_CR_TRCENA (1 << 24)
#define DWT_CR_CYCCNTENA (1 << 0)
#define WEIGHT_CAP_NUM 1 //重量采集数量 滤波使用
uint8_t ucWeightCapCompleteFlag= 0; //重量采集完成标志
uint8_t ucWeightCapCount = 0; //重量采集计数
int32_t ilWeightRawDataAddToal = 0; //重量AD数据累计
int16_t iWeightRawData = 0; //重量AD数据
/*
*********************************************************************************************************
* 函 数 名: bsp_InitDWT
* 功能说明: 初始化DWT.
*********************************************************************************************************
*/
void bsp_InitDWT(void)
{
DEM_CR |= (unsigned int)DEM_CR_TRCENA; /* Enable Cortex-M4's DWT CYCCNT reg. */
DWT_CYCCNT = (unsigned int)0u;
DWT_CR |= (unsigned int)DWT_CR_CYCCNTENA;
}
/*
*********************************************************************************************************
* 函 数 名: DWT_DelayUS
* 功能说明: 这里的延时采用CPU的内部计数实现,32位计数器
* OSSchedLock(&err);
* bsp_DelayUS(5);
* OSSchedUnlock(&err); 根据实际情况看看是否需要加调度锁或选择关中断
* 形 参: _ulDelayTime 延迟长度,单位1 us
*********************************************************************************************************
*/
void DWT_DelayUS(uint32_t _ulDelayTime)
{
uint32_t tCnt, tDelayCnt;
uint32_t tStart;
tStart = DWT_CYCCNT; /* 刚进入时的计数器值 */
tCnt = 0;
tDelayCnt = _ulDelayTime * (SystemCoreClock / 1000000); /* 需要的节拍数 */
while(tCnt < tDelayCnt)
{
tCnt = DWT_CYCCNT - tStart; /* 求减过程中,如果发生第一次32位计数器重新计数,依然可以正确计算 */
}
}
/*
*********************************************************************************************************
* 函 数 名: HX711_GPIOInit
* 功能说明: 重量芯片HX711 GPIO初始化
*********************************************************************************************************
*/
void HX711_GPIOInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //使能PORTA
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; //PA7 推挽输出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //PA6 推挽输出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
/*
*********************************************************************************************************
* 函 数 名: HX711_Init
* 功能说明: 重量芯片HX711初始化
*********************************************************************************************************
*/
void HX711_Init(void)
{
CH376_SPI_SCS = 1; //CH376 片选失能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, DISABLE);
SPI_Cmd(SPI1, DISABLE); //禁止SPI
HX711_GPIOInit(); //初始化IO
}
/*
*********************************************************************************************************
* 函 数 名: Task_WeightCap
* 功能说明: 重量采集任务
*********************************************************************************************************
*/
void Task_WeightCap(void)
{
uint32_t count = 0;
int16_t raw_data = 0;
uint8_t i;
HX711_Init(); //HX711重新初始化
ADSK = 0;
count= 0;
while(ADDO);
for(i=0; i<24; i++)
{
ADSK = 1;
DWT_DelayUS(1);
count = count << 1;
ADSK = 0;
DWT_DelayUS(1);
if(ADDO)
{
count++;
}
}
//第25个时钟信号
ADSK=1;
DWT_DelayUS(1);
ADSK=0;
DWT_DelayUS(1);
raw_data = count >> 8;
ilWeightRawDataAddToal = raw_data + ilWeightRawDataAddToal;
ucWeightCapCount++;
if(ucWeightCapCount == WEIGHT_CAP_NUM)
{
ucWeightCapCount = 0;
iWeightRawData = ilWeightRawDataAddToal / WEIGHT_CAP_NUM;
ilWeightRawDataAddToal = 0;
ucWeightCapCompleteFlag = 1;
}
}
/*
*********************************************************************************************************
* 函 数 名: GetWeightRawData
* 功能说明: 得到重量的原始值
* 形 参: iRawData 原始值
* 返 回 值: 1 已经得到 0 没有得到
*********************************************************************************************************
*/
uint8_t GetWeightRawData(int16_t *iRawData)
{
if(ucWeightCapCompleteFlag == 1)
{
*iRawData = iWeightRawData;
ucWeightCapCompleteFlag = 0;
return 1;
}
return 0;
}