proteus+51单片机+实验(LCD1620、定时器)
目录
1.LCD1602液晶显示屏
1.1基本概念
1.1.1LCD的简介
1.1.2LCD的显示原理
1.1.3LCD的硬件电路
1.1.4LCD的常见指令
1.1.5LCD的时序
1.2代码
1.2.1写命令和写数据操作
1.2.2初始化和测试代码
1. 3.3功能函数
1.3proteus代码
1.3.1器件代码
1.3.2总体Proteus
编辑 2.定时器
2.1基本概念
2.1.1定时器的简介
2.1.2定时器的计数模式
2.1.3寄存器
编辑 2.1.4中断系统
编辑 编辑
2.2代码
2.2.1定时器初始化代码
2.2.2定时器中断代码
2.2.3计数器函数
2.3proteus仿真
2.3.1定时器总体仿真
2.3.2计数器总体框图
1.LCD1602液晶显示屏
1.1基本概念
1.1.1LCD的简介
-
LCD1602(Liquid Crystal Display)液晶显示屏是一种专门用来显示字母、数字、符号和字符型等的点阵型液晶模块,可以显示ASCII码的标准字符和其它的一些内置特殊字符,还可以有8个自定义字符。
-
它是由字符型液晶显示屏(LCD)、控制驱动主电路HD44780及其扩展驱动电路HD44100,以及少量电阻、电容元件和结构件等装配在PCB板上而组成。该显示屏的优点是耗电量低、体积小、辐射低。
-
显示容量:16×2个字符,每个字符为5*7点阵,、
1.1.2LCD的显示原理
我们所用的LCD屏的命名,基本都是按照其分辨率来进行命名的比如lcd1602就是分辨率为16×2,lcd12864就是分辨率为128×64
-
LCD1602主要用来显示数字、字母、图形以及少量自定义字符。可以显示2行16个字符,拥有16个引脚,其中8位数据总线D0-D7,和RS、R/W、EN三个控制端口,工作电压为5V,并且带有字符对比度调节V0和背光源AK。
-
LCD需要背光源才能亮
- 80个字节的显示缓冲区DDRAM,分两行,地址分别为00H27H,40H67H。
- LCD1602,总共显示为16行2列,对应着32个RAM地址,在使用的时候,需要在哪个位置显示,就写入对应的RAM地址,然后再写入需要的字符,对应就会显示该字符。
- 转义字符(\)
1.1.3LCD的硬件电路
引脚 | 功能 |
VSS | 地 |
VDD | 电源正极(4.5~5.5V) |
VO | 对比度调节电压,即调节LCD的显示 |
RS | 数据/指令选择,1为数据,0为指令 |
RW | 读(read)/写(write)信号线,高电平时进行读操作,低电平时进行写操作。当RS和R/W共同为低电平时可以写入指令或显示地址;当RS为低电平,R/W为高电平时,可以读忙信号;当RS为高电平,R/W为低电平时,可以写入数据 |
E | 使能,1为数据有效,下降沿执行命令 |
D0~D7 | 8位并行数据口,数据输入/输出 |
A | 背光灯电源正极 |
K | 背光灯电源负极 |
1.1.4LCD的常见指令
ASCll码表
- 清屏指令(0x01)
(1)清除液晶显示器,即将DDRAM的内容全部填入“空白”的ASCII码20H;
(2)光标归位,将光标撤回液晶显示屏的左上方;
(3)将地址计数器(AC)的值设置为0;
-
光标复位,光标返回到地址00H
(1) 光标复位到地址00H位置
(2)LCD显示DDRAM的内容不变
-
进入模式设置指令
(1) 功能:设定每次定入1位数据后光标的移位方向,并且设定每次写入的一个字符是否移动。参数设定的情况如下所示:
(2)0=写入新数据后光标左移 ; 1=写入新数据后光标右移;
(3)S—0=写入新数据后显示屏不移动 ;1=写入新数据后显示屏整体右移1个字符
- 显示开关指令
(1)功能 : 控制显示器开/关、光标显示/关闭以及光标是否闪烁。
(2)D(Dispaly):控制整体的显示开与关,高电平表示开显示屏,低电平表示关显示屏
(3)C(Cursor):控制光标的开与关,高电平表示有光标,低电平表示无光标
(4)B(Blink):控制光标是否闪烁,高电平闪烁,低电平不闪烁
-
功能设定指令
(1) 功能 : 设定数据总线位数、显示的行数及字型
(2)DL —— 0=数据总线为4位 ; 1=数据总线为8位;
(3)N —— 0=显示1行 ; 1=显示2行;
(4)F —— 0=5×7点阵/每字符 ; 1=5×10点阵/每字符;
- 光标和显示移位
(1) SC=0,RL=0 :光标左移
(2)SC=0,RL=1 : 光标右移
(3)SC=1,RL=0时,字符和光标都左移
(4)SC=1,RL=1时字符和光标都右移
1.1.5LCD的时序
-
写指令/数据
- 读指令/数据
1.2代码
1.2.1写命令和写数据操作
sbit RS=P3^0;
sbit RW=P3^1;
sbit E=P3^2;
void writecommand(unsigned char command)
{
RS=0; //RS为低电平时此时为读数据
RW=0; //RW为低表示数据写入
E=0; //E=0表示在前半部分,此时数据没有传送无需置高
P2=command; //command为命令
Delay_ms(5);
E=1; //E此时表示传送数据有效
E=0; //E此时表示数据传送完成此时为空闲状态
}
void writedata(unsigned char dat)
{
RS=1; //RS为低电平时此时为读数据
RW=0; //RW为低表示数据写入
E=0; //E=0表示在前半部分,此时数据没有传送无需置高
P2=dat; //command为命令
Delay_ms(5);
E=1; //E此时表示传送数据有效
E=0; //E此时表示数据传送完成此时为空闲状态
}
1.2.2初始化和测试代码
void lcd_init()
{
writecommand(0x38);//设置16×2显示、5×7点阵和8位数据接口
writecommand(0x0C);//设置开启显示,不显示光标
writecommand(0x06);//显示地址地址加1,即写一个数据后,显示位置右移一位
writecommand(0x01);//显示清零,数据指针清零
}
void lcd_test()
{
writecommand(0x80); //LCD的第一行起始地址
Delay_ms(5);
writedata('A');
Delay_ms(5);
writecommand(0x80+0x40); //LCD的第二行起始地址
Delay_ms(5);
writedata('X');
Delay_ms(5);
}
1. 3.3功能函数
/**
* @brief 在LCD中显示一个字符
* @param Line:表示在第几行显示
* @param Column:表示在第几列显示
* @param Char:显示字符
* @retval
*/
void LCD_Showchar(unsigned char Line,unsigned char Column,unsigned char Char)
{
if(Line==1)
{
writecommand(0x80|(Column-1)); //此时在第一行显示
}
else
{
writecommand (0x80|(Column-1)+0x40);//此时在第二行显示,
writedata(Char);
}
}
/**
* @brief 在LCD中显示一个字符串
* @param Line:表示在第几行显示
* @param Column:表示在第几列显示
* @param Char:显示字符串
* @retval
*/
void LCD_Showstring(unsigned char Line,unsigned char Column,unsigned char *String)
{
unsigned char i;
if(Line==1)
{
writecommand(0x80|(Column-1)); //此时在第一行显示
}
else
{
writecommand (0x80|(Column-1)+0x40);//此时在第二行显示,
}
for(i=0;String[i]!='\0';i++)
{
writedata(String[i]);
}
}
/**
* @brief 立方函数
* @param x为分子
* @param y为立方根
*/
int LCD_POW(int x,int y)
{
unsigned char i;
int result=1;
for(i=0;i<y;i++)
{
result*=x;
}
return result;
}
/**
* @brief 设置字符位置
* @param x为行
* @param y为列
*/
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{
unsigned char i;
if(Line==1)
{
writecommand(0x80|(Column-1)); //此时在第一行显示
}
else
{
writecommand (0x80|(Column-1)+0x40);//此时在第二行显示,
}
}
/**
* @brief 设置数字
*/
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned char Num,unsigned char Length)
{
unsigned char i;
LCD_SetCursor(Line,Column);
for(i=Length;i>0;i--)
{
writedata(Num/LCD_POW(10,i-1)%10+0x30);//得到数字的高位);
}
}
1.3proteus代码
1.3.1器件代码
1.3.2总体Proteus
2.定时器
2.1基本概念
2.1.1定时器的简介
(1)STC89C52系列单片机内部设置的两个16位定时器/计数器T0和T1都具有计数方式和定时方式两种工作方式。对每个定时器/计数器(T0和T1),在特殊功能寄存器TM0D中都有一控制位一C/T来选择T0或T1为定时器还是计数器。
(2)定时器/计数器的核心部件是一个加法(也有减法)的计数器,其本质是对脉冲进行计数。只是计数脉冲来源不同:如果计数脉冲来自系统时钟,则为定时方式,此时定时器/计数器每12个时钟或者每6个时钟得到一个计数脉冲,计数值加1;如果计数脉冲来自单片机外部引脚(T0为P3.4,T1为P3.5),则为计数方式,每来一个脉冲加1。
(3)SYSclk:系统时钟,即晶振周期,晶振为12MHz
(4)当定时器/计数器工作在定时模式时,可在烧录用户程序时在STC-ISP编程器中设置(如下
图所示)是系统时钟÷12还是系统时钟÷6后让T0和T1进行计数。当定时器/计数器工作在计数模式时,对外部脉冲计数不分频。
(5)GATE:门控位,用于控制定时/计数器的启动是否受外部中断请求信号的影响。
2.1.2定时器的计数模式
- 模式1(16位定时器/计数器)及其测试程序
- 模式2(8位计数器模式)
- 16位定时器工作方式
(1)计数值为N和初值X关系:X=65536-N(12/fosc),N的单位为us即定义的时间
(2)上次计数完,计数器值为0,要重复计数需重置初值。
fosc为晶振频率,51单片机一般为12MHz或者11.0592MHz
- 16位计数器工作方式
(1)16位定时/计数器方式计数值为N和初值X关系:X=65536-N
(2)上次计数完,计数器值为0,要重复计数需重置初值。
2.1.3寄存器
- 定时器/计数器控制寄存器TCON
- 定时器/计数器工作模式寄存器TMOD
2.1.4中断系统
2.2代码
2.2.1定时器初始化代码
void timerinit()
{
TMOD=0x01; //定时器0工作在16位定时器模式下,TH0、TL0全用
TF0=0; //防止开始定时器溢出产生中断,因此将TF0定时器清零
TH0=(65536-50000)/256; //计时50000us,并且除以2^8相当于右移8位,取出了高八位
TH0=(65536-50000)%256; //取出低八位,
ET0=1; //开启定时器0的中断
EA=1; //开启总中断
TR0=1; //启动定时器0
PT0=0; //配置低优先级
}
2.2.2定时器中断代码
void timer_isr() interrupt 1 //0表示外部中断0:1表示定时器中断0:2表示外部中断1;3表示定时器中断1;4表示串口中断
{
TH0=(65536-50000)/256;
TH0=(65536-50000)%256;
count++;
if(count==10)count=0;
P2=s[count];
// Delay_ms(200);
}
2.2.3计数器函数
void timerinit()
{
TMOD=0x06; //定时器0工作在8位自动重载计数器模式下,TH0、TL0全用
TF0=0; //防止开始计数器溢出产生中断,因此将TF0计数器清零
TH0=256-3; //计数值为3,由于是8位所以不需要将数据取出
TH0=256-3; //计数器3
ET0=1; //开启定时器0的中断
EA=1; //开启总中断
TR0=1; //启动定时器0
PT0=0; //配置低优先级
}
void count_isr() interrupt 1 //0表示外部中断0:1表示定时器中断0:2表示外部中断1;3表示定时器中断1;4表示串口中断
{
num++; //每隔3次,进入计数器的中断函数使得Num的值加1
}