(简单易懂)
1.---------------序
2.HX711测重模块
3.LCD1602显示模块
4.电子秤整体实现原理
5.模块升级>>去皮与还原
6.源代码
零.先来一个效果展示
这里可以看到3个20g砝码加上去显示60g的重量
5个20g砝码加上去显示100g的重量,精度是比较准的
一.首先考虑如何把这样一个项目设计出来
1.明确目标
–做这样一个东西,我们需要实现怎样的效果–
2.思路清晰
–整个执行过程我门需要设计哪些事–
–整个执行过程我们要按照怎样的一个逻辑–
3.确保执行
–有效(花时间并不等于有效)的执行力是成功所必不可缺的–
4.总结收获
–在实现项目过程中我们学到了什么–
–以后应对不同的项目有哪些想法是可以通用的–
二.HX711测重模块原理
1.HX711模块可以看成由三个部分组成>>压力传感器,电压放大器,ad转换芯片
压力传感器:感知物体重力,并转化为电压信号 这里是0~5kg压力传感器,灵敏电压为1mv, 即1kg重力产生1mv电压 电压放大器:由于压力传感器产生电压太小,需要对电压信号放大 这里用的是128倍电压增益 ad转换芯片(24位):将模拟信号(放大后的电压值)转化为数字信号(ad值)
2.ad值转化为重力大小
假设重力为x kg, ad = (x/5)*128*2^24*(5/5000),(满量程为5kg,128倍放大,精度为2^24) (传感器满偏电压5mv,单片机为5v) ad = 429496.7296x >> x = ad/429496.7296 (按g显示再乘1000即可)
//ad转化为重力大小公式,(float)将整除转化为小数运算,再将运算结果强制转化为无符号整型数值
Weight_Shiwu = (unsigned int)((float)Weight_Shiwu/423.15);
//理论上是除以429.5,实际上存在误差(传感器曲线以及电压的微小误差),需要根据显示情况来调整这一数值
3.HX711时序图 & ad取值代码
sbit HX711_DOUT = P2^1; //声明P2^1口接HX711数据线
sbit HX711_SCK = P2^0; //声明P2^0口接HX711时钟线
unsigned long HX711_Read(void)
{
unsigned long count; //存ad值
unsigned char i;
HX711_DOUT = 1; //数据端口拉高,参照时序图写
_nop_(); //延时
_nop_();
HX711_SCK = 0; //时钟端口拉低
count = 0; //ad值初始化
for(i=0; i<24; i++) //循环24次传数据,按位接收数据
{
HX711_SCK = 1; //准备转换数据
count = count << 1; //向左移位,即向低位补0,空出最低位进行传值操作,如1<<1为10
HX711_SCK = 0; //时钟脉冲下降延,数据开始转换
if(HX711_DOUT)
count++; //数据端为高则最低位+1,为1,数据端为低则最低位不变,为0(左移把最低位空出)
}
HX711_SCK = 1; //第25个脉冲延
count = count^0x800000; //异或输出原码
_nop_();
_nop_();
HX711_SCK = 0; //结束ad转换
return(count); //传出ad值
}
ad值以二进制补码输出
这里用的是128倍增益A通道
三.LCD1602液晶显示模块原理
引脚说明
读写说明
写指令/数据时序图
1.写指令(发送写下的指令码给LCD1602并执行)
sbit LCD1602_RS = P3^5;
//sbit LCD1602_RW = P2^5; //郭天祥51板LCDRW端直接接了地,故省略(就不能拉高不能读指令/数据操作)
sbit LCD1602_EN = P3^4;
void LCD1602_write_com(unsigned char com) //声明指令参数
{
LCD1602_RS = 0;
Delay(10);
LCD1602_EN = 1;
P0 = com; //生成指令
Delay(10);
LCD1602_EN = 0;
}
lcd1602指令表
2.写数据(把数据写入LCD1602并显示)
void LCD1602_write_data(unsigned char dat) //声明数据参数
{
LCD1602_RS = 1;
Delay(10);
P0 = dat; //生成数据
LCD1602_EN = 1;
Delay(10);
LCD1602_EN = 0;
}
3.写连续字符(字符串)
void LCD1602_write_word(unsigned char *s)
{
while(*s>0)
{
LCD1602_write_data(*s); //写指针位置处字符数据
s++; //指针++指向连续字符下一个位置
}
}
4.LCD1602初始化
void Init_LCD1602()
{
LCD1602_EN = 0;
//LCD1602_RW = 0; //设置为写状态
LCD1602_write_com(0x38); //显示模式设定
LCD1602_write_com(0x0c); //开关显示、光标有无设置、光标闪烁设置
LCD1602_write_com(0x06); //写一个字符后指针加一
LCD1602_write_com(0x01); //清屏指令
}
四.电子秤整体实现原理
1.HX711模块与51单片机的通信(获取到重量电压信号ad值传给单片机)
2.51单片机与LCD1602的通信(在LCD1602上显示ad值转换为的实际重量)
以下是如何显示重量值
/*0x80为移动光标到显示屏第一行首位,+0x40是光标到第二行首位,再+0x09是光标再往后挪九格,指令表中可查*/
LCD1602_write_com(0x80+0x49);
/*取千位具体数字值,+0x30表示将该数字值转为ASCII码表地址,例int a=8,ASCII码表中8的地址为0x38,即a+0x30*/
LCD1602_write_data(Weight_Shiwu%10000/1000 + 0X30);
LCD1602_write_com(0x80+0x49); //光标移动第二行第九个位置
LCD1602_write_data(Weight_Shiwu%10000/1000 + 0X30); //千位
LCD1602_write_data(Weight_Shiwu%1000/100 + 0X30); //百位
LCD1602_write_data(Weight_Shiwu%100/10 + 0X30); //十位
LCD1602_write_data(Weight_Shiwu%10 + 0X30); //个位
LCD1602_write_word(" g"); //显示单位克
五.模块升级>>去皮与还原
1.首先理解去皮的含义:
假如你有一个梨,你想知道它的重量,看看卖家有没有坑你,以后能不能再到这买梨,
可你觉得秤太脏了,秤一下梨都没有食欲不想吃了,灵光突然一闪想到可以用一个碗垫着秤,
想法不错可问题就来了,碗的重量怎么办呢,这时去皮的意义就出来了
先把碗放在秤盘上,这时显示屏显示的是碗的重量,小手一抖按一下去皮键,
碗的重量就没有了,显示屏显示0,这下可以安心秤梨了
2.去皮如何实现:
I/O口声明&变量声明
sbit key1 = P3^6; //声明按键1(去皮键)具体I/O口和单片机型号有关
sbit key2 = P3^7; //声明按键2(还原键)
unsigned long Weight_Shiwu = 0; //无符号长型变量存实物重量
unsigned long Weight_Maopi = 0; //毛皮重量(相当于碗的重量)
先判断去皮键是否被按下
void Keyscan()
{
if(key1 == 0)
Delay(10); //消抖
if(key1 == 0){
Get_Maopi(); //获取毛皮重量(相当于碗的重量)
while(!key1); //松手检测
}
}
去皮键按下后,就可以获取毛皮重量(碗重量)了
void Get_Maopi()
{
Weight_Maopi = HX711_Read(); //把ad值获取到
Weight_Maopi = (unsigned int)((float)Weight_Maopi/423.15); //换算成真正的毛皮重量
}
将按键扫描放在主函数while(1)死循环的最开始,去皮键按下才执行
去皮键未按下就直接称重,跳过去皮环节
while(1)
{
Keyscan();
Get_Weight();
/*............*/
void Get_Weight()
{
Weight_Shiwu = HX711_Read(); //把ad值获取到
Weight_Shiwu = (unsigned int)((float)Weight_Shiwu/423.15); //换算成真正的实物重量
Weight_Shiwu = Weight_Shiwu - Weight_Maopi; //毛皮重量初始为0
}
3.如何还原去皮:
在按键扫描函数中再加一个还原按键
如果还原键按下,毛皮重量被初始化(置0)
就实现了还原去皮的效果
void Keyscan()
{
if(key1 == 0)
Delay(10);
if(key1 == 0){
Get_Maopi();
while(!key1);
}
if(key2 == 0)
Delay(10);
if(key2 == 0){
Weight_Maopi = 0; //毛皮重量置0
while(!key2);
}
}
六.源代码及注释
#include
#include
/*I/O口声明*/
sbit LCD1602_RS = P3^5;
//sbit LCD1602_RW = P2^5;
sbit LCD1602_EN = P3^4;
sbit HX711_DOUT = P2^1;
sbit HX711_SCK = P2^0;
sbit key1 = P3^6;
sbit key2 = P3^7;
/*全局变量定义*/
unsigned long Weight_Shiwu = 0;
unsigned long Weight_Maopi = 0;
/*函数声明*/
void Delay(unsigned int n);
void Init_LCD1602();
void LCD1602_write_com(unsigned char com);
void LCD1602_write_word(unsigned char *s);
void LCD1602_write_data(unsigned char dat);
unsigned long HX711_Read(void);
void Keyscan();
void Get_Maopi();
void Get_Weight();
int main()
{
Init_LCD1602(); //LCD1602初始化
LCD1602_write_com(0x80); //移动光标到第一行首位
LCD1602_write_word(" Dian Zi Cheng! "); //显示 Dian Zi Cheng!
LCD1602_write_com(0x80 + 0x40); //移动光标到第二行首位
LCD1602_write_word("Weight :"), //显示Weight :
Delay(1000); //1s延时
while(1)
{
Keyscan();
Get_Weight();
LCD1602_write_com(0x80+0x49); //移动光标到第二行第九位
LCD1602_write_data(Weight_Shiwu%10000/1000 + 0X30);
LCD1602_write_data(Weight_Shiwu%1000/100 + 0X30);
LCD1602_write_data(Weight_Shiwu%100/10 + 0X30);
LCD1602_write_data(Weight_Shiwu%10 + 0X30);
LCD1602_write_word(" g");
}
return 0;
}
/*称实物重*/
void Get_Weight()
{
Weight_Shiwu = HX711_Read();
Weight_Shiwu = (unsigned int)((float)Weight_Shiwu/423.15);
Weight_Shiwu = Weight_Shiwu - Weight_Maopi;
}
/*延时子函数*/
void Delay(unsigned int n)
{
int i, j;
for(i=0; i<n; i++)
for(j=0; j<110; j++);
}
/*写指令*/
void LCD1602_write_com(unsigned char com)
{
LCD1602_RS = 0;
Delay(10);
LCD1602_EN = 1;
P0 = com;
Delay(10);
LCD1602_EN = 0;
}
/*写数据*/
void LCD1602_write_data(unsigned char dat)
{
LCD1602_RS = 1;
Delay(10);
P0 = dat;
LCD1602_EN = 1;
Delay(10);
LCD1602_EN = 0;
}
/*写连续字符(字符串)*/
void LCD1602_write_word(unsigned char *s)
{
while(*s>0)
{
LCD1602_write_data(*s);
s++;
}
}
/*初始化LCD1602*/
void Init_LCD1602()
{
LCD1602_EN = 0;
//LCD1602_RW = 0;
LCD1602_write_com(0x38);
LCD1602_write_com(0x0c);
LCD1602_write_com(0x06);
LCD1602_write_com(0x01);
}
/*获取ad值*/
unsigned long HX711_Read(void)
{
unsigned long count;
unsigned char i;
HX711_DOUT = 1;
_nop_();
_nop_();
HX711_SCK = 0;
count=0;
for(i=0; i<24; i++)
{
HX711_SCK = 1;
count = count << 1;
HX711_SCK = 0;
if(HX711_DOUT)
count++;
}
HX711_SCK = 1;
count = count^0x800000;
_nop_();
_nop_();
HX711_SCK = 0;
return(count);
}
/*称毛皮重*/
void Get_Maopi()
{
Weight_Maopi = HX711_Read();
Weight_Maopi = (unsigned int)((float)Weight_Maopi/423.15);
}
/*按键扫描*/
void Keyscan()
{
if(key1 == 0)
Delay(10);
if(key1 == 0){
Get_Maopi();
while(!key1);
}
if(key2 == 0)
Delay(10);
if(key2 == 0){
Weight_Maopi = 0;
while(!key2);
}
}