小实验--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是数据引脚。
我们来逐一解析初始化序列中的指令:
- 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点阵字符。这是后续所有操作的基础。- 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)都是关闭状态。这是在清屏和改变设置时的一种常见做法,防止在初始化过程中出现乱码。- 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的位置)。- 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)。- 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)。这样屏幕上就只显示字符,没有多余的光标下划线或闪烁块。