接线如下:
一、初始化IO口
void LCD_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB|RCC_AHB1Periph_GPIOE|
RCC_AHB1Periph_GPIOF|RCC_AHB1Periph_GPIOG
,ENABLE);
//PB0,PB1
GPIO_InitStructure.GPIO_Pin=LCD_BL_Pin|LCD_RS_Pin;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;//普通输出
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//上拉
GPIO_Init(LCD_RS_PORT,&GPIO_InitStructure);
GPIO_SetBits(LCD_RS_PORT,LCD_RS_Pin);
GPIO_ResetBits(LCD_BL_PORT,LCD_BL_Pin);//点亮背光
//PE3,PE4,PE5
GPIO_InitStructure.GPIO_Pin=LCD_RW_Pin|LCD_EN_Pin|LCD_PSB_Pin;
GPIO_Init(LCD_EN_PORT,&GPIO_InitStructure);
GPIO_SetBits(LCD_EN_PORT,LCD_RW_Pin|LCD_EN_Pin|LCD_PSB_Pin);
GPIO_InitStructure.GPIO_Pin=LCD_D0_Pin;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;//普通输出
GPIO_InitStructure.GPIO_OType=GPIO_OType_OD;//开漏输出
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//上拉
GPIO_Init(LCD_D0_PORT,&GPIO_InitStructure);
GPIO_SetBits(LCD_D0_PORT,LCD_D0_Pin);
GPIO_InitStructure.GPIO_Pin=LCD_D1_Pin|LCD_D2_Pin;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;//普通输出
GPIO_InitStructure.GPIO_OType=GPIO_OType_OD;//开漏输出
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//上拉
GPIO_Init(LCD_D1_PORT,&GPIO_InitStructure);
GPIO_SetBits(LCD_D1_PORT,LCD_D1_Pin|LCD_D2_Pin);
GPIO_InitStructure.GPIO_Pin=LCD_D3_Pin|LCD_D4_Pin|LCD_D5_Pin|LCD_D6_Pin|LCD_D7_Pin;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;//普通输出
GPIO_InitStructure.GPIO_OType=GPIO_OType_OD;//开漏输出
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//上拉
GPIO_Init(LCD_D3_PORT,&GPIO_InitStructure);
GPIO_SetBits(LCD_D3_PORT,LCD_D3_Pin|LCD_D4_Pin|LCD_D5_Pin|LCD_D6_Pin|LCD_D7_Pin);
}
二、LCD12864初始化
void LCD12864_Init(void)
{
LCD_PSB=1;
WriteToLCD(LCD_CMD,0x34);//扩充指令操作
delay_ms(100);
WriteToLCD(LCD_CMD,0x30);//基本指令操作
delay_ms(100);
WriteToLCD(LCD_CMD,0x0C);//显示开,关光标
delay_ms(100);
WriteToLCD(LCD_CMD,0x01);//清LCD
delay_ms(5);
}
其中函数
//写指令/数据到LCD
void WriteToLCD(uint8_t mode,uint8_t byte)
{
if(mode==LCD_CMD)//写指令
{
while(LCD_Busy());
LCD_RS = 0;//指令
LCD_RW = 0;//写
LCD_EN = 0;
delay_us(5);
GPIO_Set(GPIOE,PIN6,GPIO_MODE_OUT,GPIO_OTYPE_OD,GPIO_SPEED_100M,GPIO_PUPD_PU); GPIO_Set(GPIOF,PIN6|PIN11,GPIO_MODE_OUT,GPIO_OTYPE_OD,GPIO_SPEED_100M,GPIO_PUPD_PU);
GPIO_Set(GPIOG,PIN6|PIN7|PIN8|PIN13|PIN15,GPIO_MODE_OUT,GPIO_OTYPE_OD,GPIO_SPEED_100M,GPIO_PUPD_PU);
WriteByteToLCD(byte);//写
delay_us(5);
LCD_EN = 1;
delay_us(5);
LCD_EN = 0;
}else //写数据
{
while(LCD_Busy());
LCD_RS = 1;//数据
LCD_RW = 0;
LCD_EN = 0;
delay_us(5);
GPIO_Set(GPIOE,PIN6,GPIO_MODE_OUT,GPIO_OTYPE_OD,GPIO_SPEED_100M,GPIO_PUPD_PU);
GPIO_Set(GPIOF,PIN6|PIN11,GPIO_MODE_OUT,GPIO_OTYPE_OD,GPIO_SPEED_100M,GPIO_PUPD_PU);
GPIO_Set(GPIOG,PIN6|PIN7|PIN8|PIN13|PIN15,GPIO_MODE_OUT,GPIO_OTYPE_OD,GPIO_SPEED_100M,GPIO_PUPD_PU);
WriteByteToLCD(byte);//写
delay_us(5);
LCD_EN = 1;
delay_us(5);
LCD_EN = 0;
}
}
函数的编写根据数据手册
LCD_RS = 0;//选择指令
LCD_RW = 0;//选择写
LCD_EN = 0;
数据引脚全部设置为输出
WriteByteToLCD(byte);//准备数据写
delay_us(5);
LCD_EN = 1;//写数据
delay_us(5);
LCD_EN = 0;//数据传输结束
数据与命令只有一点不同
LCD_RS = ;//选择数据
三、相关函数的调用
源文件如下
#include "lcd12864.h"
#include "delay.h"
*************************************************************************************/
/*************************************************************************************
LCD12864
LCD_RS PB1
LCD_RW PE3
LCD_EN PE4
LCD_PSB PE5
LCD_RST 接到板子RST上
LCD_D0 PE6
LCD_D1 PF6
LCD_D2 PF11
LCD_D3 PG6
LCD_D4 PG7
LCD_D5 PG8
LCD_D6 PG13
LCD_D7 PG15
************************************************************************************/
uint8_t LCD_GRAM[32][32];
void LCD_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB|RCC_AHB1Periph_GPIOE|
RCC_AHB1Periph_GPIOF|RCC_AHB1Periph_GPIOG
,ENABLE);
//PB0,PB1
GPIO_InitStructure.GPIO_Pin=LCD_BL_Pin|LCD_RS_Pin;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;//普通输出
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//上拉
GPIO_Init(LCD_RS_PORT,&GPIO_InitStructure);
GPIO_SetBits(LCD_RS_PORT,LCD_RS_Pin);
GPIO_ResetBits(LCD_BL_PORT,LCD_BL_Pin);//点亮背光
//PE3,PE4,PE5
GPIO_InitStructure.GPIO_Pin=LCD_RW_Pin|LCD_EN_Pin|LCD_PSB_Pin;
GPIO_Init(LCD_EN_PORT,&GPIO_InitStructure);
GPIO_SetBits(LCD_EN_PORT,LCD_RW_Pin|LCD_EN_Pin|LCD_PSB_Pin);
GPIO_InitStructure.GPIO_Pin=LCD_D0_Pin;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;//普通输出
GPIO_InitStructure.GPIO_OType=GPIO_OType_OD;//开漏输出
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//上拉
GPIO_Init(LCD_D0_PORT,&GPIO_InitStructure);
GPIO_SetBits(LCD_D0_PORT,LCD_D0_Pin);
GPIO_InitStructure.GPIO_Pin=LCD_D1_Pin|LCD_D2_Pin;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;//普通输出
GPIO_InitStructure.GPIO_OType=GPIO_OType_OD;//开漏输出
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//上拉
GPIO_Init(LCD_D1_PORT,&GPIO_InitStructure);
GPIO_SetBits(LCD_D1_PORT,LCD_D1_Pin|LCD_D2_Pin);
GPIO_InitStructure.GPIO_Pin=LCD_D3_Pin|LCD_D4_Pin|LCD_D5_Pin|LCD_D6_Pin|LCD_D7_Pin;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;//普通输出
GPIO_InitStructure.GPIO_OType=GPIO_OType_OD;//开漏输出
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//上拉
GPIO_Init(LCD_D3_PORT,&GPIO_InitStructure);
GPIO_SetBits(LCD_D3_PORT,LCD_D3_Pin|LCD_D4_Pin|LCD_D5_Pin|LCD_D6_Pin|LCD_D7_Pin);
}
//数据格式
//D7 D6 D5 D4 D3 D2 D1 D0
uint8_t ReadByteFromLCD(void)
{
uint8_t res=0;
res=(LCD_D0_IN<<0)|(LCD_D1_IN<<1)
|(LCD_D2_IN<<2)|(LCD_D3_IN<<3)
|(LCD_D4_IN<<4)|(LCD_D5_IN<<5)
|(LCD_D6_IN<<6)|(LCD_D7_IN<<7);
return res;
}
void WriteByteToLCD(uint8_t byte)
{
LCD_D0_OUT=(byte&0x01)>>0;
LCD_D1_OUT=(byte&0x02)>>1;
LCD_D2_OUT=(byte&0x04)>>2;
LCD_D3_OUT=(byte&0x08)>>3;
LCD_D4_OUT=(byte&0x10)>>4;
LCD_D5_OUT=(byte&0x20)>>5;
LCD_D6_OUT=(byte&0x40)>>6;
LCD_D7_OUT=(byte&0x80)>>7;
}
/*************************************************************************************
************************************************************************************/
/*************************************************************************************
LCD判忙函数
1:忙
0:不忙
************************************************************************************/
uint8_t LCD_Busy(void)
{
uint8_t res=0;
LCD_RS = 0;
LCD_RW = 1;
LCD_EN = 1;
//数据线IO方向设定
GPIO_Set(GPIOE,PIN6,GPIO_MODE_IN,0,0,GPIO_PUPD_PU);
GPIO_Set(GPIOF,PIN6|PIN11,GPIO_MODE_IN,0,0,GPIO_PUPD_PU);
GPIO_Set(GPIOG,PIN6|PIN7|PIN8|PIN13|PIN15,GPIO_MODE_IN,0,0,GPIO_PUPD_PU);
delay_us(5);
//读数据
res=(ReadByteFromLCD()&0x80);
LCD_EN = 0;
return res;
}
//写指令/数据到LCD
void WriteToLCD(uint8_t mode,uint8_t byte)
{
if(mode==LCD_CMD)//写指令
{
while(LCD_Busy());
LCD_RS = 0;//指令
LCD_RW = 0;//写
LCD_EN = 0;
delay_us(5);
GPIO_Set(GPIOE,PIN6,GPIO_MODE_OUT,GPIO_OTYPE_OD,GPIO_SPEED_100M,GPIO_PUPD_PU);
GPIO_Set(GPIOF,PIN6|PIN11,GPIO_MODE_OUT,GPIO_OTYPE_OD,GPIO_SPEED_100M,GPIO_PUPD_PU);
GPIO_Set(GPIOG,PIN6|PIN7|PIN8|PIN13|PIN15,GPIO_MODE_OUT,GPIO_OTYPE_OD,GPIO_SPEED_100M,GPIO_PUPD_PU);
WriteByteToLCD(byte);//写
delay_us(5);
LCD_EN = 1;
delay_us(5);
LCD_EN = 0;
}else //写数据
{
while(LCD_Busy());
LCD_RS = 1;//数据
LCD_RW = 0;
LCD_EN = 0;
delay_us(5);
GPIO_Set(GPIOE,PIN6,GPIO_MODE_OUT,GPIO_OTYPE_OD,GPIO_SPEED_100M,GPIO_PUPD_PU);
GPIO_Set(GPIOF,PIN6|PIN11,GPIO_MODE_OUT,GPIO_OTYPE_OD,GPIO_SPEED_100M,GPIO_PUPD_PU);
GPIO_Set(GPIOG,PIN6|PIN7|PIN8|PIN13|PIN15,GPIO_MODE_OUT,GPIO_OTYPE_OD,GPIO_SPEED_100M,GPIO_PUPD_PU);
WriteByteToLCD(byte);//写
delay_us(5);
LCD_EN = 1;
delay_us(5);
LCD_EN = 0;
}
}
void LCD12864_Init(void)
{
LCD_PSB=1;
WriteToLCD(LCD_CMD,0x34);//扩充指令操作
delay_ms(100);
WriteToLCD(LCD_CMD,0x30);//基本指令操作
delay_ms(100);
WriteToLCD(LCD_CMD,0x0C);//显示开,关光标
delay_ms(100);
WriteToLCD(LCD_CMD,0x01);//清LCD
delay_ms(5);
}
void LCD12864_Clear(void)
{
WriteToLCD(LCD_CMD,0x01);//清LCD
delay_ms(5);
}
//设定显示位置
//x=0-3,y=0-7
//128*64=16*8*16*4
void LCD12864_SetCursor(uint8_t x,uint8_t y)
{
if (y==0)
{y=0x80;}
else if (y==1)
{y=0x90;}
else if (y==2)
{y=0x88;}
else if (y==3)
{y=0x98;}
WriteToLCD(LCD_CMD,x+y); //显示地址
}
/*************************************************************************************/
void LCD12864_ShowString(uint8_t x,uint8_t y, uint8_t *s)//显示字符串
{
LCD12864_SetCursor(x,y);
while(*s!='\0')
{
WriteToLCD(LCD_DATA,*s++);
}
*s=0;
}
u32 LCD12864_Pow(uint8_t m,uint8_t n)
{
u32 result=1;
while(n--)result*=m;
return result;
}
void LCD12864_Showchar(uint8_t x,uint8_t y, uint8_t s)//显示字符
{
LCD12864_SetCursor(x,y);
WriteToLCD(LCD_DATA,s);
}
//显示数字
void LCD12864_Shownum(uint8_t x,uint8_t y,uint32_t num,uint8_t len)
{
uint8_t t;
uint8_t temp[10];
for(t=0;t>8))|(0x01<<(7-x_bit)));
WriteToLCD(LCD_DATA,(uint8_t)readdata);
}else
{
WriteToLCD(LCD_DATA,(uint8_t)(readdata>>8));
WriteToLCD(LCD_DATA,(uint8_t)readdata|(0x01<<(15-x_bit)));
}
WriteToLCD(LCD_CMD,LCD_DRAW_ON);//开绘图显示
WriteToLCD(LCD_CMD,LCD_BASIC_SET);//回到基本指令集
}
void LCD12864_Refresh_GRAM(void)
{
uint8_t i;uint16_t j;
WriteToLCD(LCD_CMD,LCD_EXTERN_SET);//扩展指令集
WriteToLCD(LCD_CMD,LCD_DRAW_OFF);//关掉绘图显示
for(i=0;i<32;i++)//遍历0-31行
{
WriteToLCD(LCD_CMD,0x80+i);//写入行地址
WriteToLCD(LCD_CMD,0x80); //写入列地址
for(j=0;j<32;j++)
{
WriteToLCD(LCD_DATA,LCD_GRAM[i][j]);
}
}
WriteToLCD(LCD_CMD,LCD_DRAW_ON);//开启绘图显示
WriteToLCD(LCD_CMD,LCD_BASIC_SET);//回到基本指令集
}
void LCD12864_Clear_DGRAM(void)
{
uint8_t i,j;
for(i=0;i<32;i++)//清屏
{
for(j=0;j<32;j++)//每行占用位置 16*16/8=32个字节
{
LCD_GRAM[i][j]=0x00;
}
}
}
//x:0-127
//y:0-63
//mode:1,画点
//mode:0,清空
void LCD12864_DrawPoint(uint8_t x,uint8_t y,uint8_t mode)
{
//判断处于哪行哪列
uint8_t x_pos,x_bit;//x_pos用来判断处于位址,x_bit用来判断处于位址中的位置
uint8_t y_pos,y_bit;//y_pos用来判断处于上半屏还是下半屏 y_bit用来判断位于哪行
// uint8_t x_pos_temp;
if((x>127)||(y>63)||(x<1)||(y<1))return;//去掉不合理参数
y_pos=y/32; //0:上半屏;1:下半屏
y_bit=y%32; //得到具体行位置
x_pos=x/16;
x_bit=x%16;
if(y_pos>0)//下半屏
{
if(mode)
{
if(x_bit<8)
{
LCD_GRAM[y_bit][x_pos*2+16]|=(1<<(7-x_bit));
LCD_GRAM[y_bit][x_pos*2+1+16]|=0x00;
}else
{
LCD_GRAM[y_bit][x_pos*2+16]|=0x00;
LCD_GRAM[y_bit][x_pos*2+1+16]|=(1<<(15-x_bit));
}
}
else
{
if(x_bit<8)
{
LCD_GRAM[y_bit][x_pos*2+16]&=~(1<<(7-x_bit));
LCD_GRAM[y_bit][x_pos*2+1+16]&=~0x00;
}else
{
LCD_GRAM[y_bit][x_pos*2+16]&=~0x00;
LCD_GRAM[y_bit][x_pos*2+1+16]&=~(1<<(15-x_bit));
}
}
}else//上半屏
{
if(mode)
{
if(x_bit<8)
{
LCD_GRAM[y_bit][x_pos*2]|=(1<<(7-x_bit));
LCD_GRAM[y_bit][x_pos*2+1]|=0x00;
}else
{
LCD_GRAM[y_bit][x_pos*2]|=0x00;
LCD_GRAM[y_bit][x_pos*2+1]|=(1<<(15-x_bit));
}
}
else
{
if(x_bit<8)
{
LCD_GRAM[y_bit][x_pos*2]&=~(1<<(7-x_bit));
LCD_GRAM[y_bit][x_pos*2+1]&=~0x00;
}else
{
LCD_GRAM[y_bit][x_pos*2]&=~0x00;
LCD_GRAM[y_bit][x_pos*2+1]&=~(1<<(15-x_bit));
}
}
}
//LCD12864_Refresh_GRAM();
}
void LCD12864_DrawLine(uint8_t x1, uint8_t y1,uint8_t x2, uint8_t y2) //直线
{
uint8_t distance_x, distance_y;//距离计算公式
uint8_t i;
distance_x=x2-x1;
distance_y=y2-y1;
if(distance_x==0)//x不变,y变竖线
{
for(i=0;i
补充:
头文件(个别函数自己补充,封装成库了,有点难找到原来写的时候的文件了)
#ifndef __LCD12864_H
#define __LCD12864_H
#include "sys.h"
#define LCD_RS_PORT GPIOB
#define LCD_RW_PORT GPIOE
#define LCD_EN_PORT GPIOE
#define LCD_PSB_PORT GPIOE
#define LCD_BL_PORT GPIOB
#define LCD_D0_PORT GPIOE
#define LCD_D1_PORT GPIOF
#define LCD_D2_PORT GPIOF
#define LCD_D3_PORT GPIOG
#define LCD_D4_PORT GPIOG
#define LCD_D5_PORT GPIOG
#define LCD_D6_PORT GPIOG
#define LCD_D7_PORT GPIOG
#define LCD_D0_Pin GPIO_Pin_6
#define LCD_D1_Pin GPIO_Pin_6
#define LCD_D2_Pin GPIO_Pin_11
#define LCD_D3_Pin GPIO_Pin_6
#define LCD_D4_Pin GPIO_Pin_7
#define LCD_D5_Pin GPIO_Pin_8
#define LCD_D6_Pin GPIO_Pin_13
#define LCD_D7_Pin GPIO_Pin_15
#define LCD_RS_Pin GPIO_Pin_1
#define LCD_RW_Pin GPIO_Pin_3
#define LCD_EN_Pin GPIO_Pin_4
#define LCD_PSB_Pin GPIO_Pin_5
#define LCD_BL_Pin GPIO_Pin_0
#define LCD_RS PBout(1)
#define LCD_RW PEout(3)
#define LCD_EN PEout(4)
#define LCD_PSB PEout(5)
#define LCD_BL PBout(0)
#define LCD_D0_OUT PEout(6)
#define LCD_D1_OUT PFout(6)
#define LCD_D2_OUT PFout(11)
#define LCD_D3_OUT PGout(6)
#define LCD_D4_OUT PGout(7)
#define LCD_D5_OUT PGout(8)
#define LCD_D6_OUT PGout(13)
#define LCD_D7_OUT PGout(15)
#define LCD_D0_IN PEin(6)
#define LCD_D1_IN PFin(6)
#define LCD_D2_IN PFin(11)
#define LCD_D3_IN PGin(6)
#define LCD_D4_IN PGin(7)
#define LCD_D5_IN PGin(8)
#define LCD_D6_IN PGin(13)
#define LCD_D7_IN PGin(15)
#define LCD_CMD 0
#define LCD_DATA 1
//基本指令集
#define LCD_BASIC_SET 0x30
//扩充指令集
#define LCD_EXTERN_SET 0x34
//绘图显示开
#define LCD_DRAW_ON LCD_EXTERN_SET|0x02
//绘图显示关
#define LCD_DRAW_OFF LCD_EXTERN_SET|0x00
//暂定 反白指令在扩充指令集中
#define LCD_INVERSE_ONE 0x04|0x00
#define LCD_INVERSE_TWO 0x04|0x01
#define LCD_INVERSE_THREE 0x04|0x02
#define LCD_INVERSE_FOUR 0x04|0x03
#define ISTRUE(x) (x>0?1:0)
/*********************************************底层驱动库************************************************/
void LCD_GPIO_Init(void); //初始化IO
uint8_t ReadByteFromLCD(void); //读取1个字节
void WriteByteToLCD(uint8_t byte); //写一个字节
uint8_t LCD_Busy(void); //检测LCD是否忙状态
void WriteToLCD(uint8_t mode,uint8_t byte); //写一个字节到LCD,区分命令数据
void LCD12864_Init(void); //LCD初始化
void LCD12864_Clear(void); //LCD清屏函数
void LCD12864_SetCursor(uint8_t x,uint8_t y); //LCD设置光标函数
void LCD12864_SetPoint(uint8_t x,uint8_t y); //LCD画点函数
void LCD12864_Clear_DGRAM(void); //清除DGRAM
void LCD12864_Refresh_GRAM(void); //更新DGRAM
/************************************LCD12864函数库****************************************************/
void LCD12864_DrawPoint(uint8_t x,uint8_t y,uint8_t mode);//画点
void LCD12864_DrawLine(uint8_t x1, uint8_t y1,uint8_t x2, uint8_t y2); //画直线
void LCD12864_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2); //画矩形
void LCD12864_ShowString(uint8_t x,uint8_t y,uint8_t *s); //显示字符串
void LCD12864_Shownum(uint8_t x,uint8_t y,uint32_t num,uint8_t len);//显示数字
void LCD12864_Showchar(uint8_t x,uint8_t y, uint8_t s);//显示字符
void lcd12864_clean_12816( uint8_t y1);
#endif