LCD1602单片机(STC51/STM32)驱动程序详解

作者:hackett

微信公众号:加班猿

一、LCD1602简介

LCD1602液晶显示器是宽泛应用的一种字符型液晶显示模块。它是由字符型液晶显示屏(LCD)、管制驱动主电路HD44780及其扩大驱动电路HD44100,以及大量电阻、电容元件和结构件等拆卸在PCB板上而组成。

LCD1602利用很宽泛,无论是各大电子公司的产品上还是各大高校电赛的较量作品上都能看到它的身影,上面来细说一下怎么驱动这块1602液晶屏。

二、LCD1602引脚

图1:引脚阐明

图2:原理图

一、咱们重点关注几个引脚:

  1. 液晶显示偏压:VL对应原理图V0引脚,作用是调整1602的显示对比度,可外接电位器进行调节对比度,上图原理图接地引脚电压为0这时候对比度最高。
  2. 数据/命令抉择端:RS对应原理图RES引脚,引脚高电平:进行数据字节传输,引脚低电平:进行命令字节传输。
  3. 读/写抉择端:R/W对应原理图R/W引脚,引脚高电平:对1602进行读数据,引脚低电平:对1602进行写数据,个别利用都是间接拉低只进行写数据
  4. 使能信号:E对应原理图E引脚,该引脚回升沿代表对1602开始数据传输,降落沿代表数据传输完结
  5. 背光管制:原理图K+引脚,该引脚高电平:背光敞开,引脚低电平:背光关上。

二、咱们只须要写数据给1602显示,只看写操作时序:

2写指令跟4写数据比照可看出RW读写引脚为低电平,E为高电平,D0~D7为传输的数据是命令/数据,RS数据/命令抉择端(高:数据 , 低:命令)。

三、罕用的写指令如下,其余指令可去查1602的datasheet:

四、数据写入CGRAM指令:

此指令能够自定义显示一个字符,咱们写地址的丝毫应该是0x40+Address

三、LCD1602驱动(11脚)

51单片机跟STM32单片机的驱动基本一致次要是引脚的配置不怎么一样,特地留神STM32驱动写指令/数据GPIO_Write(GPIOA,(GPIO_ReadOutputData(GPIOA) & 0xff00) | cmd/data)为对电平的读取再写数据,其余均与51驱动统一。

1、51单片机:LCD1602.h

#ifndef __LCD1602_H #define __LCD1602_H  #define LCD1602_BKL_ON 0 //背光开 #define LCD1602_BKL_OFF 1 //背光关  #define LCD1602_DB P2 //数据端口  D0~D7 sbit LCD_RES = P4^1; //1602的数据/指令抉择控制线 sbit LCD_EN = P4^2; //1602的使能控制线 sbit Lcd1602_light = P0^2;      //背光引脚  /*****************************************************************************/ void LCD1602_Init(); void LCD1602_Clear();  void LCD1602_write_cmd(unsigned char cmd); void LCD1602_write_data(unsigned char date); void LCD1602_wtire_CGRAM();  void LCD1602_SetCursor(unsigned char x,unsigned char y); void LCD1602_ShowChar(unsigned char xpos,unsigned char ypos,unsigned char xsz); void LCD1602_ShowStr(unsigned char xpos,unsigned char ypos,char *p); void LCD1602_ShowNum(char x, char y, unsigned int num);  void LCD1602_BKLSet(unsigned char val); unsigned char LCD1602_BKLGet();  void Delay_ms(unsigned int nms); #endif

 

2、51单片机:LCD1602.h

#include "LCD1602.h"  /******************************************************************************  * 函数名称:void Delay_ms(unsigned int nms)       *  * 函数性能:写命令函数        *  * 输出参数: //nms为要延时的ms数    *  * 返回值  :无           *  * 其余阐明:          *  ******************************************************************************/ void Delay_ms(unsigned int nms) //@11.0592MHz {  unsigned char i, j; //用单片机小工具依据本人的单片机类型及晶振间接生成对应的延时函数即可  while(nms--)  {  i = 15;  j = 90;  do  {  while (--j);  } while (--i);  } } /******************************************************************************  * 函数名称:void LCD1602_write_cmd(unsigned char cmd)       *  * 函数性能:写命令函数        *  * 输出参数: cmd 命令    *  * 返回值  :无           *  * 其余阐明:          *  ******************************************************************************/ void LCD1602_write_cmd(unsigned char cmd)  {  LCD1602_DB=cmd;  LCD_RES=0;  LCD_EN=1;  Delay_ms(10);   LCD_EN=0; } /******************************************************************************  * 函数名称:void LCD1602_write_data(unsigned char date)       *  * 函数性能:写数据函数        *  * 输出参数: date 数据       *  * 返回值  :无           *  * 其余阐明:          *  ******************************************************************************/  void LCD1602_write_data(unsigned char date)  {  LCD1602_DB=date;  LCD_RES=1;  LCD_EN=1;  Delay_ms(10);  LCD_EN=0; } /******************************************************************************  * 函数名称:void LCD1602_Init(void)                     *  * 函数性能:1602初始化函数        *  * 输出参数: 无       *  * 返回值  :无           *  * 其余阐明:          *  ******************************************************************************/  void LCD1602_Init()  {  LCD1602_BKLSet(LCD1602_BKL_ON); //背光开启  LCD1602_write_cmd(0x01); //显示清屏  LCD1602_write_cmd(0x38); //显示模式设置  LCD1602_write_cmd(0x0C); //显示开及光标设置  LCD1602_write_cmd(0x06); //显示光标挪动地位 } /******************************************************************************  * 函数名称:void LCD1602_Clear(void)                     *  * 函数性能:1602清屏函数        *  * 输出参数: 无       *  * 返回值  :无           *  * 其余阐明:          *  ******************************************************************************/ void LCD1602_Clear() {  LCD1602_write_cmd(0x01); }  /******************************************************************************  * 函数名称:void LCD1602_BKLSet(unsigned char val)               *  * 函数性能:关上1602背光函数        *  * 输出参数: LCD1602_BKL_ON 开LCD1602_BKL_OFF 关 *   * 返回值  :无           *  * 其余阐明:          *  ******************************************************************************/ void LCD1602_BKLSet(unsigned char val) {  Lcd1602_light = val; } /******************************************************************************  * 函数名称:unsigned char LCD1602_BKLGet()                     *  * 函数性能:获取1602背光函数        *  * 输出参数:无       *  * 返回值  : 0 开1 关 *  * 其余阐明:          *  ******************************************************************************/ unsigned char LCD1602_BKLGet() {  return Lcd1602_light; } /******************************************************************************  * 函数名称:void LCD1602_SetCursor(unsigned char x,unsigned char y) *  * 函数性能:设置1602地位函数        *  * 输出参数:x 横坐标 y 纵坐标       *  * 返回值  : 无           *  * 其余阐明:          *  ******************************************************************************/ void LCD1602_SetCursor(unsigned char x,unsigned char y) {  unsigned char addr;  if(y==0)  addr=0x00+x;  else  addr=0x40+x;  LCD1602_write_cmd(addr | 0x80); } /******************************************************************************  * 函数名称:void LCD1602_ShowNum(char x, char y, unsigned int num)  *  * 函数性能:指定地位显示数字函数        *  * 输出参数:x 横坐标 y 纵坐标 num 数字       *  * 返回值  : 无           *  * 其余阐明:          *  ******************************************************************************/ void LCD1602_ShowNum(char x, char y, unsigned int num) {  unsigned int i,j,k,l,n;  i=num/10000;  j=(num-10000*i)/1000;  k=(num-10000*i-1000*j)/100;  l=(num-10000*i-1000*j-100*k)/10;  n=num%10;  LCD1602_SetCursor(x,y);  if(i!=0)LCD1602_write_data(i+0x30);  if((i!=0)||(j!=0))LCD1602_write_data(j+0x30);  if((i!=0)||(j!=0)||(k!=0))LCD1602_write_data(k+0x30);  if((i!=0)||(j!=0)||(k!=0)||(l!=0))LCD1602_write_data(l+0x30);  LCD1602_write_data(n+0x30); } /******************************************************************************  * 函数名称:void LCD1602_ShowChar(unsigned char xpos,unsigned char ypos,char xsz)  *  * 函数性能:指定地位显示字符函数        *  * 输出参数:xpos 横坐标 ypos 纵坐标 xsz 字符       *  * 返回值  : 无           *  * 其余阐明:          *  ******************************************************************************/ void LCD1602_ShowChar(unsigned char xpos,unsigned char ypos,char xsz)  {  ypos%=2;  if(ypos==0)  {  LCD1602_write_cmd(0x80+xpos);  }  else  {  LCD1602_write_cmd(0x80+0x40+xpos);  }  LCD1602_write_data(xsz); } /******************************************************************************  * 函数名称:void LCD1602_ShowStr(unsigned char xpos,unsigned char ypos,char *p) *  * 函数性能:指定地位显示字符串函数        *  * 输出参数:xpos 横坐标 ypos 纵坐标 *p 字符串       *  * 返回值  : 无           *  * 其余阐明:          *  ******************************************************************************/ void LCD1602_ShowStr(unsigned char xpos,unsigned char ypos,char *p) {  if(ypos>1)return;  while(*p!='0')  {  LCD1602_ShowChar(xpos++,ypos,*p++);  if(*p=='n')  {  xpos=0;  ypos++;  p++;  }  } } unsigned char code code_Y[8]={0x11,0x0A,0x04,0x04,0x04,0x04,0x04,0x00};//相似Y的字模 /******************************************************************************  * 函数名称:void LCD1602_wtire_CGRAM(void) *  * 函数性能:自定义显示字符函数        *  * 输出参数:   无       *  * 返回值  : 无           *  * 其余阐明:          *  ******************************************************************************/ void LCD1602_wtire_CGRAM() {  unsigned char num;  LCD1602_write_cmd(0x40);    //对CGRAM第一个自定义字符操作,若是第二个则为0x48,  //其次类推(下面有对顶的关系)  for(num=0;num<8;num++)  {  LCD1602_write_data(code_Y[num]);  }   LCD1602_write_cmd(0x80);    //规定显示在第一行第一个地位   LCD1602_write_data(0x00);   //显示第一个自定义字符 (0x40对应第一个:0x00)  } /********************************************************************/ 

 
 

3、STM32:LCD1602.h

 #ifndef __LCD1602_H #define __LCD1602_H   /***************************依据本人的硬件引脚做批改*****************************/ #define LCD_RS_Set() GPIO_SetBits( GPIOB, GPIO_Pin_12 )//1602的数据/指令抉择控制线 #define LCD_RS_Clr() GPIO_ResetBits( GPIOB, GPIO_Pin_12 )  #define LCD_RW_Set() GPIO_SetBits( GPIOB, GPIO_Pin_13 )//1602的读写控制线 #define LCD_RW_Clr() GPIO_ResetBits( GPIOB, GPIO_Pin_13 )  #define LCD_EN_Set() GPIO_SetBits( GPIOB, GPIO_Pin_14 )//1602的使能控制线 #define LCD_EN_Clr() GPIO_ResetBits( GPIOB, GPIO_Pin_14 )  #define DATAOUT( x ) GPIO_Write( GPIOA, x ) //1602的8条数据控制线  void GPIO_Configuration();  void LCD1602_Init();  void LCD1602_Wait_Ready();  void LCD1602_Write_Cmd( u8 cmd );  void LCD1602_Write_Dat( u8 data );  void LCD1602_ClearScreen();  void LCD1602_Set_Cursor( u8 x, u8 y );  void LCD1602_Show_Str( u8 x, u8 y, u8 *str );  #endif

4、STM32:LCD1602.c

 #include  "LCD1602.h" /******************************************************************************  * 函数名称:void GPIO_Configuration()       *  * 函数性能:LCD1602引脚初始化        *  * 输出参数:无       *  * 返回值  :无           *  * 其余阐明:          *  ******************************************************************************/ /*******************依据本人的硬件引脚做批改*****************************************/ void GPIO_Configuration() {  GPIO_InitTypeDef GPIO_InitStructure;  RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE );  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14;  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//抉择工作频率  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//设置工作模式  GPIO_Init( GPIOB, &GPIO_InitStructure );   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 |   GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//设置工作模式  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//抉择工作频率  GPIO_Init( GPIOA, &GPIO_InitStructure ); } /******************************************************************************  * 函数名称:void LCD1602_Init()       *  * 函数性能:LCD1602初始化        *  * 输出参数:无       *  * 返回值  :无           *  * 其余阐明:          *  ******************************************************************************/ void LCD1602_Init() {  GPIO_Configuration(); //初始化引脚   LCD1602_Write_Cmd( 0x38 );      //显示模式设置  delay_ms( 5 );  LCD1602_Write_Cmd( 0x0c );      //显示开及光标设置  delay_ms( 5 );  LCD1602_Write_Cmd( 0x06 );      //显示光标挪动地位  delay_ms( 5 );  LCD1602_Write_Cmd( 0x01 );      //显示清屏  delay_ms( 5 );  } /******************************************************************************  * 函数名称:void LCD1602_Write_Cmd(u8 cmd)       *  * 函数性能:写命令函数        *  * 输出参数: cmd 命令       *  * 返回值  :无           *  * 其余阐明:          *  ******************************************************************************/ void LCD1602_Write_Cmd( u8 cmd ) {  LCD_RS_Clr();  LCD_RW_Clr();  LCD_EN_Set();   GPIO_Write( GPIOA, (GPIO_ReadOutputData( GPIOA ) & 0xff00) | cmd );//对电平的读取   DATAOUT( cmd );  delay_ms( 5 );  LCD_EN_Clr(); }  /******************************************************************************  * 函数名称:void LCD1602_Write_Dat(u8 date)       *  * 函数性能:写数据函数        *  * 输出参数: date 数据       *  * 返回值  :无           *  * 其余阐明:          *  ******************************************************************************/ void LCD1602_Write_Dat( u8 data ) {  LCD_RS_Set();  LCD_RW_Clr();  LCD_EN_Set();   GPIO_Write( GPIOA, (GPIO_ReadOutputData( GPIOA ) & 0xff00) | data );//对电平的读取   delay_ms( 5 );  LCD_EN_Clr(); }  /******************************************************************************  * 函数名称:void LCD1602_ClearScreen()       *  * 函数性能:1602清屏函数        *  * 输出参数:无       *  * 返回值  :无           *  * 其余阐明:          *  ******************************************************************************/ void LCD1602_ClearScreen() {  LCD1602_Write_Cmd( 0x01 ); }  /******************************************************************************  * 函数名称:void LCD1602_Set_Cursor(u8 x, u8 y)       *  * 函数性能:设置1602地位函数        *  * 输出参数:x 横坐标 y 纵坐标       *  * 返回值  :无           *  * 其余阐明:          *  ******************************************************************************/ void LCD1602_Set_Cursor( u8 x, u8 y ) {  u8 addr;   if ( y == 0 )  addr = 0x00 + x;  else  addr = 0x40 + x;  LCD1602_Write_Cmd( addr | 0x80 ); }  /******************************************************************************  * 函数名称:void LCD1602_Show_Str( u8 x, u8 y, u8 *str )       *  * 函数性能:指定地位显示字符串函数        *  * 输出参数:x 横坐标 y 纵坐标 *str 字符串       *  * 返回值  : 无           *  * 其余阐明:          *  ******************************************************************************/ void LCD1602_Show_Str( u8 x, u8 y, u8 *str ) {  LCD1602_Set_Cursor( x, y );  while ( *str != '0' )  {  LCD1602_Write_Dat( *str++ );  } }

四、LCD1602 STM32驱动(6线)

LCD1602 的接口模式是并行的,它有 8 条数据线、3 条控制线。这样就须要 11 条线来管制它的失常工作。尽管它还能够工作在 4 位数据线的模式,最精简的模式是 6 条线。

咱们能够用74HC595 进行串-并转换,74HC595 是“串入并出”的移位寄存器芯片,它须要用 3 条线控制数据的输出,能力失常的输入 8 位数据,总共6条线即可进行LCD1602的管制。

这里多用了一块芯片然而省了5个IO口,对于某些我的项目单片机引脚不够用的状况下能够利用上。

原理图如下:

1、STM32:LCD1602.h

 #ifndef __LCD1602_H #define __LCD1602_H    //1602液晶指令/数据或抉择引脚 #define LCD_RS_PORT   GPIOB #define LCD_RS_PIN GPIO_Pin_10  #define  LCD_RS_0   GPIO_ResetBits(LCD_RS_PORT, LCD_RS_PIN) #define  LCD_RS_1   GPIO_SetBits(LCD_RS_PORT, LCD_RS_PIN)   //1602液晶使能引脚 #define LCD_EN_PORT   GPIOB #define LCD_EN_PIN GPIO_Pin_11 //PB11  #define  LCD_EN_0   GPIO_ResetBits(LCD_EN_PORT, LCD_EN_PIN) #define  LCD_EN_1   GPIO_SetBits(LCD_EN_PORT, LCD_EN_PIN)  //1602液晶数据端口  #define MOSIO PBout(0)  #define R_CLK PCout(5) #define S_CLK PCout(4)  /*********************函数申明*****************/ void LCD1602_Init(void); void LCD1602_Clear(void); void LCD1602_ShowStr(unsigned char xpos,unsigned char ypos,char *p); void LCD1602_BKLSet(unsigned char on); unsigned char LCD1602_BKLGet(void); void LCD1602_ShowLineStr(unsigned char xpos,unsigned char ypos,char *p); void LCD1602_ShowState(unsigned char Signal, unsigned char GprsState); /**********************************************/ #endif  

2、STM32:LCD1602.c

 #include "LCD1602.h" #include "delay.h"//程序中的延时函数依据本人32单片机来就行   void hc595SendData(unsigned char sendVal) {  unsigned char i;  //从CPU中向595一位一位发送,595一位一位接管  for(i = 0; i < 8; i++)  {  if((sendVal << i) & 0x80)  MOSIO = 1;  else MOSIO = 0;  S_CLK = 0;  S_CLK = 1;   }  //CPU发送完后,R_CLK将数据并行输入,  //实现了只占用CPU一个输入口就能够输入8bit数据  R_CLK = 0;  R_CLK = 1;  }  void LCD1602_write_com(unsigned char com)  {  hc595SendData(com);  LCD_RS_0;  LCD_EN_0;  delay_ms(10);   LCD_EN_1; }  void LCD1602_write_data(unsigned char date)  {  hc595SendData(date);  LCD_RS_1;  LCD_EN_0;  delay_ms(10);  LCD_EN_1; }  void LCD1602_Init(void)  {  GPIO_InitTypeDef  GPIO_InitStructure;    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC, ENABLE );    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;  //推挽输入  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  GPIO_InitStructure.GPIO_Pin =  LCD_RS_PIN | LCD_EN_PIN | GPIO_Pin_0;  GPIO_Init(GPIOB, &GPIO_InitStructure);    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;  //推挽输入  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  GPIO_InitStructure.GPIO_Pin =   GPIO_Pin_4 | GPIO_Pin_5;   GPIO_Init(GPIOC, &GPIO_InitStructure);     LCD1602_write_com(0x01);   LCD1602_write_com(0x38);  LCD1602_write_com(0x0C);//开显示,不须要光标   LCD1602_write_com(0x06); }  void LCD1602_Clear(void) {  LCD1602_write_com(0x01); }  void LCD1602_ShowChar(unsigned char xpos,unsigned char ypos,char xsz)  {  ypos%=2;  if(ypos==0)  {  LCD1602_write_com(0x80+xpos);  }  else  {  LCD1602_write_com(0x80+0x40+xpos);  }  LCD1602_write_data(xsz); }  void LCD1602_ShowLineStr(unsigned char xpos,unsigned char ypos,char *p) {  unsigned char i=0;  if(ypos>1 || xpos>=16)return;  while(*p!='0' && i<16 && xpos<16)  {  i++;  LCD1602_ShowChar(xpos++,ypos,*p++);  delay_us(500);  } }  void LCD1602_ShowStr(unsigned char xpos,unsigned char ypos,char *p) {  if(ypos>1)return;  while(*p!='0')  {  LCD1602_ShowChar(xpos++,ypos,*p++);  if(*p=='n')//当检测到换行符时,进行换行检测  {  xpos=0;  ypos++;  p++;  }  } }

如果你感觉文章还不错,记得"点赞关注"

关注我的微信公众号【 加班猿 】能够获取更多内容