这里我们只讲解接线和代码实现
下方代码的实现也是基于上一篇的讲解顺序来的
设备: STM32F407ZGT6
引脚接线:
VSS——GND
VDD——VCC(5V or 3.3V)
V0 亮度调节 不接
CS ——接VCC,持续高电平,一直选通。
SID ——接PE1
SCLK ——接PE0
PSB——接GND 串行模式 或者飞线与1脚相连
BLA——VCC(5V or 3.3V) 或者飞线与2脚相连
BLK——接GND 或者飞线与1脚相连
剩余引脚不接,留空
这样我们最少只会用到4根线 VCC电源 GND地线 SID串行输入 SCLK 时钟 便可以实现串行通信
代码实现:
LCD写入一个字节:
#define WRITE_CMD 0xF8//写命令
#define WRITE_DAT 0xFA//写数据
/*!
* @brief LCD串行发送一个字节
* @since v1.0
* @param byte 写入字节
* @author Z小旋
*/
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
}
/*或
SID = (Dbyte 《《 i) & 0x80;
上面那样为了方便理解
*/
SCLK = 0; //时钟线置低 允许SID变化
delay_us(5); //延时使数据写入
SCLK = 1; //拉高时钟,让从机读SID
}
}
/*!
* @brief LCD写指令
* @since v1.0
* @param Cmd 要写入的指令
* @author Z小旋
*/
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); //低四位(先执行《《)
}
/*!
* @brief LCD写数据
* @since v1.0
* @param Dat 要写入的数据
* @author Z小旋
*/
void Lcd_WriteData(u8 Dat )
{
delay_ms(1); //由于我们没有写LCD正忙的检测,所以直接延时1ms,使每次写入数据或指令间隔大于1ms 便可不用写忙状态检测
SendByte(WRITE_DAT); //11111,RW(0),RS(1),0
SendByte(0xf0&Dat); //高四位
SendByte(Dat《《4); //低四位(先执行《《)
}
向LCD发送一个字节,也就是SID引脚相对于高低电平 高电平=1 低电平=0 同时时钟线变化,使得数据可以读取和发送
LCD初始化:
这里为了方便移植,将GPIO的初始化与LCD初始化分为两个,使用时根据自己的引脚只修改GPIO初始化即可
宏定义和GPIO初始化:
#define WRITE_CMD 0xF8//写命令
#define WRITE_DAT 0xFA//写数据
//接口(SID: PE1 SCLK: PE0)
#define SID PEout(1)
#define SCLK PEout(0)
/*!
* @brief GPIO_init
* @since v1.0
* @param None
* @author Z小旋
* 使用时自行修改这里的初始化即可
*/
void lcd_GPIO_init()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);//使能GPIOE时钟
//GPIOE0,E1初始化设置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//无上拉
GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化
SID=1;
SCLK=1;
}
根据不同的型号和管脚修改对应初始化即可
LCD初始化:
/*!
* @brief LCD初始化
* @since v1.0
* @param None
* @author Z小旋
*/
void Lcd_Init(void)
{
delay_ms(50); //等待液晶自检(延时》40ms)
Lcd_WriteCmd(0x30); //功能设定:选择基本指令集 ,选择8bit数据流
delay_ms(1);//延时》137us
Lcd_WriteCmd(0x0c); //开显示
delay_ms(1); //延时》100us
Lcd_WriteCmd(0x01); //清除显示,并且设定地址指针为00H
delay_ms(30); //延时》10ms
Lcd_WriteCmd(0x06); //每次地址自动+1,初始化完成
}
LCD写入字符或汉字:
/* 字符显示RAM地址 4行8列 */
uint8_t 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} //第四行
};
/*!
* @brief 显示字符或汉字
* @since v1.0
* @param x: row(0~3)
* @param y: line(0~7)
* @param str: 要显示的字符或汉字
* @author Z小旋
*/
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++;
}
}
首先写入DDRAM对应初始游标位置,然后在该位置写入字符串 写一个字节之后,DDRAM对应游标地址就自动+1到下一个游标位置继续写,直到字符串空为止
LCD清屏:
/*!
* @brief 清屏函数
* @since v1.0
* @param None
* @author Z小旋
*/
void LCD_Clear(void)
{
Lcd_WriteCmd(0x01); //清屏指令
delay_ms(2); //延时以待液晶稳定【至少1.6ms】
}
LCD显示图片:
/*!
* @brief 显示图片
* @since v1.0
* @param *pic 图片地址
* @author
*/
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); //切换回基本指令
}
具体原理可以结合 LCD图片显示 部分查看
这里要注意 在显示一幅图片之后,要加上2s左右延时,否则不会有图片显示
这里再把显示步骤放在下面,方便理解
图片显示的步骤
1切换到扩充指令
2 关闭绘图显示功能
3 先将垂直的坐标(Y)写入CGRAM地址
4 再将水平的位元组坐标(X)写入CGRAM地址
5 将高位字节D15-D8写入RAM中
6 将低位字节D7-D0写入到RAM中
重复3-6步,完成图片各个部分的写入 先写上半屏,再写下半屏
7 打开绘图显示功能
8 切换回基本指令
使用图片取模软件时要注意 图片取模方式:横向取模,字节正序
到此基本的功能都已经实现了,我把完整的工程代码放到下面,有需要的可以自行下载查看
至此,LCD12864完毕,
PS: 代码没有任何问题,直接修改GPIO初始化部分即可,如果亮不了,先自行检查,还有查看评论区,看下自己是否有相同问题(供电,接线,F1与F4GPIO初始化不同。..等等),不行就在评论区留言,我看到都会回复帮您解决。
这里我们只讲解接线和代码实现
下方代码的实现也是基于上一篇的讲解顺序来的
设备: STM32F407ZGT6
引脚接线:
VSS——GND
VDD——VCC(5V or 3.3V)
V0 亮度调节 不接
CS ——接VCC,持续高电平,一直选通。
SID ——接PE1
SCLK ——接PE0
PSB——接GND 串行模式 或者飞线与1脚相连
BLA——VCC(5V or 3.3V) 或者飞线与2脚相连
BLK——接GND 或者飞线与1脚相连
剩余引脚不接,留空
这样我们最少只会用到4根线 VCC电源 GND地线 SID串行输入 SCLK 时钟 便可以实现串行通信
代码实现:
LCD写入一个字节:
#define WRITE_CMD 0xF8//写命令
#define WRITE_DAT 0xFA//写数据
/*!
* @brief LCD串行发送一个字节
* @since v1.0
* @param byte 写入字节
* @author Z小旋
*/
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
}
/*或
SID = (Dbyte 《《 i) & 0x80;
上面那样为了方便理解
*/
SCLK = 0; //时钟线置低 允许SID变化
delay_us(5); //延时使数据写入
SCLK = 1; //拉高时钟,让从机读SID
}
}
/*!
* @brief LCD写指令
* @since v1.0
* @param Cmd 要写入的指令
* @author Z小旋
*/
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); //低四位(先执行《《)
}
/*!
* @brief LCD写数据
* @since v1.0
* @param Dat 要写入的数据
* @author Z小旋
*/
void Lcd_WriteData(u8 Dat )
{
delay_ms(1); //由于我们没有写LCD正忙的检测,所以直接延时1ms,使每次写入数据或指令间隔大于1ms 便可不用写忙状态检测
SendByte(WRITE_DAT); //11111,RW(0),RS(1),0
SendByte(0xf0&Dat); //高四位
SendByte(Dat《《4); //低四位(先执行《《)
}
向LCD发送一个字节,也就是SID引脚相对于高低电平 高电平=1 低电平=0 同时时钟线变化,使得数据可以读取和发送
LCD初始化:
这里为了方便移植,将GPIO的初始化与LCD初始化分为两个,使用时根据自己的引脚只修改GPIO初始化即可
宏定义和GPIO初始化:
#define WRITE_CMD 0xF8//写命令
#define WRITE_DAT 0xFA//写数据
//接口(SID: PE1 SCLK: PE0)
#define SID PEout(1)
#define SCLK PEout(0)
/*!
* @brief GPIO_init
* @since v1.0
* @param None
* @author Z小旋
* 使用时自行修改这里的初始化即可
*/
void lcd_GPIO_init()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);//使能GPIOE时钟
//GPIOE0,E1初始化设置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//无上拉
GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化
SID=1;
SCLK=1;
}
根据不同的型号和管脚修改对应初始化即可
LCD初始化:
/*!
* @brief LCD初始化
* @since v1.0
* @param None
* @author Z小旋
*/
void Lcd_Init(void)
{
delay_ms(50); //等待液晶自检(延时》40ms)
Lcd_WriteCmd(0x30); //功能设定:选择基本指令集 ,选择8bit数据流
delay_ms(1);//延时》137us
Lcd_WriteCmd(0x0c); //开显示
delay_ms(1); //延时》100us
Lcd_WriteCmd(0x01); //清除显示,并且设定地址指针为00H
delay_ms(30); //延时》10ms
Lcd_WriteCmd(0x06); //每次地址自动+1,初始化完成
}
LCD写入字符或汉字:
/* 字符显示RAM地址 4行8列 */
uint8_t 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} //第四行
};
/*!
* @brief 显示字符或汉字
* @since v1.0
* @param x: row(0~3)
* @param y: line(0~7)
* @param str: 要显示的字符或汉字
* @author Z小旋
*/
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++;
}
}
首先写入DDRAM对应初始游标位置,然后在该位置写入字符串 写一个字节之后,DDRAM对应游标地址就自动+1到下一个游标位置继续写,直到字符串空为止
LCD清屏:
/*!
* @brief 清屏函数
* @since v1.0
* @param None
* @author Z小旋
*/
void LCD_Clear(void)
{
Lcd_WriteCmd(0x01); //清屏指令
delay_ms(2); //延时以待液晶稳定【至少1.6ms】
}
LCD显示图片:
/*!
* @brief 显示图片
* @since v1.0
* @param *pic 图片地址
* @author
*/
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); //切换回基本指令
}
具体原理可以结合 LCD图片显示 部分查看
这里要注意 在显示一幅图片之后,要加上2s左右延时,否则不会有图片显示
这里再把显示步骤放在下面,方便理解
图片显示的步骤
1切换到扩充指令
2 关闭绘图显示功能
3 先将垂直的坐标(Y)写入CGRAM地址
4 再将水平的位元组坐标(X)写入CGRAM地址
5 将高位字节D15-D8写入RAM中
6 将低位字节D7-D0写入到RAM中
重复3-6步,完成图片各个部分的写入 先写上半屏,再写下半屏
7 打开绘图显示功能
8 切换回基本指令
使用图片取模软件时要注意 图片取模方式:横向取模,字节正序
到此基本的功能都已经实现了,我把完整的工程代码放到下面,有需要的可以自行下载查看
至此,LCD12864完毕,
PS: 代码没有任何问题,直接修改GPIO初始化部分即可,如果亮不了,先自行检查,还有查看评论区,看下自己是否有相同问题(供电,接线,F1与F4GPIO初始化不同。..等等),不行就在评论区留言,我看到都会回复帮您解决。
举报