(1)实验平台普中 51-Ai8051 开发板https://item.taobao.com/item.htm?abbucket17id1026052331067(2)资料下载 普中科技-各型号产品资料下载链接在前面章节 我们已经学习过几种显示装置 例如数码管、 8*8LED 点阵、 串口通信。 使用它们可以直观显示一些字符数据 但是也有各种局限性 比如显示字符数据太少 硬件设计复杂、 代码编写难度大等。 本章就来介绍一种非常简单且常用的显示装置--LCD1602 液晶显示器 使用它可以显示更多的字符。 我们开发板上集成了一个 LCD1602 液晶显示器接口 将 LCD1602 液晶对应插入即可。 本章学习使用 AI8051 对 LCD1602 液晶屏显示控制。 本章分为如下几部分内容28.1 实验介绍28.1.1 实验简介28.1.1.1 LCD1602 简介28.1.1.2 LCD1602 常用指令28.1.1.3 LCD1602 使用28.1.2 实验目的28.2 硬件设计28.3 软件设计28.3.1 创建和配置工程28.3.1.1 GPIO 配置28.3.1.2 配置 UART128.3.1.3 生成工程28.3.2 添加用户驱动代码28.3.2.1 lcd1602.c 文件28.3.2.2 main.c 文件28.4 实验现象28.1 实验介绍28.1.1 实验简介28.1.1.1 LCD1602 简介1602 液晶也叫 1602 字符型液晶 它能显示 2 行字符信息 每行又能显示 16个字符。 它是一种专门用来显示字母、 数字、 符号的点阵型液晶模块。 它是由若干个 5x7 或者 5x10 的点阵字符位组成 每个点阵字符位都可以用显示一个字符每位之间有一个点距的间隔 每行之间也有间隔 起到了字符间距和行间距的作用 正因为如此 所以它不能很好的显示图片。 其实物图如下所示大家手上拿到的 LCD1602 外观可能和上图不一样 这是由于不同厂家设计所致 但使用方法是一样的。 在上图中可以看到有 16 个管脚孔 从左至右管脚编号顺序是 1-16 其功能定义如下所示下面对几个管脚做下说明3 脚VL 液晶显示偏压信号 用于调整 LCD1602 的显示对比度 一般会外接电位器用以调整偏压信号 注意此脚电压为 0 时可以得到最强的对比度。4 脚RS 数据/命令选择端 当此脚为高电平时 可以对 1602 进行数据字节的传输操作 而为低电平时 则是进行命令字节的传输操作。 命令字节 即是用来对 LCD1602 的一些工作方式作设置的字节 数据字节 即使用以在 1602 上显示的字节。 值得一提的是 LCD1602 的数据是 8 位的。5 脚R/W 读写选择端。 当此脚为高电平可对 LCD1602 进行读数据操作反之进行写数据操作。6 脚E 使能信号 其实是 LCD1602 的数据控制时钟信号 利用该信号的上升沿实现对 LCD1602 的数据传输。7~14 脚8 位并行数据口 而 51 单片机一组 IO 也是 8 位 使得对 LCD1602的数据读写大为方便。在 LCD1602 内部含有 80 个字节的 DDRAM 它是用来寄存显示字符的。 其地址和屏幕的对应关系如下表从上图可知 不是所有的地址都可以直接用来显示字符数据 只有第一行中的 00-0F 第二行中的 40-4F 才能显示 其他地址只能用于存储。 要显示字符时要先输入显示字符地址 也就是告诉模块在哪里显示字符 例如第二行第一个字符的地址是 40H 那么是否直接写入 40H 就可以将光标定位在第二行第一个字符的位置呢 这样不行 因为写入显示地址时要求最高位 D7 恒定为高电平 1所以实际写入的数据应该是 01000000B(40H 10000000B(80H)11000000B(C0H)。 在 1602 中我们就用前 16 个就行了。 第二行也一样用前 16 个地址。28.1.1.2 LCD1602 常用指令在使用 LCD1602 时 我们需要掌握一些常用的指令 这些指令对于 LCD1602初始化是必须的。1 清屏指令功能1 清除液晶显示器 即将 DDRAM 的内容全部填入空白的 ASCII 码 20H;2 光标归位 即将光标撤回液晶显示屏的左上方;3 将地址计数器(AC)的值设为 0。2 模式设置指令功能设定每次写入 1 位数据后光标的移位方向 并且设定每次写入的一个字符是否移动。I/D 0写入新数据后光标左移 1写入新数据后光标右移S 0写入新数据后显示屏不移动 1写入新数据后显示屏整体右移 1 个字符3 显示开关控制指令功能控制显示器开/关、 光标显示/关闭以及光标是否闪烁。D 0显示功能关 1显示功能开C 0无光标 1有光标B 0光标闪烁 1光标不闪烁4 功能设定指令功能设定数据总线位数、 显示的行数及字型。DL 0数据总线为 4 位 1数据总线为 8 位N 0显示 1 行 1显示 2 行F 05× 7 点阵/每字符 15× 10 点阵/每字符28.1.1.3 LCD1602 使用要使用 LCD1602 首先需要对其初始化 即通过写入一些特定的指令实现。然后选择要在 LCD1602 的哪个位置显示并将所要显示的数据发送到 LCD 的DDRAM。 使用 LCD1602 通常都是用于写数据进去 很少使用读功能。 LCD1602 操作步骤如下所示1 初始化2 写命令RSL 设置显示坐标3 写数据RSH在此 不需要读出它的数据的状态或者数据本身。 所以只需要看两个写时序①当要写指令字 设置 LCD1602 的工作方式时 需要把 RS 置为低电平 RW置为低电平 然后将数据送到数据口 D0~D7 最后 E 引脚一个高脉冲将数据写入。②当要写入数据字 在 1602 上实现显示时 需要把 RS 置为高电平 RW 置为低电平 然后将数据送到数据口 D0~D7 最后 E 引脚一个高脉冲将数据写入。写指令和写数据 差别仅仅在于 RS 的电平不一样而已。 以下是 LCD1602 的时序图从上图可以看到 以上给的时间参数全部是 ns 级别的 而 AI8051 单片机的指令周期时间非常短 因此需要在程序里加延时程序 配合 LCD1602 的时序要求。当要写命令字节的时候 时间由左往右 RS 变为低电平 R/W 变为低电平注意看是 RS 的状态先变化完成。 然后这时 DB0~DB7 上数据进入有效阶段 接着 E 引脚有一个整脉冲的跳变 接着要维持时间最小值为 tpw400ns 的 E 脉冲宽度。然后E引脚负跳变 RS电平变化 R/W 电平变化。这样便是一个完整的LCD1602写命令的时序。至此 我们就把 LCD1602 介绍完了 大家如果想要更详细的了解它 可以查看资料“\6--芯片资料\LCD1602 液晶完整中文资料.pdf” 。28.1.2 实验目的LCD1602 液晶显示字符。28.2 硬件设计本实验使用到硬件资源如下1 LCD1602 液晶2 串口 1相关电路在前面章节已经介绍过 此处省略。 LCD1602 液晶接口电路图如下图所示从上图中可知 LCD1602 的 8 位数据口 DB0-DB7 与单片机的 P00-P07 管脚连接 LCD1602 的 RS、 RW、 E 脚与单片机的 P26、 P37、 P27 管脚连接。 RJ1 是一个电位器 用来调节 LCD1602 对比度即显示亮度。28.3 软件设计28.3.1 创建和配置工程按照前面章节内容创建一份新工程 并命名为 25-lcd1602 如下图所示28.3.1.1 GPIO 配置使能端口和时钟 将 UART1 管脚配置为 P30 和 P31 LCD1602 端口设置为推挽输出模式、 使能上拉电阻等。 如下图所示28.3.1.2 配置 UART1在 UART1 的参数设置界面中 可选择“与 printf 函数关联” 这样就可以非常方便的使用 printf 输出调试结果信息。 如下图所示28.3.1.3 生成工程配置完成后 按下代码生成按钮 自动创建工程 系统开始生成初始化代码。生成工程文件目录如下图所示在工程文件夹内新建一个 APP 文件夹 用于存储用户编写的外设驱动 方便后期工程管理和程序移植。 在 APP 文件夹下新建 lcd1602 文件夹 并在该文件夹内新建 lcd1602.c 和 lcd1602.h 用于保存 LCD1602 相关驱动。然后在导出的工程中添加 APP 组 并将 xx.c 导入到工程组内 最后添加头文件路径 否则编译将报错。 如下28.3.2 添加用户驱动代码28.3.2.1 lcd1602.c 文件#include lcd1602.h /******************************************************************************* * 函 数 名 : lcd1602_write_cmd * 函数功能 : LCD1602写命令 * 输 入 : cmd指令 * 输 出 : 无 *******************************************************************************/ void lcd1602_write_cmd(u8 cmd) { LCD1602_RS0;//选择命令 LCD1602_RW0;//选择写 LCD1602_E0; LCD1602_DATAPORTcmd;//准备命令 delay_us(1000); LCD1602_E1;//使能脚E先上升沿写入 delay_us(1000); LCD1602_E0;//使能脚E后负跳变完成写入 } /******************************************************************************* * 函 数 名 : lcd1602_write_data * 函数功能 : LCD1602写数据 * 输 入 : dat数据 * 输 出 : 无 *******************************************************************************/ void lcd1602_write_data(u8 dat) { LCD1602_RS1;//选择数据 LCD1602_RW0;//选择写 LCD1602_E0; LCD1602_DATAPORTdat;//准备数据 delay_us(1000); LCD1602_E1;//使能脚E先上升沿写入 delay_us(1000); LCD1602_E0;//使能脚E后负跳变完成写入 } /******************************************************************************* * 函 数 名 : lcd1602_init * 函数功能 : LCD1602初始化 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void lcd1602_init(void) { lcd1602_write_cmd(0x38);//数据总线8位显示2行5*7点阵/字符 lcd1602_write_cmd(0x0c);//显示功能开无光标光标闪烁 lcd1602_write_cmd(0x06);//写入新数据后光标右移显示屏不移动 lcd1602_write_cmd(0x01);//清屏 } /******************************************************************************* * 函 数 名 : lcd1602_clear * 函数功能 : LCD1602清屏 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void lcd1602_clear(void) { lcd1602_write_cmd(0x01); } /******************************************************************************* * 函 数 名 : lcd1602_show_string * 函数功能 : LCD1602显示字符 * 输 入 : x,y显示坐标x0~15y0~1; str显示字符串 * 输 出 : 无 *******************************************************************************/ void lcd1602_show_string(u8 x,u8 y,u8 *str) { u8 i0; if(y1||x15)return;//行列参数不对则强制退出 if(y1) //第1行显示 { while(*str!\0)//字符串是以\0结尾只要前面有内容就显示 { if(i16-x)//如果字符长度超过第一行显示范围则在第二行继续显示 { lcd1602_write_cmd(0x80ix);//第一行显示地址设置 } else { lcd1602_write_cmd(0x400x80ix-16);//第二行显示地址设置 } lcd1602_write_data(*str);//显示内容 str;//指针递增 i; } } else //第2行显示 { while(*str!\0) { if(i16-x) //如果字符长度超过第二行显示范围则在第一行继续显示 { lcd1602_write_cmd(0x800x40ix); } else { lcd1602_write_cmd(0x80ix-16); } lcd1602_write_data(*str); str; i; } } } /******************************************************************************* * 函 数 名 : lcd1602_show_num * 函数功能 : LCD1602显示数字字符 * 输 入 : x,y显示坐标x0~15y0~1; num显示数字 modemode1:转换为ASCII mode0:不转换为ASCII * 输 出 : 无 *******************************************************************************/ void lcd1602_show_num(u8 x,u8 y,u8 num,u8 mode) { u8 i0; if(y1||x15)return;//行列参数不对则强制退出 if(y1) //第1行显示 { if(i16-x)//如果字符长度超过第一行显示范围则在第二行继续显示 { lcd1602_write_cmd(0x80x);//第一行显示地址设置 } else { lcd1602_write_cmd(0x400x80x-16);//第二行显示地址设置 } if(mode) lcd1602_write_data(num0x30);//显示内容 else lcd1602_write_data(num); } else //第2行显示 { if(i16-x) //如果字符长度超过第二行显示范围则在第一行继续显示 { lcd1602_write_cmd(0x800x40x); } else { lcd1602_write_cmd(0x80x-16); } if(mode) lcd1602_write_data(num0x30);//显示内容 else lcd1602_write_data(num); } } //m^n函数 //返回值:m^n次方. u32 num_pow(u8 m,u8 n) { u32 result1; while(n--)result*m; return result; } //显示数字,高位为0,还是显示 //x,y:起点坐标 //num:数值(0~999999999); //len:长度(即要显示的位数) //mode: //[7]:0,不填充;1,填充0. //[6:0]:保留 void lcd1602_show_nums(u8 x,u8 y,u32 num,u8 len,u8 mode) { u8 t,temp; u8 enshow0; for(t0;tlen;t) { temp(num/num_pow(10,len-t-1))%10; if(enshow0t(len-1)) { if(temp0) { if(mode0x80)lcd1602_show_num(xt,y,0,0); else lcd1602_show_num(xt,y, ,0); continue; }else enshow1; } lcd1602_show_num(xt,y,temp,1); } }lcd1602_write_cmd 函数是 LCD1602 写命令 lcd1602_write_data 函数是LCD1602 写数据 它们之间的区别仅在于控制脚 RS 的值 如果为 0 则写命令为 1 则写数据。lcd1602_init 函数是 LCD1602 初始化函数 根据其命令设置相应的值 开启LCD1602 显示。lcd1602_clear 函数是 LCD1602 清屏函数 实际上也是调用lcd1602_write_cmd 函数写 0X01 命令。lcd1602_show_string 函数是 LCD1602 显示字符函数 该函数有 3 个入口参数 x 和 y 用来确定显示的坐标 x 范围是 0-15 y 范围是 0-1。 str 参数是一个指针类型变量 用于传递显示的内容。 函数内首先判断 xy 坐标是否有效 无效则强制退出 然后根据 xy 值在对应的坐标位置显示内容。lcd1602_show_num 函数是显示单字符函数 该函数有 4 个入口参数 x 和 y用来确定显示的坐标 num 参数是显示字符内容 mode 参数是显示模式 如果为0 则 num 内容不转换为 ascii 码 也就是说 num 可以直接传入字符即可显示。 如果为 1 则 num 内容为十进制数 里面会自动将传入的数转换为字符显示。lcd1602_show_nums 函数可以显示多位数字 有 5 个入口参数 xy 起点坐标 num 为数值 len 为数值长度 mode 为当数值小于设定长度 前面是否补 0。28.3.2.2 main.c 文件//AICUBE_USER_HEADER_REMARK_BEGIN /* 深圳市普中科技有限公司PRECHIN 普中 * 在线视频https://space.bilibili.com/2146492485/video 官网www.prechin.cn * 实验名称LCD1602液晶显示实验 * * 接线说明参考电路图 * * 实验现象程序下载成功后LCD1602液晶显示字符 * * 注意事项 * */ //AICUBE_USER_HEADER_REMARK_END #include config.h //默认已包含stdio.h、intrins.h、ai_usb.h等头文件 //AICUBE_USER_INCLUDE_BEGIN // 在此添加用户头文件包含 #include lcd1602.h //AICUBE_USER_INCLUDE_END //AICUBE_USER_GLOBAL_DEFINE_BEGIN // 在此添加用户全局变量定义、用户宏定义以及函数声明 //AICUBE_USER_GLOBAL_DEFINE_END //////////////////////////////////////// // 项目主函数 // 入口参数: 无 // 函数返回: 无 //////////////////////////////////////// void main(void) { //AICUBE_USER_MAIN_INITIAL_BEGIN // 在此添加用户主函数初始化代码 //AICUBE_USER_MAIN_INITIAL_END SYS_Init(); printf(Hello World !\n); //AICUBE_USER_MAIN_CODE_BEGIN // 在此添加主函数中运行一次的用户代码 lcd1602_init(); lcd1602_show_string(0,0,Hello World!); lcd1602_show_string(0,1,www.prechin.cn); //AICUBE_USER_MAIN_CODE_END while (1) { //AICUBE_USER_MAIN_LOOP_BEGIN // 在此添加主函数中用户主循环代码 //AICUBE_USER_MAIN_LOOP_END } }主函数实现的功能很简单 首先调用初始化函数。 然后调用前面写的 lcd1602初始化函数以及显示字符串函数 在第 1、 2 行分别显示字符串内容。28.4 实验现象将程序编译下载到目标板运行 打开串口助手“\5--开发工具\5-串口调试助手\串口调试助手丁丁 \sscom5.13.1.exe” 实验现象 LCD1602 液晶显示字符。如果出现显示看不清 可调节板子 LCD1602 接口下的 RJ1 电位器。 如果LCD1602 无法显示 可重启电源或复位。
【普中 51-Ai8051 开发攻略】-- 第 28 章 LCD1602 液晶显示实验
发布时间:2026/5/16 3:09:24
(1)实验平台普中 51-Ai8051 开发板https://item.taobao.com/item.htm?abbucket17id1026052331067(2)资料下载 普中科技-各型号产品资料下载链接在前面章节 我们已经学习过几种显示装置 例如数码管、 8*8LED 点阵、 串口通信。 使用它们可以直观显示一些字符数据 但是也有各种局限性 比如显示字符数据太少 硬件设计复杂、 代码编写难度大等。 本章就来介绍一种非常简单且常用的显示装置--LCD1602 液晶显示器 使用它可以显示更多的字符。 我们开发板上集成了一个 LCD1602 液晶显示器接口 将 LCD1602 液晶对应插入即可。 本章学习使用 AI8051 对 LCD1602 液晶屏显示控制。 本章分为如下几部分内容28.1 实验介绍28.1.1 实验简介28.1.1.1 LCD1602 简介28.1.1.2 LCD1602 常用指令28.1.1.3 LCD1602 使用28.1.2 实验目的28.2 硬件设计28.3 软件设计28.3.1 创建和配置工程28.3.1.1 GPIO 配置28.3.1.2 配置 UART128.3.1.3 生成工程28.3.2 添加用户驱动代码28.3.2.1 lcd1602.c 文件28.3.2.2 main.c 文件28.4 实验现象28.1 实验介绍28.1.1 实验简介28.1.1.1 LCD1602 简介1602 液晶也叫 1602 字符型液晶 它能显示 2 行字符信息 每行又能显示 16个字符。 它是一种专门用来显示字母、 数字、 符号的点阵型液晶模块。 它是由若干个 5x7 或者 5x10 的点阵字符位组成 每个点阵字符位都可以用显示一个字符每位之间有一个点距的间隔 每行之间也有间隔 起到了字符间距和行间距的作用 正因为如此 所以它不能很好的显示图片。 其实物图如下所示大家手上拿到的 LCD1602 外观可能和上图不一样 这是由于不同厂家设计所致 但使用方法是一样的。 在上图中可以看到有 16 个管脚孔 从左至右管脚编号顺序是 1-16 其功能定义如下所示下面对几个管脚做下说明3 脚VL 液晶显示偏压信号 用于调整 LCD1602 的显示对比度 一般会外接电位器用以调整偏压信号 注意此脚电压为 0 时可以得到最强的对比度。4 脚RS 数据/命令选择端 当此脚为高电平时 可以对 1602 进行数据字节的传输操作 而为低电平时 则是进行命令字节的传输操作。 命令字节 即是用来对 LCD1602 的一些工作方式作设置的字节 数据字节 即使用以在 1602 上显示的字节。 值得一提的是 LCD1602 的数据是 8 位的。5 脚R/W 读写选择端。 当此脚为高电平可对 LCD1602 进行读数据操作反之进行写数据操作。6 脚E 使能信号 其实是 LCD1602 的数据控制时钟信号 利用该信号的上升沿实现对 LCD1602 的数据传输。7~14 脚8 位并行数据口 而 51 单片机一组 IO 也是 8 位 使得对 LCD1602的数据读写大为方便。在 LCD1602 内部含有 80 个字节的 DDRAM 它是用来寄存显示字符的。 其地址和屏幕的对应关系如下表从上图可知 不是所有的地址都可以直接用来显示字符数据 只有第一行中的 00-0F 第二行中的 40-4F 才能显示 其他地址只能用于存储。 要显示字符时要先输入显示字符地址 也就是告诉模块在哪里显示字符 例如第二行第一个字符的地址是 40H 那么是否直接写入 40H 就可以将光标定位在第二行第一个字符的位置呢 这样不行 因为写入显示地址时要求最高位 D7 恒定为高电平 1所以实际写入的数据应该是 01000000B(40H 10000000B(80H)11000000B(C0H)。 在 1602 中我们就用前 16 个就行了。 第二行也一样用前 16 个地址。28.1.1.2 LCD1602 常用指令在使用 LCD1602 时 我们需要掌握一些常用的指令 这些指令对于 LCD1602初始化是必须的。1 清屏指令功能1 清除液晶显示器 即将 DDRAM 的内容全部填入空白的 ASCII 码 20H;2 光标归位 即将光标撤回液晶显示屏的左上方;3 将地址计数器(AC)的值设为 0。2 模式设置指令功能设定每次写入 1 位数据后光标的移位方向 并且设定每次写入的一个字符是否移动。I/D 0写入新数据后光标左移 1写入新数据后光标右移S 0写入新数据后显示屏不移动 1写入新数据后显示屏整体右移 1 个字符3 显示开关控制指令功能控制显示器开/关、 光标显示/关闭以及光标是否闪烁。D 0显示功能关 1显示功能开C 0无光标 1有光标B 0光标闪烁 1光标不闪烁4 功能设定指令功能设定数据总线位数、 显示的行数及字型。DL 0数据总线为 4 位 1数据总线为 8 位N 0显示 1 行 1显示 2 行F 05× 7 点阵/每字符 15× 10 点阵/每字符28.1.1.3 LCD1602 使用要使用 LCD1602 首先需要对其初始化 即通过写入一些特定的指令实现。然后选择要在 LCD1602 的哪个位置显示并将所要显示的数据发送到 LCD 的DDRAM。 使用 LCD1602 通常都是用于写数据进去 很少使用读功能。 LCD1602 操作步骤如下所示1 初始化2 写命令RSL 设置显示坐标3 写数据RSH在此 不需要读出它的数据的状态或者数据本身。 所以只需要看两个写时序①当要写指令字 设置 LCD1602 的工作方式时 需要把 RS 置为低电平 RW置为低电平 然后将数据送到数据口 D0~D7 最后 E 引脚一个高脉冲将数据写入。②当要写入数据字 在 1602 上实现显示时 需要把 RS 置为高电平 RW 置为低电平 然后将数据送到数据口 D0~D7 最后 E 引脚一个高脉冲将数据写入。写指令和写数据 差别仅仅在于 RS 的电平不一样而已。 以下是 LCD1602 的时序图从上图可以看到 以上给的时间参数全部是 ns 级别的 而 AI8051 单片机的指令周期时间非常短 因此需要在程序里加延时程序 配合 LCD1602 的时序要求。当要写命令字节的时候 时间由左往右 RS 变为低电平 R/W 变为低电平注意看是 RS 的状态先变化完成。 然后这时 DB0~DB7 上数据进入有效阶段 接着 E 引脚有一个整脉冲的跳变 接着要维持时间最小值为 tpw400ns 的 E 脉冲宽度。然后E引脚负跳变 RS电平变化 R/W 电平变化。这样便是一个完整的LCD1602写命令的时序。至此 我们就把 LCD1602 介绍完了 大家如果想要更详细的了解它 可以查看资料“\6--芯片资料\LCD1602 液晶完整中文资料.pdf” 。28.1.2 实验目的LCD1602 液晶显示字符。28.2 硬件设计本实验使用到硬件资源如下1 LCD1602 液晶2 串口 1相关电路在前面章节已经介绍过 此处省略。 LCD1602 液晶接口电路图如下图所示从上图中可知 LCD1602 的 8 位数据口 DB0-DB7 与单片机的 P00-P07 管脚连接 LCD1602 的 RS、 RW、 E 脚与单片机的 P26、 P37、 P27 管脚连接。 RJ1 是一个电位器 用来调节 LCD1602 对比度即显示亮度。28.3 软件设计28.3.1 创建和配置工程按照前面章节内容创建一份新工程 并命名为 25-lcd1602 如下图所示28.3.1.1 GPIO 配置使能端口和时钟 将 UART1 管脚配置为 P30 和 P31 LCD1602 端口设置为推挽输出模式、 使能上拉电阻等。 如下图所示28.3.1.2 配置 UART1在 UART1 的参数设置界面中 可选择“与 printf 函数关联” 这样就可以非常方便的使用 printf 输出调试结果信息。 如下图所示28.3.1.3 生成工程配置完成后 按下代码生成按钮 自动创建工程 系统开始生成初始化代码。生成工程文件目录如下图所示在工程文件夹内新建一个 APP 文件夹 用于存储用户编写的外设驱动 方便后期工程管理和程序移植。 在 APP 文件夹下新建 lcd1602 文件夹 并在该文件夹内新建 lcd1602.c 和 lcd1602.h 用于保存 LCD1602 相关驱动。然后在导出的工程中添加 APP 组 并将 xx.c 导入到工程组内 最后添加头文件路径 否则编译将报错。 如下28.3.2 添加用户驱动代码28.3.2.1 lcd1602.c 文件#include lcd1602.h /******************************************************************************* * 函 数 名 : lcd1602_write_cmd * 函数功能 : LCD1602写命令 * 输 入 : cmd指令 * 输 出 : 无 *******************************************************************************/ void lcd1602_write_cmd(u8 cmd) { LCD1602_RS0;//选择命令 LCD1602_RW0;//选择写 LCD1602_E0; LCD1602_DATAPORTcmd;//准备命令 delay_us(1000); LCD1602_E1;//使能脚E先上升沿写入 delay_us(1000); LCD1602_E0;//使能脚E后负跳变完成写入 } /******************************************************************************* * 函 数 名 : lcd1602_write_data * 函数功能 : LCD1602写数据 * 输 入 : dat数据 * 输 出 : 无 *******************************************************************************/ void lcd1602_write_data(u8 dat) { LCD1602_RS1;//选择数据 LCD1602_RW0;//选择写 LCD1602_E0; LCD1602_DATAPORTdat;//准备数据 delay_us(1000); LCD1602_E1;//使能脚E先上升沿写入 delay_us(1000); LCD1602_E0;//使能脚E后负跳变完成写入 } /******************************************************************************* * 函 数 名 : lcd1602_init * 函数功能 : LCD1602初始化 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void lcd1602_init(void) { lcd1602_write_cmd(0x38);//数据总线8位显示2行5*7点阵/字符 lcd1602_write_cmd(0x0c);//显示功能开无光标光标闪烁 lcd1602_write_cmd(0x06);//写入新数据后光标右移显示屏不移动 lcd1602_write_cmd(0x01);//清屏 } /******************************************************************************* * 函 数 名 : lcd1602_clear * 函数功能 : LCD1602清屏 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void lcd1602_clear(void) { lcd1602_write_cmd(0x01); } /******************************************************************************* * 函 数 名 : lcd1602_show_string * 函数功能 : LCD1602显示字符 * 输 入 : x,y显示坐标x0~15y0~1; str显示字符串 * 输 出 : 无 *******************************************************************************/ void lcd1602_show_string(u8 x,u8 y,u8 *str) { u8 i0; if(y1||x15)return;//行列参数不对则强制退出 if(y1) //第1行显示 { while(*str!\0)//字符串是以\0结尾只要前面有内容就显示 { if(i16-x)//如果字符长度超过第一行显示范围则在第二行继续显示 { lcd1602_write_cmd(0x80ix);//第一行显示地址设置 } else { lcd1602_write_cmd(0x400x80ix-16);//第二行显示地址设置 } lcd1602_write_data(*str);//显示内容 str;//指针递增 i; } } else //第2行显示 { while(*str!\0) { if(i16-x) //如果字符长度超过第二行显示范围则在第一行继续显示 { lcd1602_write_cmd(0x800x40ix); } else { lcd1602_write_cmd(0x80ix-16); } lcd1602_write_data(*str); str; i; } } } /******************************************************************************* * 函 数 名 : lcd1602_show_num * 函数功能 : LCD1602显示数字字符 * 输 入 : x,y显示坐标x0~15y0~1; num显示数字 modemode1:转换为ASCII mode0:不转换为ASCII * 输 出 : 无 *******************************************************************************/ void lcd1602_show_num(u8 x,u8 y,u8 num,u8 mode) { u8 i0; if(y1||x15)return;//行列参数不对则强制退出 if(y1) //第1行显示 { if(i16-x)//如果字符长度超过第一行显示范围则在第二行继续显示 { lcd1602_write_cmd(0x80x);//第一行显示地址设置 } else { lcd1602_write_cmd(0x400x80x-16);//第二行显示地址设置 } if(mode) lcd1602_write_data(num0x30);//显示内容 else lcd1602_write_data(num); } else //第2行显示 { if(i16-x) //如果字符长度超过第二行显示范围则在第一行继续显示 { lcd1602_write_cmd(0x800x40x); } else { lcd1602_write_cmd(0x80x-16); } if(mode) lcd1602_write_data(num0x30);//显示内容 else lcd1602_write_data(num); } } //m^n函数 //返回值:m^n次方. u32 num_pow(u8 m,u8 n) { u32 result1; while(n--)result*m; return result; } //显示数字,高位为0,还是显示 //x,y:起点坐标 //num:数值(0~999999999); //len:长度(即要显示的位数) //mode: //[7]:0,不填充;1,填充0. //[6:0]:保留 void lcd1602_show_nums(u8 x,u8 y,u32 num,u8 len,u8 mode) { u8 t,temp; u8 enshow0; for(t0;tlen;t) { temp(num/num_pow(10,len-t-1))%10; if(enshow0t(len-1)) { if(temp0) { if(mode0x80)lcd1602_show_num(xt,y,0,0); else lcd1602_show_num(xt,y, ,0); continue; }else enshow1; } lcd1602_show_num(xt,y,temp,1); } }lcd1602_write_cmd 函数是 LCD1602 写命令 lcd1602_write_data 函数是LCD1602 写数据 它们之间的区别仅在于控制脚 RS 的值 如果为 0 则写命令为 1 则写数据。lcd1602_init 函数是 LCD1602 初始化函数 根据其命令设置相应的值 开启LCD1602 显示。lcd1602_clear 函数是 LCD1602 清屏函数 实际上也是调用lcd1602_write_cmd 函数写 0X01 命令。lcd1602_show_string 函数是 LCD1602 显示字符函数 该函数有 3 个入口参数 x 和 y 用来确定显示的坐标 x 范围是 0-15 y 范围是 0-1。 str 参数是一个指针类型变量 用于传递显示的内容。 函数内首先判断 xy 坐标是否有效 无效则强制退出 然后根据 xy 值在对应的坐标位置显示内容。lcd1602_show_num 函数是显示单字符函数 该函数有 4 个入口参数 x 和 y用来确定显示的坐标 num 参数是显示字符内容 mode 参数是显示模式 如果为0 则 num 内容不转换为 ascii 码 也就是说 num 可以直接传入字符即可显示。 如果为 1 则 num 内容为十进制数 里面会自动将传入的数转换为字符显示。lcd1602_show_nums 函数可以显示多位数字 有 5 个入口参数 xy 起点坐标 num 为数值 len 为数值长度 mode 为当数值小于设定长度 前面是否补 0。28.3.2.2 main.c 文件//AICUBE_USER_HEADER_REMARK_BEGIN /* 深圳市普中科技有限公司PRECHIN 普中 * 在线视频https://space.bilibili.com/2146492485/video 官网www.prechin.cn * 实验名称LCD1602液晶显示实验 * * 接线说明参考电路图 * * 实验现象程序下载成功后LCD1602液晶显示字符 * * 注意事项 * */ //AICUBE_USER_HEADER_REMARK_END #include config.h //默认已包含stdio.h、intrins.h、ai_usb.h等头文件 //AICUBE_USER_INCLUDE_BEGIN // 在此添加用户头文件包含 #include lcd1602.h //AICUBE_USER_INCLUDE_END //AICUBE_USER_GLOBAL_DEFINE_BEGIN // 在此添加用户全局变量定义、用户宏定义以及函数声明 //AICUBE_USER_GLOBAL_DEFINE_END //////////////////////////////////////// // 项目主函数 // 入口参数: 无 // 函数返回: 无 //////////////////////////////////////// void main(void) { //AICUBE_USER_MAIN_INITIAL_BEGIN // 在此添加用户主函数初始化代码 //AICUBE_USER_MAIN_INITIAL_END SYS_Init(); printf(Hello World !\n); //AICUBE_USER_MAIN_CODE_BEGIN // 在此添加主函数中运行一次的用户代码 lcd1602_init(); lcd1602_show_string(0,0,Hello World!); lcd1602_show_string(0,1,www.prechin.cn); //AICUBE_USER_MAIN_CODE_END while (1) { //AICUBE_USER_MAIN_LOOP_BEGIN // 在此添加主函数中用户主循环代码 //AICUBE_USER_MAIN_LOOP_END } }主函数实现的功能很简单 首先调用初始化函数。 然后调用前面写的 lcd1602初始化函数以及显示字符串函数 在第 1、 2 行分别显示字符串内容。28.4 实验现象将程序编译下载到目标板运行 打开串口助手“\5--开发工具\5-串口调试助手\串口调试助手丁丁 \sscom5.13.1.exe” 实验现象 LCD1602 液晶显示字符。如果出现显示看不清 可调节板子 LCD1602 接口下的 RJ1 电位器。 如果LCD1602 无法显示 可重启电源或复位。