工作于并行模式时的引脚定义:
PIN1------------------GND 电源接入-,一般接0V(视具体液晶型号)
PIN2------------------电源接入+,一般接5V(视具体液晶型号)
PIN3------------------对比度调整端,VDD和GND接可调电阻两端,中间抽头接至V0
PIN4------------------RS指令/数据选择
PIN5------------------R/W读写选择
PIN6------------------E,使能信号
PIN7------------------D0,数据位0
PIN8------------------D1,数据位1
PIN9------------------D2,数据位2
PIN10------------------D3,数据位3
PIN11------------------D4,数据位4
PIN12------------------D5,数据位5
PIN13------------------D6,数据位6
PIN14------------------D7,数据位7
PIN15------------------PSB 并行:PSB=1,可以接VCC,串行:PSB=0,一般接GND
PIN16------------------NC,不连接
PIN17------------------~RST,模块复位,可不连接
PIN18------------------NC,不连接
PIN19------------------LED+,背光+,一般接5V(视具体液晶型号)
PIN20------------------LED-,背光-,一般接GND
工作于串行模式时的引脚定义:
PIN1------------------GND 电源接入-,一般接0V(视具体液晶型号)
PIN2------------------电源接入+,一般接5V(视具体液晶型号)
PIN3------------------对比度调整端,VDD和GND接可调电阻两端,中间抽头接至V0
PIN4------------------RS(CS),片选
PIN5------------------R/W(SID),数据
PIN6------------------E(SCK),脉冲
PIN7------------------NC,不连接
PIN8------------------NC,不连接
PIN9------------------NC,不连接
PIN10------------------NC,不连接
PIN11------------------NC,不连接
PIN12------------------NC,不连接
PIN13------------------NC,不连接
PIN14------------------NC,不连接
PIN15------------------PSB 并行:PSB=1,可以接VCC,串行:PSB=0,一般接GND
PIN16------------------NC,不连接
PIN17------------------~RST,模块复位,可不连接
PIN18------------------NC,不连接
PIN19------------------LED+,背光+,一般接5V(视具体液晶型号)
PIN20------------------LED-,背光-,一般接GND
12864液晶并口驱动程序用的比较多,但是考虑到有的时候单片机或者MCU的IO口有限时就可以使用串行驱动方法。以下是12864液晶串行时序图,下面就根据这个图来分析一下12864串行时序的实现,只有真正弄清楚了时序图才能真正了解串行传输的原理。
从图上可以看出串行传输时需要用到CS,SCLK,SID三根信号线,但是由于CS是高电平有效,所以也可以把CS长接高电平,那样就只需要两根线就OK了,当然当使用12864串行模式时,PSB引脚必须接低电平,复位RST引脚可以悬空不接,因为12864内部有上电复位威廉希尔官方网站
。
由于数据是传输是以一个字节8bits为单位,所以下面贴出传输一个字节的函数实现
从时序图上可以看出,要想完整的把一个字节的数据传出去,需要传送三次才能实现,也就是需要传送三个字节,这三个字节分别是:命令控制字,字节的高四位+低四位0组成的字节,字节的低四位+高四位0组成的字节。
命令控制字11111RWRS0
RW代表读还是写液晶,为0代表写,为1代表读。RS代表写命令还是数据,为0代表写命令,为1代表写数据,其余6位固定。所以假设要向液晶写数据,就必须首先发送11111010,写命令就发送11111000。
下面是程序的具体实现,这是关键!
硬件:
单片机型号:STM32L052K8* 其实不管哪款单片机实现效果是一样的
液晶型号:LCD12864
接线:
PA0 接 RS(CS)
PA1 接 R/W(SID)
PA2 接 E(SCK)
PA3 接 RST 这个可以不接,悬空或接高电平(VCC),液晶内部有上电复位的功能,看自己的实现需要添加
lcd12864.c
#include "lcd12864.h"
#include "main.h"
/******************************************
*名称:void Write_8bits(uint8_t W_bits)
*功能:按照液晶的串口通信协议,发送数据
*输入:W_bits
*输出:无
*******************************************/
void Write_8bits(uint8_t W_bits)
{
uint8_t i,Temp_data;
for(i=0; i<8; i++)//总共移动八次,就可以把8bits数据全部传完
{
Temp_data = W_bits;
Temp_data <<= i;//把数据依次左移
if((Temp_data&0x80)==0) //判断对应位是否为0
{
HAL_GPIO_WritePin(SID_GPIO_Port,SID_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(CLK_GPIO_Port,CLK_Pin,GPIO_PIN_RESET); //SCLK = 0;//在时钟的下降沿把数据传输出去
HAL_GPIO_WritePin(CLK_GPIO_Port,CLK_Pin,GPIO_PIN_SET); // SCLK = 1;//置高电平,为下次传输做准备
}
else //对应位为1
{
HAL_GPIO_WritePin(SID_GPIO_Port,SID_Pin,GPIO_PIN_SET); //SID = 1;
HAL_GPIO_WritePin(CLK_GPIO_Port,CLK_Pin,GPIO_PIN_RESET); //SCLK = 0;//在时钟的下降沿把数据传输出去
HAL_GPIO_WritePin(CLK_GPIO_Port,CLK_Pin,GPIO_PIN_SET); // SCLK = 1;//置高电平,为下次传输做准备
}
}
}
/****************************************
*名称:void W_1byte(uint8_t RW, uint8_t RS, uint8_t W_data)
*功能:写串口数据,根据RW RS的配置,确定是传输命令还是传输数据
*输入:uint8_t RW, uint8_t RS, uint8_t W_data
*输出:无
******************************************/
void W_1byte(uint8_t RW, uint8_t RS, uint8_t W_data)
{
uint8_t H_data,L_data,S_ID = 0xf8; //11111RWRS0
if(RW == 0)
{
S_ID &=~ 0x04;
}
else //if(RW==1)
{
S_ID |= 0X04;
}
if(RS == 0)
{
S_ID &=~ 0x02;
}
else //if(RS==1)
{
S_ID |= 0X02;
}
//以上是根据读写命令以及是发送数据还是命令来组合命令字
H_data = W_data;
H_data &= 0xf0; //屏蔽低4位的数据
L_data = W_data; //xxxx0000格式
L_data &= 0x0f; //屏蔽高4位的数据
L_data <<= 4; //xxxx0000格式
HAL_GPIO_WritePin(CS_GPIO_Port,CS_Pin,GPIO_PIN_SET); //CS = 1; 时能发送
Write_8bits(S_ID); //发送命令字S_ID
Write_8bits(H_data); //发送H_data
Write_8bits(L_data); //发送L_data
HAL_GPIO_WritePin(CS_GPIO_Port,CS_Pin,GPIO_PIN_RESET); //CS = 0; 时能发送
}
/*****************************************
*功能:lcdinit()
*功能:初始化函数
*输入:cmdcode
*输出:无
*****************************************/
void lcdinit(void)
{
HAL_Delay(10);
W_1byte(0,0,0x30);//功能设置 8位数据,基本指令;
HAL_Delay(10);
//W_1byte(0,0,0x02); //地址归位
//HAL_Delay(10);
//W_1byte(0,0,0x06); //游标及显示右移一位
//HAL_Delay(10);
W_1byte(0,0,0x0c); //显示状态 ON,游标OFF,反白OFF
HAL_Delay(10);
W_1byte(0,0,0x01); //清除显示
HAL_Delay(10);
}
/******************************************
*名称:void LCD_Wmessage(uint8_t* message,uint8_t address)
*功能:向LCD12864中写入一行数据(因为你不可能每次只发送一字节数据)
*输入:uint8_t* message,uint8_t address
*输出:无
******************************************/
void LCD_Wmessage(uint8_t* message,uint8_t address)
{
W_1byte(0, 0, address);
while(*message>0)//这个判断很关键,判断你的内容有没有发完
{
W_1byte(0,1,*message); //内核还是发字节函数
message++; //指针挺好用的。。
}
}
lcd12864.h
#include "main.h"
#define LINE1 0x80 //第一行起始地址,下同
#define LINE2 0x90
#define LINE3 0x88
#define LINE4 0x98
void Write_8bits(uint8_t W_bits);
void W_1byte(uint8_t RW, uint8_t RS, uint8_t W_data);
void lcdinit(void);
void LCD_Wmessage(uint8_t *message,uint8_t address);
main.c
int main(void)
{
/* USER CODE BEGIN 1 */
uint8_t dis3[]={"床前明月光,"};
uint8_t dis4[]={"疑是地上霜,"};
uint8_t dis5[]={"举头望明月,"};
uint8_t dis6[]={"低头思故乡。"};
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
/* USER CODE BEGIN 2 */
lcdinit();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
LCD_Wmessage(dis3,LINE1);
LCD_Wmessage(dis4,LINE2);
LCD_Wmessage(dis5,LINE3);
LCD_Wmessage(dis6,LINE4);
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
效果如下:
工作于并行模式时的引脚定义:
PIN1------------------GND 电源接入-,一般接0V(视具体液晶型号)
PIN2------------------电源接入+,一般接5V(视具体液晶型号)
PIN3------------------对比度调整端,VDD和GND接可调电阻两端,中间抽头接至V0
PIN4------------------RS指令/数据选择
PIN5------------------R/W读写选择
PIN6------------------E,使能信号
PIN7------------------D0,数据位0
PIN8------------------D1,数据位1
PIN9------------------D2,数据位2
PIN10------------------D3,数据位3
PIN11------------------D4,数据位4
PIN12------------------D5,数据位5
PIN13------------------D6,数据位6
PIN14------------------D7,数据位7
PIN15------------------PSB 并行:PSB=1,可以接VCC,串行:PSB=0,一般接GND
PIN16------------------NC,不连接
PIN17------------------~RST,模块复位,可不连接
PIN18------------------NC,不连接
PIN19------------------LED+,背光+,一般接5V(视具体液晶型号)
PIN20------------------LED-,背光-,一般接GND
工作于串行模式时的引脚定义:
PIN1------------------GND 电源接入-,一般接0V(视具体液晶型号)
PIN2------------------电源接入+,一般接5V(视具体液晶型号)
PIN3------------------对比度调整端,VDD和GND接可调电阻两端,中间抽头接至V0
PIN4------------------RS(CS),片选
PIN5------------------R/W(SID),数据
PIN6------------------E(SCK),脉冲
PIN7------------------NC,不连接
PIN8------------------NC,不连接
PIN9------------------NC,不连接
PIN10------------------NC,不连接
PIN11------------------NC,不连接
PIN12------------------NC,不连接
PIN13------------------NC,不连接
PIN14------------------NC,不连接
PIN15------------------PSB 并行:PSB=1,可以接VCC,串行:PSB=0,一般接GND
PIN16------------------NC,不连接
PIN17------------------~RST,模块复位,可不连接
PIN18------------------NC,不连接
PIN19------------------LED+,背光+,一般接5V(视具体液晶型号)
PIN20------------------LED-,背光-,一般接GND
12864液晶并口驱动程序用的比较多,但是考虑到有的时候单片机或者MCU的IO口有限时就可以使用串行驱动方法。以下是12864液晶串行时序图,下面就根据这个图来分析一下12864串行时序的实现,只有真正弄清楚了时序图才能真正了解串行传输的原理。
从图上可以看出串行传输时需要用到CS,SCLK,SID三根信号线,但是由于CS是高电平有效,所以也可以把CS长接高电平,那样就只需要两根线就OK了,当然当使用12864串行模式时,PSB引脚必须接低电平,复位RST引脚可以悬空不接,因为12864内部有上电复位威廉希尔官方网站
。
由于数据是传输是以一个字节8bits为单位,所以下面贴出传输一个字节的函数实现
从时序图上可以看出,要想完整的把一个字节的数据传出去,需要传送三次才能实现,也就是需要传送三个字节,这三个字节分别是:命令控制字,字节的高四位+低四位0组成的字节,字节的低四位+高四位0组成的字节。
命令控制字11111RWRS0
RW代表读还是写液晶,为0代表写,为1代表读。RS代表写命令还是数据,为0代表写命令,为1代表写数据,其余6位固定。所以假设要向液晶写数据,就必须首先发送11111010,写命令就发送11111000。
下面是程序的具体实现,这是关键!
硬件:
单片机型号:STM32L052K8* 其实不管哪款单片机实现效果是一样的
液晶型号:LCD12864
接线:
PA0 接 RS(CS)
PA1 接 R/W(SID)
PA2 接 E(SCK)
PA3 接 RST 这个可以不接,悬空或接高电平(VCC),液晶内部有上电复位的功能,看自己的实现需要添加
lcd12864.c
#include "lcd12864.h"
#include "main.h"
/******************************************
*名称:void Write_8bits(uint8_t W_bits)
*功能:按照液晶的串口通信协议,发送数据
*输入:W_bits
*输出:无
*******************************************/
void Write_8bits(uint8_t W_bits)
{
uint8_t i,Temp_data;
for(i=0; i<8; i++)//总共移动八次,就可以把8bits数据全部传完
{
Temp_data = W_bits;
Temp_data <<= i;//把数据依次左移
if((Temp_data&0x80)==0) //判断对应位是否为0
{
HAL_GPIO_WritePin(SID_GPIO_Port,SID_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(CLK_GPIO_Port,CLK_Pin,GPIO_PIN_RESET); //SCLK = 0;//在时钟的下降沿把数据传输出去
HAL_GPIO_WritePin(CLK_GPIO_Port,CLK_Pin,GPIO_PIN_SET); // SCLK = 1;//置高电平,为下次传输做准备
}
else //对应位为1
{
HAL_GPIO_WritePin(SID_GPIO_Port,SID_Pin,GPIO_PIN_SET); //SID = 1;
HAL_GPIO_WritePin(CLK_GPIO_Port,CLK_Pin,GPIO_PIN_RESET); //SCLK = 0;//在时钟的下降沿把数据传输出去
HAL_GPIO_WritePin(CLK_GPIO_Port,CLK_Pin,GPIO_PIN_SET); // SCLK = 1;//置高电平,为下次传输做准备
}
}
}
/****************************************
*名称:void W_1byte(uint8_t RW, uint8_t RS, uint8_t W_data)
*功能:写串口数据,根据RW RS的配置,确定是传输命令还是传输数据
*输入:uint8_t RW, uint8_t RS, uint8_t W_data
*输出:无
******************************************/
void W_1byte(uint8_t RW, uint8_t RS, uint8_t W_data)
{
uint8_t H_data,L_data,S_ID = 0xf8; //11111RWRS0
if(RW == 0)
{
S_ID &=~ 0x04;
}
else //if(RW==1)
{
S_ID |= 0X04;
}
if(RS == 0)
{
S_ID &=~ 0x02;
}
else //if(RS==1)
{
S_ID |= 0X02;
}
//以上是根据读写命令以及是发送数据还是命令来组合命令字
H_data = W_data;
H_data &= 0xf0; //屏蔽低4位的数据
L_data = W_data; //xxxx0000格式
L_data &= 0x0f; //屏蔽高4位的数据
L_data <<= 4; //xxxx0000格式
HAL_GPIO_WritePin(CS_GPIO_Port,CS_Pin,GPIO_PIN_SET); //CS = 1; 时能发送
Write_8bits(S_ID); //发送命令字S_ID
Write_8bits(H_data); //发送H_data
Write_8bits(L_data); //发送L_data
HAL_GPIO_WritePin(CS_GPIO_Port,CS_Pin,GPIO_PIN_RESET); //CS = 0; 时能发送
}
/*****************************************
*功能:lcdinit()
*功能:初始化函数
*输入:cmdcode
*输出:无
*****************************************/
void lcdinit(void)
{
HAL_Delay(10);
W_1byte(0,0,0x30);//功能设置 8位数据,基本指令;
HAL_Delay(10);
//W_1byte(0,0,0x02); //地址归位
//HAL_Delay(10);
//W_1byte(0,0,0x06); //游标及显示右移一位
//HAL_Delay(10);
W_1byte(0,0,0x0c); //显示状态 ON,游标OFF,反白OFF
HAL_Delay(10);
W_1byte(0,0,0x01); //清除显示
HAL_Delay(10);
}
/******************************************
*名称:void LCD_Wmessage(uint8_t* message,uint8_t address)
*功能:向LCD12864中写入一行数据(因为你不可能每次只发送一字节数据)
*输入:uint8_t* message,uint8_t address
*输出:无
******************************************/
void LCD_Wmessage(uint8_t* message,uint8_t address)
{
W_1byte(0, 0, address);
while(*message>0)//这个判断很关键,判断你的内容有没有发完
{
W_1byte(0,1,*message); //内核还是发字节函数
message++; //指针挺好用的。。
}
}
lcd12864.h
#include "main.h"
#define LINE1 0x80 //第一行起始地址,下同
#define LINE2 0x90
#define LINE3 0x88
#define LINE4 0x98
void Write_8bits(uint8_t W_bits);
void W_1byte(uint8_t RW, uint8_t RS, uint8_t W_data);
void lcdinit(void);
void LCD_Wmessage(uint8_t *message,uint8_t address);
main.c
int main(void)
{
/* USER CODE BEGIN 1 */
uint8_t dis3[]={"床前明月光,"};
uint8_t dis4[]={"疑是地上霜,"};
uint8_t dis5[]={"举头望明月,"};
uint8_t dis6[]={"低头思故乡。"};
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
/* USER CODE BEGIN 2 */
lcdinit();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
LCD_Wmessage(dis3,LINE1);
LCD_Wmessage(dis4,LINE2);
LCD_Wmessage(dis5,LINE3);
LCD_Wmessage(dis6,LINE4);
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
效果如下:
举报