LCD1602(Liquid Crystal Display)是一种工业字符型液晶,能够同时显示 16×02 即 32 字符(16列两行)

第 1 脚: VSS 为电源地

第 2 脚: VDD 接 5V 正电源

第 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 脚:背光源负极。



开发逻辑

  • 在哪显示

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

  • 显示什么

    读写操作时序
    读操作

    检测忙信号的时候需要读时序
  • /*当 RS 为低电平 R/W 为高电平时可以读忙信号读忙信号和光标地址。
    BF(bit7):为忙标志位,高电平表示忙,此时模块不能接收命令或者数据,
    如果为低电平表示不忙。
    */
    
    void check_busy()//检测忙信号
    {
    	char tmp = 0x80;
    	dataBuff = 0x80;
    	while(tmp & 0x80){//检测BF,1忙 0闲
    	
    	RS = 0;
    	RW = 1;
    	
    	EN = 0;
    	_nop_();
    	EN = 1;
    	_nop_();
    	_nop_();
    	tmp = dataBuff; 
    	_nop_();
    	EN = 0;
    	_nop_();
    	}
    }
    

    写操作
    数序参数

    /*
    RS 为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。
    
    */
    void Write_Cmd_Func(char cmd)
    {
    	check_busy();
    	RS = 0;
    	RW = 0;
    	
    	EN = 0;
    	_nop_();
    	
    	dataBuff = cmd;
    	_nop_();
    	
    	EN = 1;
    	_nop_();
    	_nop_();
    	EN = 0;
    	_nop_();
    	
    }
    
    void Write_Data_Func(char dataShow)
    {
    	check_busy();
    	RS = 1;
    	RW = 0;
    	
    	EN = 0;
    	_nop_();
    	
    	dataBuff = dataShow;
    	_nop_();
    	
    	EN = 1;
    	_nop_();
    	_nop_();
    	EN = 0;
    	_nop_();
    }
    

    LCD1602的初始化函数

    void LCD1602_INIT()
    {
     //(1)延时 15ms
    
     Delay15ms();
    
    //(2)写指令 38H(不检测忙信号) 
    
     Write_Cmd_Func(0x38);
    
    //(3)延时 5ms
    
     Delay5ms();
    
    //(4)以后每次写指令,读/写数据操作均需要检测忙信号
    	check_busy();
    
    //(5)写指令 38H:显示模式设置
    
     Write_Cmd_Func(0x38);
    
    //(6)写指令 08H:显示关闭
    
     Write_Cmd_Func(0x08);
    
    //(7)写指令 01H:显示清屏
    
     Write_Cmd_Func(0x01);
    
    //(8)写指令 06H:显示光标移动设置
    
     Write_Cmd_Func(0x06);
    
    //(9)写指令 0CH:显示开及光标设置}
    
     Write_Cmd_Func(0x0c);
    }
    
    

    C51实验显示:hello world

    #include "reg52.h"
    #include "intrins.h"
    
    #define dataBuff P0
    
    sbit RS = P2^6;
    sbit RW = P2^5;
    sbit EN = P2^7;
    
    /*当 RS 为低电平 R/W 为高电平时可以读忙信号读忙信号和光标地址。
    BF(bit7):为忙标志位,高电平表示忙,此时模块不能接收命令或者数据,
    如果为低电平表示不忙。
    */
    
    void check_busy()//检测忙信号
    {
    	char tmp = 0x80;
    	dataBuff = 0x80;
    	while(tmp & 0x80){//检测BF,1忙 0闲
    	
    	RS = 0;
    	RW = 1;
    	
    	EN = 0;
    	_nop_();
    	EN = 1;
    	_nop_();
    	_nop_();
    	tmp = dataBuff; 
    	_nop_();
    	EN = 0;
    	_nop_();
    	}
    }
    
    /*
    RS 为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。
    
    */
    void Write_Cmd_Func(char cmd)
    {
    	check_busy();
    	RS = 0;
    	RW = 0;
    	
    	EN = 0;
    	_nop_();
    	
    	dataBuff = cmd;
    	_nop_();
    	
    	EN = 1;
    	_nop_();
    	_nop_();
    	EN = 0;
    	_nop_();
    	
    }
    
    void Write_Data_Func(char dataShow)
    {
    	check_busy();
    	RS = 1;
    	RW = 0;
    	
    	EN = 0;
    	_nop_();
    	
    	dataBuff = dataShow;
    	_nop_();
    	
    	EN = 1;
    	_nop_();
    	_nop_();
    	EN = 0;
    	_nop_();
    }
    
    
    void Delay5ms() //@11.0592MHz
    
    {
     unsigned char i, j;
     i = 9;
     j = 244;
     do
    
     {
     while (--j);
     } while (--i);
    }
    
    void Delay15ms() //@11.0592MHz
    
    {
     unsigned char i, j;
     i = 27;
     j = 226;
     do
    
     {
     while (--j);
     } while (--i);
    }
    
    
    void LCD1602_INIT()
    {
     //(1)延时 15ms
    
     Delay15ms();
    
    //(2)写指令 38H(不检测忙信号) 
    
     Write_Cmd_Func(0x38);
    
    //(3)延时 5ms
    
     Delay5ms();
    
    //(4)以后每次写指令,读/写数据操作均需要检测忙信号
    	check_busy();
    
    //(5)写指令 38H:显示模式设置
    
     Write_Cmd_Func(0x38);
    
    //(6)写指令 08H:显示关闭
    
     Write_Cmd_Func(0x08);
    
    //(7)写指令 01H:显示清屏
    
     Write_Cmd_Func(0x01);
    
    //(8)写指令 06H:显示光标移动设置
    
     Write_Cmd_Func(0x06);
    
    //(9)写指令 0CH:显示开及光标设置}
    
     Write_Cmd_Func(0x0c);
    }
    
    void lcd1602_Show_line(int row,int col,char *SendData)
    {
    	switch(row){
    		case 1:
    						Write_Cmd_Func(0x80+col);
    					while(*SendData){
    						Write_Data_Func(*SendData);
    						SendData++;
    					}
    					break;
    		
    		case 2:
    					Write_Cmd_Func(0x80+0x40+col);
    					while(*SendData){
    						Write_Data_Func(*SendData);
    						SendData++;
    					}
    					break;
    		
    	}
    	
    }
    
    void main()
    {
    	LCD1602_INIT();
    	
    	lcd1602_Show_line(1,3,"hello world");
    
    	
    
    }
    

    STM32HAL库

    RS、RW、EN三根信号线经常需要进行拉高/拉低操作,可以进行封装

    #define RS_GPIO_Port GPIOB
    #define RW_GPIO_Port GPIOB
    #define EN_GPIO_Port GPIOB
    #define RS_Pin GPIO_PIN_1
    #define RW_Pin GPIO_PIN_2
    #define EN_Pin GPIO_PIN_10

    #define RS_HIGH HAL_GPIO_WritePin(RS_GPIO_Port, RS_Pin, GPIO_PIN_SET)

    #define RS_LOW HAL_GPIO_WritePin(RS_GPIO_Port, RS_Pin, GPIO_PIN_RESET)

    #define RW_HIGH HAL_GPIO_WritePin(RW_GPIO_Port, RW_Pin, GPIO_PIN_SET)

    #define RW_LOW HAL_GPIO_WritePin(RW_GPIO_Port, RW_Pin, GPIO_PIN_RESET)

    #define EN_HIGH HAL_GPIO_WritePin(EN_GPIO_Port, EN_Pin, GPIO_PIN_SET)

    #define EN_LOW HAL_GPIO_WritePin(EN_GPIO_Port, EN_Pin, GPIO_PIN_RESET)

    如何将一个字节的数据按位一次性发送到GPIOA的8个管脚?

    GPIOA->ODR = cmd;

    #define RS_GPIO_Port GPIOB
    #define RW_GPIO_Port GPIOB
    #define EN_GPIO_Port GPIOB
    #define RS_Pin GPIO_PIN_1
    #define RW_Pin GPIO_PIN_2
    #define EN_Pin GPIO_PIN_10
    #define RS_HIGH HAL_GPIO_WritePin(RS_GPIO_Port, RS_Pin, GPIO_PIN_SET)
    
    #define RS_LOW HAL_GPIO_WritePin(RS_GPIO_Port, RS_Pin, GPIO_PIN_RESET)
    
    #define RW_HIGH HAL_GPIO_WritePin(RW_GPIO_Port, RW_Pin, GPIO_PIN_SET)
    
    #define RW_LOW HAL_GPIO_WritePin(RW_GPIO_Port, RW_Pin, GPIO_PIN_RESET)
    
    #define EN_HIGH HAL_GPIO_WritePin(EN_GPIO_Port, EN_Pin, GPIO_PIN_SET)
    
    #define EN_LOW HAL_GPIO_WritePin(EN_GPIO_Port, EN_Pin, GPIO_PIN_RESET)
    
    void Write_Cmd_Func(uint8_t cmd)
    {
    
     RS_LOW;
    
     RW_LOW;
    
     EN_LOW;
    
     GPIOA->ODR = cmd;
    
     HAL_Delay(5);
    
     EN_HIGH;
    
     HAL_Delay(5);
    
     EN_LOW;
    }
    
    void Write_Data_Func(uint8_t dataShow)
    {
    
     RS_HIGH;
    
     RW_LOW;
    
     EN_LOW;
    
     GPIOA->ODR = dataShow;
    
     HAL_Delay(5);
    
     EN_HIGH;
    
     HAL_Delay(5);
    
     EN_LOW;
    }
    
    void LCD1602_INIT(void)
    {
    
    //(1)延时 15ms
    
     HAL_Delay(15);
    
    //(2)写指令 38H(不检测忙信号) 
    
     Write_Cmd_Func(0x38);
    
    //(3)延时 5ms
    
     HAL_Delay(5);
    
    //(4)以后每次写指令,读/写数据操作均需要检测忙信号
    
    //(5)写指令 38H:显示模式设置
    
     Write_Cmd_Func(0x38);
    
    //(6)写指令 08H:显示关闭
     Write_Cmd_Func(0x08);
    
    //(7)写指令 01H:显示清屏
    
     Write_Cmd_Func(0x01);
    
    //(8)写指令 06H:显示光标移动设置
    
     Write_Cmd_Func(0x06);
    
    //(9)写指令 0CH:显示开及光标设置}
    
     Write_Cmd_Func(0x0c);
    }
    
    void LCD1602_showLine(char row, char col, char *string)
    {
    
     switch(row){
    
     case 1:
    
     Write_Cmd_Func(0x80+col);
    
     while(*string){
    
     Write_Data_Func(*string);
    
     string++;
    
     }
    
     break;
    
     case 2:
    
     Write_Cmd_Func(0x80+0x40+col);
    
     while(*string){
    
     Write_Data_Func(*string);
    
     string++;
    
     }
    
     break;
    
     }
    }
    
    main函数里:
    
     //char position = 0x80 + 0x05;
    
     //char dataShow = 'C';
    
     LCD1602_INIT();
    
     //Write_Cmd_Func(position);//选择要显示的地址
    
     //Write_Data_Func(dataShow);//发送要显示的字符
    
     LCD1602_showLine(1,5,"hello world");
    
    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32—LCD1602

    发表评论