STM32驱动5V的12864LCD,控制脚和数据较最好接到STM32能容忍5v的IO口,外加上拉电阻时,控制脚和数据脚设置成开漏输出。不加上拉电阻时,控制脚设置为推拉输出,数据脚输出时,设置成推拉输出,输入时设置成上拉输入。加不加上拉电阻都能点亮LCD,关键是脚位配置。
GPIOE的PE0-PE7做数据线,控制线定义如下:
//————-PORTE———————
#define R_S GPIO_Pin_8
#define R_W GPIO_Pin_9
#define EN GPIO_Pin_10
#define _CS1 GPIO_Pin_11
#define _CS2 GPIO_Pin_12
#define _RST GPIO_Pin_13
首先IO口初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOE, &GPIO_InitStructure);
GPIO_ResetBits(GPIOE, EN );
GPIO_SetBits(GPIOE,_CS1 | _CS2 );
注意_CS1,_CS2初始化是一定要拉高,否则检测忙信号时,忙信号会一直是高。我就是因为这个问题卡了好几天。
以下是LCD驱动程序:
//指令宏定义
#define Display_On 0x3f //显示开指令
#define Display_Off 0x3e //显示关指令
#define Y_Col_Addr 0x40 //定位到第0列指令(列起始地址)(0-63)
#define X_Page_Addr 0xb8 //定位到第0页指令(页起始地址)(0-7)
#define Start_Line 0xc0 //定位从DDROM中的第0行开始往屏幕上显示
u16_t LCD_ReadStatus(void);
#define LCD_Write(x) GPIOE->ODR=(GPIOE->ODR&0xFF00)|(x);
/***********************************************************************
**Delay
************************************************************************/
void Delay(void)
{
u8_t i;
for(i=0;i<125;i++);
}
/************************************************************************
**DATA_Input
*************************************************************************/
void DATA_Input(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Configure LCD_DATA GPIO Pin as input floating */
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_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOE,&GPIO_InitStructure);
}
/***********************************************************************
**DATA_Output
************************************************************************/
void DATA_Output(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Configure LCD_DATA GPIO Pin as output push-pull */
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_2MHz;
GPIO_Init(GPIOE,&GPIO_InitStructure);
}
/***********************************************************************
**LCD_Command
************************************************************************/
void Write_Cmd(u8_t Port)
{
DATA_Output();
Delay();
GPIO_ResetBits(GPIOE,EN);
Delay();
GPIO_ResetBits(GPIOE,R_S);
Delay();
GPIO_ResetBits(GPIOE,R_W);
Delay();
LCD_Write(Port);
Delay();
GPIO_SetBits(GPIOE,EN);
Delay();
GPIO_ResetBits(GPIOE,EN);
Delay();
while(LCD_ReadStatus()&0x0080==0x0080);
}
/***********************************************************************
**LCD_ReadStatus
************************************************************************/
u16_t LCD_ReadStatus(void)
{
u16_t Status;
GPIO_ResetBits(GPIOE,EN);
Delay();
DATA_Input();
Delay();
GPIO_ResetBits(GPIOE,R_S);
Delay();
GPIO_SetBits(GPIOE,R_W);
Delay();
GPIO_SetBits(GPIOE,EN);
Delay();
Status=GPIO_ReadInputData(GPIOE);
Delay();
GPIO_ResetBits(GPIOE,EN);
Delay();
return Status;
}
/***********************************************************************
**LCD_WriteData
************************************************************************/
void Write_Data(u8_t Data)
{
DATA_Output();
Delay();
GPIO_ResetBits(GPIOE,EN);
Delay();
GPIO_SetBits(GPIOE,R_S);
Delay();
GPIO_ResetBits(GPIOE,R_W);
Delay();
LCD_Write(Data);
Delay();
GPIO_SetBits(GPIOE,EN);
Delay();
GPIO_ResetBits(GPIOE,EN);
Delay();
while(LCD_ReadStatus()&0x0080==0x0080);
}
/*—————————————————————————————————-*/
//设定行地址(页)–X 0-7
void SetPage(u8_t page)
{
Write_Cmd(0xb8 | page);
}
//设定列地址–Y 0-63
void SetColumn(u8_t column)
{
Write_Cmd(0x40 | column);
}
//设定显示开始行–XX
void SetStartLine(u8_t startline) //0–63
{
Write_Cmd(0xc0 | startline);
}
/*————————————————————–*/
//液晶定位(8*8)
//液晶规划:
//x: 0 – 7 (行)
//y: 0 -15 (列)
void LCD_pos(u8_t x, u8_t y)
{
if(y < 8)
{
GPIO_SetBits(GPIOE,_CS1); //左半屏
GPIO_ResetBits(GPIOE,_CS2);
}
else
{
y -= 8; //右半屏
GPIO_SetBits(GPIOE,_CS2);
GPIO_ResetBits(GPIOE,_CS1);
}
SetPage(x); //页地址
SetColumn(y * 8);//列地址
}
//液晶字符输出(8*16字体)
//x: 0 -3/7 (行)
//y: 0 -15 (列)
void LCD_printc(u8_t x, u8_t y, u16_t c_dat)
{
u8_t i, j;
for(j = 0; j < 2; j++)
{
LCD_pos((x * 2 + j), y);
for(i = 0; i < 8; i++) Write_Data(Font_code[c_dat – 32][8 * j + i]);
}
}
/*————————————————————–*/
//液晶字符串输出
//x: 0 – 3 (行)
//y: 0 -15 (列)
void LCD_prints(u8_t x, u8_t y, u16_t *s_dat)
{
u8_t i;
for(i=0;i<16;i++)
LCD_printc(x, y++, *s_dat++);
}
void DispData(u8_t x,u16_t *s,u8_t num)
{
num = num;
LCD_prints(x-1,0, s);
}
/*————————————————————–*/
//液晶字节定位(8*1)
//液晶规划:
//x: 0 – 7 (行)
//y: 0 -127 (列)
void LCD_byte_pos(u8_t x, u8_t y)
{
if(y < 64)
{
GPIO_SetBits(GPIOE,_CS2); //左半屏
GPIO_ResetBits(GPIOE,_CS1);
}
else
{
y -= 64;
GPIO_SetBits(GPIOE,_CS1); //左半屏
GPIO_ResetBits(GPIOE,_CS2);
} //右半屏
// LCD_write_cmd(Start_Line); //起始行地址
Write_Cmd(X_Page_Addr + x); //页地址0-7
Write_Cmd(Y_Col_Addr + y); //列地址0-63
}
/*————————————————————–*/
//液晶定位写入数据一个字节
//液晶规划:
//x: 0 – 7 (页)
//y: 0 -127 (列)
void LCD_write_dat_pos(u8_t x, u8_t y, u8_t dat)
{
LCD_byte_pos(x, y);
Write_Data(dat);
}
/*————————————————————–*/
//显示128X64图片
//取码规则: 低位在前, 列行扫描, 阴码(1-亮, 0-灭)
void LCD_picture(u8_t const *img_dat)
{
u8_t i, j;
for(j = 0; j < 8; j++)
{
for(i = 0; i < 128; i++)
{
LCD_write_dat_pos(j, i, img_dat[j * 128 + i]);
}
}
}
/*—————————————————————————————————*/
//选择屏幕
//screen: 0-全屏,1-左屏,2-右屏
void SelectScreen(u8_t screen)
{ //北京显示器:负有效 cs1: 0–右; cs2: 0–左
switch(screen)
{
case 0:
GPIO_ResetBits(GPIOE,_CS2);//全屏
Delay();
GPIO_ResetBits(GPIOE,_CS1);
Delay();
break;
case 1:
GPIO_SetBits(GPIOE,_CS1);//左屏
Delay();
GPIO_ResetBits(GPIOE,_CS2);
Delay();
break;
case 2:
GPIO_ResetBits(GPIOE,_CS1); //右屏
Delay();
GPIO_SetBits(GPIOE,_CS2);
Delay();
break;
}
}
/*—————————————————————————————————*/
//清屏
//screen: 0-全屏,1-左屏,2-右
void ClearScreen(u8_t screen)
{
u8_t i,j;
SelectScreen(screen);
for(i=0;i<8;i++)
{
SetPage(i);
for(j=0;j<64;j++)
{
Write_Data(0x00);
}
}
}
/***********************************************************************
**LCD_Init
************************************************************************/
void LCD_Init(void)
{
u16_t s[]={‘0′,’1′,’2′,’3′,’4′,’5′,’6′,’7′,’8′,’9′,’a’,’b’,’c’,’d’,’e’,’f’};
Delay();
GPIO_ResetBits(GPIOE,_RST);
Delay();
GPIO_SetBits(GPIOE,_RST);
Delay();
//ClearScreen(0);
Write_Cmd(0x3e); //关显示
SetPage(0);//选择0页
SetColumn(0);//选择0列
SetStartLine(0);//选择起始行
Write_Cmd(0x3f);//开显示
LCD_prints(0, 0, s);
LCD_prints(1, 0, s);
LCD_prints(2, 0, s);
LCD_prints(3, 0, s);
}