基于Proteus无实物零基础STM32入门自学教程(十)--LCD1602液晶显示

本节课我们继续来点亮高端一点的显示器件--lcd1602液晶。作为工控领域最普遍的显示器件,也是显示内容更多价格最便宜的显示器件。至今仍然称为工控产品的主流显示器件之一,只有极个别产品对成本要求高时会使用7段数码管作为显示器件。但是数码管显示的字符毕竟有限,且极不形象。故LCD1602为代表的液晶,因其能显示众多字符逐渐称为主流,个别液晶集成了汉字字库更使其称为工程师的首选。

一、Protues仿真图

上图为本次仿真的硬件连接和仿真效果图。全部使用PB端口连接整个液晶,包括数据DB0-DB7、EN、RS、RW这些数据和控制端口。具体连接如上,VDD和VEE之间需要串联一个可变电阻,用于调节液晶的字符显示亮度。这个并不影响软件的仿真,但是设计思路与实物一致,大家可以直接照搬到自己的硬件设计上。

在基本有了一个概念后,我们来看看LCD1602的液晶的工作原理。先来看看1602的实物样子。

大家可以数一下现在图片里显示的字符的数量。A-T一共是16个,a-t也是16个。所以LCD1602的意思是16个字符,能显示2行。所以名叫LCD1602液晶。记住字符是针对英文字符,不是中文。

液晶引脚的定义如上图,15和16可选,带背光的液晶会在液晶下方加入一个LED的光源,它的电源由15和16提供。如果不带背光的液晶15和16引脚接了也没有用。看了以上引脚定义再结合我的硬件图应该有一个基本的概念了。那么接下来说一下液晶的工作原理。

DB0-DB7是数据端口,同时该端口承担接收命令和接收数据的功能,那么液晶不是人怎么能区分你单片机发过来的是数据还是命令呢?那么RS,RW和EN这三端起着重要的作用,单片机通过控制这三端的高低电平的组合让液晶知道现在给你发送的是命令还是数据。这种组合关系需要通过LCD的时序图自己结合程序一点点观察。网络截一张比较易懂的图给大家看看。

1602液晶的读操作一般比较少就不单独给大家列出来了。知道了怎么让液晶识别命令还是数据之后,还需要知道液晶字符显示的位置,得让字符按照我们的心意,让它们在哪显示就在哪出现。因此需要指导如下图的RAM地址。

从上图可知道,16x2一共32个字符分别对应的地址为00--0F和40--4F。剩下的10-27和50-67可以作为滚动显示的隐藏字幕工大家使用。而实际使用中由于硬件控制器的原因,我们实际的显示地址都需要加上0x80这个基地址,即从上看第一行第一列的地址是0x00,直接送的显示地址应该为0x80+0x00。第二行的也是一样应该是0x80+0x40,其他显示位置以此类推。

最后根据液晶数据手册的说明书,我们可以开始玩了,让液晶使用什么功能就按照液晶给出的寄存器代码直接写命令给液晶就可以了。

二、MDK代码

LCD1602的核心代码如下

#include lcd1602.h


/****  1602液晶初始化函数,包括stm32的GPIO底层配置函数  ****/
void LCD1602_Init(void)
{
	   LCD1602_GPIO_Config();   //开启GPIO口
       LCD1602_WriteCmd(0X38);  //16*2显示,5*7点阵,8位数据接口
       LCD1602_WriteCmd(0x0C);  //显示器开,光标关闭
       LCD1602_WriteCmd(0x06);  //文字不动,地址自动+1
       LCD1602_WriteCmd(0x01);  //清屏
}


/****  1602液晶检测忙命令函数,经仿真测试可不用此函数  ****/
void LCD1602_WaitReady(void) //检测忙状态
{
		uint8_t sta;

		GPIOB->ODR =0x00FF;
		LCD_RS_Clr();
		LCD_RW_Set();
		LCD_EN_Set();
//	delay_us(1);
		do{
			sta=GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7);
			LCD_EN_Clr();
		   }while(sta);
}


/****  1602液晶写命令函数,cmd为写入的命令  ****/
void LCD1602_WriteCmd(uint8_t cmd) //写指令
{
//	LCD1602_WaitReady();
		LCD_RS_Clr();
		LCD_RW_Clr();
//	LCD_EN_Clr();
//	delay_us(1);
		LCD_EN_Set();
		WriteData(cmd);
		LCD_EN_Clr();
		delay_us(400);
}
/****  1602液晶写数据函数,dat为写入的数据  ****/
void LCD1602_WriteDat(uint8_t dat) //写数据
{
 //	LCD1602_WaitReady();
		LCD_RS_Set();
		LCD_RW_Clr();
//	delay_us(30);
		LCD_EN_Set();
		WriteData(dat);
		LCD_EN_Clr();
		delay_us(400);
}


/****  根据1602的RAM起始地址,定位(x,y)-对应屏幕上的字符坐标  ****/
void LCD1602_SetCursor(uint8_t x, uint8_t y)
{
    uint8_t addr;
    
    if (y == 0)  //由输入的屏幕坐标计算显示RAM的地址
		{addr = 0x80 + 0x00 + x;}  //第一行字符地址从0x00起始,RAM地址为0x80
    else
		{addr = 0x80 + 0x40 + x;}  //第二行字符地址从0x40起始,RAM地址为0x80
    LCD1602_WriteCmd(addr); 
}
      
/****  1602液晶数字显示函数  ****/        
void LCD_ShowNum(uint8_t x, uint8_t y,uint8_t num)
{     

	  LCD1602_SetCursor(x, y);	//定位起始地址
      LCD_ShowChar(x,y,num+'0');
	
} 

/****  1602液晶字符显示函数  ****/  
void LCD_ShowChar(uint8_t x, uint8_t y,uint8_t dat)
{

	  LCD1602_SetCursor(x, y);	//定位起始地址
	  LCD1602_WriteDat(dat);
}


/****  1602液晶字符串显示函数  ****/
void LCD1602_ShowStr(uint8_t x, uint8_t y, uint8_t *str)
{
      LCD1602_SetCursor(x, y);	 //定位起始地址
      while(*str != '\0')       
		  {
		    LCD1602_WriteDat(*str++);
		  }
}

主函数调用时候则异常简单,一个初始化,一个调用函数完成功能。

​
#include "stm32f10x.h"
#include "lcd1602.h"


int main(void)
	
{

 	LCD1602_Init();
	LCD1602_ShowStr(1,0,"LCD1602 is OK.");
while(1)
	{	


  }

}

​

三、仿真效果和源代码资源

 基于Proteus无实物零基础STM32入门自学教程(十)--LCD1602液晶显示-单片机文档类资源-CSDN下载

 

 

 

 

 

 

  • 5
    点赞
  • 68
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
首先,你需要在 Proteus 中添加 51 单片机和 DS18B20 温度传感器、HC-SR04 超声波测距模块以及 1602A 液晶显示屏。 接下来,你需要编写 51 单片机的程序,用于读取 DS18B20 传感器的温度和 HC-SR04 模块的距离,并将它们显示在 1602A 液晶显示屏上。 以下是一个简单的示例程序: ``` #include <reg52.h> #include <stdio.h> #define LCD_RS P1_0 #define LCD_RW P1_1 #define LCD_E P1_2 #define LCD_DATA P2 sbit Trig = P3^5; // 超声波模块触发管脚 sbit Echo = P3^2; // 超声波模块回波管脚 sbit DQ = P3^7; // 温度传感器管脚 unsigned char idata temp[5]; // 存储温度值 unsigned char idata dis[5]; // 存储距离值 void delay(unsigned int x) // 延时函数 { unsigned int i, j; for (i = x; i > 0; i--) { for (j = 110; j > 0; j--); } } void write_command(unsigned char cmd) // 写命令函数 { LCD_RS = 0; LCD_RW = 0; LCD_E = 1; LCD_DATA = cmd; delay(5); LCD_E = 0; } void write_data(unsigned char dat) // 写数据函数 { LCD_RS = 1; LCD_RW = 0; LCD_E = 1; LCD_DATA = dat; delay(5); LCD_E = 0; } void init_lcd() // 初始化液晶屏函数 { write_command(0x38); write_command(0x0c); write_command(0x06); write_command(0x01); delay(20); } void write_string(unsigned char x, unsigned char y, unsigned char *s) // 写字符串函数 { unsigned char i = 0; if (y == 0) { write_command(0x80 + x); } else { write_command(0xc0 + x); } while (s[i] != '\0') { write_data(s[i]); i++; } } void ds18b20_init() // 初始化温度传感器函数 { DQ = 1; delay(1); DQ = 0; delay(480); DQ = 1; delay(60); } void ds18b20_write(unsigned char dat) // 写入温度传感器函数 { unsigned char i; for (i = 0; i < 8; i++) { DQ = 0; DQ = dat & 0x01; delay(6); DQ = 1; dat >>= 1; } } unsigned char ds18b20_read() // 读取温度传感器函数 { unsigned char i, dat = 0; for (i = 0; i < 8; i++) { DQ = 0; dat >>= 1; DQ = 1; if (DQ) { dat |= 0x80; } delay(6); } return dat; } void ds18b20_convert() // 转换温度函数 { ds18b20_init(); ds18b20_write(0xcc); ds18b20_write(0x44); } void ds18b20_readtemp() // 读取温度函数 { unsigned char i; ds18b20_init(); ds18b20_write(0xcc); ds18b20_write(0xbe); for (i = 0; i < 5; i++) { temp[i] = ds18b20_read(); } } void ultrasonic_init() // 初始化超声波模块函数 { Trig = 0; } void ultrasonic_send() // 发送超声波函数 { Trig = 1; delay(10); Trig = 0; } void ultrasonic_receive() // 接收超声波函数 { unsigned int i, j; if (Echo == 1) { while (Echo == 1); i = TH0; j = TL0; dis[0] = i / 100 + '0'; dis[1] = i % 100 / 10 + '0'; dis[2] = i % 10 + '0'; dis[3] = '.'; dis[4] = j / 10 + '0'; } } void main() { TMOD = 0x11; // 定时器 T0 和 T1 工作方式都为模式 1 TH1 = 0xfd; // 定时器 T1 计数初值,用于波特率设置 TL1 = 0xfd; TR1 = 1; // 启动定时器 T1 PCON = 0x80; // 波特率加倍 SCON = 0x50; // 串口工作方式为模式 1,允许接收 ES = 1; // 允许串口中断 EA = 1; // 允许总中断 TH0 = 0; TL0 = 0; ultrasonic_init(); init_lcd(); write_string(0, 0, "Temp:"); write_string(0, 1, "Dist:"); while (1) { ds18b20_convert(); delay(100); ds18b20_readtemp(); ultrasonic_send(); while (!Echo); TR0 = 1; while (Echo); TR0 = 0; ultrasonic_receive(); write_string(6, 0, temp); write_string(6, 1, dis); delay(1000); } } void ser() interrupt 4 // 串口中断函数 { if (RI == 1) { RI = 0; } if (TI == 1) { TI = 0; } } ``` 这个程序使用 51 单片机来读取 DS18B20 温度传感器和 HC-SR04 超声波测距模块的数据,然后将它们显示在 1602A 液晶显示屏上。程序通过串口将数据发送到计算机上,可以使用串口助手等工具来查看数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

永远都是新手

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值