数据端口GPIO定义:
LCD_DB0 GPIOE GPIO_Pin_0
LCD_DB1 GPIOE GPIO_Pin_1
LCD_DB2 GPIOE GPIO_Pin_2
LCD_DB3 GPIOE GPIO_Pin_3
LCD_DB4 GPIOE GPIO_Pin_4
LCD_DB5 GPIOE GPIO_Pin_5
LCD_DB6 GPIOE GPIO_Pin_6
LCD_DB7 GPIOE GPIO_Pin_7
控制端口GPIO硬件连接:
LCD_RST GPIOD GPIO_Pin_0
LCD_PSB GPIOD GPIO_Pin_1
LCD_EN GPIOD GPIO_Pin_8
LCD_RW GPIOD GPIO_Pin_9
LCD_RS GPIOD GPIO_Pin_10
LCD12864.c
#include "12864LCD.h"
unsigned char dis1[10];
void LCD12864_PORT_Init(void)
{
GPIO_InitTypeDef GPIO_PortInit;
/************配置控制IO端口**********/
RCC_AHB1PeriphClockCmd(LCD_CONTROL_PORT_CLOCK, ENABLE);//使能GPIOD时钟
GPIO_PortInit.GPIO_Pin = LCD_CONTROL_PIN;//控制IO端口
GPIO_PortInit.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
GPIO_PortInit.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_PortInit.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_PortInit.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(LCD_CONTROL_PORT, &GPIO_PortInit);//初始化控制端口GPIO
/************配置数据端口*************/
RCC_AHB1PeriphClockCmd(LCD_DATA_PORT_CLOCK, ENABLE);//使能GPIOE时钟
GPIO_PortInit.GPIO_Pin = LCD_DATA_PIN;//
GPIO_PortInit.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
GPIO_PortInit.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_PortInit.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_PortInit.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(LCD_DATA_PORT, &GPIO_PortInit);//始化数据端口GPIO
}
//稍作延时
void _NOP_(void)
{
u8 i = 200;
while(i > 0)
{
i--;
}
}
/*******************************************************************/
/* */
/*写指令数据到LCD */
/*RS=L,RW=L,E=高脉冲,D0-D7=指令码。 */
/* */
/*******************************************************************/
void LCD12864_WriteCmd(u8 cmd) //写命令函数
{
//WaitBusy();
Clear_LCD_RS; //RS = 0.
Clear_LCD_RW; //RW = 0.
Set_LCD_EN; //EN = 1.
_NOP_();
_NOP_();
LCD_DATA_PORT->ODR = ((LCD_DATA_PORT->ODR & 0xff00) | cmd); //此处,只有直接操作寄存器才能
//达到,只改变输出数据寄存器ODR的低8位,其它位
//不变的目的。因为,只有低8位是数据引脚,
//其它位可能是控制引脚,不能改变。
_NOP_();
_NOP_();
Clear_LCD_EN; //EN = 0;
_NOP_();
_NOP_();
}
/*******************************************************************/
/* */
/*写显示数据到LCD */
/*RS=H,RW=L,E=高脉冲,D0-D7=数据。 */
/* */
/*******************************************************************/
void LCD12864_WriteData(u8 data) //写数据函数
{
//WaitBusy();
Set_LCD_RS; //RS = 1.
Clear_LCD_RW; //RW = 0.
Set_LCD_EN; //EN = 1.
_NOP_();
_NOP_();
LCD_DATA_PORT->ODR = ((LCD_DATA_PORT->ODR & 0xff00) | data); //同上。
_NOP_();
_NOP_();
Clear_LCD_EN; //EN = 0;
_NOP_();
_NOP_();
}
/*******************************************************************/
/* */
/* LCD12864初始化 */
/* */
/*******************************************************************/
void LCD12864_Init(void) //初始化 12864
{
Clear_LCD_RST;
delay_ms(2);
Set_LCD_RST;
delay_ms(2);
Set_LCD_PSB; //令PSB=1,设置为并行数据模式。
delay_ms(2);
LCD12864_WriteCmd(0x30); //选择基本指令集,和,8位数据模式。
delay_ms(2);
LCD12864_WriteCmd(0x0c); //开显示,无游标,不反白.
delay_ms(2);
LCD12864_WriteCmd(0x01); //清除显示,并将 DDRAM 的地址计数器 AC 设为 00H.
delay_ms(2);
LCD12864_WriteCmd(0x06); //设置,外部读写数据后,地址记数器 AC 会自动加 1。
delay_ms(2);
LCD12864_WriteCmd(0x80); //将 DDRAM 地址计数器 AC 设为 0.
delay_ms(2);
}
/****************************************************************/
/* */
/* 设定显示位置,以下是光标定位函数,第一个参数为行坐标, */
/* 第二个为列坐标,起始坐标是1行1列。只能以16个点的宽度为单位移动 */
/* */
/****************************************************************/
void Locate16(u8 X, u8 Y)
{
switch(X)
{
case 1:
LCD12864_WriteCmd(0x80 + Y);
break;
case 2:
LCD12864_WriteCmd(0x90 + Y);
break;
case 3:
LCD12864_WriteCmd(0x88 + Y);
break;
case 4:
LCD12864_WriteCmd(0x98 + Y);
break;
}
}
/*******************************************************************/
/* */
/* LCD12864显示字符串 */
/* */
/*******************************************************************/
void DisPlayString(u8 X, u8 Y, u8 *str) //显示字符串的函数
{
if(X > 4)
{
X = 1;
}
if(Y > 4)
{
Y = 0;
}
Locate16(X, Y) ;
while(*str != '\0')
{
LCD12864_WriteData(*str);
str++;
delay_ms(5);
}
}
//清屏,清除LCD12864显示
void LCD12864_Clear(void)
{
LCD12864_WriteCmd(0x01);
}
//屏幕整体左移一格,用于LCD12864来做滚动显示
void LCD_ShiftLeft(void)
{
LCD12864_WriteCmd(0x18);
}
//屏幕整体右移一格,用于LCD12864来做滚动显示
void LCD_ShiftRight(void)
{
LCD12864_WriteCmd(0x1C);
}
LCD12864.h
#ifndef __12864LCD_H__
#define __12864LCD_H__
#include "stm32f4xx.h"
#include "stm32f4xx_gpio.h"
#include "sys.h"
#include "delay.h"
#include <stdlib.h>
/***控制端口GPIO定义***/
#define LCD_RST GPIO_Pin_0
#define LCD_PSB GPIO_Pin_1
#define LCD_EN GPIO_Pin_8
#define LCD_RW GPIO_Pin_9
#define LCD_RS GPIO_Pin_10
//定义控制端口 置1
#define Set_LCD_RS GPIO_SetBits(GPIOD,LCD_RS)
#define Set_LCD_RW GPIO_SetBits(GPIOD,LCD_RW)
#define Set_LCD_EN GPIO_SetBits(GPIOD,LCD_EN)
#define Set_LCD_PSB GPIO_SetBits(GPIOD,LCD_PSB)
#define Set_LCD_RST GPIO_SetBits(GPIOD,LCD_RST)
//定义控制端口 清0
#define Clear_LCD_RS GPIO_ResetBits(GPIOD,LCD_RS)
#define Clear_LCD_RW GPIO_ResetBits(GPIOD,LCD_RW)
#define Clear_LCD_EN GPIO_ResetBits(GPIOD,LCD_EN)
#define Clear_LCD_PSB GPIO_ResetBits(GPIOD,LCD_PSB)
#define Clear_LCD_RST GPIO_ResetBits(GPIOD,LCD_RST)
/********数据端口GPIO定义*********/
#define LCD_DB0 GPIO_Pin_0
#define LCD_DB1 GPIO_Pin_1
#define LCD_DB2 GPIO_Pin_2
#define LCD_DB3 GPIO_Pin_3
#define LCD_DB4 GPIO_Pin_4
#define LCD_DB5 GPIO_Pin_5
#define LCD_DB6 GPIO_Pin_6
#define LCD_DB7 GPIO_Pin_7
#define LCD_CONTROL_PORT GPIOD
#define LCD_DATA_PORT GPIOE
//GPIO时钟
#define LCD_CONTROL_PORT_CLOCK RCC_AHB1Periph_GPIOD
#define LCD_DATA_PORT_CLOCK RCC_AHB1Periph_GPIOE
#define LCD_CONTROL_PIN LCD_RST | LCD_PSB| LCD_EN | LCD_RW | LCD_RS
#define LCD_DATA_PIN LCD_DB0 | LCD_DB1|LCD_DB2 | LCD_DB3 | LCD_DB4 |LCD_DB5 | LCD_DB6 | LCD_DB7
void _NOP_(void);
void LCD12864_PORT_Init(void);
void LCD12864_WriteCmd(u8 cmd); //写命令函数。
void LCD12864_WriteData(u8 data); //写数据函数。
void LCD12864_Init(void); //初始化 12864 和要用到的 STM 32 的引脚。
void Locate16(u8 X, u8 Y);
void DisPlayString(u8 X, u8 Y, u8 *str); //显示字符串的函数。
void LCD12864_Clear(void);
void LCD_ShiftLeft(void);
void LCD_ShiftRight(void);
#endif
main.c
#include "12864LCD.h"
int main(void)
{
u8 buf[] = "2023-7-11";
u8 temp;
SystemInit();
delay_init(168);
LCD12864_PORT_Init();
LCD12864_Init();
while(1)
{
DisPlayString(1, 0, buf); //显示字符串的函数
for(temp = 0; temp < 16; temp++) //LCD上显示时间数据,每200ms屏向左移动一次
{
LCD_ShiftLeft();
delay_ms(200);
}
}
}