发个刚做的自行车测速、里程计!

2020-01-16 18:33发布

我比较喜欢骑自行车出去走走,以前也做了个自行车测速(里程)计,用4位数码管输出数据的,它的优点是驱动简单,电压范围广,可用3.7V的锂电池直接供电,整个电路结构简单,耗能低,但它的缺点也是显而易见的,数码管在阳光下,无法看清楚,而且只有一组4位数据,不能同时查看速度及里程,不方便。由于购得更小的液晶模块,所以近期用液晶做输出显示器件,做了一个新的里程(速度)计。在阳光下清晰,晚上可用背光,2行共16个字符,并带存储器。有系统运行时间显示,外中断信号与写数据信号、电池低指示。
  整体尺寸为65X35X12。加上电池(880mah),厚度要增加3mm,电池接上码表正在测试,已运行14个小时,理论可运行40多小时。

(原文件名:http_imgload.jpg)
// 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---------------------------------------------------------------
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
99条回答
guhenggao
1楼-- · 2020-01-19 17:14
mark
chchg
2楼-- · 2020-01-19 22:33
回复【24楼】whitecloud588
哦,原来只有我自己能看。
问一下,楼主骑车最快速度多少?我记得当时接近25km/h。可惜我的屏后来烧坏了
-----------------------------------------------------------------------

我不是运动型的自行车阿!普通的那种,我记得最高速度好像是21.4km/h,再快怕那破车要散架了!
chchg
3楼-- · 2020-01-19 23:20
//下面是整理过,简化过的程序!
// 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---------------------------------------------------------------
chchg
4楼-- · 2020-01-20 03:25
 精彩回答 2  元偷偷看……
efen
5楼-- · 2020-01-20 06:27
利害!
ccstc
6楼-- · 2020-01-20 07:22
回复【18楼】chchg
以前没注意霍尔元件的功耗,觉得好就用了,刚单独测了下,在5V时,电流3.1ma,有磁吸的时候3.25ma左右,看来霍尔还是有些耗电的,我刚才写程序还觉得TINY13的电流在500uA太大了!!!
-----------------------------------------------------------------------
线性霍尔很费电的
你应该选用开关型霍尔就很省电了
比如A3212E稳态电流就只有10个uA不到

一周热门 更多>