单片机测速1602显示
- 格式:docx
- 大小:80.61 KB
- 文档页数:4
单片机1602液晶显示原理
首先,从硬件连接方面来看,单片机与1602液晶显示器之间的连接通常需要16个引脚。
这些引脚包括数据总线(D0-D7)、控制引脚(RS、RW、E)以及电源和地线。
数据总线用于传输要显示的数据,而控制引脚用于控制液晶显示器的工作状态。
单片机通过这些引脚与液晶显示器进行通信,从而实现对显示内容的控制。
其次,从工作原理方面来看,单片机控制1602液晶显示器的基本原理是利用单片机的IO口向液晶显示器发送指令和数据。
当单片机需要在液晶显示器上显示内容时,首先需要向液晶显示器发送控制指令,如清屏、定位光标等,然后再发送要显示的数据。
液晶显示器接收到指令和数据后,根据单片机发送的信号来控制液晶显示器的内部驱动电路,从而在屏幕上显示相应的内容。
总的来说,单片机1602液晶显示原理涉及到单片机与液晶显示器之间的硬件连接和通信协议。
通过单片机向液晶显示器发送指令和数据,实现对液晶显示器显示内容的控制。
这样的设计使得单片机能够方便地控制液晶显示器,实现各种复杂的显示效果。
1602详细资料和实例1602字符液晶在实际的产品中运用的也比较多了,前几天留意了一下,发现宿舍门前的自动售水机就是采用的1602液晶进行显示的。
而且对于单片机的学习而言,掌握1602的用法是每一个学习者必然要经历的过程。
在此,我将使用1602过程中遇到的问题以及感受记录下来,希望能够给初学者带来一点指导,少走一点弯路。
所谓1602是指显示的内容为16*2,即可以显示两行,每行16个字符。
目前市面上字符液晶绝大多数是基于HD44780液晶芯片的,控制原理是完全相同的,因此基于HD44780写的控制程序可以很方便地应用于市面上大部分的字符型液晶。
1602液晶的正面(绿色背光,黑色字体)1602液晶背面(绿色背光,黑色字体)另一种1602液晶模块,显示屏是蓝色背光白色字体字符型LCD1602通常有14条引脚线或16条引脚线的LCD,多出来的2条线是背光电源线VCC(15脚)和地线GND(16脚),其控制原理与14脚的LCD完全一样,引脚定义如下表所示:HD44780内置了DDRAM、CGROM和CGRAM。
DDRAM就是显示数据RAM,用来寄存待显示的字符代码。
共80个字节,其地址和屏幕的对应关系如下表:也就是说想要在LCD1602屏幕的第一行第一列显示一个"A"字,就要向DDRAM的00H地址写入“A”字的代码(指A的字模代码,0x20~0x7F为标准的ASCII码,通过这个代码,在CGROM中查找到相应的字符显示)就行了。
但具体的写入是要按LCD模块的指令格式来进行的,后面我会说到的。
那么一行可有40个地址呀?是的,在1602中我们就用前16个就行了。
第二行也一样用前16个地址。
对应如下:DDRAM地址与显示位置的对应关系。
(事实上我们往DDRAM里的00H地址处送一个数据,譬如0x31(数字1的代码,见字模关系对照表)并不能显示1出来。
这是一个令初学者很容易出错的地方,原因就是如果你要想在DDRAM的00H地址处显示数据,则必须将00H加上80H,即80H,若要在DDRAM的01H处显示数据,则必须将01H加上80H即81H。
/***********************************************程序名称:DS18b20温度显示编写:wdc日期:2010-4-27简要说明:使用DS18b20A/D转化器,P3^7接数据I/O口DQ,P2^0-P2^7接1602的D0-D7,P3^0接rs,P3^1接r/w,P3^2接en 函数列表:void delay(int a);延时,以us计算void delayms(int z); 延时,以ms计算unsigned char reset(void) 复位程序unsigned char read_bit(void) 从DS18b20读一个位unsigned char read_byte(void) 从DS18b20读一个字节void write_bit(char bitval) 向DS18b20写一个位void write_byte(char val) 向DS18b20写指令一个字节void tmconvert(void) 温度转化int gettm(void) 读取温度修改记录:增加1602显示:void display(long m)定时器0中断:void timer0() interrupt 1***********************************************/#include <reg51.h>#define uchar8 unsigned char#define uint16 unsigned intuchar8 dis[6] = { 0, 0, 0, 0, 0, 0 };uchar8 code wendu[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39}; //0到9的代码uchar8 code name[]={"by:wdc 2010-5-1"};uchar8 flag,sig; //flag用于判定是否有中断,sig判定温度符号sbit rs = P3^0; //1602 数据/命令sbit rw = P3^1; // 读/写sbit en = P3^2; // 使能端sbit DQ = P3^7; //18b20与单片机连接的DQ总线/*延时函数*/void delay (int us) //DELAY-11.0592MHZ 调用程序大约为24us,每次循环为16us {int s;for(s=0;s<us;s++);}void delayms(int z) //z为毫秒数{int x,y;for(x=z;x>0;x--)for(y=125;y>0;y--);}/**********************函数名称:写指令输入参数:指令输出参数:数据口输出指令功能:对1602执行特定命令***********************/void write_com(uchar8 com) //写指令{delayms(5);rs = 0; //选择写指令rw = 0;P2 = com;en = 1; //en先1后0为高脉冲delayms(5);en = 0;}/**********************函数名称:写数据输入参数:数据,字母则是ASCIL值输出参数:数据口输出数据功能:令1602显示数据***********************/void write_dat(uchar8 dat) //写数据{delayms(5);rs = 1; //选择写数据rw = 0;P2 = dat;en = 1; //en先1后0为高脉冲delayms(5);en = 0;}/**********************函数名称:初始化输入参数:无输出参数:无调用函数:void w_cmd(uchar cmd)功能:对1602进行初始化,具体过程应严格参照产品说明书***********************/void init(viod) //初始化{TMOD=0x01; //定时器0设为工作方式1TH0 =0x3c; //(65536-50000)/256;TL0 =0xb0; //(65536-50000)%256;EA=1; //开总中断ET0=1; //开定时器0中断TR0=1; //启动定时器0rw = 0; //读/写置低write_com(0x38); //设置16x2显示,5x7点阵,8位数据口write_com(0x08); //显示关闭write_com(0x01); //显示清屏,数据指针以及所有显示清零write_com(0x06); //读写数据,光标及数据指针加一write_com(0x0c); //开显示,光标不显示}/***************函数名称:写字符串输入参数:字符串首地址输出参数:无功能:使1602显示字符串****************/void write_char(uchar8 *cha) //字符串的输入{uchar8 i = 0;while (cha[i] != 0){write_dat(cha[i]); //写一个数据i++; //i自加一次delayms(50); //延时50ms}}/*复位程序*/unsigned char reset(void){uchar8 presence;DQ=0; //拉低总线。
/*****************************************************************************/Name: LCD1602+US-100+STC89C52HC-SR04 超声波测距模块串口程序晶振: 11.0592MDesigned by : 庶野琴风Date:2016/08/11QQ:397739038接线:模块TRIG接 P3.1 ECH0 接 P3.0RS(CS)接P2.0;RW(SID)接P2.1;E(SCLK)接P2.2;BF接P0.7;/*****************************************************************************/#include<reg52.h>#include<intrins.h>#define nops {_nop_();_nop_();_nop_();_nop_();}/******************************引脚及变量的定义****************************/ sbit RS = P2^0; // 寄存器选择位sbit RW = P2^1; // 读取选择位sbit E = P2^2;// 使能信号位sbit BF = P0^7; // 忙碌信号位unsigned char code Tab[] = {"0123456789"};unsigned char code string[] = {"range:2cm--4.5m"};char part,ge,shi,bai;char idata GLengthLoh[2];// 接收缓冲区bit success_flag;// 定义测试成功标志位/*********************************************************//********* /********* /*********函数名称: delay1ms(void)函数功能:延时 1 毫秒函数参数: void******************/******************/******************//*********************************************************/void delay1ms(void)// 误差-0.651041666667us{char a,b;for(b=102;b>0;b--)for(a=3;a>0;a--);}/*********************************************************//*********函数名称: delaynms(char n)******************//*********函数功能:延时n 个 1 毫秒******************//*********函数参数: n******************/ /*********************************************************/void delaynms(char n){char a;for(a = 0;a > n;a--)delay1ms();}/*********************************************************//*********函数名称: BusyTest(void)******************//*********函数功能:判断液晶模块忙碌状态******************//*********函数参数:返回值:result******************//*********************************************************/unsigned char BusyTest(){bit result;RS=0;RW=1;//RS为低电平,RW 为高电平时,可以读状态E=1; nops; result = BF; E=0;// 使能为高电平时可读取信息// 延时 40us,给硬件反应时间// 将忙碌标志位电平赋给result // 使能 1 到 0:执行指令return result;}/*********************************************************//*********函数名称: WriteInstruction(char dictate)*******//*********函数功能:将模式设置指令或显示地址写入液晶模块**/ /*********函数参数: dictate******************//*********************************************************/void WriteInstruction(char dictate){while(BusyTest() == 1);// 如果忙碌标志位忙碌则等待RS=0;RW=0;//RS/RW 位同时为低电平时可写入指令E=0;//使能0到 1:写入指令nops;P0 = dictate;// 将数据送入 P0 口,写入数据或地址nops;E=1;//使能0到 1:写入指令nops;E=0;//使能1到 0:执行指令}/*********************************************************//*********函数名称: WriteAddress(char x)*******//*********函数功能:指定字符显示的实际地址***********//*********函数参数: x******************//*********************************************************/void WriteAddress(char x){WriteInstruction(x|0x80);// 80H+地址码}/*********************************************************//*********函数名称: WriteData(char y)*******//*********函数功能:将数据(字符的标准ASCII码 )写入液晶模块 *//*********函数参数: y******************//*********************************************************/void WriteData(char y){while(BusyTest() == 1);// 如果忙碌标志位忙碌则等待RS=1;RW = 0;//RS 为高电平, RW 为低电平时,可以写入数据E=0;P0 = y;nops;E=1;nops;E=0;}/*********************************************************//*********函数名称: LCDInit(void)*******//*********函数功能:液晶模块初始化****************//*********函数参数: void******************//*********************************************************/void LCDInit(void){delaynms(15);// 延时 15 毫秒,首次写入液晶指令应给反应时间WriteInstruction(0x38);// 显示模式设置:16× 2 显示, 5× 7 点阵, 8 位数据接口delaynms(5);//延时 5秒,反应时间WriteInstruction(0x38);delaynms(5);//延时 5秒,反应时间WriteInstruction(0x38);delaynms(5);// 连续三次,确保初始化成功WriteInstruction(0x0c);// 显示模式设置:显示开,无光标,光标不闪烁delaynms(5);WriteInstruction(0x06);// 显示模式设置:显示光标右移,屏幕不移动delaynms(5);WriteInstruction(0x01);// 清屏delaynms(5);}/*********************************************************//********* /*********函数名称: UART_Send(char dat)函数功能:串口发送函数*******/****************//*********函数参数: dat******************/ /*********************************************************/void UART_Send(char dat){TI=0; SBUF = dat;//清发送标志//如果 TI为 0等待while (!TI);// 等待发送数据}/*********************************************************//*********函数名称: UART_Init()***************//*********函数功能:串口初始化函数****************//*********函数参数:无******************//*********************************************************/void UART_Init(){TH1 = 0xFD;TL1 = 0xFD;TMOD = 0x21;// 设置定时器 1 为模式 2;定时器 0 为模式 1 TH0 =(65536-2500)/256;// 约 2.50MS 定时器初值TL0 =(65536-2500)%256;// 约 2.50MS 定时器初值ET0 = 1;TR0 = 1;// 启动定时器TR1 = 1;// 启动定时器SM0SM1SM0 = 0;// 串口通信模式设置00 = 0SM1 = 1;//0 1 = 1//10 = 2//1 1 = 3 REN = 1;// 串口允许接收数据ES = 1;// 开串中断EA=1;}/*********************************************************//*********函数名称: UART_ISR(void)***************//*********函数功能:串口中断函数****************//*********函数参数: void******************//*********************************************************/void UART_ISR(void) interrupt 4{char temp,k;ES=0;if(RI){// 关中断RI=0;temp = SBUF;// 清接收标志GLengthLoh[k] = temp;k++;if(k == 2) //k= 数据长度k = 0;}ES=1;// 开中断}/*********************************************************//********* /********* /*********函数名称: timer0()函数功能:定时器函数函数参数: void***************/****************/******************//*********************************************************/timer0() interrupt 1//定时器0 中断是 1 号{TH0 =(65536-2500)/256; // 约TL0 =(65536-2500)%256; // 约2.50MS 定时器初值2.50MS 定时器初值TH0 = 0xef;TL0 = 0x94;// 写入定时器0 初始值}/*********************************************************//*********函数名称: conversion(int8 temp_data)*******//*********函数功能:数据转换****************//*********函数参数: temp_data******************//*********************************************************/void conversion(int temp_data){char part_data,ge_data,shi_data,bai_data;bai_data = temp_data / 1000;shi_data = (temp_data % 1000) / 100;ge_data = (temp_data % 100) / 10;part_data = temp_data % 10;EA=0;bai = bai_data;shi = shi_data;ge = ge_data;part = part_data;EA=1;}/*********************************************************//*********函数名称: main(void)*******/ /*********函数功能:主函数****************/ /*********函数参数: void******************/ /*********************************************************/void main(void){int k;long PreLength;LCDInit();// 调用液晶初始化函数delaynms(10);UART_Init();PreLength = 0;k = 0;while(1){WriteAddress(0x01);while(string[k] != '\0'){WriteData(string[k]);k++;}UART_Send(0X55);PreLength = GLengthLoh[0] * 256 + GLengthLoh[1] - 5;conversion(PreLength);WriteAddress(0x41); WriteData('J');// 从第 2 行第 6 列开始显示// 将特定的字符常量写入LCDWriteData('U');WriteData('L');WriteData('I');WriteData(':');if(PreLength <= 4500 && PreLength >= 20){WriteData(Tab[bai]);// 将百位数字的字符常量写入LCD WriteData(Tab[shi]);// 将十位数字的字符常量写入LCD WriteData(Tab[ge]);// 将个位数字的字符常量写入LCD WriteData('.');WriteData(Tab[part]);}else{WriteData('-');WriteData('-');WriteData('-');WriteData('-');WriteData('-');}WriteData(' ');WriteData('c');WriteData('m');} }。
标签:单片机LCD基于51单片机的1602LCD显示基于51单片机的1602LCD显示LCD(liquid crystal display)为液晶显示器,它一般不会单独使用,而是将LCD面板、驱动与控制电路组合成LCD模块(1iquid crystal display moulde,简称为LCM)来使用。
LCM是一种很省电的显示设备,常被应用在数字或微处理器控制的系统,做为简易的人机接口,但人们一般还是习惯称之为LCD显示器。
1 硬件设计采用51单片机控制1602LCD显示器的电路如下所示。
在桌面上双击图标,打开ISIS 7 Professional窗口(本人使用的是v7.4 SP3中文版)。
单击菜单命令“文件”→“新建设计”,选择DEFAULT 模板,保存文件名为“LCD.DSN”。
在器件选择按钮中单击“P”按钮,或执行菜单命令“库”→“拾取元件/符号”,添加如下表所示的元件。
51单片机AT89C51 一片晶体CRYSTAL 12MHz 一只瓷片电容CAP 22pF 二只电解电容CAP-ELEC 10uF 一只电阻RES 10K 一只排阻RESPAC-8 10K 一只1602液晶显示器LM016L 一只若用Proteus软件进行仿真,则上图中的晶振和复位电路以及U1的31脚,都可以不画,它们都是默认的。
在ISIS原理图编辑窗口中放置元件,再单击工具箱中元件终端图标,在对象选择器中单击POWER和GROUND放置电源和地。
放置好元件后,布好线。
左键双击各元件,设置相应元件参数,完成电路图的设计。
2 软件设计用1602LCD显示两行字符的流程图如下所示。
用1602LCD显示“Welcom to China”和“Hi!Good morning!”的详细C51程序如下。
//用LCD循环显示"Welcome to China"和"Hi!Good morning!"#include<reg51.h> //包含单片机的头文件#include<intrins.h> //包含_nop_()函数定义的头文件sbit RS="P2"^0; //寄存器选择位,将RS位定义为P2.0引脚sbit RW="P2"^1; //读写选择位,将RW位定义为P2.1引脚sbit E="P2"^2; //使能信号位,将E位定义为P2.2引脚sbit BF="P0"^7; //忙碌标志位,,将BF位定义为P0.7引脚unsigned char code string[ ]={"Welcome to China"};unsigned char code string1[ ]={"Hi!Good morning!"};/*************************************************函数功能:延时1ms(3j+2)*i=(3×33+2)×10=1010(微秒),可以认为是1毫秒*************************************************/void delay1ms(){unsigned char i,j;for(i=0;i<10;i++)for(j=0;j<33;j++);}/*****************************函数功能:延时若干毫秒入口参数:n******************************/void delay(unsigned char n){unsigned char i;for(i=0;i<n;i++)delay1ms();}/*******************************************函数功能:判断液晶模块的忙碌状态返回值:result。
液晶显示(所有程序都经过测试合格)一、基础部分。
(以1602与12864介绍)本部分以液晶1602为主,来引出关于单片机操作液晶的基本知识。
为以后液晶的高级应用打好基础。
Ⅰ、本程序最终目的为:显示一个双行数字,并实现整屏移动。
总的原理图及源程序如下:原理图:液晶电路图\液晶显示.ddb源程序:液晶例程\液晶显示.c#include<reg52.h>#define uchar unsigned char#define uint unsigned intuchar code table[]="I LIKE MCU!";uchar code table1[]="";sbit lcdwr=P2^5;//R/S命令选择端,H/L;sbit lcden=P2^7;//使能端sbit lcdrs=P2^6;//RS数据/命令选择端。
H/L;//sbit dula=P2^6;//sbit wela=P2^7;uchar num;void delay(uint z)//延时程序,z的数是几就是几ms{uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}void write_com(uchar com)//写命令函数,{lcdrs=0;//写入命令初始化,设置为低电平表示命令选择端。
P0=com; //由时序图可知,在使能en触发时,早就有数据写入。
delay(5); //并且有一段延时,此处设置为5毫秒lcden=1; //使能端开始拉高delay(5); //由时序图,使能端拉低一段时间thD2后,数据传输?lcden=0; //然后将使能端拉低}void write_data(uchar date){lcdrs=1;P0=date;delay(5);//此处延时,是为了对应数据中:在E拉高之前,有数据的一段准备时间。
超声波测距LCD1602显示超声波测距模块:1、采用IO口TRIG触发测距,给至少10us的高电平信号;2、模块自动发送8个40khz的方波,自动检测是否有信号返回;3、有信号返回,通过IO口ECHO输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间。
测试距离=(高电平时间*声速(340M/S))/2。
液晶LCD1602电路接口超声波测距LCD1602显示程序源代码/*******************超声波测距1602显示********************* 单片机:51单片机* 开发环境:keil* 名称:超声波测距1602显示注意:用杜邦线将超声波模块的VCC接开发板5V对外供电接口用杜邦线将超声波模块的GND接开发板GND用杜邦线将超声波模块的Trig接单片机的P1.5用杜邦线将超声波模块的Echo接单片机的P1.6/************************包含头文件************************/#include <reg51.h>#define LCD_Data P0#define Busy 0x80/**************************宏定义**************************/#define SPEED_30C 3495 //30摄氏度时的声速,声速V=331.5+0.6*温度;#define SPEED_23C 3453 //23摄氏度时的声速,声速V=331.5+0.6*温度;/**************************位定义**************************/sbit ECHO = P2^1; //回声接收端口sbit TRIG = P2^0; //超声触发端口sbit BEEP = P2^3; //蜂鸣器sbit LCD_RS = P1^0;sbit LCD_RW = P1^1;sbit LCD_E = P2^5;/**********************定义变量和数组**********************/long int distance = 0; //距离变量unsigned char code table0[] = {" SL-51A "};unsigned char code table1[] = {" NO ECHO "};unsigned char code table2[] = {"Distance:xxx.xcm"};unsigned char count;void Delay5Ms(void);void delay(int In,int Out);void WriteDataLCD(unsigned char WDLCD);void WriteCommandLCD(unsigned char WCLCD,BuysC);unsigned char ReadDataLCD(void);unsigned char ReadStatusLCD(void);void LCDInit(void);void DisplayOneChar(unsigned char X,unsigned char Y,unsigned char DData);void DisplayListChar(unsigned char X,unsigned char Y,unsigned char code *DData); /**********************************************************//* 函数名称 : Delay_xMs *//* 函数描述 : 延时函数 *//* 输入参数 : x *//* 参数描述 : 延时时间 *//* 返回值 : 无 *//**********************************************************/void Delay_xMs(unsigned int x){unsigned int i,j;for(i=0;i<x;i++){for(j=0;j<3;j++){;}}}/**********************************************************//* 函数名称 : delayt *//* 函数描述 : 延时函数 *//* 输入参数 : x *//* 参数描述 : 延时时间数据 *//* 返回值 : 无 *//**********************************************************/void delayt(unsigned int x){unsigned char j;while(x-->0){for(j=0;j<125;j++){;}}}/*************************5ms延时函数**********************/void Delay5Ms(void){unsigned int TempCyc = 3552;while(TempCyc--);}/**************************延迟函数************************/void delay(int In,int Out) {int i,j;for(i=0;i<In;i++){for(j=0;j<Out;j++){;}}}/**********************************************************//* 函数名称 : Alarm *//* 函数描述 : 蜂鸣器发声函数 *//* 输入参数 : t *//* 参数描述 : 发声的次数 *//* 返回值 : 无 *//**********************************************************/void Alarm(unsigned char t){unsigned char i;for(i=0;i<t;i++){BEEP=0;delay(10,1000);BEEP=1;delay(10,1000);}}/**********************************************************//* 函数名称 : Init_timer *//* 函数描述 : 初始化单片机函数 *//* 输入参数 : 无 *//* 参数描述 : 无 *//* 返回值 : 无 *//**********************************************************/void Init_timer(void){TMOD=0x01; //定时器2初始化,设置为16位自动重装模式TL0=0x66;TH0=0xfc; //1msET0=1; //开定时器2EA=1; //总中断使能}/**********************************************************//* 函数名称 : Init_Parameter *//* 函数描述 : 初始化参数和IO口函数 *//* 输入参数 : 无 *//* 参数描述 : 无 *//* 返回值 : 无 *//**********************************************************/void Init_Parameter(void){TRIG=1;ECHO=1;count=0;distance=0;}/**********************************************************//* 函数名称 : display *//* 函数描述 : 显示数字 *//* 输入参数 : number,address *//* 参数描述 : number写入的数据 *//* 返回值 : 无 *//**********************************************************/ void display(int number){unsigned char b,c,d,e;b=(number/1000);c=(number/100)%10;d=(number/10)%10;e=number%10; DisplayOneChar(9,1,(0x30+b));DisplayOneChar(10,1,(0x30+c));DisplayOneChar(11,1,(0x30+d));DisplayOneChar(13,1,(0x30+e));}/**********************************************************//* 函数名称 : Trig_SuperSonic *//* 函数描述 : 发出声波函数 *//* 输入参数 : 无 *//* 参数描述 : 无 *//* 返回值 : 无 *//**********************************************************/ void Trig_SuperSonic(void) //出发声波{TRIG=1;delayt(1);TRIG=0;}/**********************************************************//* 函数名称 : Measure_Distance *//* 函数描述 : 计算距离函数 *//* 输入参数 : 无 *//* 参数描述 : 无 *//* 返回值 : 无 *//**********************************************************/ void Measure_Distance(void){unsigned char l;unsigned int h,y;TR0=1;while(ECHO){;}TR0=0;l=TL0;h=TH0;y=(h<<8)+l;y=y-0xfc66; //us部分distance=y+1000*count; //计算总时间TL0=0x66;TH0=0xfc;delayt(30);distance=SPEED_30C*distance/20000;}/*********************写数据函数***************************/void WriteDataLCD(unsigned char WDLCD){ReadStatusLCD(); //检测忙LCD_Data=WDLCD;LCD_E=0; //若晶振速度太高可以在这后加小的延时LCD_E=0; //延时LCD_RS=1;LCD_RW=0;LCD_E=1;LCD_E=0;}/***********************写指令函数*************************/void WriteCommandLCD(unsigned char WCLCD,BuysC) //BuysC为0时忽略忙检测{if (BuysC) ReadStatusLCD(); //根据需要检测忙LCD_Data=WCLCD;LCD_E=0;LCD_E=0;LCD_RS=0;LCD_RW=0;LCD_E=1;LCD_E=0;}/************************读数据函数************************/unsigned char ReadDataLCD(void){LCD_RS=1;LCD_RW=1;LCD_E=0;LCD_E=0;LCD_E=1;return(LCD_Data);}/************************读状态函数************************/unsigned char ReadStatusLCD(void){LCD_Data=0xFF;LCD_RS=0;LCD_RW=1;LCD_E=0;LCD_E=0;LCD_E=1;while (LCD_Data & Busy); //检测忙信号return(LCD_Data);}/************************LCD初始化*************************/void LCDInit(void) //LCD初始化{LCD_Data=0;WriteCommandLCD(0x38,0);Delay5Ms(); //三次显示模式设置,不检测忙信号WriteCommandLCD(0x38,0);Delay5Ms();WriteCommandLCD(0x38,0);Delay5Ms();WriteCommandLCD(0x38,1); //显示模式设置, 开始要求每次检测忙信号 WriteCommandLCD(0x08,1); //关闭显示WriteCommandLCD(0x01,1); //显示清屏WriteCommandLCD(0x06,1); //显示光标移动设置WriteCommandLCD(0x0C,1); //显示开及光标设置}/***********************清屏函数***************************/void LCD_Clear(void){WriteCommandLCD(0x01,1);Delay5Ms();}/*******************按指定位置显示一个字符******************/void DisplayOneChar(unsigned char X,unsigned char Y,unsigned char DData){Y&=0x1;X&=0xF; //限制X不能大于15,Y不能大于1if(Y)X|=0x40; //当要显示第二行时地址码+0x40;X|=0x80; //算出指令码WriteCommandLCD(X, 0); //这里不检测忙信号,发送地址码WriteDataLCD(DData);}/********************按指定位置显示一串字符*****************/void DisplayListChar(unsigned char X,unsigned char Y,unsigned char code *DData) {unsigned char ListLength;ListLength=0;Y&=0x1;X&=0xF; //限制X不能大于15,Y不能大于1 while (DData[ListLength]>=0x20) //若到达字串尾则退出{if(X<=0xF) //X坐标应小于0xF{DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符ListLength++;X++;}}}/**********************************************************//* 函数名称 : main *//* 函数描述 : 主函数 *//* 输入参数 : 无 *//* 参数描述 : 无 *//* 返回值 : 无 *//**********************************************************/void main(void){LCDInit();Init_timer();Init_Parameter();Alarm(2);DisplayListChar(0,0,table0);DisplayListChar(0,1,table1);while(1){Trig_SuperSonic(); //触发超声波发射while(ECHO==0){;} //等待回声Measure_Distance(); //计算脉宽并转换为距离DisplayListChar(0,1,table2);display(distance); //显示距离Init_Parameter(); //参数重新初始化delayt(100); //延时,两次发射之间要至少有10ms间隔 }}/**********************************************************//* 函数名称 : timer0 *//* 函数描述 : T0中断处理函数 *//* 输入参数 : 无 *//* 参数描述 : 无 *//* 返回值 : 无 *//**********************************************************/void timer0 (void) interrupt 1{TF0=0;TL0=0x66;TH0=0xfc;count++;if(count==18) //超声波回声脉宽最多18ms{TR0=0;TL0=0x66;TH0=0xfc;count=0;}}。
#include<regx52.h> //器件配置文件#include <intrins.h>#define TX P1_2 //Trig#define RX P1_3 //Echo#define LCM_RS P2_5 //概念LCD引脚#define LCM_RW P2_6#define LCM_E P2_7#define LCM_Data P0#define Busy 0x80 //用于检测LCM状态字中的Busy标识#define uint unsigned int#define uchar unsigned charsbit P10=P2^1;//操纵左电机前进sbit P11=P2^2;//操纵左电机后退sbit P12=P2^3;//操纵右电机前进sbit P13=P2^4;//操纵右电机后退sbit P14=P1^4;//寻迹左sbit P15=P1^5;//寻迹中sbit P16=P1^6;//寻迹右sbit P17=P1^7;//避障void LCMInit(void);void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData); void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData);void Delay5Ms(void);void Delay400Ms(void);void Decode(unsigned char ScanCode);void WriteDataLCM(unsigned char WDLCM);void WriteCommandLCM(unsigned char WCLCM,BuysC);void fun2(void);void fun3(void);void fun4(void);void fun5(void);unsigned char ReadDataLCM(void);unsigned char ReadStatusLCM(void);unsigned char code mcustudio[] ={"…………. "};unsigned char code email[] = {"………… "};unsigned char code Cls[] = {"……………"};unsigned char code ASCII[15] = {'0','1','2','3','4','5','6','7','8','9','.','-','M'};static unsigned char DisNum = 0; //显示用指针unsigned int time=0;unsigned long S=0;bit flag =0;unsigned char disbuff[4] ={ 0,0,0,0,};bit Flg_5ms=0;unsigned char Counter_100ms=0;unsigned char buf[5]={0,0,0,0,0};unsigned int Speed;unsigned int speed_frequency; // frequencyunsigned int speed_catch1; //catch 1unsigned int speed_catch2; //catch 2unsigned char speed_t2_ovf_count_temp; //T1 overflow counter temp register unsigned char speed_t2_ovf_count; //T1 overflow counter register unsigned char speed_catch_p; //catch pointer//写数据void WriteDataLCM(unsigned char WDLCM){ReadStatusLCM(); //检测忙LCM_Data = WDLCM;LCM_RS = 1;LCM_RW = 0;LCM_E = 0; //假设晶振速度太高能够在这后加小的延时LCM_E = 0; //延时LCM_E = 1;}//写指令void WriteCommandLCM(unsigned char WCLCM,BuysC) //BuysC为0时忽略忙检测{if (BuysC) ReadStatusLCM(); //依照需要检测忙LCM_Data = WCLCM;LCM_RS = 0;LCM_RW = 0;LCM_E = 0;LCM_E = 0;LCM_E = 1;}//读数据unsigned char ReadDataLCM(void){LCM_RS = 1;LCM_RW = 1;LCM_E = 0;LCM_E = 0;LCM_E = 1;return(LCM_Data);}//读状态unsigned char ReadStatusLCM(void){LCM_Data = 0xFF;LCM_RS = 0;LCM_RW = 1;LCM_E = 0;LCM_E = 0;LCM_E = 1;while (LCM_Data & Busy); //检测忙信号return(LCM_Data);}void LCMInit(void) //LCM初始化{LCM_Data = 0;WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号Delay5Ms();WriteCommandLCM(0x38,0);Delay5Ms();WriteCommandLCM(0x38,0);Delay5Ms();WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号WriteCommandLCM(0x08,1); //关闭显示WriteCommandLCM(0x01,1); //显示清屏WriteCommandLCM(0x06,1); // 显示光标移动设置WriteCommandLCM(0x0F,1); // 显示开及光标设置}//按指定位置显示一个字符void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData) {Y &= 0x1;X &= 0xF; //限制X不能大于15,Y不能大于1if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;X |= 0x80; //算出指令码WriteCommandLCM(X, 1); //发命令字WriteDataLCM(DData); //发数据}//按指定位置显示一串字符void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData) {unsigned char ListLength;ListLength = 0;Y &= 0x1;X &= 0xF; //限制X不能大于15,Y不能大于1while (DData[ListLength]>0x19) //假设抵达字串尾那么退出{if (X <= 0xF) //X坐标应小于0xF{DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符ListLength++;X++;}}}//5ms延时void Delay5Ms(void){unsigned int TempCyc = 5552;while(TempCyc--);}//400ms延时void Delay400Ms(void){unsigned char TempCycA = 5;unsigned int TempCycB;while(TempCycA--){TempCycB=7269;while(TempCycB--);};}/********************************************************/ void Conut(void){time=TH0*256+TL0;TH0=0;TL0=0;S=(time*1.7)/100; //算出来是CMif((S>=700)||flag==1) //超出测量范围显示"-"{flag=0;DisplayOneChar(0, 1, ASCII[11]);DisplayOneChar(1, 1, ASCII[10]); //显示点DisplayOneChar(2, 1, ASCII[11]);DisplayOneChar(3, 1, ASCII[11]);DisplayOneChar(4, 1, ASCII[12]); //显示M}else{disbuff[0]=S%1000/100;disbuff[1]=S%1000%100/10;disbuff[2]=S%1000%10 %10;DisplayOneChar(0, 1, ASCII[disbuff[0]]);DisplayOneChar(1, 1, ASCII[10]); //显示点DisplayOneChar(2, 1, ASCII[disbuff[1]]);DisplayOneChar(3, 1, ASCII[disbuff[2]]);DisplayOneChar(4, 1, ASCII[12]); //显示M}}/********************************************************/void zd0() interrupt 1 //T0中断用来计数器溢出,超过测距范围{flag=1; //中断溢出标志}/********************************************************/ void StartModule() //启动模块{TX=1; //启动一次模块_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();TX=0;}//--------------------------------------------void fun2(void){ P10=1;P11=0;P12=1;P13=0;} //前进void fun3(void){ P10=0;P11=0;P12=1;P13=0;}//左转void fun4(void){ P10=1;P11=0;P12=0;P13=0;} //右转void fun5(void){ P10=0;P11=0;P12=0;P13=0;}//停止/********************************************************/void timer1() interrupt 3 //T0中断用来计数器溢出,超过测距范围{Flg_5ms=1;TH1=0xee;TL1=0;TF1=0;if(P14==1&&P15==0&&P16==1) fun2();if((P14==0&&P15==0&&P16==1)||(P14==0&&P15==1&&P16==1)) fun3();if((P14==1&&P15==0&&P16==0)||(P14==1&&P15==1&&P16==0)) fun4();if((P14==1&&P15==1&&P16==1)||(P14==0&&P15==0&&P16==0)||(P17==0)) fun5();}//-------------------------------------------void Timer2() interrupt 5 //按时器2捕捉中断,溢出中断{if(TF2){if(speed_t2_ovf_count_temp < 2) speed_t2_ovf_count_temp++;else{speed_frequency = 0; // frequencyspeed_catch1 = 0; //catch 1speed_catch2 = 0; //catch 2speed_catch_p = 0; //catch pointerspeed_t2_ovf_count_temp = 0; //T2 overflow counter temp registerspeed_t2_ovf_count = 0; //T2 overflow counter registerSpeed=0;}TF2=0;}if(EXF2){switch(speed_catch_p){case 0:speed_catch1 = RCAP2H;speed_catch1 <<=8;speed_catch1 += RCAP2L;speed_catch_p++;break;case 1:speed_catch2 = RCAP2H;speed_catch2 <<=8;speed_catch2 += RCAP2L;speed_t2_ovf_count = speed_t2_ovf_count_temp;speed_catch_p++;break;default:break;}speed_t2_ovf_count_temp = 0;EXF2=0;}}/*********************************************************/void main(void){unsigned char TempCyc;unsigned long temp;Delay400Ms(); //启动等待,等LCM讲入工作状态LCMInit(); //LCM初始化Delay5Ms(); //延时片刻(可不要)DisplayListChar(0, 0, mcustudio);DisplayListChar(0, 1, email);ReadDataLCM();//测试用句无心义for (TempCyc=0; T empCyc<10; T empCyc++)Delay400Ms(); //延时DisplayListChar(0, 1, Cls);Speed=0;speed_frequency = 0; // frequencyspeed_catch1 = 0; //catch 1speed_catch2 = 0; //catch 2speed_catch_p = 0; //catch pointerspeed_t2_ovf_count_temp = 0; //T2 overflow counter temp register speed_t2_ovf_count = 0; //T2 overflow counter register while(1){TMOD=0x11; //设T0为方式1,GATE=1;TH0=0;TL0=0;TH1=0xee;TL1=0;T2CON = 0x09; //捕捉模式ET0=1; //许诺T0中断ET1=1; //许诺T0中断ET2=1;EA=1; //开启总中断TR1=1; //开启计数TR2=1;while(1){if(Flg_5ms){Flg_5ms=0;if(Counter_100ms<39){Counter_100ms++;if(Counter_100ms==20){if(speed_catch_p > 1){temp =(unsigned long)(( 65536UL * speed_t2_ovf_count)+ speed_catch2 - speed_catch1); //calculate TSpeed= (unsigned int)(9584640UL / temp);speed_catch_p = 0;}if(Speed >9999U) Speed=9999U;buf[0]=Speed/1000;buf[1]=(Speed/100)%10;buf[2]=(Speed/10)%10;buf[3]=Speed %10;DisplayOneChar(8, 1, ASCII[buf[0]]);DisplayOneChar(9, 1, ASCII[buf[1]]);DisplayOneChar(10, 1, ASCII[buf[2]]);DisplayOneChar(11, 1, ASCII[buf[3]]);DisplayOneChar(12, 1, 'm'); //显示MDisplayOneChar(13,1, 'm'); //显示MDisplayOneChar(14,1, '/');DisplayOneChar(15,1, 's');}}else{Counter_100ms=0;StartModule();// DisplayOneChar(0, 1, ASCII[0]);TH0=0;TL0=0;while(!RX); //当RX为零时等待TR0=1; //开启计数while(RX); //当RX为1计数并等待TR0=0; //关闭计数Conut(); //计算}}}}}。
程序:
#include <reg51.H>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char //宏定义
/*-----------------------端口命名------------------------*/
sbit rs=P2^0; //LCD的数据/命令选择端
sbit rw=P2^1; //LCD的读写选择端
sbit e=P2^2; //LCD的使能信号端
/*-------------------------------------------------------*/
/*-----------------------定义参数------------------------*/
uint i,z,count,zhuan,msec; //定义参数
uchar display[]={" speed= r/min "}; //定义显示参数/*-------------------------------------------------------*/ /*-----------------------毫秒延时------------------------*/
void delay(uint ms)
{
uint i,j; //为延时引入i,j两参数
for (j=0;j<ms;j++) //延时第一循环
for (i=0;i<120;i++); //延时第二循环
}
/*-------------------------------------------------------*/
/*--------------------向LCD1602写命令--------------------*/
void write_command(uchar command)
{
rs=0; //数据、命令选择端0为命令
rw=0; //读、写选择端0为写
P0=command; //向LCD写命令
delay(5); //稍做延迟,代替检测忙状态
e=1; //信号使能端高电平
delay(5); //稍做延迟,代替检测忙状态
e=0; //信号使能端低电平
}
/*-------------------------------------------------------*/
/*--------------------向LCD1602写数据--------------------*/
void write_data(uchar data0)
{
rs=1; //数据、命令选择端1为数据
rw=0; //读、写选择端0为写
P0=data0; //向LCD写数据
delay(5); //稍做延迟,代替检测忙状态
e=1; //信号使能端高电平
delay(5); //稍做延迟,代替检测忙状态
e=0; //信号使能端低电平
}
/*-------------------------------------------------------*/
/*-------------------外部中断0计数程序-------------------*/
void counter(void) interrupt 0
{
EX1=0; //关外部中断1
count++;
if(count==2) //2次循环为发动机转一圈
{
count=1; //初始化计数
z++; //转圈计数加1
} //计数+1
EX1=1; //开外部中断1
return;
}
/*-------------------------------------------------------*/
/*------------------------LCD显示------------------------*/
void displaytolcd()
{
write_command(0x80); //向LCD1602写命令80H
for (i=0;i<sizeof(display)-1;i++) //循环要传输的字符个数次,每一次传一个字符{
write_data(display[i]);
delay(5);
}
} /*-------------------------------------------------------*/
/*-----------------内部中断0计时计数程序-----------------*/
void Timer_0(void) interrupt 1
{
TH0=0x65; //50ms定时
TL0=0xF3;
msec++;
if(msec==20) //50*20=1S
{
displaytolcd();
msec=0;
zhuan=30*z;
z=0;
}
}
/*-------------------------------------------------------*/
/*----------------------端口初始化-----------------------*/
void int_all()
{
z=0; //初始化z的值
count=0; //初始化count的值
zhuan=0; //初始化转的值
rw=0; //选择LCD写数据指令
delay(15); //延时15ms
write_command(0x38); //向LCD1602写命令38H delay(5); //延时5ms
write_command(0x0e); //向LCD1602写命令0EH delay(5); //延时5ms
write_command(0x06); //向LCD1602写命令06H TMOD=0x01; //内部中断定时器选择
TH0=0x66; //50ms定时
TL0=0x50;
EA=1; //开中断总开关
ET0=1; //开内部中断0
TR0=1; //计时器开始工作
IT0=1; //外部中断0为下降沿触发
EX0=1; //开外部中断0
}
/*-------------------------------------------------------*/
/*-----------------------数据处理------------------------*/ void disp_count()
{
display[9]=(zhuan/1000+'0'); //转换转速的千位display[10]=(zhuan/100%10+'0'); //转换转速的百位display[11]=(zhuan/10%10+'0'); //转换转速的十位display[12]=(zhuan%10+'0'); //转换转速的个位
}
/*-------------------------------------------------------*/
/*------------------------主函数-------------------------*/ void main()
{
int_all(); //全局初始化
while(1)
{
disp_count(); //数据处理
displaytolcd(); //LCD显示
}
}
/*-------------------------------------------------------*/
电路图:
捕获.PNG(64.4 KB, 下载次数: 59)
单片机测速电路。