//LCD 命令/数据端
//LCD 读/写端
//LCD 使能端
//MCP3001 与 AT89S52 的管脚接线定义
//字符串显示函数
//显示子函数
//算术平均滤波程序
//Busy 标志
//显示
//显示表头
#include
#include
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
sbit RS=P2^0;
sbit RW=P2^1;
sbit LCDE=P2^2;
sbit MCP_CS=P2^3;
sbit MCP_DO=P2^4;
sbit MCP_CLK=P2^5;
uint measure;
uchar flag;
uchar code dis[]={"Measure Start"};
uchar code dis1[] = {"Distance:"};
uchar code dis2[] = {"0123456789.cm"};
uchar code dis3[]={"Out Measure!"};
uchar dis_buf[6];
void L_delay(void);
void delay_ms(uint n);
uint read_MCP(void);
void init_1602(void);
void busy(void);
void dat_wrt(uchar dat);
void cmd_wrt(uchar cmd);
uint distance(void);
void lcd_start(uchar start);
void LCD_Clear(void);
uchar dat_adj(uint dat1);
void print(uchar *str);
void disp(uint dat);
uint average(void);
/****************************主函数*******************************/
main()
{
//延时函数
//读 MCP3001
//1602 初始化函数
//LCD 忙标志判断函数
//显示代码
//显示
//显示缓冲区
//短延时
//写数据子函数
//写命令子函数
//距离计算函数
//设定显示位置函数
//LCD 清屏函数
//显示数据调整函数
init_1602();
print(dis);
delay_ms(1000);
while(1)
{
measure=distance();
disp(measure);
delay_ms(100);
}
//显示测量开始
//显示高度
}
/**************************延时函数**************************/
void delay_ms(uint n)
{
uint j;
while(n--)
{
for(j=0;j<125;j++);
}
}
/***************************短延时****************************/
void L_delay(void)
{
uchar i;
for(i=0;i<5;i++)_nop_();
}
/************************读 MCP3001 函数*************************/
uint read_MCP(void)
{
uchar i;
uint temp=0;
MCP_CS=1;
L_delay();
MCP_CS=0;
for(i=0;i<13;i++)
{
MCP_CLK=0;
L_delay();
MCP_CLK=1;
temp<<=1;
if(MCP_DO==1)temp|=0x01;
}
MCP_CS=1;
temp&=0x03ff;
return(temp);
//CS 置低,开始采样数据
//读转换的 10 位数据
//获取有效转换值
}
/************************LCD 忙标志判断函数*******************/
void busy(void)
{
flag=0x80;
while (flag&0x80)
{
P0=0xff;
RS=0;
//赋初值 高位为 1 禁止
//读写操作使能位禁止时等待 继续检测
//指向地址计数器
RW=1;
LCDE=1;
flag=P0;
LCDE=0;
}
//读
//信号下降沿有效
//读状态位 高位为状态
}
/************************写数据子函数************************/
void dat_wrt(uchar dat)
{
busy();
LCDE=0;
RS=1;
RW=0;
P0=dat;
LCDE=1;
LCDE=0;
//检测 读写操作使能吗
//指向数据寄存器
//写
//写数据
//高电平有效
}
/*************************写命令子函数************************/
void cmd_wrt(uchar cmd)
{
LCDE=0;
busy();
P0=cmd;
RS=0;
RW=0;
LCDE=1;
LCDE=0;
//检测 读写操作使能吗
//命令
//指向命令计数器
//写
//高电平有效
}
/***********************距离计算函数***************************/
uint distance(void)
{
uint temp1;
temp1=average();
if((temp1>160)&(temp1<960))
{
//在正常测量范围?
temp1=13569/(temp1+7)-4;
//转换测量数据
}
else
{
temp1=0x00ff;
}
return(temp1);
//超出测量范围,返回错误标志
}
/************************算术平均滤波程序**********************/
uint average(void)
{
uchar i;
uint av_dat;
ulong ave=0;
for(i=0;i<10;i++)
{
ave+=read_MCP();
L_delay();
}
av_dat=(uint)(ave/10);
return(av_dat);
//连续读取 10 个数据值
//读转换数据
//求平均值
}
/*************************1602 初始化函数************************/
void init_1602(void)
{
cmd_wrt(0x01);
cmd_wrt(0x0c);
cmd_wrt(0x06);
示不发生移位
cmd_wrt(0x38);
//清屏
//开显示,不显示光标,不闪烁
//完成一个字符码传送后,光标左移,显
//16×2 显示,5×7 点阵,8 位数据接口
}
/************************设定显示位置函数************************/
void lcd_start(uchar start)
{
cmd_wrt(start|0x80);
}
/************************LCD 清屏函数****************************/
void LCD_Clear(void)
{
cmd_wrt(0x01);
delay_ms(1);
//写入清屏指令
}
/************************显示数据调整函数************************/
uchar dat_adj(uint dat1)
{
uchar i;
dis_buf[0]=(uchar)(dat1/10);
dis_buf[1]=(uchar)(dat1%10);
dis_buf[2]=11;
dis_buf[3]=12;
if(dis_buf[0]==0)i=1;
return(i);
}
//十位
//个位
/**************************字符串显示函数**************************/
void print(uchar *str)
{
while(*str!='\0')
{
dat_wrt(*str);
str++;
}
//直到字符串结束
//指向下一个字符
}
/***************************显示子函数****************************/
void disp(uint dat)
{
uchar temp,j;
if(dat!=0x00ff)
{
temp=dat_adj(dat);
LCD_Clear();
lcd_start(0x00);
print(dis1);
lcd_start(0x45+temp);
for(j=temp;j<4;j++)
dat_wrt(dis2[dis_buf[j]]);
//显示文字
//确定显示起始位置
//写显示数据
}
else
{
}
}
LCD_Clear();
lcd_start(0x42+temp);
print(dis3);
//确定显示起始位置