大家好,我是老耿,高职青椒一枚,一直从事单片机、嵌入式、物联网等课程的教学。对于高职的学生层次,同行应该都懂的,老师在课堂上教学几乎是没什么成就感的。正因如此,才有了借助 CSDN 平台寻求认同感和成就感的想法。在这里,我准备陆续把自己花了很多心思的教学设计分享出来,主要面向广大师生朋友,单片机老鸟就略过吧。欢迎点赞+关注,各位的支持是本人持续输出的动力,多谢多谢!

我在高职教STM32——LCD液晶显示(4)-LMLPHP

        前边我们讲解了LED、按键和蜂鸣器的应用,这三类器件本身工作原理十分简单,因此我们的重点是放在STM32的GPIO上面。这一章我们来学习一下开发板配套的那块厚厚的液晶屏——LCD1602,聚焦的是这个器件本身的特点和工作时序。因此,我们需要熟读它的数据手册,因为手册里告诉了编程的要点、参数、时序等。阅读器件手册是做单片机和嵌入式开发必备的基本能力,我们就从这一章开始锻炼起来吧。为了不让篇幅太长,本章打算分四个部分来讲解,本文是第四部分。

【学习目标】

  1. 了解LCD1602的工作原理
  2. 掌握LCD1602的工作时序
  3. 领悟软件模拟时序的思路和方法

四、字符跳动显示实验

        我们在前面的液晶指令描述中可以看到,LCD1602还支持光标和屏幕移动,下面我们就通过两个实验来感受一下动态显示的效果。

4.1 任务描述

        这个实验是让字符串里的每个字符逐个跳出来显示,我们将实验的动态效果分解在图18中,中间部分做了一些省略。

4.2 工程源码剖析

        对于底层的 lcd1602.clcd1602.h 驱动文件来说,我们尽量不去改动。控制字符跳出的代码在主程序里实现,见如下代码清单16。

/**
 ******************************************************
 * 代码清单16:main.c
 * 项    目:LCD1602液晶显示
 * 任务描述:字符跳到显示
 * 实验平台:OneNET STM32开发板V3.2
 * 作    者:老耿
 * 日    期:yyyy/mm/dd
 ******************************************************
**/
 
//-----------------------------------------------------
// 必要的头文件
//-----------------------------------------------------
#include "delay.h"
#include "lcd1602.h"

int main()
{
	u8 i;	//控制列坐标的变量
	u8 *p;	//指向字符串的指针
	
	delay_init();			//Systick初始化,用于普通的延时
	Lcd1602_Init();			//LCD1602初始化
	
	while(1)
	{
		i = 2;	            //列坐标初值
		p = "STM32 Board";	//指向待显示的字符串

		Lcd1602_Clear(2);	//每次开始显示前先清屏
		Lcd1602_ShowStr(0, 3, "KylinV3.2");	//首行静态显示
		delay_ms(250);		//停留一下进入下面的字符跳出效果
		
		/* ------------ 以下是控制字符逐个跳出的循环 -------------*/
		while(*p)	//只要不是结束字符就循环,即while(*p!='\0')
		{	
			Lcd1602_ShowChar(1, i, *p);	//第二行指定位置显示一个字符
			i++;			//下一列
			p++;			//下一个字符
			delay_ms(250);	//每个字符跳出的间隔
		}
		
		delay_ms(250);		//跳完停留一下
	}
}

五、液晶滚动显示实验

5.1 任务描述

        这个实验是让整个屏幕画面整体向左或向右滚动显示,我们将实验动态效果分解在图19中,中间部分做了一些省略。

5.2 工程源码剖析

        同理,还是只修改主程序里的控制代码,见如下代码清单17。

/**
 ******************************************************
 * 代码清单17:main.c
 * 项    目:LCD1602液晶显示
 * 任务描述:滚动显示
 * 实验平台:OneNET STM32开发板V3.2
 * 作    者:老耿
 * 日    期:yyyy/mm/dd
 ******************************************************
**/
 
//-----------------------------------------------------
// 必要的头文件
//-----------------------------------------------------
#include "delay.h"
#include "lcd1602.h"

int main()
{
	delay_init();			//Systick初始化,用于普通的延时
	Lcd1602_Init();			//LCD1602初始化

	Lcd1602_ShowStr(0, 3, "KylinV3.2");
	Lcd1602_ShowStr(1, 2, "STM32 Board");
	
	while(1)
	{
		Lcd1602_WriteCmd(0x18);		//画面整体左移一个字符位置
		//Lcd1602_WriteCmd(0x1C);	//画面整体右移一个字符位置
		delay_ms(250);
	}
}

六、液晶显示功能的扩展

        在上面的实验中,我们通过 Lcd1602_ShowStr() 函数实现了字符串信息的显示。但不知你是否考虑过,倘若显示的内容不是字符的类型,比如传感器采集温湿度值、ADC采集的电压值等,这些数据都是浮点类型的,也想通过液晶显示出来,该如何处理呢?

        针对以上问题,我们补充一个显示函数 Lcd1602_Printf(),来实现多种数据类型的显示,就像使用 printf() 函数那样,可以通过%d、%f、%s这样的形式来指定显示内容的数据类型。该函数用到了C语言中解决变参问题的操作方式,想详细了解这部分知识的同学请自行搜索查阅,这里不展开。源码见如下代码清单18。

/*
************************************************************
*	代码清单18:	Lcd1602_Printf()函数
*	函数功能:	设置LCD1602显示的内容
*	入口参数:	x和y:显示的起始坐标(同上)
*				fmt:不定长参
*	返回参数:	无
*	说明:		
************************************************************
*/
void Lcd1602_Printf(u8 x, u8 y, char *fmt, ...)
{
	u8 LcdPrintfBuf[33];	//”打印“字符的缓冲区
	va_list ap;		//定义一个可变参数列表
	u8 *ptr = LcdPrintfBuf;	//指向缓冲区的指针
	
	va_start(ap, fmt);	//获取可变参数列表第一个参数的地址
	vsprintf((char *)LcdPrintfBuf, fmt, ap);	//把可变参数列表内容格式化成字符串存入缓冲区
	va_end(ap);			//清空可变参数列表
	
	Lcd1602_SetCursor(x, y);	//设置显示位置
	while(*ptr)		//循环显示缓冲区里的每个字符
	{
		Lcd1602_WriteData(*ptr);
		ptr++;
	}
}

        有了这个函数,我们就可以在主程序中像使用 printf() 函数那样在液晶屏上“打印”需要的内容了,代码清单19给了一个简单示例。

/**
 ******************************************************
 * 代码清单18:main.c
 * 项    目:LCD1602液晶显示
 * 任务描述:用液晶“打印”函数来显示
 * 实验平台:OneNET STM32开发板V3.2
 * 作    者:老耿
 * 日    期:yyyy/mm/dd
 ******************************************************
**/
 
//-----------------------------------------------------
// 必要的头文件
//-----------------------------------------------------
#include "delay.h"
#include "lcd1602.h"

int main()
{
	char *str = "Kylin STM32";	//字符串类型
	float ver = 3.2;			//浮点类型
	
	delay_init();				//Systick初始化,用于普通的延时
	Lcd1602_Init();				//LCD1602初始化
	
	Lcd1602_Printf(0, 0, "%s", str);
	Lcd1602_Printf(1, 0, "version:%.1f", ver);
	while(1);
}

        可以看到,带变参的 Lcd1602_Printf() 函数更灵活通用,使我们不必再纠结显示内容究竟是什么数据类型,这是它的优势。那有没有劣势呢?当然有了,在显示同样内容的情况下,使用Lcd1602_Printf() 函数比用 Lcd1602_ShowStr() 函数编译出来的代码量大了不是一点儿,如图20所示。

(第四部分完,共四部分)

06-24 15:28