标题:
stc15w4单片机+HX711称重传感器+12864源程序
[打印本页]
作者:
hzw854025403
时间:
2019-8-5 15:08
标题:
stc15w4单片机+HX711称重传感器+12864源程序
这是我从网上一堆程序整合成的电子秤,发给大家参考参考,有什么不对的希望大家指出。
程序已经完全调试正常,在虽然小数点的显示不出来,但是稳定在克是没有什么问题的。
单片机源程序如下:
/*********************************************************************
//主时钟在 common.H 定义
//u8,u16,u32已在"STC15Fxxxx.h"定义
//因为15W系列快89系列 6——12倍,
//时序图上面的时间也要相应的加倍,具体多少要具体测试
*********************************************************************/
/*
**********************************************************************
* 头文件包含
**********************************************************************
*/
#include "common.h"
#include "LCD12864.h"
#include "HX711.h"
//使用了宏晶科技的资料及程序
/*********************************************************************
0 0 准双向口(标准 8051 单片机输出模式),灌电流可达 20mA,拉电流典型 值为 200uA,由于制造误差,实际为 150~270 uA。
0 1 推挽输出,强上拉输出,可达 20 mA,外加限流电阻,尽量少用
1 0 仅为输入(高阻)
1 1 开漏,内部上拉电阻断开,要外接上拉电阻才可以输出高电平。
**********************************************************************/
void port_mode(void)
{
P0M1 = 0; P0M0 = 0; //设置为准双向口
P1M1 = 0; P1M0 = 0; //设置为准双向口
P2M1 = 0; P2M0 = 0; //设置为准双向口
P3M1 = 0; P3M0 = 0; //设置为准双向口
P4M1 = 0; P4M0 = 0; //设置为准双向口
P5M1 = 0; P5M0 = 0; //设置为准双向口
P6M1 = 0; P6M0 = 0; //设置为准双向口
P7M1 = 0; P7M0 = 0; //设置为准双向口
}
/*********************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 参数列表 : 无
* 函数输出 : 无
*********************************************************************/
void main(void)
{
port_mode(); //设置为准双向口
Lcd12864Init(); //初始化
Lcd12864ClearScreen(); // 清屏
Lcd12864ShowStr(0,0," Holle word!");
Lcd12864FlashScreen();
delay_ms(200);
Lcd12864ClearScreen(); // 清屏
delay_ms(1);
chengzhongmain(); //显示重量:单位G
while(1);
}
复制代码
所有资料51hei提供下载:
stc15w4k.zip
(141.24 KB, 下载次数: 114)
2019-8-5 15:07 上传
点击文件名下载附件
12864+hx711
下载积分: 黑币 -5
作者:
hzw854025403
时间:
2019-8-5 15:14
12864的部分代码
/*
**********************************************************************
* 头文件包含
**********************************************************************
*/
#include "lcd12864.h"
#include "delay.h"
/*
**********************************************************************
* 本地全局变量
**********************************************************************
*/
sbit gLcd12864_E = P5^2; // LCD12864控制总线的使能信号
sbit gLcd12864_RW = P5^1; // LCD12864控制总线的读写选择信号
sbit gLcd12864_RS = P5^0; // LCD12864控制总线的数据/命令选择信号
sbit gLcd12864_PSB= P5^4; // PSB脚为12864-12系列的串、并通讯功能切换,PSB=1为并口,PSB=0为串口
// 显示的图片字模,取模软件在光盘工具软件目录下的字模提取软件
// 注意要设置为横向取模,不要勾选字节倒序
/*
**********************************************************************
* 内部函数原型声明
**********************************************************************
*/
/*********************************************************************
* 函 数 名 : Lcd12864WaitNoBusy
* 函数功能 : 阻塞等待LCD12864直到不忙状态
* 参数列表 : 无
* 函数输出 : 无
*********************************************************************/
static void Lcd12864WaitNoBusy(void) //忙检测函数,判断bit7是0,允许执行;1禁止
{
u8 sta = 0;
LCD12864_DATA_PORT = 0xff;
gLcd12864_RS = 0;
gLcd12864_RW = 1;
do
{
gLcd12864_E = 1;
sta = LCD12864_DATA_PORT;
gLcd12864_E = 0; //使能,用完就拉低,释放总线
}while(sta & 0x80);
}
/*********************************************************************
* 函 数 名 : Lcd12864WriteCmd
* 函数功能 : 按照LCD12864低层时序向LCD内部写入8位命令字
* 参数列表 : cmd - 待写入的8位命令字
* 函数输出 : 无
*********************************************************************/
static void Lcd12864WriteCmd(u8 cmd)
{
Lcd12864WaitNoBusy(); // 先等待LCD1602处于不忙状态
gLcd12864_E = 0; // 禁止LCD
// Delay100us();
gLcd12864_RS = 0; // 选择发送命令模式
// Delay100us();
gLcd12864_RW = 0; // 选择写入模式
// Delay100us();
LCD12864_DATA_PORT = cmd; // 将1字节命令字放入8位并行数据端口
Delay100us();
gLcd12864_E = 1; // 使能LED
Delay100us();
gLcd12864_E = 0; // 禁止LCD
}
/*********************************************************************
* 函 数 名 : Lcd12864WriteData
* 函数功能 : 按照LCD12864低层时序向LCD内部写入8位数据
* 参数列表 : dat - 待写入的8位命令字
* 函数输出 : 无
*********************************************************************/
static void Lcd12864WriteData(u8 dat)
{
Lcd12864WaitNoBusy(); // 先等待LCD12864处于不忙状态
gLcd12864_E = 0; // 禁止LCD
// Delay100us();
gLcd12864_RS = 1; // 选择发送数据模式
// Delay100us();
gLcd12864_RW = 0; // 选择写入模式
// Delay100us();
LCD12864_DATA_PORT = dat; // 将1字节命令字放入8位并行数据端口
Delay100us();
gLcd12864_E = 1; // 使能LED
Delay100us();
gLcd12864_E = 0; // 禁止LCD
}
/************* 上面是底层时序函数,下面是高层时序函数 ***************/
/*********************************************************************
* 函 数 名 : Lcd12864Init
* 函数功能 : 按照LCD12864低层时序进行初始化序列
* 参数列表 : 无
* 函数输出 : 无
*********************************************************************/
void Lcd12864Init(void)
{
gLcd12864_PSB = 1; // 设置为8位并行总线
Delay100us();
// 发送初始化序列
Lcd12864WriteCmd(0x30); // 0x30为基本指令集
Lcd12864WriteCmd(0x01); // 0x01为清屏指令
Lcd12864WriteCmd(0x06); // 地址自动加1
Lcd12864WriteCmd(0x0c); // 整体显示、游标关闭
}
/*********************************************************************
* 函 数 名 : Lcd12864ClearScreen
* 函数功能 : 清屏,即清除屏幕整个显示内容
* 参数列表 : 无
* 函数输出 : 无
*********************************************************************/
void Lcd12864ClearScreen(void)
{
// 发送初始化序列
Lcd12864WriteCmd(0x01); // 0x01为清屏指令
// Lcd12864WriteCmd(0x34); // 0x34为扩充指令集
// Lcd12864WriteCmd(0x30); // 0x30为基本指令集
}
/*********************************************************************
* 函 数 名 : Lcd12864FlashScreen3
* 函数功能 : 屏幕闪烁3次
* 参数列表 : 无
* 函数输出 : 无
*********************************************************************/
void Lcd12864FlashScreen(void)
{
u8 time = 0;
for (time=0; time<3; time++)
{
Lcd12864WriteCmd(0x08);
Delay500ms();
Lcd12864WriteCmd(0x0c);
Delay500ms();
}
}
/****************************************************
//显示一个字符
void Lcd12864ShowChar(u8 x, u8 y, u8 DData)
{
switch (y)
{
case 0:
x |= 0x80; break;
case 1:
x |= 0x90; break;
case 2:
x |= 0x88; break;
case 3:
x |= 0x98; break;
default:
break;
}
Lcd12864WriteCmd(x); //这里不检测忙信号,发送地址码
Lcd12864WriteData(DData);
}
*******************************************************/
/*********************************************************************
* 函 数 名 : Lcd12864ShowStr
* 函数功能 : 从坐标(x, y)开始显示字符串str,注意这个函数不能跨行
* 显示,因为显存地址是不连续的。
* 参数列表 : x - 横向坐标,范围是0-7
* y - 纵向坐标,范围是0-3
* pStr - 指向待显示的字符串的指针
* 函数输出 : 无
*********************************************************************/
void Lcd12864ShowStr(u8 x, u8 y, u8 *pStr) //显示字符串
{
switch (y)
{
case 0:
x |= 0x80; break;
case 1:
x |= 0x90; break;
case 2:
x |= 0x88; break;
case 3:
x |= 0x98; break;
default:
break;
}
Lcd12864WriteCmd(x); // 发送地址码
while (*pStr != '\0') // 若到达字串尾则退出
{
Lcd12864WriteData(*pStr);
pStr++;
Delay100us();
}
}
/*********************************************************************
* 函 数 名 : Lcd12864ShowImage
* 函数功能 : 显示一个128*64分辨率的2值位图。
* 参数列表 : pData - 指向待显示的位图图像数组指针
* 函数输出 : 无
*********************************************************************/
//void Lcd12864ShowImage(u8 *pData)
//{
// u8 x = 0, y = 0, i = 0;
// u16 tmp = 0;
// //分两屏,上半屏和下半屏,因为起始地址不同,需要分开
// for (i=0; i<9; i+=8)
// {
// for (x=0; x<32; x++)
// { //32行
// Lcd12864WriteCmd(0x34);
// Lcd12864WriteCmd(0x80 + x); // 列地址
// Lcd12864WriteCmd(0x80 + i); // 行地址,下半屏,即第三行地址0X88
// Lcd12864WriteCmd(0x30);
// for (y=0; y<16; y++)
// Lcd12864WriteData(pData[tmp+y]); // 将取数据写入LCD
// tmp += 16;
// }
// }
// Lcd12864WriteCmd(0x36); // 扩充功能设定
// Lcd12864WriteCmd(0x30);
//}
复制代码
作者:
hzw854025403
时间:
2019-8-5 15:14
HX711部分代码
#include "HX711.h"
#include "LCD12864.h"
//校准参数
//因为不同的传感器特性曲线不是很一致,因此,每一个传感器需要矫正这里这个参数才能使测量值很准确。
//当发现测试出来的重量偏大时,增加该数值。
//如果测试出来的重量偏小时,减小改数值。
//该值可以为小数
#define GapValue A
u16 A = 442.8;//这是一个修正系数,例如100g砝码称出来是99.2g,A=99.2*A/原数据;
#define MEDIAN_LEN 9 //中值滤波的滤波长度,一般取奇数
#define MEDIAN 5 //中值在滤波数组中的位置
u32 buffer[MEDIAN_LEN]; //中值滤波的数据缓存
u16 medleng = 0; //一组中值滤波数据中,进入滤波缓存的数据个数
u32 xd,xd1; //数据对比大小中间变量
//函数或者变量声明
extern void Delay_ms(unsigned int n);
extern void Get_Maopi();
extern void Get_Weight();
extern void Scan_Key();
/*unsigned char code b[]={"0123456789.-g"}; //ZF 占两个字符*/
u8 dat[]="0000.00G";
unsigned long HX711_Buffer = 0;
unsigned long Weight_Maopi = 0;
long Weight_Shiwu = 0;
unsigned char flag = 0;
bit Flag_ERROR = 0;
sbit KEY1 = P2^3;
sbit speak= P5^5;//板子上的测试灯
//****************************************************
//读取HX711
//****************************************************
u32 HX711_Read(void) //增益128
{
unsigned long count;
unsigned char i;
HX711_DOUT=1;
Delay5us();
HX711_SCK=0;
count=0;
EA = 1;
while(HX711_DOUT);
EA = 0;
for(i=0;i<24;i++) //做24个脉冲
{
HX711_SCK=1;
count=count<<1;
HX711_SCK=0;
if(HX711_DOUT)
count++;
}
HX711_SCK=1;
count=count^0x800000;//第25个脉冲下降沿来时,转换数据
Delay5us();
HX711_SCK=0;
return(count);
}
//****************************************************
//显示称重程序
//****************************************************
void chengzhongmain()
{
u16 i;
Get_Maopi(); //称毛皮重量
Delay100us();
Get_Maopi(); //再次称毛皮重量
while(1)
{
EA = 0;
Get_Weight(); //称重
EA = 1;
Scan_Key(); //按键,触发去皮
if(medleng == 0) //缓存的第1个元素,直接放入,不需要排序
{
buffer[0] = Weight_Shiwu; medleng = 1;
}
else //插入排序算法,按从小到大的顺序排列
{
for(i = 0; i < medleng; i ++)
{
if( buffer[i] > Weight_Shiwu) // 轮询到的当前元素>AD值,则交换它们的值,xd为中间变量存放位置
{
xd = Weight_Shiwu; Weight_Shiwu = buffer[i]; buffer[i] = xd;
}
}
buffer[medleng] = Weight_Shiwu; //把轮询出较大的数放入缓存的后面.
medleng++;
}
//显示当前重量
if(medleng >= MEDIAN_LEN) //ADC采样的数据个数达到中值滤波要求的数据个数
{
Weight_Shiwu = buffer[MEDIAN]; //最终重量取中值滤波数组的中间值
medleng = 0;
if( Flag_ERROR == 1)
{
Lcd12864ClearScreen(); //清屏
Lcd12864ShowStr(2,1,"error"); //显示错误
speak=0; //大于5千克时亮
delay_ms(200);
Lcd12864ClearScreen(); //清屏
}
else
{
speak=1;
Lcd12864ShowStr(0,0,"重量:"); //占三个字符
dat[0] = Weight_Shiwu/100000+'0'; //显示千位
dat[1] = Weight_Shiwu%100000/10000+'0';
dat[2] = Weight_Shiwu%10000/1000+'0';
dat[3] = Weight_Shiwu%1000/100+'0';
dat[5] = Weight_Shiwu%100/10 + '0'; //显示小数点后一位
dat[6] = Weight_Shiwu%10 + '0';
Lcd12864ShowStr(3,0,dat); //从第三个字符开始显示,按中文字符算两个
} //中文前面不能只有一个英文字符,否则会乱码
}
}
}
//扫描按键
void Scan_Key() //key = P2^3
{
if(KEY1 == 0)
{
Delay_ms(5);
if(KEY1 == 0)
{
while(KEY1 == 0);
Get_Maopi(); //去皮
}
}
}
//****************************************************
//称重:获取被测物体重量
//****************************************************
void Get_Weight()
{
Weight_Shiwu = 100*HX711_Read(); //放大获取小数
Weight_Shiwu = Weight_Shiwu - Weight_Maopi; //获取净重
if(Weight_Shiwu > 1)
{
Weight_Shiwu = (unsigned int)((float)Weight_Shiwu/GapValue); //计算实物的实际重量,重量转换函数,传感器型号不同此函数要适当修改(修GapValue大小)
if(Weight_Shiwu > 500000) //超重报警,5千克放大了100倍
{
Flag_ERROR = 1;
}
else
{
Flag_ERROR = 0;
}
}
else
{
Weight_Shiwu = 0;
// Flag_ERROR = 1; //负重报警
}
}
//****************************************************
//获取毛皮重量,秤盘重量
//****************************************************
void Get_Maopi()
{
/*u32 hx711_dat;
u16 i;
for(i=0;i<MEDIAN_LEN;i++)
{
hx711_dat=HX711_Read(); //HX711AD转换数据处理
if(medleng == 0) //缓存的第1个元素,直接放入,不需要排序
{
buffer[0] = hx711_dat; medleng = 1;
}
else //插入排序算法,按从小到大的顺序排列
{
for(i = 0; i < medleng; i ++)
{
if( buffer[i] > hx711_dat) // 轮询到的当前元素>AD值,则交换它们的值,xd为中间变量存放位置
{
xd = hx711_dat; hx711_dat = buffer[i]; buffer[i] = xd;
}
}
buffer[medleng] = hx711_dat; //把轮询出较大的数放入缓存的后面.
medleng++;
}
if(medleng >= MEDIAN_LEN) //ADC采样的数据个数达到中值滤波要求的数据个数
{
hx711_dat = buffer[MEDIAN]; //最终重量取中值滤波数组的中间值
medleng = 0;
}
}*///去掉上面这个可以加快速度,但精度有所降低,如果不显示小数,加不加无所谓
Weight_Maopi = 100*HX711_Read(); //放大获取小数
}
复制代码
作者:
方建昌
时间:
2019-8-8 17:39
这是用的51还是?
作者:
petertang
时间:
2019-8-16 20:39
学习中,希望一次调试通过。
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1