stm32并行驱动LCD12864,最简洁代码让你的屏幕亮起来

前言

这两天因为一个项目的需要,所以又用到了LCD12864这个模块。好久都没用到这玩意了,感觉这东西好像要被淘汰的样子,没想到现在又要用到,简直了。。记得上次用还是大一参加机器人比赛的时候,整的那个小机器人举着个12864满地跑,哈哈哈。废话少叙,这玩意比较简单,但是由于很长时间没碰了,所以一开始还是在网上找资料,本以为会很快,但是发现大多写的比较乱,因此,我就萌生了自己写一个总结的想法,一来给自己做个总结,二来节省大家的时间。开始吧!

硬件部分

准备材料:LCD12864模块一个,开发板或者自己设计的板子都可以(我用的是开发板,因为自己画的板子发过去做还没做好,就先用开发板验证的,原理一样)

LCD12864引脚功能图:
stm32并行驱动LCD12864,最简洁代码让你的屏幕亮起来_第1张图片
LCD12864地址分布情况:
stm32并行驱动LCD12864,最简洁代码让你的屏幕亮起来_第2张图片
硬件连接:
stm32并行驱动LCD12864,最简洁代码让你的屏幕亮起来_第3张图片
这是我自己画的图里的连接情况,对着连上就行了。这里说明一下,第3脚V0本来我是连上3.3V的,但是开机屏幕亮,无现象,但是去掉之后就正常了,我也不清楚是什么原因。大家应该也看到了,这是并行驱动方式的。最终硬件连接图如下:
stm32并行驱动LCD12864,最简洁代码让你的屏幕亮起来_第4张图片

软件部分

看代码之前先看看LCD12864的时序图,就会理解代码里的一些操作了。
LCD12864时序图(并行):
stm32并行驱动LCD12864,最简洁代码让你的屏幕亮起来_第5张图片
1.lcd.h文件:

#ifndef _LCD_H
#define _LCD_H
#include "sys.h"
#include "delay.h"

#define RS PCout(0) //发数据/命令控制口
#define RW PCout(1) //读/写控制口,写比较常用
#define EN PCout(2) //使能口
#define			LINE1		0x80 //第一行起始地址,下同
#define			LINE2 		0x90
#define			LINE3 		0x88
#define			LINE4 		0x98

//以下是点亮你的屏幕必要的六个函数,不能再少了,想添加其他功能就得再加其他函数
void IO_Init(void); //必要的IO口初始化
void CheckBusy(void); //检查忙/闲状态
void LCD_wdat(u8 dat); //写数据
void LCD_wcmd(u8 com); //写命令
void LCD_Init(void); //LCD初始化
void LCD_Wmessage(u8* message,u8 address); //向屏幕里写入字串

#endif

2.lcd.c文件:

#include "lcd.h"
#include "sys.h"
#include "delay.h"

u16 temp;

void IO_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC,ENABLE);
	
	//想实现控制,激活控制口(PC0,PC1,PC2)必不可少
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOC,&GPIO_InitStructure);
	
	//想发送数据,激活数据口(PA0~PA7)必不可少
	GPIO_InitStructure.GPIO_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_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);	
}
//LCD初始化
void LCD_Init()
{
	LCD_wcmd(0x30);//功能设定:基本指令集
	delay_ms(5);
	LCD_wcmd(0x0C);//显示开,关光标
	delay_ms(5);
	LCD_wcmd(0x01);//清除显示
}
//忙判断
void CheckBusy(void)
{
	u8 status;
	RS=0;
	RW=1; //读出数据,RW=1
	GPIOA->ODR = 0xFF;
	do
	{
		EN = 1;
		delay_ms(5);
		status = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_7);//接收BF位,判断是否忙
	}while(status & 0x80);
	EN=0;
}
//LCD写命令
void LCD_wcmd(u8 cmd)
{
	CheckBusy();
	RS=0;
	RW=0;
	delay_ms(5);
	temp=(temp&0xff00)|cmd;//temp的低八位清零后将cmd放进去
	GPIO_Write(GPIOA,temp);//通过GPIO_Write()函数将数据发到A端口(也就是LCD的数据口)
	EN=1;//使能位开启
	delay_ms(10);//10ms应该能发送完了
	EN=0;//使能位关闭
}
//LCD写数据
void LCD_wdat(u8 dat)
{
	CheckBusy();
	RS=1;
	RW=0;
	delay_ms(5);
	temp=(temp&0xff00)|dat; //temp的低八位清零后将dat放进去
	GPIO_Write(GPIOA,temp);//通过GPIO_Write()函数将数据发到A端口(也就是LCD的数据口)
	EN=1;//使能位开启
	delay_ms(10);//10ms应该能发送完了
	EN=0;//使能位关闭
}
//向LCD12864中写入一行数据(因为你不可能每次只发送一字节数据)
void LCD_Wmessage(u8* message,u8 address)
{
	LCD_wcmd(address);//要显示的位置,你想让内容显示在LCD的哪一行,就把该行的起始地址通过写命令的方式发送出去,很神奇,有木有
	while(*message>0)//这个判断很关键,判断你的内容有没有发完
	{
		LCD_wdat(*message); //内核还是发字节函数
		message++; //指针挺好用的。。
	}
}

到此,就没了。下面写个main函数验证一下效果

#include "stm32f10x.h"
#include "sys.h"
#include "lcd.h"
#include "delay.h"
/************************
注意:一行16个字节,一个汉字2字节,一个字母1字节,每个汉字只能在偶字节处起
************************/
int main(void)
{	
	u8 dis3[]={"我王境泽就是饿死"};
	u8 dis4[]={"死外边"};
	u8 dis5[]={"也不吃你一口饭!"};
	u8 dis6[]={"艾玛,真香!"};
	delay_init();
	IO_Init();
	LCD_Init();
	while(1)
	{
		LCD_Wmessage(dis3,LINE1);
		LCD_Wmessage(dis4,LINE2);
		LCD_Wmessage(dis5,LINE3);
		LCD_Wmessage(dis6,LINE4);
	}
}

效果:
stm32并行驱动LCD12864,最简洁代码让你的屏幕亮起来_第6张图片
完。希望这篇文章可以节约大家的时间。比较简单,工程文件我就不放出来了,有需要可以加我QQ:643152272索取。加好友时请务必注明自己所在的学校和机构。

你可能感兴趣的:(stm32,LCD12864,嵌入式)