guoqing_ 2023-11-27 22:30 采纳率: 46.2%
浏览 45

LCD1602 显示一行方块

LCD1602 显示一行方块,并未按照代码显示内容,经测试硬件没有问题 (绝大部代码已被注释只保留了按键和LCD1602的代码,其中只有main是自己写的,其他都是引用江科大的应该没有问题)

#include <REGX52.H>
#include "Delay.h"
#include "Key.h"
#include "Nixie.h"
#include "Timer0.h"
#include "LCD1602.h"
#include "int0.h"
sbit Motor=P1^0;

unsigned int Compare=0;    
unsigned char KeyNum;
unsigned int hallnumber=0,speed,halltime=0;

void main ()
{
    //int0_init();  //外部中断用于霍尔元件测速
    //Timer0_Init(); //计时器0初始化
    LCD_Init();
    while(1)
    {
          
          KeyNum=Key();
          if(KeyNum==1){Compare=0; }    
            if(KeyNum==2){Compare=Compare+10;}
            if(KeyNum==3){Compare=Compare-10;}
            if(KeyNum==4){Compare=100;}
            LCD_ShowNum(1,1,Compare,3);
            LCD_ShowChar(2,1,);
           //LCD_ShowNum(1,1,Compare,3);
            //显示compare 占空比
          //if(halltime==100)  //0.1s 计算当前转速
            //{
            //    speed=hallnumber*100;
            //    hallnumber=0;
            //    halltime=0;
            //}
            //LCD_ShowString(1,5,"speed:");
         // LCD_ShowNum(1,11,speed,4);
    }
}

#include <REGX52.H>
#include "Delay.h"

/**
  * @brief  获取独立按键键码
  * @param  无
  * @retval 按下按键的键码,范围:0~4,无按键按下时返回值为0
  */
unsigned char Key()
{
    unsigned char KeyNumber=0;
    
    if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);KeyNumber=1;}
    if(P3_0==0){Delay(20);while(P3_0==0);Delay(20);KeyNumber=2;}
    if(P3_2==0){Delay(20);while(P3_2==0);Delay(20);KeyNumber=3;}
    if(P3_3==0){Delay(20);while(P3_3==0);Delay(20);KeyNumber=4;}
    
    return KeyNumber;

  • 写回答

1条回答 默认 最新

  • CSDN-Ada助手 CSDN-AI 官方账号 2023-11-28 08:44
    关注

    【相关推荐】



    • 这篇博客也许可以解决你的问题👉 :LCD1602显示 解决老古董出现的系列问题
    • 您还可以看一下 朱有鹏老师的LCD1602和12864显示器-第1季第17部分课程中的 1.17.3.开始学习LCD1602小节, 巩固相关知识点
    • 除此之外, 这篇博客: LCD1602液晶显示屏在51单片机上的使用中的 LCD1602液晶显示屏在51单片机上的使用 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:

      以下是我在学习使用51单片机时的心得体会,在这里记录我的学习历程,本文使用的教程的代码,如果有侵权的可能,请告知。

      ​ LCD1602液晶屏是我购买的普中51单片机自带的外设之一,学习这一款液晶屏的使用不仅仅在于学习这块液晶屏,更是学习一种连接外设的方式。
      ​ 这一款液 晶屏的屏幕有两行,每一行都有一定的格子去装写入的字符,这个格子的大小可以选择,有5X7和5X10两个选择。
      ​ 以下是1602的引脚说明摘录:
      在这里插入图片描述

      ​ 在以后的程序中,BLA和BLK这两个东西没有接触到,VL这个东西是拿来调整1602的亮度的,VSS和VDD不用多说,是不需要用软件来操作的,剩下的部分就是变成要注意的地方。

      首先介绍1602的几个关键性指令:

      1. 清屏
        在这里插入图片描述
        如图所示,开头两位都是0,这显示了,这是一个命令选择端,并且为写选择端。

      即将 DDRAM 的内容全部填入"空白"的 ASCII码 01H; 并且光标归位,将地址计数器AC的值设为0.

      1. 进入模式设置指令

      在这里插入图片描述
      功能 : 设定每次定入 1 位数据后光标的移位方向 , 并且设定每次写入的一个字符是否移动。参数设定的情况如下所示:

      位名 设置
      I/D 0=写入新数据后光标左移 1=写入新数据后光标右移
      S 0=写入新数据后显示屏不移动 1=写入新数据后显示屏整体右移 1 个字符
      (至于显示屏右移,下文会详细说明)

      1. 显示开关控制指令

      在这里插入图片描述

      ​ 功能:控制显示器开/关、光标显示/关闭以及光标是否闪烁。参数设定的情况如下:

      位名 设置
      D 0=显示功能关 1=显示功能开
      C 0=无光标 1=有光标
      B 0=光标闪烁 1=光标不闪烁

      1. 功能设定指令

      在这里插入图片描述

      功能:设定数据总线位数、显示的行数及字型。参数设定的情况如下:

      位名 设置
      DL 0=数据总线为 4 位 1=数据总线为 8 位 (我用的普中51单片机是默认8位的)
      N 0=显示 1 行 1=显示 2 行
      F 0=5×7 点阵/每字符 1=5×10 点阵/每字符

      ​ 在设置完成之后我们就要明白具体是在哪显示,在哪个位置显示?在对液晶模块的初始化中要先设置其显示模式, 在液晶模块显示字符时光标是自动右移的, 无需人工干预。 每次输入指令前都要判断液晶模块是否处于忙的状态。DDRAM 就是显示数据 RAM ,用来寄存待显示的字符代码。共 80 个字节,其地址和屏幕的对应关系如下表:

      在这里插入图片描述

      这里要注意一下,80个字节,不是每一个都可以出现在屏幕上的,一般来说,出现的只有8*2行,即16个字节,其余的字节是存在的,而且可以存储数据,让他们出来,需要用到显示屏移动的指令。

      要显示字符时要先输入显示字符地址,也就是告诉模块在哪里显示字符,例如第二行第一个字符的地址是 40H, 那么是否直接写入 40H 就可以将光标定位
      在第二行第一个字符的位置呢?这样不行,因为写入显示地址时要求最高位 D7
      恒定为高电平 1 所以实际写入的数据应该是 01000000B(40H)
      +10000000B(80H)=11000000B(C0H)。

      (总之全部地址都加上80H就对了)

      前面16个字节的地址如下:

      在这里插入图片描述

      以下是操作步骤:

      1602的基本操作

      ①读状态:RS=0,RW=1,E=高脉冲。输出:D0~D7为状态字。

      ②读数据:RS=1,RW=1,E=高脉冲。输出:D0~D7为数据。

      ③写指令:RS=0,RW=0,E=高脉冲。输出:无

      ④写数据:RS=1,RW=0,E=高脉冲。输出:无。

      初始化:根据硬件约定对1602进行启动设置。
      写命令(RS=L)设置显示坐标
      写数据(RS=H)

      操作的具体步骤(代码怎么写):

      首先用一个h文件写下所有的函数定义和变量如下:

      #ifndef __LCD_H_
      #define __LCD_H_
      /**********************************
      当使用的是4位数据传输的时候定义,
      使用8位取消这个定义
      **********************************/
      //#define LCD1602_4PINS
      
      /**********************************
      包含头文件
      **********************************/
      #include<reg51.h>
      
      //---重定义关键词---//
      #ifndef uchar
      #define uchar unsigned char
      #endif
      
      #ifndef uint 
      #define uint unsigned int
      #endif
      
      /**********************************
      PIN口定义
      **********************************/
      #define LCD1602_DATAPINS P0
      sbit LCD1602_E=P2^7;
      sbit LCD1602_RW=P2^5;
      sbit LCD1602_RS=P2^6;
      //普中赠送的开发板原理图有关于使用管脚的说明。
      
      /**********************************
      函数声明
      **********************************/
      /*在51单片机12MHZ时钟下的延时函数*/
      void Lcd1602_Delay1ms(uint c);   //误差 0us
      /*LCD1602写入8位命令子函数*/
      void LcdWriteCom(uchar com);
      /*LCD1602写入8位数据子函数*/	
      void LcdWriteData(uchar dat)	;
      /*LCD1602初始化子程序*/		
      void LcdInit();						  
      
      #endif
      

      然后是c文件进行函数的各种定义,包括初始化等函数

      #include "lcd.h"
      
      /*******************************************************************************
      * 函 数 名         : Lcd1602_Delay1ms
      * 函数功能		   : 延时函数,延时1ms
      * 输    入         : c
      * 输    出         : 无
      * 说    名         : 该函数是在12MHZ晶振下,12分频单片机的延时。
      *******************************************************************************/
      
      void Lcd1602_Delay1ms(uint c)   //误差 0us
      {
          uchar a,b;
      	for (; c>0; c--)
      	{
      		 for (b=199;b>0;b--)
      		 {
      		  	for(a=1;a>0;a--);
      		 }      
      	}
          	
      }
      
      /*******************************************************************************
      * 函 数 名         : LcdWriteCom
      * 函数功能		   : 向LCD写入一个字节的命令
      * 输    入         : com
      * 输    出         : 无
      *******************************************************************************/
      #ifndef 	LCD1602_4PINS	 //当没有定义这个LCD1602_4PINS时
      void LcdWriteCom(uchar com)	  //写入命令
      {
      	LCD1602_E = 0;     //使能
      	LCD1602_RS = 0;	   //选择发送命令
      	LCD1602_RW = 0;	   //选择写入
      	
      	LCD1602_DATAPINS = com;     //放入命令
      	Lcd1602_Delay1ms(1);		//等待数据稳定
      
      	LCD1602_E = 1;	          //写入时序
      	Lcd1602_Delay1ms(5);	  //保持时间
      	LCD1602_E = 0;
      }
      #else //因为普中51单片机默认是8字节通道,所以上面的函数无效,直接跳入下方的函数
      void LcdWriteCom(uchar com)	  //写入命令
      {
      	LCD1602_E = 0;	 //使能清零
      	LCD1602_RS = 0;	 //选择写入命令
      	LCD1602_RW = 0;	 //选择写入
      
      	LCD1602_DATAPINS = com;	//由于4位的接线是接到P0口的高四位,所以传送高四位不用改
      	Lcd1602_Delay1ms(1);
      
      	LCD1602_E = 1;	 //写入时序
      	Lcd1602_Delay1ms(5);
      	LCD1602_E = 0;
      
      	LCD1602_DATAPINS = com << 4; //发送低四位
      	Lcd1602_Delay1ms(1);
      
      	LCD1602_E = 1;	 //写入时序
      	Lcd1602_Delay1ms(5);
      	LCD1602_E = 0;
      }
      #endif
      /*******************************************************************************
      * 函 数 名         : LcdWriteData
      * 函数功能		   : 向LCD写入一个字节的数据
      * 输    入         : dat
      * 输    出         : 无
      *******************************************************************************/		   
      #ifndef 	LCD1602_4PINS		   
      void LcdWriteData(uchar dat)			//写入数据
      {
      	LCD1602_E = 0;	//使能清零
      	LCD1602_RS = 1;	//选择输入数据
      	LCD1602_RW = 0;	//选择写入
      
      	LCD1602_DATAPINS = dat; //写入数据
      	Lcd1602_Delay1ms(1);
      
      	LCD1602_E = 1;   //写入时序
      	Lcd1602_Delay1ms(5);   //保持时间
      	LCD1602_E = 0;
      }
      #else
      void LcdWriteData(uchar dat)			//写入数据
      {
      	LCD1602_E = 0;	  //使能清零
      	LCD1602_RS = 1;	  //选择写入数据
      	LCD1602_RW = 0;	  //选择写入
      
      	LCD1602_DATAPINS = dat;	//由于4位的接线是接到P0口的高四位,所以传送高四位不用改
      	Lcd1602_Delay1ms(1);
      
      	LCD1602_E = 1;	  //写入时序
      	Lcd1602_Delay1ms(5);
      	LCD1602_E = 0;
      
      	LCD1602_DATAPINS = dat << 4; //写入低四位
      	Lcd1602_Delay1ms(1);
      
      	LCD1602_E = 1;	  //写入时序
      	Lcd1602_Delay1ms(5);
      	LCD1602_E = 0;
      }
      #endif
      /*******************************************************************************
      * 函 数 名       : LcdInit()
      * 函数功能		 : 初始化LCD屏
      * 输    入       : 无
      * 输    出       : 无
      *******************************************************************************/		   
      #ifndef		LCD1602_4PINS
      void LcdInit()						  //LCD初始化子程序
      {
       	LcdWriteCom(0x38);  //开显示
      	LcdWriteCom(0x0c);  //开显示不显示光标
      	LcdWriteCom(0x06);  //写一个指针加1
      	LcdWriteCom(0x01);  //清屏
      	LcdWriteCom(0x80);  //设置数据指针起点
      }
      #else
      void LcdInit()						  //LCD初始化子程序
      {
      	LcdWriteCom(0x32);	 //将8位总线转为4位总线
      	LcdWriteCom(0x28);	 //在四位线下的初始化
      	LcdWriteCom(0x0c);  //开显示不显示光标
      	LcdWriteCom(0x06);  //写一个指针加1
          //这里说的指针加一其实有点模糊,不过应该指的是屏幕移动方向。
      	LcdWriteCom(0x01);  //清屏
      	LcdWriteCom(0x80);  //设置数据指针起点
      }
      #endif
      
      

      剩下就是main.c文件的代码,引入之前的h和c文件,想显示什么,在Main文件中写入即可

      /**************************************************************************************
      *		              LCD1602液晶显示实验												  *
      实现现象:下载程序后插上LCD1602液晶在开发板上,即可显示
      注意事项:如果不想让点阵模块显示,可以将74HC595模块上的JP595短接片拔掉。																				  
      ***************************************************************************************/
      
      #include "reg52.h"			 //此文件中定义了单片机的一些特殊功能寄存器
      #include "lcd.h"
      
      typedef unsigned int u16;	  //对数据类型进行声明定义
      typedef unsigned char u8;
      
      u8 Disp[]=" Pechin Science ";
      
      //如果要显示什么123456789,换一个数组就可以,不过要注意
      //这个液晶屏显示的是字符类变量,如果使用的是int格式,要给它加上'0'.
      
      /*******************************************************************************
      * 函 数 名         : main
      * 函数功能		   : 主函数
      * 输    入         : 无
      * 输    出         : 无
      *******************************************************************************/
      void main(void)
      {
      	u8 i;
      	LcdInit();
      	for(i=0;i<16;i++)
      	{
      		LcdWriteData(Disp[i]);	
      	}
      	while(1);//这里的while是用来防止单片机关闭的,不然的话,几微妙的时间内单片机就运转完了。				
      }
      
      

      最后是1602的原理图,看看就好,以后插外设的时候可以参考一下:
      在这里插入图片描述


    如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^
    评论

报告相同问题?

问题事件

  • 创建了问题 11月27日