STM32 使用LCD12864显示屏(串行方式)

LCD12864

简介

12864LCD液晶显示模块是一款4位/8位并行、2线或3线接口方式,内部含有国际一级、二级简体中文字库的图形点阵液晶模块。显示分辨率为12864,内置8198个1616点汉字,和128个16*8点ASCII字符集。

功能引脚图

在这里插入图片描述

串口通讯需要使用的引脚

  1. CS片选信号 (如果只有一款屏,可以将CS直接接到VCC上,实现两线通讯。)
  2. SID数据传输引脚
  3. CLK时钟
  4. PSB(低电平表示串行通讯,串口通讯时可以直接接地。)
  5. VSS、VDD电源脚

原理图

工作电压:5V
驱动电压:0-7V
逻辑电平:2.7-5.5V
工作温度:0-55°C
在这里插入图片描述

串行时序图

  1. 在操作液晶屏前,将CS片选信号拉高。
  2. SID前8位是控制字符,1-5位固定为1。
    RW为0时,表示写操作。RS为1时,表示写数据,RS为0时,表示写指令。
    因此写指令CMD固定为0xF8,写数据DAT固定为0xFA。
  3. 发送数据分为两组,将发送的8位数据截取成两段,第一段发送给1byte的高4位,第二段发送给2byte的高4位。
    在这里插入图片描述

基本指令说明

  1. 功能设定
    本设计使用(0x30),表示8位MPU控制,选择基本指令集。
    在这里插入图片描述

  2. 显示开关设置
    本设计使用(0x0C),表示设定显示开,关闭光标,正常显示。
    在这里插入图片描述

  3. 进入设定点
    本设计使用(0x06),表示显示数据的读写时,设定游标方向右移,DDRAM地址计数器加1。
    在这里插入图片描述

  4. 清楚显示
    本设计使用(0x01),表示清除显示。
    在这里插入图片描述

  5. 设定DDRAM地址
    本设计使用(0x80),表示设置启动位置到地址计数器。
    128x64点阵原理上等同于256x32点阵,第三行对应的DDRAM地址紧接着第一行,第四行对应的DDRAM地址紧接着第二行。在使用反白功能时,第一行反白,第三行必然反白。
    在这里插入图片描述

6. 屏幕与DDRAM地址的对应关系

在这里插入图片描述

代码配置

lcd12864.h

#ifndef __LCD12864_H
#define __LCD12864_H

#include "stm32f10x.h"
#include "Delay.h"

#define CS 	GPIO_Pin_0	//片选信号
#define SID GPIO_Pin_1	//数据传输
#define CLK GPIO_Pin_2	//时钟
#define PSB GPIO_Pin_3	//串并选择 低电平为串行
#define CMD_PROT GPIOC	//GPIO分组

#define CS_HIGH GPIO_SetBits(CMD_PROT,CS)
#define CS_LOW GPIO_ResetBits(CMD_PROT,CS)
#define SID_HIGH GPIO_SetBits(CMD_PROT,SID)
#define SID_LOW GPIO_ResetBits(CMD_PROT,SID)
#define CLK_HIGH GPIO_SetBits(CMD_PROT,CLK)
#define CLK_LOW GPIO_ResetBits(CMD_PROT,CLK)
#define PSB_HIGH GPIO_SetBits(CMD_PROT,PSB)
#define PSB_LOW GPIO_ResetBits(CMD_PROT,PSB)

#define CMD 0xF8	//写指令
#define DAT 0xFA	//写数据

typedef struct{
	uint8_t com;	//地址
	uint8_t num;	//长度
	uint8_t *dat;	//数据
}LCD_InitTypeDef;	//定义写文字用的结构体

void LCD12864_UserConfig(void);/*用户配置*/
void LCD12864_Write_Init(void);/*LCD12864上电初始化流程*/
void LCD12864_Write_CMD_Data(uint8_t cmd,uint8_t data);/*LCD12864写函数 传入指令写指令,传入数据写数据*/
void LCD12864_Write_Word(LCD_InitTypeDef LCD_InitStructure);/*LCD12864写文字*/
void LCD12864_Write_Number(uint8_t com,uint8_t num);/*LCD12864写数字*/
void LCD12864_Open(void);/*屏幕开显示*/
void LCD12864_Shut(void);/*屏幕关显示,进入睡眠*/

#endif

lcd12864.c

#include "lcd12864.h"

/*用户配置*/
void LCD12864_UserConfig(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
	
	GPIO_InitStructure.GPIO_Pin	= CS|SID|CLK|PSB;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
	GPIO_Init(CMD_PROT,&GPIO_InitStructure);
}

/*LCD12864写一个字节*/
void LCD12864_Write_Byte(uint8_t data)
{
	uint8_t WBi;
	CS_HIGH;	//写之前拉高片选信号
	for(WBi=0;WBi<8;WBi++)
	{
		(data<<WBi&0x80)?SID_HIGH:SID_LOW;	//移位,判断高位
	
		CLK_LOW;	//拉低时钟
		CLK_HIGH;	//拉高时钟
	}
	CS_LOW;		//释放片选,不再占据总线
}
	
/*LCD12864写函数 传入指令写指令,传入数据写数据*/
void LCD12864_Write_CMD_Data(uint8_t cmd,uint8_t data)
{
	LCD12864_Write_Byte(cmd);
	LCD12864_Write_Byte(data&0xf0);			//根据时序图,传入数据的高4位变成发送数据的高4位,发送的数据低4位为0。例0x38 0011 1000 & 1111 0000
	LCD12864_Write_Byte((data<<4)&0xf0);	//再取传入数据的低4位,变成发送数据的高4位,发送的数据低4位为0。例0x38<<4 1000 & 1111 0000
	Delay_ms(2);	//设置传输延时
}

/*LCD12864上电初始化流程*/
void LCD12864_Write_Init(void)
{
	PSB_LOW;								//设置串行通讯
	LCD12864_Write_CMD_Data(CMD,0x30);		//功能设定,8位MCU接口,基本指令集
	LCD12864_Write_CMD_Data(CMD,0x06);		//显示数据的读写时,设定游标方向右移,DDRAM地址计数器加1
	LCD12864_Write_CMD_Data(CMD,0x0C);		//开显示,关闭光标
	LCD12864_Write_CMD_Data(CMD,0x01);		//清除显示
	LCD12864_Write_CMD_Data(CMD,0x80);		//设置启动位置
}
	
/*屏幕开显示*/
void LCD12864_Open(void)
{
	LCD12864_Write_CMD_Data(CMD,0x0C);	
}

/*屏幕关显示,进入睡眠*/
void LCD12864_Shut(void)
{
	LCD12864_Write_CMD_Data(CMD,0x08);		//进入睡眠模式
}

/*LCD12864写文字*/
void LCD12864_Write_Word(LCD_InitTypeDef LCD_InitStructure)
{
	uint8_t LWWi;
	LCD12864_Write_CMD_Data(CMD,LCD_InitStructure.com);		//写指令:写入地址
	
	for(LWWi=0;LWWi<LCD_InitStructure.num;LWWi++)
	{
		LCD12864_Write_CMD_Data(DAT,*LCD_InitStructure.dat++);	//根据数据长度写入字节
		Delay_ms(200);
	}
}
	
/*LCD12864写数字*/
void LCD12864_Write_Number(uint8_t com,uint8_t num)
{
	const uint8_t number[] = {"0123456789"};
	LCD12864_Write_CMD_Data(CMD,com);					//写地址
	
	LCD12864_Write_CMD_Data(DAT,number[num/1000]);		//1234 1
	LCD12864_Write_CMD_Data(DAT,number[num%1000/100]);	//1234 2
	LCD12864_Write_CMD_Data(DAT,number[num%100/10]);	//1234 3
	LCD12864_Write_CMD_Data(DAT,number[num%100%10]);	//1234 4
}

main.c

#include "stm32f10x.h"   // Device header
#include "lcd12864.h"
#include "Delay.h"

LCD_InitTypeDef LCD_InitStructure;

int main(void)
{
	LCD12864_UserConfig();		//LCD12864用户配置初始化
	LCD12864_Write_Init();		//LCD12864流程初始化
	
	LCD_InitStructure.com = 0x80;	//0x80-0x87 16 8
	LCD_InitStructure.num =16;
	LCD_InitStructure.dat = (u8*)&"桃之夭夭灼灼其华";
	LCD12864_Write_Word(LCD_InitStructure);
	
	LCD_InitStructure.com = 0x90;	//0x90-0x97 16 8
	LCD_InitStructure.num =16;
	LCD_InitStructure.dat = (u8*)&"之子于归宜其室家";
	LCD12864_Write_Word(LCD_InitStructure);
	
	LCD_InitStructure.com = 0x88;	//0x88-0x8F 16 8
	LCD_InitStructure.num =16;
	LCD_InitStructure.dat = (u8*)&"桃之夭夭有蕡其实";
	LCD12864_Write_Word(LCD_InitStructure);
	
	LCD_InitStructure.com = 0x98;	//0x98-0x9F 16 8
	LCD_InitStructure.num =16;
	LCD_InitStructure.dat = (u8*)&"之子于归宜其家室";
	LCD12864_Write_Word(LCD_InitStructure);
	
	Delay_ms(500);	//等待500ms
	
	LCD12864_Write_CMD_Data(CMD,0x01);	//清屏
	while(1)
	{
		uint8_t i;
		for(i=0;i<200;i++)
		{
			LCD12864_Write_Number(0x90,i);		//第二行显示动态的数字
			Delay_ms(200);
		}
	}
}

  • 13
    点赞
  • 97
    收藏
    觉得还不错? 一键收藏
  • 25
    评论
以下是一个简单的基于STM32串行驱动LCD12864显示屏程序。它使用的是基于ST的HAL库。 ```c #include "stm32f10x.h" #include "stm32f10x_gpio.h" #include "stm32f10x_spi.h" #define LCD_PORT GPIOA #define LCD_CS GPIO_Pin_4 #define LCD_A0 GPIO_Pin_5 #define LCD_RST GPIO_Pin_6 void LCD_WriteCmd(uint8_t cmd); void LCD_WriteData(uint8_t data); void LCD_Init(void); void LCD_Clear(void); void LCD_SetPos(uint8_t x, uint8_t y); void LCD_WriteChar(uint8_t x, uint8_t y, char c); void LCD_WriteString(uint8_t x, uint8_t y, char* str); int main(void) { LCD_Init(); LCD_Clear(); LCD_WriteString(0, 0, "Hello, World!"); while(1) { } } void LCD_WriteCmd(uint8_t cmd) { GPIO_ResetBits(LCD_PORT, LCD_A0); // Set A0 low for command GPIO_ResetBits(LCD_PORT, LCD_CS); // Select LCD SPI_I2S_SendData(SPI1, cmd); // Send command via SPI while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET); // Wait for SPI transmission to complete GPIO_SetBits(LCD_PORT, LCD_CS); // Deselect LCD } void LCD_WriteData(uint8_t data) { GPIO_SetBits(LCD_PORT, LCD_A0); // Set A0 high for data GPIO_ResetBits(LCD_PORT, LCD_CS); // Select LCD SPI_I2S_SendData(SPI1, data); // Send data via SPI while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET); // Wait for SPI transmission to complete GPIO_SetBits(LCD_PORT, LCD_CS); // Deselect LCD } void LCD_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; SPI_InitTypeDef SPI_InitStruct; // Enable clock for GPIOA and SPI1 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1, ENABLE); // Configure GPIO pins GPIO_InitStruct.GPIO_Pin = LCD_CS | LCD_A0 | LCD_RST; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(LCD_PORT, &GPIO_InitStruct); // Reset LCD GPIO_ResetBits(LCD_PORT, LCD_RST); GPIO_SetBits(LCD_PORT, LCD_RST); // Configure SPI SPI_InitStruct.SPI_Direction = SPI_Direction_1Line_Tx; SPI_InitStruct.SPI_Mode = SPI_Mode_Master; SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b; SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low; SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge; SPI_InitStruct.SPI_NSS = SPI_NSS_Soft; SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStruct.SPI_CRCPolynomial = 7; SPI_Init(SPI1, &SPI_InitStruct); // Enable SPI SPI_Cmd(SPI1, ENABLE); // Initialize LCD LCD_WriteCmd(0x30); LCD_WriteCmd(0x0C); LCD_WriteCmd(0x01); } void LCD_Clear(void) { uint8_t x, y; for(x = 0; x < 16; x++) { for(y = 0; y < 8; y++) { LCD_WriteChar(x, y, ' '); } } } void LCD_SetPos(uint8_t x, uint8_t y) { LCD_WriteCmd(0x80 | (x & 0x0F)); LCD_WriteCmd(0x40 | (y & 0x07)); } void LCD_WriteChar(uint8_t x, uint8_t y, char c) { uint8_t i; LCD_SetPos(x, y); for(i = 0; i < 8; i++) { LCD_WriteData(Font8x8[c][i]); } } void LCD_WriteString(uint8_t x, uint8_t y, char* str) { while(*str) { LCD_WriteChar(x++, y, *str++); } } ``` 注释已经解释了代码的作用。你需要将对应的字库文件添加到代码中,这里使用的是Font8x8,你也可以选择其他字库。该代码可以将任何字符写入LCD屏幕,并在位置(x,y)处显示字符串。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值