文章目录
动机
并行通信单片机需要用很多引脚连接LCD12864。串行可以最少只用2根通信引脚就能让显示屏显示。
接线描述
- 12864液晶串行显示测试程序
- 第 1脚 VSS -------- GND
- 第 2脚 VCC -------- 3.3V/5V
- 第 3脚 V0 -------- 对比度调节 可不接 LCD12864背面自带一个
- 第 4脚 RS/CS -------- 3.3V。接高电平直接片选上。
- 第 5脚 RW/SID -------- PA12 通信引脚
- 第 6脚 EN/SCLK -------- PA15 通信引脚
- 第15脚 PSB -------- 接GND。接低电平表示串行通信,接高电平表示并行通信。
- 第17脚 RST -------- 不接或者接高电平。低电平会导致复位。
- 第19脚 LEDA -------- 3.3V/5V
- 第20脚 LEDK -------- GND
- 其余引脚悬空。
- 并不是所有的12864都支持串口,程序不行就考虑是不是买到次品了
效果
原理图
main.c
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "lcd12864.h"
int main( void )
{
NVIC_PriorityGroupConfig( NVIC_PriorityGroup_2 ); /* 设置NVIC中断分组2:2位抢占优先级,2位响应优先级 */
delay_init(); /* 延时函数初始化 */
RCC_APB2PeriphClockCmd( RCC_APB2Periph_AFIO, ENABLE );
GPIO_PinRemapConfig( GPIO_Remap_SWJ_JTAGDisable, ENABLE ); /* 关闭jtag,使能SWD,可以用SWD模式调试 */
Lcd_Init();
LCD_Display_Words( 0, 0, "串行通信测试ABCD" );
LCD_Display_Words( 1, 0, "1234567812345678" );
LCD_Display_Words( 2, 0, "无奈朝来寒雨晚来" );
LCD_Display_Words( 3, 0, "风。@@@@@@@@@@@@" );
while ( 1 )
{
}
}
lcd12864.c
#include "lcd12864.h"
#include "delay.h"
/*
* 12864液晶串行显示测试程序
* 第 1脚 VSS -------- GND
* 第 2脚 VCC -------- 3.3V/5V
* 第 3脚 V0 -------- 对比度调节 可不接 LCD12864背面自带一个
* 第 4脚 RS/CS -------- 3.3V。接高电平直接片选上。
* 第 5脚 RW/SID -------- PA12 通信引脚
* 第 6脚 EN/SCLK -------- PA15 通信引脚
* 第15脚 PSB -------- 接GND。接低电平表示串行通信,接高电平表示并行通信。
* 第17脚 RST -------- 不接或者接高电平。低电平会导致复位。
* 第19脚 LEDA -------- 3.3V/5V
* 第20脚 LEDK -------- GND
* 其余引脚悬空。
* 并不是所有的12864都支持串口,程序不行就考虑是不是买到次品了
*
*/
#define LCDCS PAout( 11 )
#define LCDPSB PAout( 4 )
#define LCDRST PAout( 5 )
void lcd_GPIO_init()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE );
/* GPIOE0,E1初始化设置 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_15 | GPIO_Pin_4 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; /* 100MHz */
GPIO_Init( GPIOA, &GPIO_InitStructure ); /* 初始化 */
SID = 1;
SCLK = 1;
LCDCS = 1;
LCDPSB = 0;
LCDRST = 1;
}
/* 字符显示RAM地址 4行8列 */
u8 LCD_addr[4][8] = {
{
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87 }, /* 第一行 */
{
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97 }, /* 第二行 */
{
0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F }, /* 第三行 */
{
0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F } /* 第四行 */
};
/* LCD串行发送一个字节 */
void SendByte( u8 byte )
{
u8 i;
for ( i = 0; i < 8; i++ )
{
if ( (byte << i) & 0x80 ) /* 0x80(1000 0000) 只会保留最高位 */
{
SID = 1; /* 引脚输出高电平,代表发送1 */
}else {
SID = 0; /* 引脚输出低电平,代表发送0 */
}
SCLK = 0; /* 时钟线置低 允许SID变化 */
delay_us( 5 ); /* 延时使数据写入 */
SCLK = 1; /* 拉高时钟,让从机读SID */
}
}
/* LCD写指令 */
void Lcd_WriteCmd( u8 Cmd )
{
delay_ms( 1 ); /* 由于我们没有写LCD正忙的检测,所以直接延时1ms,使每次写入数据或指令间隔大于1ms 便可不用写忙状态检测 */
SendByte( WRITE_CMD ); /* 11111,RW(0),RS(0),0 */
SendByte( 0xf0 & Cmd ); /* 高四位 */
SendByte( Cmd << 4 ); /* 低四位(先执行<<) */
}
/* LCD写数据 */
void Lcd_WriteData( u8 Dat )
{
delay_ms( 1 );
SendByte( WRITE_DAT ); /* 11111,RW(0),RS(1),0 */
SendByte( 0xf0 & Dat ); /* 高四位 */
SendByte( Dat << 4 ); /* 低四位(先执行<<) */
}
/* LCD初始化 */
void Lcd_Init( void )
{
lcd_GPIO_init();
delay_ms( 50 ); /* 等待液晶自检(延时>40ms) */
Lcd_WriteCmd( 0x30 ); /* 功能设定:选择基本指令集 */
delay_ms( 1 ); /* 延时>100us */
Lcd_WriteCmd( 0x30 ); /* 功能设定:选择8bit数据流 */
delay_ms( 1 ); /* 延时>37us */
Lcd_WriteCmd( 0x0c ); /* 开显示 */
delay_ms( 1 ); /* 延时>100us */
Lcd_WriteCmd( 0x01 ); /* 清除显示,并且设定地址指针为00H */
delay_ms( 30 ); /* 延时>10ms */
Lcd_WriteCmd( 0x06 ); /* 进入设定点,初始化完成 */
}
/* 显示字符或汉字 x: row(0~3) y: line(0~7) str: 要显示的字符或汉字 */
void LCD_Display_Words( uint8_t x, uint8_t y, uint8_t*str )
{
Lcd_WriteCmd( LCD_addr[x][y] ); /* 写初始光标位置 */
while ( *str > 0 )
{
Lcd_WriteData( *str ); /* 写数据 */
str++;
}
}
/* 显示图片 *pic 图片地址 */
void LCD_Display_Picture( uint8_t *img )
{
uint8_t x, y, i;
Lcd_WriteCmd( 0x34 ); /* 切换到扩充指令 */
Lcd_WriteCmd( 0x34 ); /* 关闭图形显示 */
for ( i = 0; i < 1; i++ ) /*上下屏写入 */
{
for ( y = 0; y < 32; y++ ) /* 垂直Y写32次 */
{
for ( x = 0; x < 8; x++ ) /* 横向X写8次 */
{
Lcd_WriteCmd( 0x80 + y ); /* 行地址 */
Lcd_WriteCmd( 0x80 + x + i ); /* 列地址 */
Lcd_WriteData( *img++ ); /* 写高位字节数据 D15-D8 */
Lcd_WriteData( *img++ ); /* 写低位字节数据 D7-D0 */
}
}
}
Lcd_WriteCmd( 0x36 ); /* 打开图形显示 */
Lcd_WriteCmd( 0x30 ); /* 切换回基本指令 */
}
/* 清屏函数 */
void LCD_Clear( void )
{
Lcd_WriteCmd( 0x01 ); /* 清屏指令 */
delay_ms( 2 ); /* 延时以待液晶稳定【至少1.6ms】 */
}
lcd12864.h
#ifndef __lcd12864_H_
#define __lcd12864_H_
#include "sys.h"
#define WRITE_CMD 0xF8 /* 写命令 */
#define WRITE_DAT 0xFA /* 写数据 */
#define SID PAout( 12 ) /* SID引脚设置 */
#define SCLK PAout( 15 ) /* SCLK引脚设置 */
void lcd_GPIO_init( void );
void Lcd_Init( void );
void SendByte( u8 Dbyte );
void LCD_Clear( void );
void LCD_Display_Words( uint8_t x, uint8_t y, uint8_t*str );
void LCD_Display_Picture( uint8_t *img );
void Lcd_WriteData( u8 Dat );
void Lcd_WriteCmd( u8 Cmd );
#endif