STM32驱动LCD1602液晶8线并行和4线并行详解

目录

LCD1602液晶

引脚定义说明

字库概述 

LCD1602原理图

 LCD1602时序图

LCD1602代码

接线图

用结构体的方式显示字符

LCD1602动态显示数字

4线驱动LCD1602



LCD1602液晶

液晶模块和数码管相比,液晶模块会显得更加专业、漂亮。液晶显示器以其体积小、功耗低、超薄、轻巧、显示内容丰富、使用方便等等诸多有点,在电子设备、通讯、家用电器、仪器仪表等低功耗应用系统之中得到越来越广泛的应用了,使得这一些电子设备的人机界面变得越来越直观、越来越形象了,液晶模块现在已经广泛的应用于液晶电视机、电子表、复印机、计算器、便携式电脑、IC卡电话机、掌上型电子玩具、传真机等许多方面。1602的字符型液晶模块(带背光),是现在工控系统之中使用最为广泛的液晶屏之一了。1602采用了标准的16脚接口。

引脚定义说明

字库概述 

        1602的液晶模块内一般都是带有标准字库的,在内部的字符发生存储器(CGROM)已经是存储了192个5×7的点阵字符,32个5×10的点阵字符。另外还会有字符生成RAM(CGRAM) 512字节,供给用户来自定义字符,比如表1所示,这一些字符都有:英文字母的大小写、阿拉伯数组、常用的符号以及日文假名等,每一个字符都会有一个固定的代码,比如大写的英文字母“A”的代码是01000001B(41H),显示是模块会吧地址41H中的点阵字符图形给显示出来,我们就能看到字母“A”了。

        液晶显示模块时一个慢显示器件,所以在执行每一条指令之前都一定要确认模块得忙标志位为低电平,代表不忙,否则此指令会失效。要显示字符时需要先输入显示字符地址,也就是说告诉模块在哪里显示字符。

LCD1602原理图

 LCD1602时序图

RS = 0 写指令;RS = 1 写数据

LCD1602代码

LCD1602.c

#include "LCD1602.h"

void LCD1602_UserInit(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF, ENABLE);
	
	//配置控制I/O口
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;	//推挽输出
	GPIO_InitStructure.GPIO_Pin   = RS | RW | EN;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
	GPIO_Init(CMD_PROT, &GPIO_InitStructure);
	
	//配置数据I/O口
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;	//推挽输出
	GPIO_InitStructure.GPIO_Pin   = DATA;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
	GPIO_Init(CMD_PROT, &GPIO_InitStructure);	
}

void LCD1602_Write_Cmd_Data(uint8_t cmd, uint8_t data)
{
	if (cmd) //1 数据
	{        
		RS_HIGH;
		RW_LOW;
		EN_LOW;		
		GPIO_Write(DATA_PROT, data); Delay_ms(3);		
		EN_HIGH; Delay_ms(3);
		EN_LOW;		
	}        
	else	 //0 指令
	{
		RS_LOW;
		RW_LOW;
		EN_LOW;		
		GPIO_Write(DATA_PROT, data); Delay_ms(3);		
		EN_HIGH; Delay_ms(3);
		EN_LOW;
	}
}

void LCD1602_Write_Init(void)
{
	LCD1602_Write_Cmd_Data(CMD, 0x38);	//基本设置 显示模式设置
	LCD1602_Write_Cmd_Data(CMD, 0x06);	//显示光标移动位置
	LCD1602_Write_Cmd_Data(CMD, 0x0C);	//开启显示 不显示光标 并且光标不闪烁
	LCD1602_Write_Cmd_Data(CMD, 0x01);	//清除屏幕内容
	LCD1602_Write_Cmd_Data(CMD, 0x80);	//设置起始地址
}

//开启显示
void LCD1602_Open(void)
{
	LCD1602_Write_Cmd_Data(CMD, 0x38);	//基本设置 显示模式设置
	LCD1602_Write_Cmd_Data(CMD, 0x0C);
}

//关闭显示
void LCD1602_Shut(void)
{
	LCD1602_Write_Cmd_Data(CMD, 0x38);	//基本设置 显示模式设置
	LCD1602_Write_Cmd_Data(CMD, 0x08);
}

/**
 * @brief  
 * @param  com  写的地址   //1602 第一行数据0x80~0x8F 第二行数据0xC0~0xCF
 * @param  num  写的长度
 * @param  *dat 写的内容
 * @retval 无
 */
void LCD1602_Write_Word_Display(uint8_t com, uint8_t num, uint8_t *dat)
{
	LCD1602_Write_Cmd_Data(CMD, com);
	for (uint8_t i = 0; i < num; i ++)
	{
		LCD1602_Write_Cmd_Data(DAT,*dat++);
	}
	
}

LCD1602.h 

#ifndef __LCD1602_H__
#define __LCD1602_H__

#include "stm32f10x.h"                  // Device header
#include "Delay.h"

#define RS	GPIO_Pin_0	//RS = 0,指令;RS = 1,数据
#define RW	GPIO_Pin_1	//RW = 0,写  ;RW = 1,读
#define EN	GPIO_Pin_2
#define CMD_PROT 	GPIOC

#define DATA 0x00FF	//0~7引脚
#define DATA_PROT	GPIOF

#define RS_HIGH GPIO_SetBits  (CMD_PROT, RS)
#define RS_LOW  GPIO_ResetBits(CMD_PROT, RS)

#define RW_HIGH GPIO_SetBits  (CMD_PROT, RW)
#define RW_LOW  GPIO_ResetBits(CMD_PROT, RW)

#define EN_HIGH GPIO_SetBits  (CMD_PROT, EN)
#define EN_LOW  GPIO_ResetBits(CMD_PROT, EN)

#define CMD 0	//代表RS = 0,指令
#define DAT 1	//代表RS = 1,数据

void LCD1602_UserInit(void);	//LCD1602初始化
void LCD1602_Write_Init(void);	//LCD1602写初始化
void LCD1602_Open(void);
void LCD1602_Shut(void);
void LCD1602_Write_Word_Display(uint8_t com, uint8_t num, uint8_t *dat);

#endif

主函数 

#include "stm32f10x.h"                  // Device header
//#include "Delay.h"
#include "LCD1602.h"

int main(void)
{
	Delay_Init (72);
	
	LCD1602_UserInit();		//LCD1602初始化
	LCD1602_Write_Init();	//LCD1602写初始化
//	LCD1602_Open();
//	LCD1602_Shut();
	LCD1602_Write_Word_Display(0x80, 16, (u8*)&"xiaoliangtongxue" );	
	
	while(1)
	{

	}
}

/***********************************END OF FILE***********************************/

接线图

(参考51单片机接线图)

RS RW EN 分别是PC0、PC1、PC2,数据线依次为PF0、PF1、PF2……

崩溃瞬间

插了好一会杜邦线,你竟然不亮 

 

这块LCD1602好像是坏了 

算了算了,继续敲


用结构体的方式显示字符

在LCD1602.h文件里添加结构体的声明

//使用结构体
typedef struct{
	uint8_t com;
	uint8_t num;
	uint8_t *data;
}LCD_InitTypeDef;

将LCD1602.c文件里最后一个函数的形参改成结构体,函数里对应的数据也要修改成结构体成员

void LCD1602_Write_Word_Display(LCD_InitTypeDef  LCD_InitStructure)
{
	LCD1602_Write_Cmd_Data(CMD, LCD_InitStructure.com);
	for (uint8_t i = 0; i < LCD_InitStructure.num; i ++)
	{
		LCD1602_Write_Cmd_Data(DAT,*LCD_InitStructure.data++);
	}
	
}

main.c

#include "stm32f10x.h"                  // Device header
//#include "Delay.h"
#include "LCD1602.h"

LCD_InitTypeDef  LCD_InitStructure;

int main(void)
{
	Delay_Init (72);
	
	LCD1602_UserInit();		//LCD1602初始化
	LCD1602_Write_Init();	//LCD1602写初始化
//	LCD1602_Open();
//	LCD1602_Shut();	
	
	LCD_InitStructure.com = 0xC0;	//第二行
	LCD_InitStructure.num = sizeof("xinniankuaile666")-1;	//计算长度
	LCD_InitStructure.data = (u8*)&"xinniankuaile666";	//显示的内容
	
	LCD1602_Write_Word_Display(LCD_InitStructure);	
	while(1)
	{

	}
}

LCD1602动态显示数字

void LCD1602_Number_Display(u8 com, u8 num)	//数据范围0~255
{
	const u8 numcode[] = {"0123456789"};	//只读,不可修改
	
	LCD1602_Write_Cmd_Data(CMD, com);
	LCD1602_Write_Cmd_Data(DAT, numcode[num/100]);//数位分离
	LCD1602_Write_Cmd_Data(DAT, numcode[num/10%10]);
	LCD1602_Write_Cmd_Data(DAT, numcode[num%10]);
}

while(1)里的代码

for(u8 i = 0; i < 255; i ++)
{
    LCD1602_Number_Display(0x87, i);
    Delay_ms(300);
}

4线驱动LCD1602

只用4567  四个数据引脚 

数据以四位四位的方式发送

代码部分

#include "LCD1602.h"

void LCD1602_UserInit(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF, ENABLE);
	
	//配置控制I/O口
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;	//推挽输出
	GPIO_InitStructure.GPIO_Pin   = RS | RW | EN;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
	GPIO_Init(CMD_PROT, &GPIO_InitStructure);
	
	//配置数据I/O口
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;	//推挽输出
	GPIO_InitStructure.GPIO_Pin   = DATA;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
	GPIO_Init(CMD_PROT, &GPIO_InitStructure);	
}

/*4线传输*/
void LCD1602_Write_Cmd_Data(uint8_t cmd, uint8_t data)
{
//	/*代码优化*/
//	if (cmd) //1 数据       
//		RS_HIGH;
//	else	 //0 指令
//		RS_LOW;
	
	//对上面四行代码继续优化,用到了三目运算符
	(CMD) ? RS_HIGH : RS_LOW;
	
	
	//依次执行
	RW_LOW;
	EN_LOW;	
	
	GPIO_Write(DATA_PROT, data | 0x0f); Delay_ms(3);//传输高四位数据	
	EN_HIGH; Delay_ms(3);
	EN_LOW;
	
	GPIO_Write(DATA_PROT, (data << 4) | 0x0f); Delay_ms(3);//左移四位,将低四位数据传输
	EN_HIGH; Delay_ms(3);
	EN_LOW;	
	 
	
}

void LCD1602_Write_Init(void)
{
	LCD1602_Write_Cmd_Data(CMD, 0x38);	//基本设置 显示模式设置
	LCD1602_Write_Cmd_Data(CMD, 0x33);	//设置显示模式
	LCD1602_Write_Cmd_Data(CMD, 0x32);	//设置8线转4线显示模式
	LCD1602_Write_Cmd_Data(CMD, 0x28);	//设置指定模式初始化
	LCD1602_Write_Cmd_Data(CMD, 0x06);	//显示光标移动位置
	LCD1602_Write_Cmd_Data(CMD, 0x0C);	//开启显示 不显示光标 并且光标不闪烁
	LCD1602_Write_Cmd_Data(CMD, 0x01);	//清除屏幕内容
	LCD1602_Write_Cmd_Data(CMD, 0x80);	//设置起始地址
}

//开启显示
void LCD1602_Open(void)
{
	LCD1602_Write_Cmd_Data(CMD, 0x38);	//基本设置 显示模式设置
	LCD1602_Write_Cmd_Data(CMD, 0x33);	//设置显示模式
	LCD1602_Write_Cmd_Data(CMD, 0x32);	//设置8线转4线显示模式
	LCD1602_Write_Cmd_Data(CMD, 0x28);	//设置指定模式初始化
	LCD1602_Write_Cmd_Data(CMD, 0x0C);
}

//关闭显示
void LCD1602_Shut(void)
{
	LCD1602_Write_Cmd_Data(CMD, 0x38);	//基本设置 显示模式设置
	LCD1602_Write_Cmd_Data(CMD, 0x33);	//设置显示模式
	LCD1602_Write_Cmd_Data(CMD, 0x32);	//设置8线转4线显示模式
	LCD1602_Write_Cmd_Data(CMD, 0x28);	//设置指定模式初始化
	LCD1602_Write_Cmd_Data(CMD, 0x08);
}

/**
 * @brief  
 * @param  com  写的地址   //1602 第一行数据0x80~0x8F 第二行数据0xC0~0xCF
 * @param  num  写的长度
 * @param  *dat 写的内容
 * @retval 无
 */
void LCD1602_Write_Word_Display(LCD_InitTypeDef  LCD_InitStructure)
{
	LCD1602_Write_Cmd_Data(CMD, LCD_InitStructure.com);
	for (uint8_t i = 0; i < LCD_InitStructure.num; i ++)
	{
		LCD1602_Write_Cmd_Data(DAT,*LCD_InitStructure.data++);
	}
	
}

void LCD1602_Number_Display(u8 com, u8 num)	//数据范围0~255
{
	const u8 numcode[] = {"0123456789"};	//只读,不可修改
	
	LCD1602_Write_Cmd_Data(CMD, com);
	LCD1602_Write_Cmd_Data(DAT, numcode[num/100]);//数位分离
	LCD1602_Write_Cmd_Data(DAT, numcode[num/10%10]);
	LCD1602_Write_Cmd_Data(DAT, numcode[num%10]);
}

#ifndef __LCD1602_H__
#define __LCD1602_H__

#include "stm32f10x.h"                  // Device header
#include "Delay.h"

//使用结构体
typedef struct{
	uint8_t com;
	uint8_t num;
	uint8_t *data;
}LCD_InitTypeDef;

#define RS	GPIO_Pin_0	//RS = 0,指令;RS = 1,数据
#define RW	GPIO_Pin_1	//RW = 0,写  ;RW = 1,读
#define EN	GPIO_Pin_2
#define CMD_PROT 	GPIOC

#define DATA 0x00F0	//4~7引脚
#define DATA_PROT	GPIOF

#define RS_HIGH GPIO_SetBits  (CMD_PROT, RS)
#define RS_LOW  GPIO_ResetBits(CMD_PROT, RS)

#define RW_HIGH GPIO_SetBits  (CMD_PROT, RW)
#define RW_LOW  GPIO_ResetBits(CMD_PROT, RW)

#define EN_HIGH GPIO_SetBits  (CMD_PROT, EN)
#define EN_LOW  GPIO_ResetBits(CMD_PROT, EN)

#define CMD 0	//代表RS = 0,指令
#define DAT 1	//代表RS = 1,数据

void LCD1602_UserInit(void);	//LCD1602初始化
void LCD1602_Write_Init(void);	//LCD1602写初始化
void LCD1602_Open(void);
void LCD1602_Shut(void);

void LCD1602_Write_Word_Display(LCD_InitTypeDef  LCD_InitStructure);

void LCD1602_Number_Display(u8 com, u8 num);

#endif
#include "stm32f10x.h"                  // Device header
//#include "Delay.h"
#include "LCD1602.h"

LCD_InitTypeDef  LCD_InitStructure;

int main(void)
{
	Delay_Init (72);
	
	LCD1602_UserInit();		//LCD1602初始化
	LCD1602_Write_Init();	//LCD1602写初始化
	LCD1602_Open();
//	LCD1602_Shut();		
	
	LCD_InitStructure.com = 0xC0;	//第二行
	LCD_InitStructure.num = sizeof("xinniankuaile666")-1;	//计算长度
	LCD_InitStructure.data = (u8*)&"xinniankuaile666";	//显示的内容
	LCD1602_Write_Word_Display(LCD_InitStructure);	
	
	while(1)
	{
		for(u8 i = 0; i < 255; i ++)
		{
			LCD1602_Number_Display(0x87, i);
			Delay_ms(300);
		}
		
	}
}

好像是这个函数没有取消注释才不亮 LCD1602_Open();

物联沃分享整理
物联沃-IOTWORD物联网 » STM32驱动LCD1602液晶8线并行和4线并行详解

发表评论