精华内容
下载资源
问答
  • STM32驱动lcd1602,并口8 6800时序

    千次阅读 2020-03-13 23:43:49
    STM32驱动lcd1602,并口8 6800时序 LCD1602(3.3V硬件版本)简介 1.1 引脚 引脚,lcd1602采用标准接口,6800时序8并行数据传输。 1 脚:VSS 为地电源。 2 脚:VDD 接 3.3V 正电源。 3 脚:VL 为...

    STM32驱动lcd1602,并口8位 6800时序

    一、LCD1602(3.3V硬件版本)简介

    1.1 引脚

    引脚,lcd1602采用标准接口,6800时序8位并行数据传输。
    引脚
    第 1 脚:VSS 为地电源。
    第 2 脚:VDD 接 3.3V 正电源。
    第 3 脚:VL 为液晶显示器对比度调整端,接正电源时对比度最弱,接地时对比度最高,对
    比度过高时会产生“鬼影”,使用时可以通过一个 10K 的电位器调整对比度。
    第 4 脚:RS 为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。
    第 5 脚:R/W 为读写信号线,高电平时进行读操作,低电平时进行写操作。当 RS 和 R/W
    共同为低电平时可以写入指令或者显示地址,当 RS 为低电平 R/W 为高电平时可以读忙信
    号,当 RS 为高电平 R/W 为低电平时可以写入数据。
    第 6 脚:E 端为使能端,当 E 端由高电平跳变成低电平时,液晶模块执行命令。
    第 7~14 脚:D0~D7 为 8 位双向数据线。
    第 15 脚:背光源正极。
    第 16 脚:背光源负极。

    1.2写数据/命令时序

    写时序

    1.3 命令集

    命令集
    1602 液晶模块的读写操作、屏幕和光标的操作都是通过指令编程来实现的。(说明:1 为高电平、0 为低电平)。
    指令 1:清显示,指令码 01H,光标复位到地址 00H 位置。
    指令 2:光标复位,光标返回到地址 00H。
    指令 3:光标和显示模式设置 I/D:光标移动方向,高电平右移,低电平左移 S:屏幕上所有文字是否左移或者右移。高电平表示有效,低电平则无效。
    指令 4:显示开关控制。 D:控制整体显示的开与关,高电平表示开显示,低电平表示关显示 C:控制光标的开与关,高电平表示有光标,低电平表示无光标 B:控制光标是否闪烁,高电平闪烁,低电平不闪烁。
    指令 5:光标或显示移位 S/C:高电平时移动显示的文字,低电平时移动光标。
    指令 6:功能设置命令 DL:高电平时为 4 位总线,低电平时为 8 位总线 N:低电平时为单行显示,高电平时双行显示 F: 低电平时显示 5x7 的点阵字符,高电平时显示 5x10 的点阵字符。
    指令 7:字符发生器 RAM 地址设置。
    指令 8:DDRAM 地址设置。
    指令 9:读忙信号和光标地址 BF:为忙标志位,高电平表示忙,此时模块不能接收命令或者数据,如果为低电平表示不忙。
    指令 10:写数据。
    指令 11:读数据。

    1.4 存储映射

    存储映射
    注意:写地址时格式:写地址命令0x80 | 地址

    1.5 基本初始化步骤

    初始化步骤

    1.6 复位

    复位

    二、程序实现

    2.1 stm32初始化

    在cubemx中进行gpio、rcc、sys、uart等必要的初始化。其中,lcd1602连接引脚分配如下:

    引脚 功能 初始化
    B3 RS output,pushpull,pullup,high
    B4 RW output,pushpull,pullup,high
    B5 E output,pushpull,pullup,high
    B8-B15 D0-D7 output,pushpull,pullup,high

    2.2 LCD.H

    
    ```c
    /********************************Copyright (c)**********************************\
    **
    **                   (c) Copyright 2020, Main, China, QD.
    **                           All Rights Reserved
    **
    **                                By(wo4fisher)
    **                           http://www.wo4fisher.com
    **
    **----------------------------------文件信息------------------------------------
    ** 文件名称: lcd1602.h
    ** 创建人员: wht
    ** 创建日期: 2020-03-13
    ** 文档描述: 
    **
    **----------------------------------版本信息------------------------------------
    ** 版本代号: V0.1
    ** 版本说明: 初始版本
    **
    **------------------------------------------------------------------------------
    \********************************End of Head************************************/
    
    #ifndef __LCD1602_H_
    #define __LCD1602_H_
    #include "main.h"
    #include "usart.h"
    #include "gpio.h"
    
    
    /*
    +++   Nima Askari
    +++   www.github.com/NimaLTD
    +++   www.instagram.com/github.NimaLTD
    +++   Version: 1.1.0
    */
    
    void LCD_Init(void);
    void LCD_DisplayOn(void);
    void LCD_DisplayOff(void);
    void LCD_Clear(void);
    void LCD_Puts(uint8_t x, uint8_t y, char* str);
    void LCD_BlinkOn(void);
    void LCD_BlinkOff(void);
    void LCD_CursorOn(void);
    void LCD_CursorOff(void);
    void LCD_ScrollLeft(void);
    void LCD_ScrollRight(void);
    void LCD_CreateChar(uint8_t location, uint8_t* data);
    void LCD_PutCustom(uint8_t x, uint8_t y, uint8_t location);
    void LCD_Put(uint8_t Data);
    
    #endif
    /********************************End of File************************************/
    
    

    程序参考了github里Nima Askari的代码

    2.3 lcd.c

    /********************************Copyright (c)**********************************\
    **
    **                   (c) Copyright 2020, Main, China, QD.
    **                           All Rights Reserved
    **
    **                                 By(wo4fisher)
    **                           http://www.wo4fisher.com
    **
    **----------------------------------文件信息------------------------------------
    ** 文件名称: lcd1602.c
    ** 创建人员: wht
    ** 创建日期: 2020-03-13
    ** 文档描述: 
    **
    **----------------------------------版本信息------------------------------------
    ** 版本代号: V0.1
    ** 版本说明: 初始版本
    **
    **------------------------------------------------------------------------------
    \********************************End of Head************************************/
    #include "lcd1602.h"
    //############################################################
    #define _LCD_COLS         16
    #define _LCD_ROWS         2
    //############################################################
    /*****  GPIOB3  H:data;L:command  ******/
    #define  LCD1602_RS_DATA	   		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,GPIO_PIN_SET)		
    #define  LCD1602_RS_CMD					HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,GPIO_PIN_RESET)
    /*****  GPIOB4  H:read;L:write  ******/
    #define  LCD1602_RW_READ        HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_SET)
    #define  LCD1602_RW_WRITE       HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_RESET)
    /*****  GPIOB5    ******/
    #define  LCD1602_E_HIGH           HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET)
    #define  LCD1602_E_LOW          HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_RESET)
    
    #define  LCD1602_DATA(x)				GPIOB->ODR=(GPIOB->ODR & 0x00ff) | (x<<8)
    //############################################################
    /* Commands*/
    #define LCD_CLEARDISPLAY        0x01
    #define LCD_RETURNHOME          0x02
    #define LCD_ENTRYMODESET        0x04
    #define LCD_DISPLAYCONTROL      0x08
    #define LCD_CURSORSHIFT         0x10
    #define LCD_FUNCTIONSET         0x20
    #define LCD_SETCGRAMADDR        0x40
    #define LCD_SETDDRAMADDR        0x80
    /* Flags for display entry mode */
    #define LCD_ENTRYRIGHT          0x00
    #define LCD_ENTRYLEFT           0x02
    #define LCD_ENTRYSHIFTINCREMENT 0x01
    #define LCD_ENTRYSHIFTDECREMENT 0x00
    /* Flags for display on/off control */
    #define LCD_DISPLAYON           0x04
    #define LCD_CURSORON            0x02
    #define LCD_BLINKON             0x01
    /* Flags for display/cursor shift */
    #define LCD_DISPLAYMOVE         0x08
    #define LCD_CURSORMOVE          0x00
    #define LCD_MOVERIGHT           0x04
    #define LCD_MOVELEFT            0x00
    /* Flags for function set */
    #define LCD_8BITMODE            0x10
    #define LCD_4BITMODE            0x00
    #define LCD_2LINE               0x08
    #define LCD_1LINE               0x00
    #define LCD_5x10DOTS            0x04
    #define LCD_5x8DOTS             0x00
    //############################################################
    //############################################################
    typedef struct {
    uint8_t DisplayControl;
    uint8_t DisplayFunction;
    uint8_t DisplayMode;
    uint8_t currentX;
    uint8_t currentY;
    } LCD_Options_t;
    //############################################################
    /* Private functions */
    static void LCD_Cmd(uint8_t cmd);
    static void LCD_Data(uint8_t data);
    static void LCD_CursorSet(uint8_t col, uint8_t row);
    static void LCD_EnBlink(void);
    //############################################################
    /* Private variable */
    static LCD_Options_t LCD_Opts;
    //############################################################
    void  LCD_Delay_us(uint16_t  us)
    {
        uint32_t  Div = (SysTick->LOAD+1)/1000;
        uint32_t  StartMicros = HAL_GetTick()*1000 + (1000- SysTick->VAL/Div);
        while((HAL_GetTick()*1000 + (1000-SysTick->VAL/Div)-StartMicros < us));
    }
    //############################################################
    void  LCD_Delay_ms(uint8_t  ms)
    {
        HAL_Delay(ms);
    }
    //############################################################
    void LCD_Init(void)
    {
      /* Set cursor pointer to beginning for LCD */
        LCD_Opts.currentX = 0;
        LCD_Opts.currentY = 0;
        LCD_Opts.DisplayFunction = LCD_8BITMODE | LCD_5x8DOTS | LCD_1LINE;
        if (_LCD_ROWS > 1)
        LCD_Opts.DisplayFunction |= LCD_2LINE;
      /* Set # lines, font size,8BITMODE,etc. */
        LCD_Cmd(LCD_FUNCTIONSET | LCD_Opts.DisplayFunction);
      /* Turn the display on with no cursor or blinking default */
        LCD_Opts.DisplayControl = LCD_DISPLAYON;
        LCD_DisplayOn();
        /* Default font directions 文字不动,地址自动+1*/
        LCD_Opts.DisplayMode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
        LCD_Cmd(LCD_ENTRYMODESET | LCD_Opts.DisplayMode);
        LCD_Clear();
        LCD_Delay_ms(5);
    }
    //############################################################
    void LCD_Clear(void)
    {
        LCD_Cmd(LCD_CLEARDISPLAY);
        LCD_Delay_ms(5);
    }
    //############################################################
    void LCD_Puts(uint8_t x, uint8_t y, char* str)
    {
        LCD_CursorSet(x, y);
        while (*str) {
            if (LCD_Opts.currentX >= _LCD_COLS)/*移动到下一行*/ {
                LCD_Opts.currentX = 0;
                LCD_Opts.currentY++;
                LCD_CursorSet(LCD_Opts.currentX, LCD_Opts.currentY);
            }
            if (*str == '\n') /*换行,列对其*/{
                LCD_Opts.currentY++;
                LCD_CursorSet(LCD_Opts.currentX, LCD_Opts.currentY);
            } else if (*str == '\r') /*回车,换行回行首*/{
                LCD_CursorSet(0, LCD_Opts.currentY);
            } else {
                LCD_Data(*str);
                LCD_Opts.currentX++;
            }
            str++;
        }
    }
    //############################################################
    void LCD_DisplayOn(void)
    {
        LCD_Opts.DisplayControl |= LCD_DISPLAYON;
        LCD_Cmd(LCD_DISPLAYCONTROL | LCD_Opts.DisplayControl);
    }
    //############################################################
    void LCD_DisplayOff(void)
    {
        LCD_Opts.DisplayControl &= ~LCD_DISPLAYON;
        LCD_Cmd(LCD_DISPLAYCONTROL | LCD_Opts.DisplayControl);
    }
    //############################################################
    void LCD_BlinkOn(void)
    {
        LCD_Opts.DisplayControl |= LCD_BLINKON;
        LCD_Cmd(LCD_DISPLAYCONTROL | LCD_Opts.DisplayControl);
    }
    //############################################################
    void LCD_BlinkOff(void)
    {
        LCD_Opts.DisplayControl &= ~LCD_BLINKON;
        LCD_Cmd(LCD_DISPLAYCONTROL | LCD_Opts.DisplayControl);
    }
    //############################################################
    void LCD_CursorOn(void)
    {
        LCD_Opts.DisplayControl |= LCD_CURSORON;
        LCD_Cmd(LCD_DISPLAYCONTROL | LCD_Opts.DisplayControl);
    }
    //############################################################
    void LCD_CursorOff(void)
    {
        LCD_Opts.DisplayControl &= ~LCD_CURSORON;
        LCD_Cmd(LCD_DISPLAYCONTROL | LCD_Opts.DisplayControl);
    }
    //############################################################
    void LCD_ScrollLeft(void)
    {
        LCD_Cmd(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT);
    }
    //############################################################
    void LCD_ScrollRight(void)
    {
        LCD_Cmd(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT);
    }
    //############################################################
    void LCD_CreateChar(uint8_t location, uint8_t *data)
    {
        uint8_t i;
      /* We have 8 locations available for custom characters */
        location &= 0x07;
        LCD_Cmd(LCD_SETCGRAMADDR | (location << 3));
    
        for (i = 0; i < 8; i++) {
            LCD_Data(data[i]);
        }
    }
    //############################################################
    void LCD_PutCustom(uint8_t x, uint8_t y, uint8_t location)
    {
        LCD_CursorSet(x, y);
        LCD_Data(location);
    }
    //############################################################
    static void LCD_EnBlink(void)
    {
        LCD1602_E_HIGH;
        LCD_Delay_us(50);
        LCD1602_E_LOW;
        LCD_Delay_us(50);
    }
    //############################################################
    static void LCD_Cmd(uint8_t cmd)
    {
        LCD1602_RS_CMD;
        LCD1602_RW_WRITE;
        LCD1602_DATA(cmd);
        LCD_EnBlink();
    }
    //############################################################
    static void LCD_Data(uint8_t data)
    {
        LCD1602_RS_DATA;
        LCD1602_RW_WRITE;
        LCD1602_DATA(data);
        LCD_EnBlink();
    }
    //############################################################
    static void LCD_CursorSet(uint8_t col, uint8_t row)
    {
        uint8_t row_offsets[] = {0x00, 0x40, 0x14, 0x54};
        if (row >= _LCD_ROWS)
            row = 0;
        LCD_Opts.currentX = col;
        LCD_Opts.currentY = row;
        LCD_Cmd(LCD_SETDDRAMADDR | (col + row_offsets[row]));
    }
    //############################################################
    void LCD_Put(uint8_t Data)
    {
        LCD_Data(Data);
    }
    //############################################################
    /********************************End of File************************************/
    

    2.4 使用

    在main.c中添加头文件

    #include "lcd1602.h"
    

    在完成了gpio的初始化之后,初始化lcd。

    	LCD_Init();
    

    调用puts函数,在屏幕上显示字符串,加入“\r\n”实现换行。

      LCD_Puts(0,0,"HELLO WORLD!\r\nI'm WHT.");
    

    显示效果:

    显示效果

    2.5 main.c

    /* USER CODE BEGIN Header */
    /**
      ******************************************************************************
      * @file           : main.c
      * @brief          : Main program body
      ******************************************************************************
      * @attention
      *
      * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
      * All rights reserved.</center></h2>
      *
      * This software component is licensed by ST under BSD 3-Clause license,
      * the "License"; You may not use this file except in compliance with the
      * License. You may obtain a copy of the License at:
      *                        opensource.org/licenses/BSD-3-Clause
      *
      ******************************************************************************
      */
    /* USER CODE END Header */
    
    /* Includes ------------------------------------------------------------------*/
    #include "main.h"
    #include "usart.h"
    #include "gpio.h"
    
    /* Private includes ----------------------------------------------------------*/
    /* USER CODE BEGIN Includes */
    #include "lcd1602.h"
    /* USER CODE END Includes */
    
    /* Private typedef -----------------------------------------------------------*/
    /* USER CODE BEGIN PTD */
    
    /* USER CODE END PTD */
    
    /* Private define ------------------------------------------------------------*/
    /* USER CODE BEGIN PD */
    /* USER CODE END PD */
    
    /* Private macro -------------------------------------------------------------*/
    /* USER CODE BEGIN PM */
    
    /* USER CODE END PM */
    
    /* Private variables ---------------------------------------------------------*/
    
    /* USER CODE BEGIN PV */
    
    /* USER CODE END PV */
    
    /* Private function prototypes -----------------------------------------------*/
    void SystemClock_Config(void);
    /* USER CODE BEGIN PFP */
    
    /* USER CODE END PFP */
    
    /* Private user code ---------------------------------------------------------*/
    /* USER CODE BEGIN 0 */
    uint8_t msg[] = "hello world...\n";
    
    /* USER CODE END 0 */
    
    /**
      * @brief  The application entry point.
      * @retval int
      */
    int main(void)
    {
      /* USER CODE BEGIN 1 */
    
      /* USER CODE END 1 */
      
    
      /* MCU Configuration--------------------------------------------------------*/
    
      /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
      HAL_Init();
    
      /* USER CODE BEGIN Init */
    
      /* USER CODE END Init */
    
      /* Configure the system clock */
      SystemClock_Config();
    
      /* USER CODE BEGIN SysInit */
    
      /* USER CODE END SysInit */
    
      /* Initialize all configured peripherals */
      MX_GPIO_Init();
      MX_USART1_UART_Init();
      /* USER CODE BEGIN 2 */
      printf("%s", msg);
    	LCD_Init();
      LCD_Puts(0,0,"HELLO WORLD!\r\nI'm WHT.");
      /* USER CODE END 2 */
    
    
    
      /* Infinite loop */
      /* USER CODE BEGIN WHILE */
      while (1)
      {
        /* USER CODE END WHILE */
    		HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_2);
    		HAL_Delay(1000);
        /* USER CODE BEGIN 3 */
      }
      /* USER CODE END 3 */
    }
    
    /**
      * @brief System Clock Configuration
      * @retval None
      */
    void SystemClock_Config(void)
    {
      RCC_OscInitTypeDef RCC_OscInitStruct = {0};
      RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    
      /** Initializes the CPU, AHB and APB busses clocks 
      */
      RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
      RCC_OscInitStruct.HSEState = RCC_HSE_ON;
      RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
      RCC_OscInitStruct.HSIState = RCC_HSI_ON;
      RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
      RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
      RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL6;
      if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
      {
        Error_Handler();
      }
      /** Initializes the CPU, AHB and APB busses clocks 
      */
      RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                                  |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
      RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
      RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
      RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
      RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    
      if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
      {
        Error_Handler();
      }
    }
    
    /* USER CODE BEGIN 4 */
    
    /* USER CODE END 4 */
    
    /**
      * @brief  This function is executed in case of error occurrence.
      * @retval None
      */
    void Error_Handler(void)
    {
      /* USER CODE BEGIN Error_Handler_Debug */
      /* User can add his own implementation to report the HAL error return state */
    
      /* USER CODE END Error_Handler_Debug */
    }
    
    #ifdef  USE_FULL_ASSERT
    /**
      * @brief  Reports the name of the source file and the source line number
      *         where the assert_param error has occurred.
      * @param  file: pointer to the source file name
      * @param  line: assert_param error line source number
      * @retval None
      */
    void assert_failed(uint8_t *file, uint32_t line)
    { 
      /* USER CODE BEGIN 6 */
      /* User can add his own implementation to report the file name and line number,
         tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
      /* USER CODE END 6 */
    }
    #endif /* USE_FULL_ASSERT */
    
    /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
    
    
    展开全文
  • LCD1602显示电路图大全

    2020-07-14 13:22:06
    例如屏的第一行的亮暗由RAM区的000H——00FH的16字节的内容决定,当(000H)=FFH时,则屏幕的左上角显示一条短亮线,长度为8个点;当(3FFH)=FFH时,则屏幕的右下角显示一条短亮线;当(000H)=FFH,(001H)=00H,...
  • 利用LCD1602显示超声波测距

    千次阅读 2020-04-11 12:17:46
    介绍 一、需要的器件 二、原理 工程代码 一、 LCD1602 二、超声波测距及主程序 。。。...//厘米的小数点后一位 ... Lcd1602_init();... Lcd1602_WriteCom(0x80); //0x80是第一行的第一个字符的地址 。。。。。。

    介绍

    一、需要的器件

    1. 51单片机:任意一款都可以,我这里使用的是STC89C52
    2. LCD1602显示屏:我这里使用的是LCD1602A不带转接板的八位显示屏,是比较正常的一款。
    3. 超声波测距模块:根据价钱的不同有很多可供选择,我这里推荐使用HC-SR04,因为便宜。。。
    4. 杜邦线若干:在这里使用母对母杜邦线。

    二、原理

    LCD1602显示屏的使用原理在我的这篇博客里有很详细的介绍。LCD1602介绍
    超声波模块的原理和使用方法在这篇博客有介绍。超声波测距模块介绍
    当然,我在下面的代码中,会有很多的注释,便于大家理解。

    工程代码

    一、 LCD1602

    在这里我们可以把LCD1602的使用放在一个头文件里,这样以后每次使用,我们都可以直接调用,就不用我们自己每次都要编写了。

    #ifndef __LCD1602_H_
    #define __LCD1602_H_
    #include<reg52.h>
    #include<intrins.h>  //其中有nop函数的定义
    
    /*对于延时很短的,要求在us级的,采用“_nop_”函数,
    这个函数相当汇编NOP指令,延时几微秒。NOP指令为单周期指令,
    可由晶振频率算出延时时间,对于12M晶振,延时1uS。*/
    #define uchar unsigned char
    #define uint unsigned int
    
    #define LCD1602_DATA P0
    sbit RS=P2^6;  //定义数据命令选择端
    sbit RW=P2^5;  //定义读写选择端
    sbit E=P2^7;   //定义使能端
    //注意:具体为哪一个IO口由你自己的接线来定,并不是一定要这样写!
    
      void delay_ms(uint z)  //毫秒级延时函数
        {
           uint i,j;
           for(i=z;i>0;i--)
              for(j=110;j>0;j--);
        }
        //为什么要判忙?
      /*因为LCD1602控制芯片也是一个CPU,
     它在处理上位机发来的某些指令的时候,耗时较长。
     如复位命令,全屏清除命令等。
     另外,LCD1602的CPU速度较慢,上位机较快时,
     LCD1602CPU来不及完成上条命令,会对后续命令不予理睬,
     这样就造成了命令序列不能正确完整地到达LCD1602CPU,以至于显示不正常。*/
     uchar Lcd1602_ReadBusy()   //判断lcd1602是否处于忙的状态,即读忙
        {
           uchar temp;
           RS=0;  //命令
           RW=1;  //读
           _nop_();
           P0=0xff;     //读某IO口数据前,先将该口置为1
           
           /*原因:电路中存在的一个普遍的现象:
       高电平很容易被低电平拉低,而低电平一般不可能被高电平拉高。
       所以在读数据之前将单片机IO口拉高才不会影响原来数据线上的数据!*/
           _nop_();
           E=1;
           _nop_();
           temp=P0;   //读取此时lcd1602的状态字
           _nop_();
           E=0;
           return (temp&0x80);  //如果忙
           /*状态字为temp(8位2进制数)的最高位,
     最高位为1表示禁止读写,
     为0表示允许读写,即temp&0x80
     得1表示忙 ,
     得0表示不忙*/
     }
     /*在lcd1602的资料中,读写操作都有对应的时序图,
     想要理解lcd1602的具体工作流程还得认真研究时序图!*/
      void Lcd1602_WriteCom(uchar com)  //写命令
        {
           while(Lcd1602_ReadBusy());  //判忙
           RS=0;   //命令
           RW=0;   //写
           _nop_();
           LCD1602_DATA=com;   //准备发送命令
           _nop_();//等待命令稳定
           E=1;      //由时序图知,使能端为高电平时才允许数据交换
           _nop_();
           _nop_();
           E=0;      //由时序图知,使能端在完成数据交换后要拉低
           _nop_();
           _nop_();   
        }
        void Lcd1602_WriteData(uchar dat)  //写数据
        {
           while(Lcd1602_ReadBusy());   //判忙
           RS=1;   //数据
           RW=0;   //写
           _nop_();
           LCD1602_DATA=dat;
              _nop_();
           E=1;
           _nop_();
           _nop_();
           E=0;
           _nop_();
           _nop_();   
        }
        void Lcd1602_init()   //初始化函数
        {
           delay_ms(15);
           Lcd1602_WriteCom(0x38);   //显示模式设置
           delay_ms(5);
           Lcd1602_WriteCom(0x38);
           delay_ms(5);
           Lcd1602_WriteCom(0x38);
           Lcd1602_WriteCom(0x0c);  //显示开(开显示不显示光标)
           Lcd1602_WriteCom(0x01);  //显示清屏
           Lcd1602_WriteCom(0x06);  //显示光标(写一个指针加1)
       // Lcd1602_WriteCom(0x80);         //0x80是第一行的第一个字符的地址
       // Lcd1602_WriteCom(0x80+0x40);   //0xc0是第二行的第一个字符的地址
        }
    uchar lcd1602_readData()//读数据
    {
       uchar lcddata;
        LCD1602_DATA = 0xff;   //很重要,不写则读失败          
        E = 0;
        _nop_();
        RS = 1;
        RW = 1;
        E = 1;
        _nop_();
        lcddata = LCD1602_DATA;
        _nop_();
        E = 0;
        return lcddata;
    }
    #endif

    二、超声波测距及主程序

    /*
    主程序:主程序的核心在于中断.这点很重要,超声波测距模块的重点就是在于中断,
    定时器/计数器这部分需要有一定的理解。
    首先对于单片机的IO口进行初始化,LCD1602液晶显示器的初始化,超声波模块的初始化。
    初始化的同时打开了定时器,同时内部中断打开并开始计数操作,
    待超声波的输入端接收到返回波之后关闭内部中断,
    停止计数,接下来通过记到的时间计算被测物的距离(s=time*340/2m)
    */

    //1、定义引脚
    #include<reg52.h>
    #include<LCD1602.h>
    sbit Trig = P2^0;//为了方便大家理解,我直接把名称定义为模块的引脚名
    sbit Echo = P2^1;
    unsigned char BiaoTi[]=" Juli:   ";
    unsigned char code ShuZiBiao[15] = {'0','1','2','3','4','5','6','7','8','9','.','C','M'};//这可以减少很多出错,大家可以理解一下
    unsigned char XianShi[7]    ={ 0,0,0,0,0,0,0};
    //2、设定发送时间
    void Delay10us()
    {
     TMOD |= 0x1;
     TH0 = 0xFF;
     TL0 = 0xF6;
     TR0 = 1;
     while(!TF0);
     TF0 = 0;
    }
    void Rstart()  //启动超声波模块,初始化
    {
     Trig=0;
     Trig=1;
     Delay10us();
     Trig=0;
    }
    //3、获取时间和距离
    int gettime()//获取时间
    {
     unsigned int time = 0;
     time = TH0<<8 | TL0;  //TH0*256+TL0
     return time;
    }
    int Getdis(unsigned int time)  //获取距离 
    {
     unsigned int distance;//整型的原因是方便后续LCD1602屏显示
     distance = (int)time * 0.17;
     TH0=0;
     TL0=0;//清空计时器·
     return distance;
    }
    void star()
    {
     TH0 = 0;
     TL0 = 0;
     TR0 = 1;
    }
    void end()
    {
     TR0 = 0;
    }
    void GetOnce()  //获取一次超声波测距模块的距离
    {
     Rstart();
     while(!Echo);//当Echo为零时等待
     star();
     while(Echo);//当Echo为1计数并等待
     end();
    }
    void delay()
    {
     int i;
     int j;
     for(i=0;i<100;i++)
      for(j = 0;j<2000;j++);
    }
    void main()
    {
     unsigned int time = 0;
     unsigned int i,j;
     unsigned int dis;
     while(1)
     {  
      GetOnce();
      time = gettime();
      dis = Getdis(time);//单位毫米,后面会用厘米显示
      XianShi[0]=dis/1000;//厘米的百位
      XianShi[1]=(dis/100)%10;//厘米的十位
      XianShi[2]=(dis/10)%10;//厘米的个位
      XianShi[3]=10;//显示小数点
      XianShi[4]=dis%10;//厘米的小数点后一位
      XianShi[5]=11;//显示‘C’
      XianShi[6]=12;//显示'M'
      Lcd1602_init();   //初始化函数
      Lcd1602_WriteCom(0x80);  //0x80是第一行的第一个字符的地址
        for (i=0;i<7;i++)
        {
         Lcd1602_WriteData(BiaoTi[i]);
        }
        Lcd1602_WriteCom(0x80+0x40);   //0xc0是第二行的第一个字符的地址
        for (j=0;j<7;j++)
        { 
         Lcd1602_WriteData(ShuZiBiao[XianShi[j]]);
        }
        delay();
        }
     }

    运行图

    运行图

    展开全文
  • // 1、第一行显示 This LCD is OK! 第二行显示 0123456789ABCDEF // 2.5秒过后 // 2、第一行显示自定义字符; // 2.5秒过后 // 3、 在屏幕第一行第2个位置显示9(第0个位置,第1个位置,第2个位置) // 2.5秒过后 //...

    程序验证完全可用,已修正。
    //功能:
    // 1、第一行显示 This LCD is OK! 第二行显示 0123456789ABCDEF
    // 2.5秒过后
    // 2、第一行显示自定义字符(可自己再重新生成);
    // 2.5秒过后
    // 3、 在屏幕第一行第2个位置显示9(第0个位置,第1个位置,第2个位置)
    // 2.5秒过后
    // …
    // 然后开始循环显示

    #include <STC8.H>
    #include <intrins.h>
      
    typedef unsigned char 	uint8_t;
    typedef unsigned int 	uint16_t;
    
    #define LCD1602_DATAPINS P0
    #define LCD1602_E 	P43				//LCD控制脚重新定义
    #define LCD1602_RW  P26
    #define LCD1602_RS	P27
    #define LCD1602_FIRSTLINE	0		//LCD1602第一行
    #define LCD1602_SECONDLINE	1		//LCD1602第二行
    
    bit ubLCD1602Window1Update; 		//LCD1602显示窗口更新位变量
    bit ubLCD1602Window2Update;								   
    bit ubLCD1602Window3Update;
    
    uint8_t code ucPermanentDisplay[] = "This LCD is OK!";
    //uint8_t code Numerical_ASCII[] ={'0','1','2','3','4','5','6','7','8','9'}; 
    uint8_t code Numerical_ASCII[] ="0123456789ABCDEF";//与上一个字符串同样效果
    //自定义的8个5*8点阵字符,可根据需要自己再编辑
    uint8_t code ucArrayDefine[]={	
    								0x1F,0x00,0x1F,0x1F,0x00,0x1F,0x1F,0x1F,
    								0x00,0x1F,0x00,0x00,0x1F,0x00,0x00,0x00,
    								0x02,0x04,0x0F,0x1A,0x0A,0x1F,0x02,0x02,
    								0x10,0x07,0x08,0x08,0x08,0x08,0x07,0x00,	
    								0x00,0x10,0x07,0x08,0x08,0x08,0x08,0x07,	//摄氏度 ℃
    								0x12,0x09,0x04,0x02,0x01,0x00,0x00,0x00,
    								0x12,0x09,0x04,0x12,0x09,0x04,0x02,0x01,
    								0x12,0x09,0x04,0x12,0x09,0x04,0x12,0x09}; 
    
    uint8_t ucDisplayVal;			//0~255的数字变量
    uint8_t ucDisplayValArray[4];	//将0~255数字变量转化为字符变量的对应字符数组(供LCD1602显示)
       
    /**
     * @brief  LCD1602_Delay 
     * @note   当前延时 670ns,时间受规格书时序限制,此处是调整适合自己板子的最小时间
     *			当程序无法运行时,适当将此时间调大,调整到ms级别。
     * @param  none
     * @retval none
     */
    
    void LCD1602_Delay() 	// @24.000MHz	 STC8
    {	  	
    	uint16_t i;
    	i = 3;
    	while (--i);
    }
    
    void Delay5ms()		//@24.000MHz	STC8
    {
    	unsigned char i, j;
    	_nop_();
    	_nop_();
    	i = 156;
    	j = 213;
    	do
    	{
    		while (--j);
    	} while (--i);
    }
    /**
    * @brief  读写检测(读状态,液晶屏状态字) 
    * @note   LCD1602_Delay 延时是关键,在LCD1602规格书里,有对此时间进行强调。
    *	按照长沙太阳人电子有限公司的规格书即基本操作时序里1.1读状态
    * @param  none
    * @retval none
    */
    
    void LCD1602_WaitReady()
    {
    	uint8_t sta,ucTemp;	 
    	LCD1602_DATAPINS = LCD1602_DATAPINS|0xF0;	//设置输入口
    	LCD1602_RS = 0;
    	LCD1602_RW = 1;	 				//读
    	do 
    	{
    		LCD1602_E = 1;			 
    		LCD1602_Delay();			//读操作,数据建立时间很重要。	 
    		sta = LCD1602_DATAPINS; 	//读取状态字		
    		LCD1602_E = 0;		
    		sta = sta&0xF0;		
    				 
    		LCD1602_Delay();  
    
    		LCD1602_E = 1;			 
    		LCD1602_Delay();			//读操作,数据建立时间很重要。	 
    		ucTemp = LCD1602_DATAPINS; 	//读取状态字		
    		LCD1602_E = 0;
    		ucTemp = ucTemp>>4;		
    		sta = sta|ucTemp;		//合并为8位数据	
    	} while (sta & 0x80); 		//bit7等于1表示液晶正忙,重复检测直到其等于0为止
    }
    
    /**
    * @brief  LCD1602_WriteCommand 
    * @note   向LCD写入一个字节的命令
    * @param  none
    * @retval none
    */
    
    void LCD1602_WriteCommand(uint8_t command)
    {
    	uint8_t ucTemp;	
    	LCD1602_WaitReady();
    	LCD1602_RS = 0;				
    	LCD1602_RW = 0;				//写
    
    	ucTemp = command&0xF0;		
    	LCD1602_E = 1;		   	
    	LCD1602_DATAPINS = LCD1602_DATAPINS&0x0F;	//清高四位保低四位
    	LCD1602_DATAPINS = LCD1602_DATAPINS|ucTemp;				  
    	LCD1602_Delay();
    	LCD1602_E = 0;
    
    	ucTemp = command<<4;	
    	LCD1602_E = 1;		   		
    	LCD1602_DATAPINS = LCD1602_DATAPINS&0x0F;
    	LCD1602_DATAPINS = LCD1602_DATAPINS|ucTemp;				  
    	LCD1602_Delay();
    	LCD1602_E = 0;
    }
    
    /**
    * @brief  LCD1602_WriteData 
    * @note   向LCD写入一个字节的数据
    * @param  none
    * @retval none
    */		
       
    void LCD1602_WriteData(uint8_t dat)	
    {			 
    	uint8_t ucTemp;
    	LCD1602_WaitReady();
    	LCD1602_RS = 1;	
    	LCD1602_RW = 0;	
    
    	ucTemp = dat&0xF0;	
    	LCD1602_E = 1;		  
    	LCD1602_DATAPINS = LCD1602_DATAPINS&0x0F;
    	LCD1602_DATAPINS = LCD1602_DATAPINS|ucTemp;	 					  
    	LCD1602_Delay();
    	LCD1602_E = 0;
    
    	ucTemp = dat<<4;	
    	LCD1602_E = 1;		
    	LCD1602_DATAPINS = LCD1602_DATAPINS&0x0F;
    	LCD1602_DATAPINS = LCD1602_DATAPINS|ucTemp;	   					  
    	LCD1602_Delay();
    	LCD1602_E = 0;
    }
    
    /**
     * @brief   LCD1602 显示自定义字符
     * @note	仅支持5*8点阵,显示能力有限,只能自定义8个字符
     * @param 	P 要显示出来事先自定义字符取模数组名;
     * @retval 	None
     */
     
    void LCD1602_display_customize_character(uint8_t code * P)
    {  
    	uint8_t i;				
    	LCD1602_WriteCommand(0x40);			//写指令0x40,否则字模写不进 CG RAM中
    	for(i=0; i<64; i++)			   		//定义64即将可以写入的8个自定义字符都写入到 CG RAM中
    	{	
    		LCD1602_WriteData(*P++);
    	}
    }
    
    /**
     * @brief   LCD1602 控制显示
     * @note	只能显示字符
     * @param 	x:x轴坐标范围 0~39,但是只能显示前16个,后续为了移屏准备;
     *			ucLineX:y轴坐标范围 0~1,只能显示2行;
    						LCD1602_FIRSTLINE;
    						LCD1602_SECONDLINE;
     			character 要显示出来事先定义的字符
     * @retval 	None
     */
     
    void LCD1602_display_character(uint8_t x, uint8_t ucLineX, uint8_t character)
    {    
    	switch(ucLineX)
    	{
    		case LCD1602_FIRSTLINE:					//由输入的屏幕坐标计算显示RAM的地址
    			LCD1602_WriteCommand(x | 0x80);  	//第一行字符地址从0x00起始,
    			break;
    		case LCD1602_SECONDLINE:
    			LCD1602_WriteCommand(x | 0xC0);  	//第二行字符地址从0x40起始,0x40+0x80=0xC0
    			break;
    	}
        LCD1602_WriteData(character); 				//写要显示的字符
     
    }
     
    /**
     * @brief   LCD1602 将 0~255之内的数转化为 LCD1602可显示字符,一时间不容易弄明白,就是靠猜然后程序可以跑起来,哈哈!
     * @note	根据LCD1602规格书里 Character patterns 显示 数字为 0x30 = '0'  ... 0x39 = '9'
     			\0 为字符串结束符,占用一个字节,但是不占用字符串长度;
    			字符串的结束标志就是'\0',比如说 char s[30]="abc";
    			那么其实就是 s[0]='a',s[1]='b',s[2]='c',s[3]='\0'; '\0'就代表字符串结束。
     * @param 	P(定义的数组名)定义数组元素为4个,包含'\0':转化后的字节显示字符,显示个数最多为3个。0~255用 LCD1602_display_string 函数可直接调用
     *	P_ucString 要显示出来事先定义的字符串或字符
     * @retval 	None
     */
     
    void ConvertNumToCharacter(uint8_t * P, uint8_t ucNum)
    {
    	uint8_t ucArrayTemp[3]=0;	   			//局部变量初始化,可试一下不初始化效果
    	uint8_t i,j;	  
    	uint8_t ucNumTemp;
    	i = 0;
    	ucNumTemp = ucNum;						//使传入的数据不被函数改变	
    	do
    	{
    		ucArrayTemp[i++] = ucNumTemp % 10;	//处理数据低位在前
    		ucNumTemp /= 10;				
    	}while(ucNumTemp > 0);					//可处理3位的数据 
    //有3位数的时候
    	if(3==i)
    	{
    		while(i-- > 0)
    		{
    			*P++ = ucArrayTemp[i] + '0';		//将数据按照高位到低位放到指针开始处,转换为字符形式
    		}
    	}
    //有2位数的时候	比如是 20,但是仅显示低2位,高位显示空。
    	if(i==2)
    	{
    		for(j=2; j>1; j--)
    		{
    			*P++ = ucArrayTemp[j] + ' ';	 //	*P++ = ucArrayTemp[j] + 0x20	效果一样
    		}
    
    		while(i-- > 0)
    		{
    			*P++ = ucArrayTemp[i] + '0';
    		}
    	}
    //仅有一位数的时候,比如只有一个9的时候,仅显示最低位9,百位和十位不显示
    	if(i==1)
    	{
    		for(j=2; j>0; j--)
    		{
    			*P++ = ucArrayTemp[j] + ' ';	
    		}
    
    		while(i-- > 0)
    		{
    			*P++ = ucArrayTemp[i] + '0';
    		}
    	}
    
    	*P = '\0';								//结束字符串
    }
    /**
     * @brief   LCD1602 控制显示
     * @note	只能显示字符串
     * @param 	x:x轴坐标范围 0~39,但是只能显示前16个,后续为了移屏准备;
     *			ucLineX:y轴坐标范围 0~1,只能显示2行;
    						LCD1602_FIRSTLINE;
    						LCD1602_SECONDLINE;
     *			str: 要显示出来事先定义的字符串
     			ucStringLength:字符串实际长度;
     * @retval 	None
     */
    void LCD1602_display_string(uint8_t ucLineX, uint8_t x, uint8_t *str, uint8_t ucStringLength)
    {    
    	switch(ucLineX)
    	{
    		case LCD1602_FIRSTLINE:				//由输入的屏幕坐标计算显示RAM的地址
    			LCD1602_WriteCommand(x | 0x80);  	//第一行字符地址从0x00起始,设置RAM地址 
    			break;
    		case LCD1602_SECONDLINE:
    			LCD1602_WriteCommand(x | 0xC0);  	//第二行字符地址从0x40起始,0x40+0x80=0xC0设置RAM地址  
    			break;
    	}
    
        while (ucStringLength--)         	//连续写入len个字符数据
        {
            LCD1602_WriteData(*str++); 		//先取str指向的数据,然后str自加1
        }
    }
    
    /*******************************************************************************
    * 函 数 名       : LcdInit()
    * 函数功能		 : 初始化LCD屏
    * 输    入       : 无
    * 输    出       : 无
    *******************************************************************************/		   
    void LCD1602_Init()				//LCD初始化子程序
    {
    	ubLCD1602Window1Update = 1;	//初始化LCD1602使用到的变量	 
    	ubLCD1602Window2Update = 1;
    	ubLCD1602Window3Update = 1;
    	
     	LCD1602_WriteCommand(0x28); //数据长度4位,显示两行,5*7点阵,
    	Delay5ms();
     	LCD1602_WriteCommand(0x28);	//可根据实际情况,适当的删除此重复语句
    	Delay5ms();
     	LCD1602_WriteCommand(0x28);
    	Delay5ms();
     	LCD1602_WriteCommand(0x28);
    	Delay5ms();
    	LCD1602_WriteCommand(0x08);	//显示关闭
    	LCD1602_WriteCommand(0x01);	//清屏
    	LCD1602_WriteCommand(0x06); //显示光标移动设置
    	LCD1602_WriteCommand(0x0C); //显示开及光标设置
    }
    
    /**
     * @brief   LCD1602 显示服务程序
     * @note	当前为连个窗口在时间内切换,两行轮流显示字符串3
     * @param 	None
     * @retval 	None
     */
    
    void LCD1602_display_service(void)
    {						
    	uint16_t i;
    		
    	if(ubLCD1602Window1Update == 1)		//第一屏显示测试
    	{
    	//	ubLCD1602Window1Update = 0;	
    		LCD1602_display_string(0,0,ucPermanentDisplay,15); 	//第一行显示 This LCD is OK!	
    		for(i=0; i<16; i++)	 	//第二行显示 0123456789ABCDEF
    		{
    			LCD1602_display_character(i,1,Numerical_ASCII[i]);
    		}									   
    	}
    	
    	for(i=0; i<500; i++)
    	{
    		Delay5ms();
    	}
    	LCD1602_WriteCommand(0x01);	//清屏
    	
    //显示自定义字符
    	if(ubLCD1602Window2Update == 1)	  
    	{
    	//	ubLCD1602Window2Update = 0;	
    
    		LCD1602_display_customize_character(ucArrayDefine);		//写自定义字符到CGRAM中
    			 
    		LCD1602_WriteCommand(0x80);	 		//设置开始显示位置,第一行第一个位置开始显示
    
    		for(i=0; i<8; i++)
    		{
    			LCD1602_WriteData(i);  			//显示自定义字符,DD RAM data,规格书里是一种对应关系。
    		}
    	}
    	
    	for(i=0; i<500; i++)
    	{
    		Delay5ms();
    	}		
    	LCD1602_WriteCommand(0x01);	//清屏
    
    	if(ubLCD1602Window3Update == 1)	   //显示将 类型为 uint8_t 的数 ucDisplayVal 转化为字符进行显示出来
    	{
    	//	ubLCD1602Window3Update = 0;	
    		ConvertNumToCharacter(ucDisplayValArray,ucDisplayVal);	//数字123转为为字符123存放在 ucArray 数组中
    	
    		LCD1602_display_string(LCD1602_FIRSTLINE, 0, ucDisplayValArray, 3);	   	//在第一行,第0个位置开始显示数组 ucArray ,个数为3(0~255,最多显示3位)
    	}
    	
    	for(i=0; i<500; i++)
    	{
    		Delay5ms();
    	}		
    	LCD1602_WriteCommand(0x01);	//清屏
    }
    
    
    int main(void)
    { 
    	LCD1602_Delay();	//上电之前进行短的延时,等待外围器件上电稳定
    	LCD1602_Delay();	//可单独使用较长延时,根据实际情况
    	LCD1602_Delay();
    	LCD1602_Delay();
    	LCD1602_Delay();
    	
    	ucDisplayVal = 9;
    	LCD1602_Init();	   
    
    	while(1)
    	{		  
    		LCD1602_display_service();
    	}
    
    
    	return 0;
    }
    

    //结合网友程序,再添加一些,随发出来,能否帮到你,若是,手留余香。

    展开全文
  • lcd1602引脚图功能介绍

    2020-07-16 11:12:54
    LCD1602引脚图 1602采用标准的16脚接口,其中: 1脚:VSS为电源地 2脚:VCC接5V电源正极 3脚:V0为液晶显示器对比度调整端,接正电源时对比度最弱,接地电源时对比度最高(对比度过高时会 产生“鬼影”,使用时...
  • LCD1602 与独立键盘的简单操作

    千次阅读 2020-10-27 21:02:02
    在AT89C51的控制下,利用LCD1602和两只按键完成两屏显示的切换显示:第一屏为自己姓名的拼音,第二自为子学号;第二屏显示:第一行为自己的籍贯,第二行为自己的生日。显示利用LCd命令1——8进行设置,要求至少...

    LCD1602与键盘扫描作业

    一、设计任务

    在AT89C51的控制下,利用LCD1602和两只按键完成两屏显示的切换显示:第一屏为自己姓名的拼音,第二位自为子学号;第二屏显示:第一行为自己的籍贯,第二行为自己的生日。显示利用LCd命令1——8进行设置,要求至少使用4个命令。

    二、设计思路

    选择P0口作为数据口;首先将姓名学号籍贯等数据存放在单片机的程序储存器内。再通过单片机与LCD1206以数据总线的形式相连通过R/W,E控制信号,D0~D7数据或命令信号,加上独立键盘扫描来控制显示第一屏还是第二屏显示;

    三、硬件电路

    1、LCD1206显示模块

    以P0为数据和命令端口,P2^0~P2^2为控制信号端口
    在这里插入图片描述

    LCD1206的命令字特点:

    编号 命令 Rs R/WR/ \overline{W} D7 D6 D5 D4 D3 D2 D1 D0
    1 清屏 0 0 0 0 0 0 0 0 0 1
    2 光标返回 0 0 0 0 0 0 0 0 1 ×\times
    3 显示模式 0 0 0 0 0 0 0 1 I/D S
    4 显示开关、光标设置 0 0 0 0 0 0 1 D C B
    5 光标及字符移位 0 0 0 0 0 1 S/C R/L ×\times ×\times
    6 功能设置 0 0 0 0 1 DL N F ×\times ×\times
    7 CGRAM地址 0 0 0 1
    8 DDRAm地址 0 0 1 R A M
    9 读忙标志或地址 0 1 BF
    10 写数据 1 0
    11 读数据 1 1
    • 命令1 : 光标返回00H(左上角位置)

    • 命令2: 光标返回

    • 命令3:显示设置

      I/D: (1)地址指针加一;(0)地址指针减一

      S: (1)写入字符,整屏左移或右移 ;(0)整屏显示不移动

    • 命令4:D——屏幕显示:1 开显示;0关显示
      C——光标有无:1 有; 0 无光标
      B——光标闪烁:1闪烁;0 不闪烁

    • 命令5 :SC =0 移动光标 SC =1 移动显示的字符
      RL = 0 左移RL =1 右移

    • 命令6: DL :1 八位数据 0 四位数据接口
      N:1 两行显示 0 单行显示
      F: (1)5×10\times10阵 (0)5×7\times7 点阵

    • 命令7:GGRAM地址设置,设置用户自定义的字符

    • 命令8:设置显示地址:80H + 显示位置

    • 命令9: 读忙: BF =1 忙;

    • 命令10:写数据

    • 命令10: 读数据
      控制操作:

    操作 单片机发给LCD的控制信号 LCD的输出
    读状态 RS=0, R/W\overline W=1,E= 1 D0~D7状态
    写命令 RS=0,R/W\overline W=0, D0~D7命令,E正脉冲
    读数据 RS =1,R/W\overline W=1,E =1 D0~D7数据
    写数据 RS =1,R/W\overline W=0,D0~D7 数据,E正脉冲

    2、独立键盘扫描模块

    在这里插入图片描述

    四、软件设计

    #include<reg51.h>
    #include<intrins.h>
    #define out P0  //数据和命令端口
    #define uchar unsigned char//预定义
    #define uint unsigned int
    sbit S1 =P1^0;  // 按键1
    sbit S2 =P1^1;//按键2
    uchar keyvalue; // 键值
    uchar code name[] ="Tang jie";//预存显示数据
    uchar code stu_num[] ="1808441072";
    uchar code birthplace[] ="Tong Ling";
    uchar code birthday[] = "2000/01/27";
    sbit RS  = P2^0;   //  数据或指令控制线
    sbit RW  = P2^1;   // 读写控制线
    sbit E   = P2^2;   //使能控制线 
    void key_scan(void); //键盘扫描声明
    /*********************
    延时函数
    *********************/
    void delay(uint j)
      {
      uchar i = 250;
      for(;j>0;j--)
      {
       while (--i);
       i= 249;
       while(--i);
       i=250;
      }
    }
    /*********************
    检查忙函数,检查LCD是否处于忙状态
    如果处于忙则持续检查
    *********************/
    void check_busy(void)
    {
        uchar temp;
        do{
            temp =0xff;  //
            E = 0;
            RS= 0;   //
            RW = 1;
            E =1;
            temp = out; // 
    			}while(temp&0x80);  // 如果 BF =1 则持续检查 
            E = 0; 
    }
    /*********************
    写命令函数
    *********************/
    void write_command(uchar com)
    {
        check_busy();//  首先检查忙
       E= 0;//预置0
       RS =0;
       RW =0; //按LCD写命令控制信号设置
       out = com;
       E =1; //  正脉冲
       _nop_();// 
       E = 0; // 还原E
        delay(1);
    }
    /********************
    写数据函数
    ********************/
    void write_data(uchar com) 
    {
      check_busy();
      E=0;    //预置0
      RS= 1;
      RW =0;//按LCD写数据控制信号设置
      out = com;
      E=1;// 正脉冲
      _nop_();
      E =0;
    delay(1);
      } 
    /********************
    LCD初始化函数
    ********************/  
    void lcd_initial(void) //
     {
      write_command(0x38); // 八位数据,双列显示,5X7阵
    	_nop_();
      write_command(0x0c); //开显示屏,关光标,光标不显示
    	_nop_();
      write_command(0x06); //字符不移动,每次字符地址加1
    	_nop_();
      write_command(0x01); //清屏
    	_nop_();
    	delay(100);
      }
    /********************
    //字符串显函数
    ********************/
    void string(uchar add, uchar *s)
    { 
    	 write_command(add);//显示地址
    	 while(*s != '\0')
    	{
    	  write_data(*s++);
    	}
    }
    /********************
    第一屏显示函数
    ********************/
    void key_1(void) 
    {
    lcd_initial();
    string(0x83,name); //第一行第四个开始显示学号
    string(0xc2,stu_num);//第二行第三个开始显示姓名
     do{
    	key_scan();
    	} while(S2!=0);// 持续进行键盘扫描,如果按键2没按下,则一直显示第一屏
    }
    /********************
    第二屏显示函数
    ********************/
    void key_2(void) 
    {
    lcd_initial();
    string(0x83,birthplace);//第一行第三个开始显示籍贯
    string(0xc3,birthday);//第二行第三个开始显示生日
    do{
    key_scan();
      } while(S1!=0); //持续进行键盘扫描,如果按键1没按下,则一直显示第二屏
    }
    	
    void key_scan(void)  //独立键盘扫描函数
    {
     P1 =0xff;
     if((P1&0x0f)!=0x0f)
    	{
    	  delay(10);
    	  if(S1==0)
    	   {  
    	    keyvalue =1;
    		delay(100);
    		}
    		if(S2 == 0)
    	    {
            keyvalue =2;
    		delay(100);
    		}
    	}
    }
    
    void main(void) //主函数
    {
    	lcd_initial();
    	while(1)
    	{
    	 keyvalue =0
    	 key_scan();  //按键扫描
    	 switch(keyvalue)  //按键值选择显示第几屏数据
    	 {
    	 case 1 : key_1();delay(10);break;
    	 case 2 : key_2();delay(10);break;
     	 
    	 }
    	}
    }	
    
    

    五、仿真调试

    按下按键1,显示第一屏数据,显示良好
    按下按键2,显示第二屏数据,显示良好
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • 3脚:V0为液晶显示器对比度调整端,接正电源时对比度最弱,接地电源时对比度最高,对比度过高时会产生“鬼影”,使用时可以通过个10K的电位器调整对比度 4脚:RS为寄存器选择,高电平时选择数据寄存器、低电...
  • LCD1602中文资料

    千次阅读 2012-09-08 16:03:59
    LCD1602中文资料     :液晶显示器各种图形的显示原理 线段的显示:点阵图形式液晶由M×N个显示单元组成,假设LCD显示屏有64行,每行有128列,每8列对应1字节的8,即每行由16字节,共16×8=128个点组成,...
  • 、 学习要点(串行多总线类外设): 1、 正确分析时序图; 2、 多总线(多条数据线区别于DHT11这类单总线控制线不算)操作的传感器,要区单总线的传感器DHT11等,单总线时操作的而“多总线”是字节操作的,不用8...
  • lcd1602工作原理是什么1、线段的显示点阵图形式液晶由M&TImes;N个显示单元组成,假设LCD显示屏有64行,每行有128列,每8列对应1字节的8,即每行由16字节,共16&TImes;8=128个点组成,屏上64&TImes;16...
  • LCD1602工业显示屏 LCD工业显示屏解读: 共有16个引脚,其中D0~D7为收发数据引脚,为双向并行数据接口。 16代表每行能够显示16个空格 2代表总共两行 因为每个字节能够显示0和1,有两种可能,所以要将32...
  • 1602有8的数据口和4的数据口,今天我们用到的是8的数据口。废话不多说,直接上原理图 写数据和写命令的时序 清屏指令 开显示指令 显示字符的地址 第一行0x80+0x00开始,第二行0x80+0x40开始...
  • 拿到板自己卖家给的资料后,烧写进去一脸懵逼,就第一行全黑 之前用STM32 以及51的时候也没出现过啊,显示去检查I/O引脚, arduino Nano A4 SDA A5 SCL 没错啊 然后上网搜索感觉这个I2C的IC地址有点问题 ...
  • 注意:第二段的用户码也可以在遥控应用电路中被设置成第一段用户码的反码。 传输数据定义 用户码或数据码中的每一个可以是 ‘1’ ,也可以是 ‘0’。区分 ‘0’和 ‘1’是利用脉冲的时间间隔来区分,这种...
  • 注释:1602为2行16列,屏幕所能显示的地址为00H~0FH(第一行),40H~4FH(第二行),其他地址可以存储待显示的数据。这就给我们的花样显示提供了条件哈:-D运行时序图注释:这里的读操作指的是C51读1602的总线数据,RS.....
  • 1602LCD液晶显示秒表

    2020-07-11 12:19:40
    第一次按下时,开始计时,第二次按下时,暂停计时。;第三次按下时,累计计时,第四次按下时,暂停计时。;K4---清零按键:;在任何状态下,按一下K4,均可清零。;可同时显示:时、分、秒、毫秒(带有两ms级显示);------...
  • //操作简介// 按第一个数,再按'+-*/',再按'='显示出结果,然后按C清屏// 加最大9999+9999=19998// 减最大9999-0 =9999// 乘最大9999*9999=99980001// 除 1/9=0.1111 保留小数点后4#include#define uint unsigned ...
  • //读一位数据线的值 else data = (data & 0xfe); IO1CLR = SCK; delay_us(5); } IO1SET = DATA; return(data); } //通信结束 void SHT11_end() { IO1SET = DATA; delay_us(5); IO1SET = SCK; ...
  • //从第一格开始显示 } /*LCD指令*///P2.3e P2.4 RW P2.5RS //p1.4----p1.7接LCD屏的高4 void LCD_display() { int i; for(i=0;i;i++)//X代表字符的个数 { write_data(table[i]); delay_nm(); } }
  • 基于51单片机的1602LCD时钟 最近做了个51单片机的时钟、具有设置时间、闹钟等功能 程序分为3个模块。...第一行的显示程序 mode_flag是一个标志 unsigned char Current_Time[]={“Current Time “}; ...
  • 开机后,LCD1602 第一行按秒显示更新系统运行累计时间。显示形式如下(00:00)前两为分钟,后两为秒。 开机后,点阵显示数字“0”。 按下K1-K8,点阵(8*8)分别显示数字1-8。 遥杆向上推,打开串口使能,同时...
  • /**************第一页显示子程序***************************/ void display1() { wr_com(0x80); //温度显示 wr_dat(0x54); //显示 T wr_dat(0x3a); //显示: read_temp(); //读取温度 ds1820disp( ); //温度显示 ...
  • 电子设计应用2003年5期 摘 要: 本文介绍了字符式液晶显示模块SMC1602B的工作原理及其应用,重点对ADSP2181与SMC1602B的软...本文使用的DSP是AD公司的种低价格、高性能的16定点运算DSP—ADSP2181。它集成度
  • 步骤及现象:程序下载前,stc-isp选择IRC频率:12MHz,程序下载后,LCD1602第一行显 示:“12:00:00 28.5C”,第二行显示:"2019.01.01 2 0" 。第一行显示的是时间和实 时温度,第二行显示的是日期、周几和闹钟开启...
  • //第一行的x位置显示 } else { addr = 0x40 + x; //第二行x的位置显示 } LCD1602WriteCmd(addr + 0x80); switch(dat) { case 1:LCD1602WriteData('M');//星期数为1时,显示 LCD1602Write...
  • 1602液晶显示屏是一种常见的字符型液晶显示器,1602的意思是它能够显示16*2个字符。1602显示器与Arduino的连接LCD是一个并口显示屏,有两种接线方法,4数据...1602 LCD相关参数行列image.png第一行与第一列都是...
  • 由于前面一个帖子的代码有点瑕疵,这个完善了一点,我吧第二行的第一个作为个位数,第一行的第一位作为十位数,按照01--99进行计数。哈哈,动态刷新哦!!网上太难找到这样的例子了!本人刚学会就贡献给大家,作为...
  • #include<1602.h> #define uchar unsigned char #define uint unsigned int uchar i,a,b,c,d; uint jj; uchar code table[]={'0','1','2','3','4','5','6','7','8','9'}; long bb; uint mm=1234; ...
  • WRITE_LCD1602_DAT(DIS_TAB1[i]); WRITE_LCD1602_COM(0x80+0x40); for(i=0;i;i++)//2行要显示的11个字符 { WRITE_LCD1602_DAT(table8[i]); } ctrlzhu(); if (RI==1) ...

空空如也

空空如也

1 2 3
收藏数 53
精华内容 21
关键字:

lcd1602第一位