|

楼主 |
发表于 2010-3-12 23:54:19
|
显示全部楼层
//下面是整理过,简化过的程序!
// LCM16 2*16字符 第一行0x80 第二行0xc0
// 模式(km/h) 0 0 47:59:59
// 99.9kh 999.99km
// 24C02存储 0x00-0x03: 99 99 99 99 cm
// 0x2e,0x6b,0x6d,0x05,0x06,0x07,0x20,0x3d 0x30-0x39开始是数字0-9
// . , k , m , ,/h ,black, =
//------头--------------------------------------------------------
//申明
#include "REG2051.H"
#include "INTRINS.H"
#define uchar unsigned char
#define uint unsigned int
//轮周长1.98m及各位值 0.5ms取 1.98*(1/0.5)*1000*10
#define girth 39600
#define girth_h 1
#define girth_l 98
//单片机IO连接
#define LCM16_IO P1
sbit LCM16_RS = P3^0;
sbit LCM16_RW = P3^1;
sbit LCM16_EN = P3^7;
sbit AT24_SDA = P3^4;
sbit AT24_SCL = P3^5;
sbit KEY = P3^3;
sbit SIGN = P3^2;
//液晶驱动函数定义
void LCM_WR_CMD(uchar); //写操作命令
void LCM_WR_DAT(uchar); //写数据
void LCM_WR(uchar,uchar); //输出一个字符
void LCM_WR_STR(uchar,uchar*);//输出字符串
void LCM_CUSTOM_CHAR(uchar,uchar,uchar,uchar,uchar,uchar,uchar,uchar);//自定义字符
//存储IC驱动函数定义
uchar AT24_RD(uchar); //从24c02的地址address中读取一个字节数据
void AT24_WR(uchar,uchar); //向24c02的address地址中写入一字节数据info
//函数定义
void _init(void); //软硬件初始化
void _nus(uchar); //us延时
void _nms(uchar); //ms延时
void mile_show(void); //距离数据输出
void AT24_WRAMD(void);//24c02写入RAM数据
//变量定义
uchar d_var[4]={0,0,0,0};//距离的cm值0x00-0x03双数计算
uint timej; //时间周期个数
uint int_tp; //周期个数传递
bit flg_cal;//允许计算
uchar sj; //s指示计数
uchar svj; //save
uchar timei; //外中断次数
uchar t_var[3]={0,0,0};//时间变量
uchar times; //1s循环计数
bit flg_s; //s标志位
//---- 中断 -----------------------------------------------------
//500us周期定时函数
void T0_SEV(void) interrupt 1 using 1
{
TR0 = 0; ET0 = 0; TH0 = 0xff; TL0 = 0x5a; //计时初值
timej++; //超过3.5S无中断相应,即判断速度为0,则最低速度2.04km/h
if(timej == 7000){ int_tp = 7000; timej = 0; flg_cal = 1;}
ET0 = 1; TR0 = 1;
}
//外部中断函数
void Int0_SEV(void) interrupt 0 using 0
{
EX0 = 0;
int_tp = timej; timej = 0; flg_cal = 1;//读取计数周期数
EX0 = 1;
}
//100ms周期定时函数
void T1_SEV(void) interrupt 3 using 3
{
TR1 = 0; ET1 = 0; TH1 = 0x7d; TL1 = 0xcb; //计时初值
if(times>0) times--;//s计时 1s
else{
times=9; flg_s = 1;
t_var[2]++;
if(t_var[2]==60){
t_var[2]=0; t_var[1]++;
if(t_var[1]==60){
t_var[1]=0; t_var[0]++;
if(t_var[0]==48)t_var[0]=0;
}
}
}
if(sj>0) sj--;//s计数递减 800ms
if(svj>0) svj--;
ET1 = 1; TR1 = 1;
}
//------主体--------------------------------------------------------
//主函数
void main()
{
_init(); //初始化
while(1){
if(flg_cal){ //清零 输出十分位" 0.0"
if(int_tp == 7000){
LCM_WR(0xc0,0x20); LCM_WR(0xc1,0x30); LCM_WR(0xc3,0x30);
if(timei>0) timei = 5; //写入数据
}
else{//正常计算输出
timei++; LCM_WR(0x82,0x05); sj=4;//外中断信号
//速度
if(int_tp>143){
int_tp = girth/int_tp; int_tp = (int_tp*18)/5; //kmh=3.6*ms
LCM_WR(0xc3,int_tp%10+0x30); //输出十分位
int_tp = int_tp/10;
LCM_WR(0xc1,int_tp%10+0x30);//输出个位
if(int_tp<10) LCM_WR(0xc0,0x20); //输出十位0时清除
else LCM_WR(0xc0,int_tp/10+0x30); //输出十位
}//在99.9km/h范围内
//距离
d_var[3] += girth_l;
if(d_var[3]>99){ d_var[3]-=100; d_var[2]++; }
d_var[2] += girth_h;
if(d_var[2]>99){
d_var[2]-=100;
if(d_var[1]==99){
d_var[1]=0;
if(d_var[0]==99) d_var[0]=0;
else d_var[0]++;
}
else d_var[1]++;
}//步长1.98m
mile_show(); //输出距离
}
int_tp = 0; flg_cal = 0;//复位
}//输出计算的主要数据
if(timei==5){
timei=0;
LCM_WR(0x84,0x06); svj=7;//0x06
AT24_WRAMD(); //写入存储器
}//每6个外中断信号写入数据一次
if(flg_s){
flg_s = 0;
if(t_var[0]>9) LCM_WR(0x88,t_var[0]/10+0x30);
LCM_WR(0x89,t_var[0]%10+0x30);
LCM_WR(0x8b,t_var[1]/10+0x30); LCM_WR(0x8c,t_var[1]%10+0x30);
LCM_WR(0x8e,t_var[2]/10+0x30); LCM_WR(0x8f,t_var[2]%10+0x30);
}//时间
if(!KEY){
_nms(2); //去抖延时
if(!KEY){
uchar key_tp = 136;
EA = 0; timej = 0;
do{ key_tp--; _nms(3); }while(!KEY&&key_tp>0); //长短按计时循环
EA = 1;
if(key_tp==0){
d_var[0] = 0; d_var[1] = 0; d_var[2] = 0; d_var[3] = 0; //清零
_nus(20); mile_show(); //输出距离
}//长按
//短按长按都要写入数据
LCM_WR(0x84,0x06); svj = 7;//0x06
AT24_WRAMD(); //24c02写入RAM数据
//等待释放按键
while(!KEY){ while(!KEY); _nms(2); }
}
}//按键功能,长按清除历程信息,短按储存历程信息
if(sj==1){ sj=0; LCM_WR(0x82,0x20);}//外中断信号闪更新
if(svj==1){ svj=0; LCM_WR(0x84,0x20);}//写存储器闪更新
}//主循环
}
//初始化
void _init(void)
{
_nus(255); //等待外围设备完成加电
//初始化液晶
LCM_WR_CMD(0x01); //清屏幕0x01
LCM_WR_CMD(0x38); //设置数据线模式0x38 8位 两行 5X7
LCM_WR_CMD(0x0C); //设置显示状态0x0C 整体显示开 光标关 光标闪烁关
LCM_WR_CMD(0x06); //设置输入方式0x06 增量方式 不移位
LCM_WR_CMD(0x80); //设置光标初始位
//输出 "CC Speedometer"
LCM_WR_STR(0x80,"(^_^)Speedometer"); LCM_WR_STR(0xc0,">>>>>>>>>>>>>>>>");
//初始化液晶自定义字符库
LCM_CUSTOM_CHAR(0x68,0x00,0x1E,0x1E,0x1F,0x1F,0x0F,0x0F); //自定义字符'信' 在0x05
LCM_CUSTOM_CHAR(0x70,0x00,0x1F,0x0E,0x04,0x04,0x0E,0x1F); //自定义字符'存' 在0x06
LCM_CUSTOM_CHAR(0x78,0x04,0x14,0x14,0x16,0x15,0x15,0x15); //自定义字符'/h' 在0x07
//初始化24c02
AT24_SCL = 1; _nop_(); AT24_SDA = 1; _nop_(); _nms(4);
d_var[0] = AT24_RD(0x10); d_var[1] = AT24_RD(0x11);
d_var[2] = AT24_RD(0x12); d_var[3] = 0; //读24c02 初始化d_var[]
//输入口初始化
KEY = 1; SIGN = 1;
//串口初始化
EA = 0; TMOD = 0x11; //定时中断0允许 方式0 使能off
TH0 = 0xff; TL0 = 0x5a; ET0 = 1; TR0 = 1;//500us (65536-166) /256=255 %256=90
TH1 = 0x7d; TL1 = 0xcb; ET1 = 1; TR1 = 1;
PX0 = 1; IT0 = 1; EX0 = 0; //外中断0 跳变触 使能off
//变量初始化
timej = 0; int_tp = 0; flg_cal = 0;
sj = 0; svj = 0; timei = 0; times = 0; flg_s = 0;
_nms(200); _nms(200);
//界面初始化
LCM_WR_CMD(0x01); //清屏幕0x01
LCM_WR_STR(0x80,"["); LCM_WR_STR(0x86,"]"); LCM_WR_STR(0x89,"0:00:00");//[0 0 00:00:00]
LCM_WR_STR(0xc1,"0.0km"); LCM_WR_STR(0xca,"0.00km"); //[ 0.0km 0.00km]
LCM_WR(0xc6,0x07); //[ /h ]
mile_show(); _nms(56);
EX0 = 1; EA = 1; //开启各种中断 CPU中断使能
}
//24c02写入RAM数据
void AT24_WRAMD(void)
{
uchar mem_wram;
for(mem_wram=0;mem_wram<3;mem_wram++)
AT24_WR(0x10+mem_wram,d_var[mem_wram]);
}
//距离数据显示
void mile_show(void)
{
if(d_var[0]>9){ //高位3有数据,并且有两位
LCM_WR(0xc8,d_var[0]/10+0x30); LCM_WR(0xc9,d_var[0]%10+0x30);
}
else{//高位3只有低位有数据,或没有数据
LCM_WR(0xc8,0x20);//高位3高位没有数据
if(d_var[0]>0) LCM_WR(0xc9,d_var[0]+0x30);//高位3低位有数据
else LCM_WR(0xc9,0x20);//高位3没有数据
}
LCM_WR(0xca,d_var[1]/10+0x30); LCM_WR(0xcc,d_var[1]%10+0x30);
LCM_WR(0xcd,d_var[2]/10+0x30);
}
//---- 硬件应用层驱动 ------------------------------------------------
void _nus(uchar us)
{
for(;us>0;us--)
;
}//短延时
void _nms(uchar ms)
{
for(;ms>0;ms--)
_nus(255);
}//长延时4.6ms
/*----液晶驱动函数定义------------------------------------------------------------
void LCM_WR_CMD(uchar); //写操作命令
void LCM_WR_DAT(uchar); //写数据
void LCM_WR(uchar,uchar); //输出一个字符
void LCM_RD_BUSY(void); //读忙信号
void LCM_WR_STR(uchar,uchar*);//输出字符串
void LCM_CUSTOM_CHAR(uchar,uchar,uchar,uchar,uchar,uchar,uchar,uchar);//自定义字符
--------------------------------------------------------------------------------*/
void LCM_RD_BUSY(void)
{
uchar lcm_rdby = 0x00;
LCM16_RS = 0; //RS 0
LCM16_RW = 1; //RW 1
LCM16_EN = 1; //EN 1 读忙信号
LCM16_IO = 0xff;
do{ lcm_rdby = LCM16_IO; }while(lcm_rdby&0x80); //MSB=0x80
_nop_();
}//读忙信号
void LCM_WR_CMD(uchar lcm_cmd)
{
LCM_RD_BUSY();
LCM16_RS = 0; //RS 0
LCM16_RW = 0; //RW 0
LCM16_EN = 1; //跳跃,写入数据
LCM16_IO = lcm_cmd; _nop_();
LCM16_EN = 0; _nop_();
}//写操作命令
void LCM_WR_DAT(uchar lcm_wrdat)
{
LCM_RD_BUSY();
LCM16_RS = 1; //RS 1
LCM16_RW = 0; //RW 0
LCM16_EN = 1; //跳跃,写入数据
LCM16_IO = lcm_wrdat; _nop_();
LCM16_EN = 0; _nop_();
}//写数据
void LCM_WR(uchar lcm_xy,uchar lcm_dat)
{
EA = 0;
//设置光标位置 第一行0x80,第二行0xc0
LCM_WR_CMD(lcm_xy); LCM_WR_DAT(lcm_dat);
EA = 1;
}//输出一个字符
void LCM_WR_STR(uchar lcm_xys,uchar *str)
{
EA = 0;
LCM_WR_CMD(lcm_xys);
while(*str){ LCM_WR_DAT(*str); str++;}
EA = 1;
}//输出字符串
void LCM_CUSTOM_CHAR(uchar gram_num,uchar d0,uchar d1,uchar d2,uchar d3,uchar d4,uchar d5,uchar d6)
{
LCM_WR_CMD(gram_num);
LCM_WR_DAT(d0); LCM_WR_DAT(d1); LCM_WR_DAT(d2); LCM_WR_DAT(d3);
LCM_WR_DAT(d4); LCM_WR_DAT(d5); LCM_WR_DAT(d6); LCM_WR_DAT(0x00);
}//自定义字符
/*---------------- 24C02驱动 --------------------------------------
void AT24_START(void); //开启
void AT24_STOP(void); //停止
void AT24_CK(void); //时钟
void AT24_WR_byte(uchar); //写入单字节
uchar AT24_RD_byte(void); //读入单字节
uchar AT24_RD(uchar); //从24c02的地址中读取一个字节数据
void AT24_WR(uchar,uchar); //向24c02的地址中写入一字节数据
-----------------------------------------------------------------*/
void AT24_START()
{
AT24_SDA = 1; _nop_(); AT24_SCL = 1; _nop_();
AT24_SDA = 0; _nop_(); AT24_SCL = 0; _nop_();
}//24c02启动
void AT24_STOP()
{
AT24_SDA = 0; _nop_(); AT24_SCL = 1; _nop_(); AT24_SDA = 1; _nop_();
}//24c02停止
void AT24_WR_byte(uchar mem_wrbt)
{
uchar mem_wrtp,mem_wrbtp;
mem_wrbtp = mem_wrbt;
for (mem_wrtp=8;mem_wrtp>0;mem_wrtp--){
mem_wrbtp = mem_wrbtp<<1;
AT24_SCL = 0; _nop_();
AT24_SDA = CY; _nop_(); //(bit)(mem_wrbtp&0x80)
AT24_SCL = 1; _nop_();
}
AT24_SCL = 0; _nop_(); AT24_SDA = 1; _nop_();
}//24c02写入单字节
uchar AT24_RD_byte()
{
uchar mem_rdtp,mem_rdbit,mem_rdbt=0;
AT24_SCL = 0; _nop_(); AT24_SDA = 1;
for(mem_rdtp=8;mem_rdtp>0;mem_rdtp--){
_nop_(); AT24_SCL = 1; _nop_();
if (AT24_SDA) mem_rdbit = 1;
else mem_rdbit = 0;
mem_rdbt=(mem_rdbt<<1)|mem_rdbit;
AT24_SCL = 0;
}
_nop_();
return mem_rdbt;
}//24c02读入单字节
void AT24_CK()
{
uchar mem_ck = 255;
AT24_SCL = 1; _nop_();
while((AT24_SDA)&&(mem_ck>0)) mem_ck--;
AT24_SCL = 0; _nop_();
}//24c02时钟等待
uchar AT24_RD(uchar mem_rdaddr)
{
uchar mem_rd; //在刚启动时使用,故EA不需复位
AT24_START();
AT24_WR_byte(0xa0); AT24_CK();
AT24_WR_byte(mem_rdaddr); AT24_CK();
AT24_START();
AT24_WR_byte(0xa1); AT24_CK();
mem_rd = AT24_RD_byte();
AT24_STOP(); _nms(4);
return mem_rd;
}//24c02读入
void AT24_WR(uchar mem_wraddr,uchar mem_wrinfo)
{
EA = 0; AT24_START();
AT24_WR_byte(0xa0); AT24_CK();
AT24_WR_byte(mem_wraddr); AT24_CK();
AT24_WR_byte(mem_wrinfo); AT24_CK();
AT24_STOP(); EA=1;
_nms(3);
}//24c02写入
//----END--------------------------------------------------------------- |
|