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. 3.3功能函数)

1.3proteus代码

1.3.1器件代码

1.3.2总体Proteus

[​编辑​ 2.定时器](#编辑 2.定时器)

2.1基本概念

2.1.1定时器的简介

2.1.2定时器的计数模式

2.1.3寄存器

[​编辑 2.1.4中断系统](#编辑 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写命令和写数据操作

cpp 复制代码
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初始化和测试代码

cpp 复制代码
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功能函数

cpp 复制代码
/**
 * @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定时器初始化代码

cpp 复制代码
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定时器中断代码

cpp 复制代码
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计数器函数

cpp 复制代码
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
}

2.3proteus仿真

2.3.1定时器总体仿真

2.3.2计数器总体框图

相关推荐
MGT_97969 小时前
ESP01的AT指令连接到阿里云平台
嵌入式硬件·物联网·阿里云·云计算
OH五星上将10 小时前
如何编译OpenHarmony SDK API
嵌入式硬件·移动开发·api·sdk·harmonyos·openharmony·鸿蒙开发
我的老子姓彭13 小时前
STM32启用FPU浮点运算
stm32·单片机·嵌入式硬件
AI+程序员在路上13 小时前
STM32读写内部flash
stm32·单片机·嵌入式硬件
沐欣工作室_lvyiyi16 小时前
基于单片机的风机故障检测装置的设计与实现(论文+源码)
stm32·单片机·嵌入式硬件·物联网·毕业设计
OH五星上将16 小时前
如何更换OpenHarmony SDK API 10
驱动开发·嵌入式硬件·sdk·harmonyos·openharmony·鸿蒙开发
马浩同学17 小时前
【ESP32】Arduino开发 | 中断矩阵+按键输入中断例程
c语言·单片机·嵌入式硬件·mcu
c106389151419 小时前
STM32之FMC—扩展外部 SDRAM
stm32·单片机·嵌入式硬件·fmc
CV金科21 小时前
蓝桥杯-STM32G431RBT6(解决LCD与LED引脚冲突的问题)
c语言·stm32·单片机·嵌入式硬件·蓝桥杯
每天的积累21 小时前
STM32与ESP8266的使用
stm32·单片机·嵌入式硬件