最近毕业设计中接了别人几个项目,忙完一阵是时候做一些总结。

项目名:基于单片机的自行车码表设计

功能需求: 1可以测量当前的温度和湿度并显示出来。

2时间显示。

3实时速度和行驰里程显示。

4设定里程提醒。

根据功能需求决定硬件:单片机使用STC125A60S2具有足够的资源来进行开发(使用51系列的单片也可行,并且价格更低),显示使用LCD1602,速度使用磁力传感器,温度和湿度使用DHT11传感器。时间计数应该使用外部的时钟芯片(由于没有芯片只能使用单片内部的定时器实现^^误差较大)。提醒声音使用了无源蜂鸣器(PWM波控制).

整体硬件设计图

IO脚定义

#ifndef  _CURRENCY_H_
#define  _CURRENCY_H_
#include "stc12c5a60s2.h    "
//currency.h
typedef unsigned char unchar;
typedef unsigned int  unint;sbit Data=P3^5;
sbit rs=P2^7;
sbit rw=P2^6;
sbit e =P2^5;
sbit buzzer = P3^4;//蜂鸣器     #endif

主函数部分

/*******************************************************************************
*  描述:                                                                       *
*         1602字符型LCD显示演示程序                                            *
*         在第一行显示  里程 时间                                                *
*         在第二行显示  速度 温度                                         *
*                                                                              *
********************************************************************************/#include <stc12c5a60s2.h>
#include "lcd1602.h"
#include "DHT11.h"
#include "delay.h"
#include "currency.h"unchar  test[10];
unsigned long time_ms;
unsigned long last_time;
unsigned long distance_cm;        //厘米
unsigned int  speed;           //百米/时
unsigned int  tempr;              //0.1度
unsigned int  n ;
unsigned char tm ;
unsigned int  distance;
bit           menu=0;
bit           clear_flag;
unsigned long time_menu;void Timer0Init(void)        //10毫秒@12.000MHz
{AUXR &= 0x7F;          //定时器时钟12T模式TMOD &= 0xF0;          //设置定时器模式TMOD |= 0x01;          //设置定时器模式TL0 = 0xF0;           //设置定时初值TH0 = 0xD8;            //设置定时初值TF0 = 0;               //清除TF0标志TR0 = 1;ET0 = 1;              //定时器0开始计时EA  = 1;
}
//--------------------------------------------------------
//算法实现
//--------------------------------------------------------
void show()
{unsigned char c;unsigned char h,m,s;unsigned int time;lcd_pos(0);distance = distance_cm / 10000;c = (distance / 1000) % 10 + '0';  //百位write_data(c);             //写入数据c = (distance / 100) % 10 + '0';   //十位
    write_data(c);c = (distance / 10) % 10 + '0';     //个位
    write_data(c);write_data('.');c = distance  % 10 + '0';          //小数一位
    write_data(c);//进行位提取write_data('k');write_data ('m');time = time_ms/1000;h = time / 3600;m = (time % 3600) / 60;s = time % 60;lcd_pos(9);c = h % 10 + '0';write_data(c);write_data(':');c = (m / 10)  + '0';write_data(c);c = (m % 10)  + '0';write_data(c);write_data(':');c = (s / 10)  + '0';write_data(c);c = (s % 10)  + '0';write_data(c);//时间提取lcd_pos(0x40);           //定位第二行c = (speed / 100) % 10 + '0';      //取百位
    write_data(c);                     c = (speed / 10) % 10 + '0';       //取十位
    write_data(c);write_data('.');c = speed  % 10 + '0';           //取个位
    write_data(c);write_data('k');write_data('m');write_data('/');write_data('h');//实时提取

} //开始
void main()
{int i;init_1602();          //lcd1602初始化delay_ms(1500);      //DHT11上电后要等待1.5S以越过不稳定状态在此期间不能发送任何指令
      Timer0Init();IT0=1;               //外部中断0下降沿触发EX0=1;IT1=1;                  //外部中断1下降沿触发EX1=1;               //外部中断开启动        distance_cm = 0;time_ms = 0;last_time = 0;tempr = 324;while(1){if((time_ms - last_time) > 5000)speed = 0;    P1 = 0xff;if((P1 & 0x02) == 0){distance_cm = 0;time_ms = 0;}if(menu == 0)              //菜单0显示
                 {if(clear_flag==1){      write_com(0x01);clear_flag = 0;}show();if(distance ==15)              //单位是百米
                {Buzzer_Alert();         }}else    if(menu == 1){if(clear_flag==0){ wrire_com(0x01);clear_flag = 1;}ET0 = 0;DHT11_receive();}}}void T0_Interrupt(void)    interrupt 1      //3定时器1的中断号  1定时器0的中断号 0外部中断1 2外部中断2  4串口中断
{TL0 = 0xF0;                    //设置定时初值TH0 = 0xD8;                    //设置定时初?time_ms += 10;
//     if(menu)
//     {
//      time_menu+= 10;
//test:
//      if(time_menu==10000)
//      {
//      menu=0;
//      time_menu=0;
//      }
//     }
     }
//比较重要------------------------------------
void  counter(void)         interrupt 0
{unsigned int intervel = 0;    //
   static unsigned char cnt = 0;EX0=0;distance_cm+=218;                 //一圈218厘米cnt++; if(last_time == 0){last_time = time_ms;cnt = 0;}else if(cnt >= 5){intervel = time_ms -  last_time;last_time = time_ms;speed = 360 * 5 * 218 / intervel;   //实时速度统计if(speed > 350)else cnt = 0;}EX0=1;
}void  key_menu(void)         interrupt 2
{menu=~menu;ET0 = 1;
}

 LCD1602模块函数

#include "lcd1602.h"
#include "currency.h"
#include "delay.h"
#include "intrins.h"/***********************lcd1602写命令函数************************/
void write_com(unchar com)
{e=0;rs=0;rw=0;P0=com;delay_unint(3);e=1;delay_unint(25);e=0;
}/***********************lcd1602写数据函数************************/
void write_data(unchar dat)
{e=0;rs=1;rw=0;P0=dat;delay_unint(36);e=1;delay_unint(300);e=0;
}
/***********************lcd1602写数据函数************************/
void write_data_1(unchar dat)
{e=0;rs=1;rw=0;P0=dat+48;delay_unint(432);e=1;delay_unint(3600);e=0;
}/*********************光标控制***********************/
void lcd1602_guanbiao(unchar open_off,unchar add)
{if(open_off == 1)   //开光标
    {write_com(0x80+add);              //将光标移动到秒个位write_com(0x0f);                  //显示光标并且闪烁
    }else {write_com(0x0c);           //关光标
    }
}/***********************lcd1602上显示两位十进制数************************/
void write_sfm2(unchar hang,unchar add,unchar date)
{unchar shi,ge;if(hang==1)   write_com(0x80+add);elsewrite_com(0x80+0x40+add);shi=date%100/10;ge=date%10;          write_data(0x30+shi);write_data(0x30+ge);
}/***********************lcd1602上显示这字符函数************************/
void write_string(unchar hang,unchar add,unchar *p)
{if(hang==1)   write_com(0x80+add);elsewrite_com(0x80+0x40+add);while(1)                                                         {if(*p == '\0')  break;write_data(*p);p++;delay_unint(600);}
}/***********************lcd1602上显示这字符函数************************/
void write_string_1(unchar hang,unchar add,unchar *p)
{if(hang==1)   write_com(0x80+add);elsewrite_com(0x80+0x40+add);while(1)                                                         {if(*p == '\0')  break;write_data_1(*p);p++;delay_unint(600);}
}/***********************lcd1602初始化设置************************/
void init_1602()
{write_com(0x38);    //
    write_com(0x0c);write_com(0x06);delay_unint(12000);//write_string(1,0," Welcome to use ");    //write_string(2,0," Bicycle speed  ");//lcd1602_guanbiao(1,7+0x40);  //开光标
}unchar Lcd1602_ReadBusy()   //判断lcd1602是否处于忙的状态,即读忙
    {unchar temp;rs=0;rw=1;_nop_();P0=0xff;     //读某IO口数据前,先将该口置为1            /*原因:电路中存在的一个普遍的现象:高电平很容易被低电平拉低,而低电平一般不可能被高电平拉高。所以在读数据之前将单片机IO口拉高才不会影响原来数据线上的数据!*/_nop_();e=1;_nop_();temp=P0;   //读取此时lcd1602的状态字
       _nop_();e=0;return (temp&0x80);  //如果忙/*状态字为temp(8位2进制数)的最高位,最高位为1表示禁止读写,为0表示允许读写,即temp&0x80得1表示忙,得0表示不忙*/}void Lcd1602_WriteData(unchar dat)  //写数据
    { rs=1;   //数据rw=0;   //写
       _nop_();P2=dat;_nop_();e=1;_nop_();_nop_();e=0;_nop_();_nop_();   }void lcd_pos(unchar pos){write_com(pos | 0x80);}

由于DHT11需要比较准确的延时误差在5%

delay.c延时模块

#include "delay.h"
#include "intrins.h"
#include  "DHT11.h"
//--------------------------------------------------------
//延时1ms           实际0.99ms
//--------------------------------------------------------
void delay_ms(unsigned int x)
{while(x--){    unsigned char i, j;_nop_();_nop_();i = 9;j = 120;do{while (--j);} while (--i);
}
}void delay_unint(unsigned int q)
{    while(q--);
}
//--------------------------------------------------------
//延时60s 实际63us
//--------------------------------------------------------
void Delay60us()        //@12.000MHz
{unsigned char i, j;_nop_();_nop_();i = 1;j = 180;do{while (--j);} while (--i);
}//--------------------------------------------------------
//延时80s 实际87us
//--------------------------------------------------------void Delay80us()        //@12.000MHz
{unsigned char i, j;_nop_();_nop_();i = 1;j = 255;do{while (--j);} while (--i);
}//--------------------------------------------------------
//延时30s 实际31us
//--------------------------------------------------------void Delay30us()        //@12.000MHz
{unsigned char i;i = 87;while (--i);
}void Delay50us()        //@12.000MHz
{unsigned char i, j;_nop_();_nop_();i = 1;j = 145;do{while (--j);} while (--i);
}

DHT11.C 温度采集模块

#include  "DHT11.h"
#include  "currency.h"
#include   "stc12c5a60s2.h"
#include   "delay.h"
#include   "lcd1602.h"
#include  <intrins.h> //------------------------------------
//function:rec_dat数据组清零
//------------------------------------unchar  rec_dat[9];
//------------------------------------
//function:DHT11启动
//------------------------------------
void DHT11_start()
{Data=1;Delay30us();    Data=0;delay_ms(25);   //延时18ms以上Data=1;Delay30us();
}//------------------------------------
//function:DHT11接收一个字节
//------------------------------------    

unchar DHT11_rec_byte()      //接收一个字节
{unchar i,dat=0;for(i=0;i<8;i++)    //从高到低依次接收8位数据
   {          while(!Data);   ////等待50us低电平过去Delay60us();    //延时60us,如果还为高则数据为1,否则为0 dat<<=1;        //移位使正确接收8位数据,数据为0时直接移位if(Data==1)     //数据为1时,使dat加1来接收数据1dat+=1;while(Data);    //等待数据线拉低
    } return dat;}//------------------------------------
//function:      接收DHT11的40位的数据
//------------------------------------
void DHT11_receive()      //接收40位的数据
{unchar i, R_H,R_L,T_H,T_L,RH,RL,TH,TL,revise;     DHT11_start();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();if(Data==0){   while(Data==0);          //等待拉高Delay80us();             //拉高后延时80us            R_H=DHT11_rec_byte();    //接收湿度高八位;R_L=DHT11_rec_byte();    //接收湿度低八位  T_H=DHT11_rec_byte();    //接收温度高八位  T_L=DHT11_rec_byte();    //接收温度低八位revise=DHT11_rec_byte(); //接收校正位Delay30us();             //结束if((R_H+R_L+T_H+T_L)==revise)      //校正
        {RH=R_H;RL=R_L;TH=T_H;TL=T_L;} /*数据处理,方便显示*/rec_dat[0]='0'+(RH/10);rec_dat[1]='0'+(RH%10);rec_dat[2]='R';rec_dat[3]='H';rec_dat[4]=' ';rec_dat[5]=' ';rec_dat[6]='0'+(TH/10);rec_dat[7]='0'+(TH%10);rec_dat[8]='C';lcd_pos(40);   //定位第二行的第一个for(i=0;i<9;i++){write_data(rec_dat[i]);}    }}

buzzer,c蜂鸣器模块

#include  "buzzer.h"
#include  "currency.h"
#include  "delay.h"void Buzzer_Alert()      //PWM 500hz
{long int i=2000;while(i--){buzzer=~buzzer;delay_ms(1);}
}

代码难度不大,具体注释想必有点单片机的基础都可以看懂^^

DHT11的硬件

注:这个上拉电阻主要是普通的单片机的上拉能力不强,当数据进行长距离传输时容易有较大的寄生电容造成RC放电,所以要加上 上拉电阻。短距离不用加也可以。

DHT11的操作比较简单,就是时序操作,没有什么要注意的。

总结:

按键最好要消抖,一般有两种做法,软件消抖和硬件消抖两种方法,在单片机资源足够充裕并且系统对实时性要求不高时,建议使用软件消抖,延时20ms后进行判断。不然利用硬件消抖,一般在按键端接入4.7K电阻加0.1uF的电容,在有时间后加上GPS定位功能。

转载于:https://www.cnblogs.com/Kroner/p/9073651.html

基于单片机的自行车码表相关推荐

  1. 自行车存放管理系统c语言课程设计,基于51单片机的自行车智能辅助系统设计-(Proteus仿真图+源程序+论文)...

    基于单片机的自行车智能辅助系统设计 摘 要 随着科学技术与物联网的发展,推动着智能化产品逐渐从无到有再到快速发展,智能科技逐渐改变社会发展方式,过去很多无法想象的科学技术或者生活方式,现在利用先进和智 ...

  2. 单片机c语言慧尾灯编码,(参考)基于单片机的智能尾灯开发文档.doc

    基于单片机的智能尾灯的设计 摘要 本设计是基于单片机的自行车智能尾灯控制器,该设计为STC89S52单片机做为主控芯片的自行车尾灯控制电路的设计方法,用发光二极管模拟自行车尾灯,按键开关作为转弯等控制 ...

  3. 基于51单片机自行车码表设计

    [毕设课设]基于51单片机自行车码表设计 ​效果图 Proteus仿真: 功能简介: 文件内容: 程序框架: 网盘链接: ​效果图 更多内容请关注@WENJIE电子科技 ​ 基于51单片机proteu ...

  4. 【电路方案】基于单片机智能市电温度控制系统设计-基于单片机RGB颜色智能识别系统设计-基于单片机四路红外遥控开关电路设计-基于单片机自行车自动防盗报警系统设计-基于单片机智能无线病床呼叫系统设计

    822基于单片机智能无线病床呼叫系统设计-设计资料下载 硬件构成:单片机+最小系统+LCD1602液晶显示模块+无线收发模块+蜂鸣器模块+LED指示灯模块+按键模块 本设计基于STC89C51/52( ...

  5. 单片机数码管显示自行车里程c语言,基于51单片机的自行车里程计速度计设计.doc...

    信电学院课程设计报告 题目: 基于51单片机的自行车里程计/速度计设计 学生姓名 学 号 班 级 专 业 指导教师 说 明 1. 课程设计文本材料 2. 学生根据指导教师下达的任务书.指导书完成课程设 ...

  6. 基于51单片机的自行车里程表

    电路 51单片机的自行车里程表的硬件主要由51单片机最小系统电路,LCD1602液晶显示模块,霍尔测速模块,电机模块,电位器调速模块,蜂鸣器报警电路,LED指示灯模块,按键模块,DS1302时钟模,A ...

  7. 基于单片机的压力流量报警器(附代码+仿真+论文)

    基于单片机的压力流量报警器(附代码+仿真+论文) **==完整论文+代码+仿真可关注我在主页私我==** 摘要 关键字 第一章绪论 1.1课题背景及其意义 1.2 国内外的研究状况 1.3本文的主要研 ...

  8. 单片机里程计量设计c语言,基于单片机的出租车计价器的里程计算设计

    社会发展的越快,人们的生活质量越好,从以前的走路.骑自行车,再到坐公交车地铁等,到了现在出门"打的",出租车已经成为人们出门的重要代步工具了.因此出租车计价器系统也显得尤为重要.计 ...

  9. 基于单片机的超市储物柜设计_基于单片机的自动存储柜的设计

    金红娟 张娣 王历 摘  要: 隨着科技的日趋发展,智能化产品随处可见,极大地方便了人们的生产生活.在一些综合超市,大型购物商场等一些公共场合,由于人流大,购物的人多,仅靠人工来存储物品速度慢,效率低 ...

  10. 基于单片机的6位电子时钟

    点击链接获取Keil源码与Project Backups仿真图 https://download.csdn.net/download/qq_64505944/87413394 源码获取 摘 要 近年来 ...

最新文章

  1. 图卷积神经网络分析复杂碳水化合物
  2. 微信小程序 跳转界面
  3. JVM_02 类加载器子系统
  4. 在Spring@Component vs @Repository vs @Service
  5. Linux 蓝牙读写,实战Linux Bluetooth编程(三) HCI层编程
  6. Python 创建随机mac地址(单播、组播)
  7. 蓝盾小火墙补丁_网络安全知识小科普
  8. 【离散数学】单向连通和弱连通的区别
  9. 2018年php还是python好_2018年PHP还值得学习吗?
  10. iphone在jsp显示时间会NAN解决办法
  11. 如何本地加载live2d模型 离线方式加载看板娘
  12. 10种微信公众号的推广吸粉方法
  13. Android实现身份证号码验证
  14. vba中find方法查找
  15. 企业运维自动化实战-CSDN公开课-专题视频课程
  16. 广联达报错access_广联达软件报错问题汇总和解决方案.doc
  17. 【Vue】图片加载中显示Loading
  18. google计费接入,Billing结算库支付
  19. 力扣 704.二分查找
  20. ...可变形参的使用

热门文章

  1. Echars 双击Legend 显示自己隐藏其他Legend
  2. 基于TensorRT和onnxruntime下pytorch的Bert模型加速对比实践
  3. 饿了么Redis Cluster集群化演进
  4. 2017 暑期实习校园招聘(Java后台开发方向)面经分享
  5. 支付宝支付php开发demo下载地址,tp使用支付宝接口demo
  6. JAVA自学-day11-eclipse工具的使用、API、Object类
  7. 解决安卓CPU使用率过高问题
  8. 计算机无法关闭密码保护,Win7密码保护共享关闭不了怎么办?密码保护共享关不掉的解决方法...
  9. modbusx协议讲解
  10. 融合泊车占比超过60%,除了德赛西威,还有哪些本土供应商