当前位置: 首页 > news >正文

小实验--LCD1602显示字符和字符串

代码

#include "lcd1602.h"
#include "stm32f1xx.h"
#include "delay.h"//RS引脚定义
#define RS_GPIO_Port    GPIOB
#define RS_GPIO_Pin     GPIO_PIN_1
#define RS_HIGH     HAL_GPIO_WritePin(RS_GPIO_Port,RS_GPIO_Pin,GPIO_PIN_SET);
#define RS_LOW      HAL_GPIO_WritePin(RS_GPIO_Port,RS_GPIO_Pin,GPIO_PIN_RESET);
//RW引脚定义
#define RW_GPIO_Port    GPIOB
#define RW_GPIO_Pin     GPIO_PIN_2
#define RW_HIGH     HAL_GPIO_WritePin(RW_GPIO_Port,RW_GPIO_Pin,GPIO_PIN_SET);
#define RW_LOW      HAL_GPIO_WritePin(RW_GPIO_Port,RW_GPIO_Pin,GPIO_PIN_RESET);
//EN引脚定义
#define EN_GPIO_Port    GPIOB
#define EN_GPIO_Pin     GPIO_PIN_10
#define EN_HIGH     HAL_GPIO_WritePin(EN_GPIO_Port,EN_GPIO_Pin,GPIO_PIN_SET);
#define EN_LOW      HAL_GPIO_WritePin(EN_GPIO_Port,EN_GPIO_Pin,GPIO_PIN_RESET);void lcd1602_init(void)
{//初始化GPOIlcd1602_gpio_init();//上电初始化lcd1602_start();
}void lcd1602_gpio_init(void)
{GPIO_InitTypeDef gpio_initstruct;__HAL_RCC_GPIOA_CLK_ENABLE();__HAL_RCC_GPIOB_CLK_ENABLE();gpio_initstruct.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_initstruct.Mode = GPIO_MODE_OUTPUT_PP;gpio_initstruct.Pull = GPIO_PULLUP;gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOA,&gpio_initstruct);gpio_initstruct.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_10;gpio_initstruct.Mode = GPIO_MODE_OUTPUT_PP;gpio_initstruct.Pull = GPIO_PULLUP;gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOB,&gpio_initstruct);
}void lcd1602_start(void)
{
//1.延时15msdelay_ms(15);
//2.写指令38H(不检测忙信号)lcd1602_write_cmd(0x38);
//3.延时5msdelay_ms(5);
//4.检测忙信号,(不检测忙信号也可以)
//5.写指令38H:显示模式设置lcd1602_write_cmd(0x38);
//6.写指令08H:显示关闭lcd1602_write_cmd(0x08);
//7.写指令01H:显示清屏lcd1602_write_cmd(0x01);
//8.写指令06H:显示光标移动设置lcd1602_write_cmd(0x06);
//9.写指令0CH:显示开及光标设置lcd1602_write_cmd(0x0C);
}void lcd1602_write_cmd(char cmd)    //向lcd1602写指令的函数
{RS_LOW;RW_LOW;EN_LOW;GPIOA->ODR = cmd;delay_ms(5);EN_HIGH;delay_ms(5);EN_LOW;}void lcd1602_write_data(char dataShow)  //向lcd1602写数据的函数
{RS_HIGH;RW_LOW;EN_LOW;GPIOA->ODR = dataShow;delay_ms(5);EN_HIGH;delay_ms(5);EN_LOW;
}// 第一步:告诉LCD"我要在某个位置显示"
//设置RS=0 (命令模式)
//设置数据线=0x82 (位置信息)
//发送EN脉冲 → LCD接收并处理这个位置信息// 第二步:告诉LCD"我要显示字母L"  
//设置RS=1 (数据模式)
//设置数据线=0x4C (字母L的ASCII码)
//发送EN脉冲 → LCD接收并在指定位置显示
void lcd1602_show_char(void)
{//在哪里显示lcd1602_write_cmd(0x80+0x02);//显示什么?lcd1602_write_data('L');
}void lcd1602_show_liine(char row,char col,char* string)
{switch(row){case 1:lcd1602_write_cmd(0x80+col);while(*string){lcd1602_write_data(*string);string++;}break;case 2:lcd1602_write_cmd(0x80+0x40+col);while(*string){lcd1602_write_data(*string);string++;}break;}
}

代码中有很多宏定义是方便我们在之后写代码时不用一直调用GPIO输出的函数。

首先初始化GPIO,这里就和之前初始GPIO一样。
第二步上电初始化,这里就需要将指令写入LCD中,因此根据LCD写指令的时序图写了关于写指令的函数。
指令详解:
delay_ms(15)
延时15ms,等待LCD电源稳定
lcd1602_write_cmd(0x38)
功能模式设置:设置16×2显示,5×7点阵,8位数据接口
二进制:0011 1000
delay_ms(5)
再次延时5ms,确保指令执行完成
再次lcd1602_write_cmd(0x38)
重复设置功能模式,确保设置成功
lcd1602_write_cmd(0x08)
显示关闭:关闭显示,光标消失
二进制:0000 1000
lcd1602_write_cmd(0x01)
清屏:清除显示内容,光标回到左上角
二进制:0000 0001
lcd1602_write_cmd(0x06)
光标移动设置:写入新数据后光标右移,显示不移动
二进制:0000 0110
lcd1602_write_cmd(0x0C)
显示开及光标设置:开启显示,关闭光标,光标不闪烁
二进制:0000 1100

您提供的图表是LCD1602控制指令的详细分解,它说明了每个指令字节中每一位的功能。RS和R/W是控制引脚,D7-D0是数据引脚。

我们来逐一解析初始化序列中的指令:

  1. lcd1602_write_cmd(0x38) - 功能设置 (Function Set)
    二进制: 0011 1000
    位分解:
    D7 D6 D5 D4 = 0 0 1 1: 这是指令6(功能设置)的标识头。
    D3 = 1: DL (Data Length)。1 = 使用8位数据总线。0 = 使用4位数据总线。
    D2 = 0: N (Number of Lines)。0 = 显示1行。1 = 显示2行。(注意:这里虽然是0,但0x38这个固定值通常用于设置2行显示,请以数据手册为准,可能此位解释有误或特定型号不同,通常0x38就是设置2行)
    D1 = 0: F (Font)。0 = 显示字符为 5x8 点阵。1 = 显示字符为 5x10 点阵。
    总结: 这条指令设置了LCD的工作模式:8位数据接口、2行显示、5x8点阵字符。这是后续所有操作的基础。
  2. lcd1602_write_cmd(0x08) - 显示开关控制 (Display ON/OFF Control)
    二进制: 0000 1000
    位分解:
    D7 D6 D5 D4 = 0 0 0 0: 这是指令4(显示开关)的标识头。
    D3 = 1: D (Display)。1 = 开启显示。0 = 关闭显示。
    D2 = 0: C (Cursor)。1 = 显示光标。0 = 不显示光标。
    D1 = 0: B (Blink)。1 = 光标闪烁。0 = 光标不闪烁。
    总结: 这条指令关闭了显示(D=0),同时确保光标(C=0)和闪烁(B=0)都是关闭状态。这是在清屏和改变设置时的一种常见做法,防止在初始化过程中出现乱码。
  3. lcd1602_write_cmd(0x01) - 清屏 (Clear Display)
    二进制: 0000 0001
    位分解:
    D7 D6 D5 D4 D3 D2 D1 = 0 0 0 0 0 0 0: 这是指令1(清屏幕)的标识头。
    D0 = 1: 执行清屏操作。
    总结: 将DDRAM(显示数据RAM)的内容全部写入空格(空白字符)。将地址计数器(AC)清零,也就是把光标挪到左上角(DDRAM地址0x00的位置)。
  4. lcd1602_write_cmd(0x06) - 设置输入模式 (Entry Mode Set)
    二进制: 0000 0110
    位分解:
    D7 D6 D5 D4 D3 = 0 0 0 0 0: 这是指令3(设置输入模式)的标识头。
    D2 = 1: I/D (Increment/Decrement)。1 = 地址计数器自动加1(光标右移)。0 = 地址计数器自动减1(光标左移)。
    D1 = 1: S (Shift)。1 = 使整个显示移位。0 = 显示不移位。
    总结: 设置写入数据后的光标移动方式。这里设置为:地址计数器自动加1(I/D=1),所以每写入一个字符,光标会自动右移,为写入下一个字符做准备。同时显示不移位(S=0)。
  5. lcd1602_write_cmd(0x0C) - 显示开关控制 (Display ON/OFF Control) - 再次使用
    二进制: 0000 1100
    位分解:
    D7 D6 D5 D4 = 0 0 0 0: 指令4的标识头。
    D3 = 1: D (Display)。1 = 开启显示。
    D2 = 1: C (Cursor)。0 = 不显示光标。(注意:这里代码是0x0C,二进制是1100,所以D2位是0,不显示光标)
    D1 = 0: B (Blink)。0 = 光标不闪烁。
    总结: 这条指令是最终开启显示。它打开显示(D=1),但关闭光标显示(C=0) 并且关闭光标闪烁(B=0)。这样屏幕上就只显示字符,没有多余的光标下划线或闪烁块。
http://www.dtcms.com/a/390346.html

相关文章:

  • Java 的双亲委派模型(Parent Delegation Model)
  • ​​[硬件电路-249]:LDO(低压差线性稳压器)专用于线性电源,其核心设计逻辑与线性电源高度契合,而与开关电源的工作原理存在本质冲突。
  • conda命令行指令大全
  • TCP三次握手与四次挥手
  • Python读取Excel中指定列的所有单元格内容
  • 【DMA】DMA入门:理解DMA与CPU的并行
  • Redis数据库(一)—— 初步理解Redis:从基础配置到持久化机制
  • Salesforce中的事件驱动架构:构建灵活可扩展的企业应用
  • OpenCV实现消除功能
  • Qt QValueAxis详解
  • deepseek大模型部署
  • 消息队列与定时器:如何优雅地处理耗时任务?
  • Maya绑定基础知识总结合集:父子关系和父子约束对比、目标约束示例
  • STM32开发(中断模式:外部中断)
  • (圆方树)洛谷 P4630 APIO2018 铁人两项 题解
  • windows10 使用moon-pilot并配置模型
  • Linux笔记---epoll用法及原理:从内核探究文件等待队列的本质-回调机制
  • Python快速入门专业版(三十三):函数参数陷阱:默认参数的“可变对象”问题(避坑指南)
  • Spring Security 框架 实践小项目(实现不同用户登录显示不同菜单以及每个菜单不同权限)
  • 开发避坑指南(49):Java Stream 对List中的字符串字段求和
  • 网络编程day02-组播,广播
  • 前端左侧菜单列表怎么写
  • LLM大模型和文心一言、豆包、deepseek对比
  • stm32h743iit6 配置 FMC 的时钟源
  • 中小企业数字化转型:从工具升级到思维转变
  • 数据传输中的三大难题,ETL 平台是如何解决的?
  • DAY16 字节流、字符流、IO资源的处理、Properties、ResourceBundle
  • 电气工程师面试题及答案
  • Halcon一维码与二维码识别技术解析
  • 【数据库系统Trip 第1站】总概