设计分享|基于单片机LCD数字测速仪的设计

2022-07-27 19:09:42 浏览数 (1)

具体实现功能

具体功能:

通过逻辑生成仪模拟速度,再通过LCD1602进行显示。

设计介绍

单片机介绍

51单片是一种低功耗、高性能CMOS8位微控制器,具有 8K 在系统可编程Flash 存储器。在单芯片上,拥有灵巧的8 位CPU 和在系统可编程Flash,使得STC89C51为众多嵌入式控制应用系统提供高灵活、超有效的解决方案。具有以下标准功能:8k字节Flash,512字节RAM,32 位I/O 口线,看门狗定时器,内置4KB EEPROM,MAX810复位电路,三个16 位 定时器/计数器,一个6向量2级中断结构,全双工串行口。另外 STC89X51 可降至0Hz 静态逻辑操作,支持2种软件可选择节电模式。空闲模式下,CPU 停止工作,允许RAM、定时器/计数器、串口、中断继续工作。掉电保护方式下,RAM内容被保存,振荡器被冻结,单片机一切工作停止,直到下一个中断或硬件复位为止。最高运作频率35Mhz,6T/12T可选。

设计思路

文献研究法:搜集整理相关单片机智能手环系统相关研究资料,认真阅读文献,为研究做准备;

调查研究法:通过调查、分析、具体试用等方法,发现单片机智能手环系统的现状、存在问题和解决办法;

比较分析法:比较不同单片机智能手环系统的具体原理,以及同一类传感器性能的区别,分析单片机智能手环系统的研究现状与发展前景;

软硬件设计法:通过软硬件设计实现具体硬件实物,最后测试各项功能是否满足要求。

设计内容

01

仿真图

本设计利用protues8.7软件实现仿真设计,具体如图。

Protues也是在单片机仿真设计中常用的设计软件之一,通过设计出硬件电路图,及写入驱动程序,就能在不实现硬件的情况进行电路调试。另外,protues还能实现PCB的设计,在仿真中也可以与KEIL实现联调,便于程序的调试,且支持多种平台,使用简单便捷。

02

程序

本设计利用KEIL5软件实现程序设计,具体如图。作为本科期间学习的第一门编程语言,C语言是我们最熟悉的编程语言之一。当然,由于其功能强大,C语言是当前世界上使用最广泛、最受欢迎的编程语言。在单片机设计中,C语言已经逐步完全取代汇编语言,因为相比于汇编语言,C语言编译与运行、调试十分方便,且可移植性高,可读性好,便于烧录与写入硬件系统,因此C语言被广泛应用在单片机设计中。keil软件由于其兼容单片机的设计,能够实现快速调试,并生成烧录文件,被广泛应用于C语言的编写和单片机的设计。

代码语言:javascript复制
#include "reg51.h"
#include "intrins.h"

sbit LCM_RS=P3^0;
sbit LCM_RW=P3^1;
sbit LCM_EN=P3^7;

#define BUSY      0x80              //常量定义
#define DATAPORT   P1
#define uchar     unsigned char
#define uint       unsigned int
#define L      50

uchar str0[16],str1[16],count;
uint speed;
unsigned long time;

void ddelay(uint);
void lcd_wait(void);
void display();
void initLCM();
void WriteCommandLCM(uchar WCLCM,uchar BusyC);
void STR();
void account();


/*********延时K*1ms,12.000mhz**********/

void int0_isr(void) interrupt 0         /*遥控使用外部中断0,接P3.2口*/
{
    unsigned int temp;
  time=count;
    TR0=0;
  temp=TH0;
  temp=((temp << 8) | TL0);
    TH0=0x3c;
    TL0=0xaf;
  count=0;
    TR0=1;
  time=time*50000 temp;
}

void time0_isr(void) interrupt 1        /*遥控使用定时计数器1 */
{
   TH0 =0x3c;
   TL0 =0xaf;
   count  ;
}

void main(void)
{
     TMOD=0x01;                       /*TMOD T0选用方式1(16位定时) */
    IP|=0x01;                           /*INT0 中断优先*/
    TCON|=0x11;                         /*TCON  EX0下降沿触发,启动T0*/
    IE|=0x83;  
    TH0=0x3c;
    TL0=0xaf;
  
  initLCM();
     WriteCommandLCM(0x01,1);        //清显示屏
  for(;;)
  {
    account();
    display();
  }
}

void account()
{
  unsigned long a; 
  if (time!=0)
  {
    a=L*360000000/time;
  }
  speed=a;
}



void STR()
{
  str0[0]='S';
  str0[1]='p';
  str0[2]='e';
    str0[3]='e';
  str0[4]='d';
  str0[5]=' ';  
  str0[6]=(speed0000)/10000 0x30;
  str0[7]=(speed000)/1000 0x30;
  str0[8]=(speed00)/100 0x30;
  str0[9]='.';
  str0[10]=(speed0)/10 0x30;
  str0[11]=speed 0x30;
  str0[12]='k';
  str0[13]='m';
  str0[14]='/';
  str0[15]='h';
}

void ddelay(uint k)
{
    uint i,j;
    for(i=0;i<k;i  )
    {
        for(j=0;j<60;j  )
          {;}
    }
}
/**********写指令到LCD子函数************/

void WriteCommandLCM(uchar WCLCM,uchar BusyC)
{
    if(BusyC)lcd_wait();
  DATAPORT=WCLCM;
    LCM_RS=0;                   /* 选中指令寄存器*/
    LCM_RW=0;                 // 写模式
    LCM_EN=1;
  _nop_();
  _nop_();
  _nop_();
    LCM_EN=0;

}

/**********写数据到LCD子函数************/

void WriteDataLCM(uchar WDLCM)
{
    lcd_wait( );            //检测忙信号
  DATAPORT=WDLCM;
    LCM_RS=1;               /* 选中数据寄存器  */
    LCM_RW=0;             // 写模式
    LCM_EN=1;
    _nop_();
  _nop_();
  _nop_();
    LCM_EN=0;
}

/***********lcd内部等待函数*************/

void lcd_wait(void)
{
    DATAPORT=0xff;       //读LCD前若单片机输出低电平,而读出LCD为高电平,则冲突,Proteus仿真会有显示逻辑黄色
  LCM_EN=1;
    LCM_RS=0;
    LCM_RW=1;
    _nop_();
    _nop_();
  _nop_();
    while(DATAPORT&BUSY)
  {  LCM_EN=0;
     _nop_();
     _nop_();
     LCM_EN=1;
     _nop_();
     _nop_();
  }
     LCM_EN=0;

}

/**********LCD初始化子函数***********/
void initLCM( )
{
  DATAPORT=0;
  ddelay(15);
  WriteCommandLCM(0x38,0);    //三次显示模式设置,不检测忙信号
    ddelay(5);
    WriteCommandLCM(0x38,0);
    ddelay(5);
    WriteCommandLCM(0x38,0);
    ddelay(5);

    WriteCommandLCM(0x38,1);    //8bit数据传送,2行显示,5*7字型,检测忙信号
    WriteCommandLCM(0x08,1);    //关闭显示,检测忙信号
    WriteCommandLCM(0x01,1);    //清屏,检测忙信号
    WriteCommandLCM(0x06,1);    //显示光标右移设置,检测忙信号
    WriteCommandLCM(0x0c,1);    //显示屏打开,光标不显示,不闪烁,检测忙信号
}

/****显示指定坐标的一个字符子函数****/

void DisplayOneChar(uchar X,uchar Y,uchar DData)
{
    Y&=1;
    X&=15;
    if(Y)X|=0x40;               //若y为1(显示第二行),地址码 0X40
    X|=0x80;                    //指令码为地址码 0X80
    WriteCommandLCM(X,0);
    WriteDataLCM(DData);
}

/*******显示指定坐标的一串字符子函数*****/
void DisplayListChar(uchar X,uchar Y,uchar *DData)
{
    uchar ListLength=0;
    Y&=0x01;
    X&=0x0f;
    while(X<16)
    {
        DisplayOneChar(X,Y,DData[ListLength]);
        ListLength  ;
        X  ;
    }
}

void display()
{

  STR(); 
  DisplayListChar(0,0,str0);
     DisplayListChar(0,1,str1);
}

0 人点赞