论坛风格切换切换到宽版
  • 4947阅读
  • 7回复

想做一个车用的里程速度表,请教各位 [复制链接]

上一主题 下一主题
离线BG6IAN
 
发帖
2711
只看楼主 倒序阅读 0楼 发表于: 2010-07-20
破车上的速度里程表坏了,想做个电子的,可是不懂单片机,在网上找了个电路和程序,有以下问题请教:
1、速度显示如何改为三位数、里程改为4位数的?
2、液晶屏是什么型号的,用传呼机上的显示屏可以替换吗,
3、其他问题随后再请教
源程序 :
// 1602 2*16字符 第一行0x80 第二行0xc0
// 模式(km/h) 12.5kmh | 999.99km
// 24c02存储 0x00-0x03: 99 99 99 99 cm
// 0x2e,0x6b,0x6d,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 lcm0802b_io p1
sbit lcm0802b_rs = p3^7;
sbit lcm0802b_rw = p3^5;
sbit lcm0802b_en = p3^4;
sbit key       = p3^3;
sbit sign     = p3^2;
sbit at24c02_sda = p3^1;
sbit at24c02_scl = p3^0;
//液晶驱动函数定义
void lcm_rd_busy(void);   //读忙信号
void lcm_wr_cmd(uchar);   //写操作命令
void lcm_wr_dat(uchar);   //写数据
void lcm_wr(uchar,uchar); //输出一个字符
//存储ic驱动函数定义
void at24c02_start(void);   //开启
void at24c02_stop(void);     //停止
void at24c02_ck(void);     //时钟
void at24c02_wr_byte(uchar); //写入单字节
uchar at24c02_rd_byte(void);   //读入单字节
uchar at24c02_rd(uchar);     //从24c02的地址address中读取一个字节数据
void at24c02_wr(uchar,uchar); //向24c02的address地址中写入一字节数据info
//函数定义
void _init(void);   //软硬件初始化
void at24c02_wramd(void); //24c02写入ram数据
void _nus(uchar);   //us延时
void _nms(uchar);   //ms延时
void dis_dis(void); //距离数据输出
//变量定义
uchar d_var[4]={0,0,0,0}; //距离的cm值0x00-0x03双数计算
uint timej;   //时间周期个数
uint int_tp;   //周期个数传递
bit   flg_cal; //允许计算
bit   sf;     //s指示标志
uint sj;     //s指示计数
bit   sen;     //有更新数据

//---- 中断 -----------------------------------------------------
//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 = timej; timej = 0;
flg_cal = 1;
}
if(sj>0){ sj--; }//s计数递减
et0 = 1; tr0 = 1;
}
//外部中断函数
void int0_sev(void) interrupt 0 using 0
{
ex0 = 0;
int_tp = timej; timej = 0;
flg_cal = 1;//读取计数周期数
ex0 = 1;
}

//------主体--------------------------------------------------------
//主函数  
void main()
{
_init(); //初始化
while(1){
if(!key){
_nms(2); //去抖延时
if(!key){
uchar key_tp = 200;
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); dis_dis(); //输出距离
}//长按
//短按长按都要写入数据
sj = 3000; sf = 1;
lcm_wr(0x80,0x06); //0x06
at24c02_wramd(); //24c02写入ram数据
//等待释放按键
while(!key){ while(!key); _nms(2); }
}
}//按键功能,长按清除历程信息,短按切换ms与kmh
if(flg_cal){ //清零 输出十分位" 0.0"
if(int_tp == 7000){
lcm_wr(0x81,0x20); lcm_wr(0x82,0x30); lcm_wr(0x84,0x30);
}
else{//正常计算输出
sen = 1;
//速度
if(int_tp>143){
int_tp = girth/int_tp;
int_tp = (int_tp*18)/5; // kmh=3.6*ms
lcm_wr(0x84,(int_tp%10)+0x30);     //输出十分位
int_tp = int_tp/10;
lcm_wr(0x82,(int_tp%10)+0x30);     //输出个位
if(int_tp<10) lcm_wr(0x81,0x20);   //输出十位0时清除
else lcm_wr(0x81,(int_tp/10)+0x30); //输出十位
}//在99.9km/h范围内
//距离 步长1.98m
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]++;
}
dis_dis(); //输出距离
}
int_tp = 0; flg_cal = 0;//复位
}//输出计算的主要数据
if(sj == 0){
sj = 3000;
if(sen){   //有更新数据才写入
sen = 0;
lcm_wr(0x80,0x06); //0x06
sf = 1;
at24c02_wramd(); //写入存储器
}
}
if(sf && sj<2000){
sf = 0; lcm_wr(0x80,0x20);
} //写存储器闪更新

}//主循环
}

void _init(void)
{
ea = 0; _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); //设置光标初始位
//lcm_wr(0x80,0x3f);//屏幕初始化输出"?"
//输出 bike mile
lcm_wr(0x80,0x3d); lcm_wr(0x81,0x62); lcm_wr(0x82,0x69); lcm_wr(0x83,0x6b);
lcm_wr(0x84,0x65); lcm_wr(0x85,0x3d); lcm_wr(0x86,0x3d); lcm_wr(0x87,0x3d);//=bike===
lcm_wr(0xc0,0x3d) ;lcm_wr(0xc1,0x3d); lcm_wr(0xc2,0x3d); lcm_wr(0xc3,0x6d);
lcm_wr(0xc4,0x69); lcm_wr(0xc5,0x6c); lcm_wr(0xc6,0x65); lcm_wr(0xc7,0x3d);//===mile=
//初始化液晶自定义字符库
lcm_wr_cmd(0x70); //自定义字符'┗' 在0x06
lcm_wr_dat(0x00); lcm_wr_dat(0x00); lcm_wr_dat(0x00); lcm_wr_dat(0x10);
lcm_wr_dat(0x18); lcm_wr_dat(0x1c); lcm_wr_dat(0x1e); lcm_wr_dat(0x00);
lcm_wr_cmd(0x78); //自定义字符'/h' 在0x07
lcm_wr_dat(0x04); lcm_wr_dat(0x14); lcm_wr_dat(0x14); lcm_wr_dat(0x16);
lcm_wr_dat(0x15); lcm_wr_dat(0x15); lcm_wr_dat(0x15); lcm_wr_dat(0x00);
//初始化24c02
at24c02_scl = 1; _nop_(); at24c02_sda = 1; _nop_(); _nms(4);
//读24c02到ram 初始化 d_var[]
d_var[0] = at24c02_rd(0x00); d_var[1] = at24c02_rd(0x01);
d_var[2] = at24c02_rd(0x02); d_var[3] = at24c02_rd(0x03);
if(d_var[0]>99 || d_var[1]>99 || d_var[2]>99 || d_var[3]>99){
d_var[0] = 0; d_var[1] = 0; d_var[2] = 0; d_var[3] = 0;//清零
at24c02_wramd();
}//错误数据判断 读取24c02中的距离数据,如果有数据>99,则出错,复位0
key = 1; sign = 1;
//串口初始化
tmod = 0x01; //定时中断0允许 方式0 使能off
th0 = 0xff; tl0 = 0x5a; //500us (65536-166) /256=255 %256=90
et0 = 1; tr0 = 0;
px0 = 1; it0 = 1; ex0 = 0; //外中断0 跳变触 使能off
//变量初始化
timej = 0; int_tp = 0; flg_cal = 0;
sf = 0; sj = 3000; sen = 0;
_nms(255);
//界面初始化
lcm_wr_cmd(0x01); //清屏幕0x01
lcm_wr(0x82,0x30); lcm_wr(0x83,0x2e); lcm_wr(0x84,0x30); //输出" 0.0"
lcm_wr(0x85,0x6b); lcm_wr(0x86,0x6d); lcm_wr(0x87,0x07); //输出" kmh"
lcm_wr(0xc3,0x2e); lcm_wr(0xc6,0x6b); lcm_wr(0xc7,0x6d); //输出" . km"
dis_dis(); _nms(56);
ex0 = 1; tr0 = 1; ea = 1; //开启各种中断 cpu中断使能 tr1 = 1;
}

//---- 硬件应用层驱动 ------------------------------------------------
//距离数据显示
void dis_dis(void)
{
//高位3有数据,并且有两位
if(d_var[0]>9){
lcm_wr(0xc0,(d_var[0]/10)+0x30); lcm_wr(0xc1,(d_var[0]%10)+0x30);
}
else{//高位3只有低位有数据,或没有数据
lcm_wr(0xc0,0x20);//高位3高位没有数据
if(d_var[0]>0) lcm_wr(0xc1,d_var[0]+0x30);//高位3低位有数据
else lcm_wr(0xc1,0x20);//高位3没有数据
}
lcm_wr(0xc2,(d_var[1]/10)+0x30);
lcm_wr(0xc4,(d_var[1]%10)+0x30);
lcm_wr(0xc5,(d_var[2]/10)+0x30);
}

//24c02写入ram数据
void at24c02_wramd(void)
{
uchar mem_wram;
for(mem_wram=0;mem_wram<4;mem_wram++)
at24c02_wr(mem_wram,d_var[mem_wram]);
}
//短延时
void _nus(uchar us)
{
for(;us>0;us--)
;
}
//长延时4.6ms
void _nms(uchar ms)
{
for(;ms>0;ms--)
_nus(255);
}

/*----液晶驱动函数定义------------------------------------------------------------
void lcm_wr_cmd(uchar);   //写操作命令
void lcm_wr_dat(uchar);   //写数据
void lcm_wr(uchar,uchar); //输出一个字符
void lcm_rd_busy(void);   //读忙信号
--------------------------------------------------------------------------------*/
//读忙信号
void lcm_rd_busy(void)
{
uchar lcm_rdby = 0x00;
lcm0802b_rs = 0;   //rs 0
lcm0802b_rw = 1;   //rw 1
lcm0802b_en = 1;   //en 1 读忙信号
lcm0802b_io = 0xff;
do{ lcm_rdby = lcm0802b_io; }while(lcm_rdby&0x80); //msb=0x80
_nop_();
}
//写操作命令
void lcm_wr_cmd(uchar lcm_cmd)
{
lcm_rd_busy();
lcm0802b_rs = 0;   //rs 0
lcm0802b_rw = 0;   //rw 0
lcm0802b_en = 1;   //跳跃,写入数据
lcm0802b_io = lcm_cmd; _nop_();
lcm0802b_en = 0; _nop_();
}
//写数据
void lcm_wr_dat(uchar lcm_wrdat)
{
lcm_rd_busy();
lcm0802b_rs = 1;   //rs 1
lcm0802b_rw = 0;   //rw 0
lcm0802b_en = 1;   //跳跃,写入数据
lcm0802b_io = lcm_wrdat; _nop_();
lcm0802b_en = 0; _nop_();
}
//输出一个字符
void lcm_wr(uchar lcm_xy,uchar lcm_dat)
{
ea = 0;
//设置光标位置
lcm_wr_cmd(lcm_xy); //第一行0x80,第二行0xc0
lcm_wr_dat(lcm_dat);
ea = 1;
}

/*---------------- 24c02驱动 --------------------------------------
void at24c02_start(void);   //开启
void at24c02_stop(void);     //停止
void at24c02_ck(void);     //时钟
void at24c02_wr_byte(uchar); //写入单字节
uchar at24c02_rd_byte(void);   //读入单字节
uchar at24c02_rd(uchar);     //从24c02的地址中读取一个字节数据
void at24c02_wr(uchar,uchar); //向24c02的地址中写入一字节数据
-----------------------------------------------------------------*/
//24c02启动
void at24c02_start()
{
at24c02_sda = 1; _nop_(); at24c02_scl = 1; _nop_();
at24c02_sda = 0; _nop_(); at24c02_scl = 0; _nop_();
}
//24c02停止
void at24c02_stop()
{
at24c02_sda = 0; _nop_(); at24c02_scl = 1; _nop_(); at24c02_sda = 1; _nop_();
}
//24c02写入单字节
void at24c02_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;
at24c02_scl = 0; _nop_();
at24c02_sda = cy; _nop_(); //(bit)(mem_wrbtp&0x80)
at24c02_scl = 1; _nop_();
}
at24c02_scl = 0; _nop_(); at24c02_sda = 1; _nop_();
}
//24c02读入单字节
uchar at24c02_rd_byte()
{
uchar mem_rdtp,mem_rdbit,mem_rdbt=0;
at24c02_scl = 0; _nop_(); at24c02_sda = 1;
for(mem_rdtp=8;mem_rdtp>0;mem_rdtp--){
_nop_(); at24c02_scl = 1; _nop_();
if (at24c02_sda) mem_rdbit = 1;
else mem_rdbit = 0;
mem_rdbt=(mem_rdbt<<1)|mem_rdbit;
at24c02_scl = 0;
}
_nop_();
return mem_rdbt;
}
//24c02时钟等待
void at24c02_ck()
{
uchar mem_ck = 255;
at24c02_scl = 1; _nop_();
while((at24c02_sda)&&(mem_ck>0)) mem_ck--;
at24c02_scl = 0; _nop_();
}
//24c02读入
uchar at24c02_rd(uchar mem_rdaddr)
{
uchar mem_rd; //在刚启动时使用,故ea不需复位
at24c02_start();
at24c02_wr_byte(0xa0); at24c02_ck();
at24c02_wr_byte(mem_rdaddr); at24c02_ck();
at24c02_start();
at24c02_wr_byte(0xa1); at24c02_ck();
mem_rd = at24c02_rd_byte();
at24c02_stop(); _nms(4);
return mem_rd;
}
//24c02写入
void at24c02_wr(uchar mem_wraddr,uchar mem_wrinfo)
{
ea = 0; at24c02_start();
at24c02_wr_byte(0xa0); at24c02_ck();
at24c02_wr_byte(mem_wraddr); at24c02_ck();
at24c02_wr_byte(mem_wrinfo); at24c02_ck();
at24c02_stop(); ea=1;
_nms(3);
}
//----end---------------------------------------------------------------
离线zyf_90302
发帖
336
只看该作者 1楼 发表于: 2010-07-20
这个是用在自行车上的
离线BG6IAN
发帖
2711
只看该作者 2楼 发表于: 2010-07-21
[quote=zyf_90302]这个是用在自行车上的[/quote]
通过改程序可以吗
离线zyf_90302
发帖
336
只看该作者 3楼 发表于: 2010-07-22
不懂汽车
离线BG4WCE
发帖
1079
只看该作者 4楼 发表于: 2010-07-22
汽车上的东西建议不要diy,可能会因为剩这点儿小钱闯大祸。
离线BG4EBC
发帖
17902
只看该作者 5楼 发表于: 2010-07-22
年检能够让你过关?那时不可能的。还是划2000元钱左右,更换一个新的吧。

我以前sail出过仪表盘故障---很简单的,就是齿轮时不时打滑,我本来没有发现,只是在不经意间听到“个冷”一声;我以为是什么大问题,赶紧进4s店抢修;原来是仪表盘齿轮打滑了。

更换,2000多吧。
离线QIE
发帖
11291
只看该作者 6楼 发表于: 2010-07-25
要看是什么车,便宜的也就2-300元吧。
离线bg8eqb
发帖
80
只看该作者 7楼 发表于: 2010-07-28
程序里面有注明是1602 的液晶屏,实物图上面看,也应该是1602 液晶屏,不贵才10多20 元钱一只!