Proteus-32单片机与LCD1602屏幕实现按键值显示功能详解

0、LCD1602屏幕介绍

LCD1602 是一种常见的字符型液晶显示屏,广泛应用于各种电子设备中,用于显示文本信息。它通常具有16个字符宽和2行的显示能力,因此得名“LCD1602”。以下是关于LCD1602的详细介绍,包括其特点、引脚定义、工作原理以及如何与微控制器(如51单片机或STM32)连接和控制。


  •  LCD1602的特点

  • 显示能力:16个字符宽,2行显示,共32个字符。

  • 字符集:内置5×8点阵字符集,支持ASCII字符和部分扩展字符。

  • 接口类型:并行数据接口,支持4位或8位数据传输。

  • 背光:部分型号带有背光功能,可在低光环境下使用。

  • 低功耗:工作电压通常为4.5V至5.5V,功耗低。

  • 易于控制:通过简单的指令集控制显示内容。


  • 引脚定义

  • LCD1602通常有16个引脚,具体定义如下:

    引脚号 引脚名称 功能描述
    1 VSS 地(GND)
    2 VDD 电源正极(+5V)
    3 V0 对比度调整(通过电位器调节)
    4 RS 寄存器选择(0=指令寄存器,1=数据寄存器)
    5 RW 读写选择(0=写,1=读)
    6 E 使能信号(上升沿触发)
    7-14 D0-D7 数据线(8位数据传输)
    15 A 背光正极(部分型号)
    16 K 背光负极(部分型号)

  • .工作原理
  • LCD1602通过并行数据接口与微控制器通信,支持4位和8位数据传输模式。以下是其基本工作原理:

    (1)指令和数据传输
  • 指令寄存器:用于接收控制指令(如清屏、设置光标位置等)。

  • 数据寄存器:用于接收要显示的字符数据。

  • RS引脚:用于选择当前操作是写入指令还是数据。

  • RW引脚:用于选择当前操作是写入还是读取。

  • E引脚:使能信号,上升沿触发数据或指令的读取。

  • (2)显示控制
  • 清屏指令:清除显示内容。

  • 光标控制:设置光标位置。

  • 字符显示:将字符数据写入指定位置。


  • 初始化和控制

  • 以下是使用51单片机控制LCD1602的初始化和控制代码示例:

    (1)硬件连接
  • 数据线(D0-D7)连接到51单片机的P0口。

  • 控制线

  • RS:连接到P2^0。

  • RW:连接到P2^1。

  • E:连接到P2^2。

  • 电源和地:连接到51单片机的电源和地。

  • 1、开发环境

  • proteus8.17 :制作stm32f103c8t6 和lcd1602连接电路图
  • keil mdk 编写stm32工程实现代码
  • 2、LCD1602.h代码

     

    #ifndef __LCD1602_H
    #define __LCD1602_H
    
    
    #include"stm32f10x.h"
    
    //lcd1602引脚定义
    #define LCD1602_Timer_GPIOA RCC_APB2Periph_GPIOA
    #define LCD1602_Timer_GPIOB RCC_APB2Periph_GPIOB
    #define LCD1602_GPIOA GPIOA
    #define LCD1602_GPIOB GPIOB
    #define LCD1602_RS GPIO_Pin_8
    #define LCD1602_RW GPIO_Pin_6
    #define LCD1602_E GPIO_Pin_7
    #define LCD1602_IO GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15
    
    #define LCD1602_I0_SET() GPIO_SetBits(GPIOB, LCD1602_IO)
    
    #define LCD1602_RS_SET() GPIO_SetBits(GPIOA,LCD1602_RS)
    #define LCD1602_RS_RESET() GPIO_ResetBits(GPIOA,LCD1602_RS)
    
    #define LCD1602_RW_SET() GPIO_SetBits(GPIOB,LCD1602_RW)
    #define LCD1602_RW_RESET() GPIO_ResetBits(GPIOB,LCD1602_RW)
    
    #define LCD1602_E_SET() GPIO_SetBits(GPIOB,LCD1602_E)
    #define LCD1602_E_RESET() GPIO_ResetBits(GPIOB,LCD1602_E)
    
       
    //初始化函数
    void LCD1602_Init(void);
    //显示数字 
    
    void LCD1602_ShowNum(unsigned char x,unsigned char y,unsigned char *str,unsigned char i);
    /*显示字符串函数
    	x:0,1两行
    	y:0到15个列
    	str:显示字符串
    */
    void LCD1602_ShowStr(unsigned char x,unsigned char y,unsigned char *str);
    //清屏函数
    void LCD1602_Clear(void);
    
    #endif
    

    3、LCD1602.c代码

    #include"lcd1602.h"
    void LCD1602_GPIO_Init_Out()//LCD1602端口初始化,配置为输出
    { 
       
    	 GPIO_InitTypeDef GPIO_InitStructrue;
    	 RCC_APB2PeriphClockCmd(LCD1602_Timer_GPIOA | LCD1602_Timer_GPIOB, ENABLE);//使能端口时钟
    	 GPIO_InitStructrue.GPIO_Mode = GPIO_Mode_Out_OD;//开漏输出
    	 GPIO_InitStructrue.GPIO_Pin = LCD1602_RS; 
    	 GPIO_InitStructrue.GPIO_Speed = GPIO_Speed_10MHz;//低速输出
    	 GPIO_Init(LCD1602_GPIOA, &GPIO_InitStructrue);//初始化
    	
    	 GPIO_InitStructrue.GPIO_Mode = GPIO_Mode_Out_OD;//开漏输出
    	 GPIO_InitStructrue.GPIO_Pin = LCD1602_RW |  LCD1602_E | LCD1602_IO ; 
    	 GPIO_InitStructrue.GPIO_Speed = GPIO_Speed_10MHz;// 低速输出
    	 GPIO_Init(LCD1602_GPIOB, &GPIO_InitStructrue);//初始化
    }
    
    void LCD1602_GPIO_Init_Inupt()//LCD1602端口初始化,配置为输入
    { 
       
    	 GPIO_InitTypeDef GPIO_InitStructrue;
    	 RCC_APB2PeriphClockCmd(LCD1602_Timer_GPIOB, ENABLE);//使能端口时钟
    	 
    	
    	 GPIO_InitStructrue.GPIO_Mode =  GPIO_Mode_IN_FLOATING;//浮空输入
    	 GPIO_InitStructrue.GPIO_Pin =  GPIO_Pin_15; 
    	 GPIO_Init(LCD1602_GPIOB, &GPIO_InitStructrue);//初始化
    }
    
    
    void LCD1602_WaitReady(void)//用于LCD忙检测
    { 
       
    	u8 sta = 0;
      LCD1602_GPIO_Init_Out();//LCD1602端口初始化,配置为输出
    	GPIOB->ODR =0xff00;
      LCD1602_RS_RESET();
    	LCD1602_RW_SET();//读状态
    	LCD1602_GPIO_Init_Inupt();//LCD1602端口初始化,配置为输入
    	do{ 
       
    		LCD1602_E_SET();
    		sta = GPIO_ReadInputDataBit(LCD1602_GPIOB, GPIO_Pin_15);
    		LCD1602_E_RESET();
    	  }
    		while(sta);
    		LCD1602_GPIO_Init_Out();//LCD1602端口初始化,配置为输出
    }
    
    void LCD1602_WriteCmd(u16 cmd)//用于写指令
    { 
       
    	LCD1602_WaitReady();//等待液晶准备好
    	LCD1602_RS_RESET();
    	LCD1602_RW_RESET();//写指令
    	GPIOB->ODR &=((cmd<< 8)|0x0000);
    	LCD1602_E_SET();
    	LCD1602_E_RESET();//高脉冲
    
    }
    
    void LCD1602_WriteDate(u16 date)//用于写数据
    { 
       
    	LCD1602_WaitReady();//等待液晶准备好
    	LCD1602_RS_SET();
    	LCD1602_RW_RESET();//写数据
    	GPIOB->ODR &=((date << 8)|0x0000);
    	LCD1602_E_SET();
    	LCD1602_E_RESET();//高脉冲
    }
    
    void LCD1620_SetAddress(unsigned char x,unsigned char y)
    { 
       
    	if(y == 0)
    	LCD1602_WriteCmd(0x80 | x);//从第一行开始显示
    	else 
    	LCD1602_WriteCmd(0x80 | 0x40 | x);//从第二行开始显示
    }
    
    void LCD1602_ShowStr(unsigned char x,unsigned char y,unsigned char *str)//LCD1602显示字符串
    { 
       
    	LCD1620_SetAddress(x,y);//设置数据地址指针
    	while(*str != '\0')
    	LCD1602_WriteDate(*str++);//写数据 
    }
    
    void LCD1602_ShowChar(unsigned char x,unsigned char y,unsigned char date)//LCD1602显示字符
    { 
       
    	LCD1620_SetAddress(x,y);//设置数据地址指针
    	LCD1602_WriteDate(date);//写数据 
    }
                   
    void LCD1602_ShowNum(unsigned char x,unsigned char y,unsigned char *str,unsigned char i)//LCD1602显示数字
    { 
       
    	LCD1620_SetAddress(x,y);//设置数据地址指针
    	str = str+ i;
    	LCD1602_WriteDate(*str);//写数据
    }
    
     void LCD1602_Init(void)//液晶初始化函数
    { 
       
    	LCD1602_GPIO_Init_Out();
    	LCD1602_WriteCmd(0x38);//设置16*2显示,5*7点阵,8位数据接口
    	LCD1602_WriteCmd(0x0c);//开显示,显示光标,光标不闪烁
    	LCD1602_WriteCmd(0x06);//光标加1,屏幕显示不移动
    	LCD1602_WriteCmd(0x01);//清屏
    }
    
    void LCD1602_Clear(void)
    {
    
    	LCD1602_WriteCmd(0x01);//清屏
    }
    

    4、key.c key.h按键代码

    #include "stm32f10x.h"                  // Device header
    #include "delay.h" 
    
    
    
    
    /**
      * 函    数:按键初始化
      * 参    数:无
      * 返 回 值:无
      */
    void Key_Init(void)
    {
    	/*开启时钟*/
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);		//开启GPIOB的时钟
    	
    	/*GPIO初始化*/
    	GPIO_InitTypeDef GPIO_InitStructure;
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 |GPIO_Pin_14  ;
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_Init(GPIOA, &GPIO_InitStructure);						//将PB1和PB11引脚初始化为上拉输入
    }
    
    /**
      * 函    数:按键获取键码
      * 参    数:无
      * 返 回 值:按下按键的键码值,范围:0~2,返回0代表没有按键按下
      * 注意事项:此函数是阻塞式操作,当按键按住不放时,函数会卡住,直到按键松手
      */
    
    uint8_t Key_GetNum(void)
    {
    	uint8_t KeyNum = 0;		//定义变量,默认键码值为0
    	
    
    		//按键1 检测
    	if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_13) == 0)			//读PB1输入寄存器的状态,如果为0,则代表按键1按下
    	{
    		Delay_ms(100);											//延时消抖
    		while (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_13) == 0);	//等待按键松手
    		//Delay_ms(2);											//延时消抖
    		KeyNum = 1;												//置键码为1
    	}
    	//按键2 检测
    	if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_14) == 0)			//读PB11输入寄存器的状态,如果为0,则代表按键2按下
    	{
    		Delay_ms(100);											//延时消抖
    		while (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_14) == 0);	//等待按键松手
    		//Delay_ms(2);											//延时消抖
    		KeyNum = 2;												//置键码为2
    	}
    	
    
    	
    	return KeyNum;			//返回键码值,如果没有按键按下,所有if都不成立,则键码为默认值0
    }
    

    #ifndef __KEY_H
    #define __KEY_H
    #include "stm32f10x.h"                  // Device header
    
    void Key_Init(void);
    uint8_t Key_GetNum(void);
    
    #endif
    

     5、主函数代码

    #include "stm32f10x.h"                  // Device header
    #include "lcd1602.h" 
    #include "stdio.h" 
    
    #include "Key.h" 
    
    
    char time=30;
    
    void Buzzer_delay(u32 ms)
    {
    	while(ms--);
    }
    
    //蜂鸣器
    void Buzzer_Init(void)
    {
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
        GPIO_InitTypeDef GPIO_InitStruct;
        GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
        GPIO_InitStruct.GPIO_Pin=GPIO_Pin_10;
        GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
        GPIO_Init(GPIOA,&GPIO_InitStruct);
        GPIO_WriteBit(GPIOA,GPIO_Pin_10,(BitAction)0);	//输出高电平 GPIO_SetBits(GPIOA, GPIO_Pin_0)
    }
    //蜂鸣器驱动
    
    void Buzzer_run(uint16_t xms)
    {
    			uint16_t i;
    			for(i=0;i<xms;i++)
    			{
    					GPIO_WriteBit(GPIOA,GPIO_Pin_10,(BitAction)1);
    					Buzzer_delay(2);
    					GPIO_WriteBit(GPIOA,GPIO_Pin_10,(BitAction)1);
    					Buzzer_delay(2);
    			}
    }
    
    
    //主函数
    int main(void)
    {
      unsigned char getKey,count=0;
    	char buff5[16];
    	LCD1602_Init();//lcd1602初始化
    	Key_Init();//按键初始化
    	//Buzzer_Init();//蜂鸣器初始化
    
    	LCD1602_ShowStr(0,0,"Hello Everyone!");
    	LCD1602_ShowStr(0,1,"Testing:");
    	count=2;
    	while (1)
    	{
    	
    		getKey=Key_GetNum();
    	
    		if(getKey ==1)
    		{
    			count=count+1;
    			if(count>10)
    			{
    				count=0;
    			}
    			
    		}
    		if(getKey ==2)
    		{
    			count=count-1;
    			if(count<0)
    			{
    				count=10;
    			}
    			
    		}
    //		if(count>5)
    //		{
    //			Buzzer_run(20);
    //		}
    		//显示数字
    		sprintf(buff5,"%d",count);
    		LCD1602_ShowStr(9,1,(unsigned char *)buff5);
    		Buzzer_delay(4000);
    
    		
    	}//while line
    	
    }
    

     6、proteus 电路连接图

    7、实现效果:左按键+数值,右按键-数值

     

    作者:瓢儿菜2018

    物联沃分享整理
    物联沃-IOTWORD物联网 » Proteus-32单片机与LCD1602屏幕实现按键值显示功能详解

    发表回复