实例介绍
【实例简介】该工程源码使用的开发工具是MDK5,是基于STM32串行驱动LCD12864显示屏的,实现了显示字符串,在LCD显示范围内绘制任意点、画线、显示图片等代码
【实例截图】
* @param byte: 一个字节数据
* @retval 无
*/
static void lcd_send_byte(unsigned char byte)
{
unsigned char i;
for(i=0; i<8; i )
{
LCD_CLK(0);
LCD_SID(byte & (0x80 >> i)); // 按位发送
delay_us(5);
LCD_CLK(1);
}
}
/**
* @brief LCD12864写命令
* @param cmd: 要发送的命令
* @retval 无
*/
static void lcd_write_cmd(unsigned char cmd)
{
LCD_CS(1);
delay_us(30);
lcd_send_byte(0xf8); // 写命令
lcd_send_byte(0xf0 & cmd); // 写高4位指令
lcd_send_byte(cmd << 4); // 写低4位指令
LCD_CS(0);
}
/**
* @brief LCD12864写数据
* @param data: 要发送的数据
* @retval 无
*/
static void lcd_write_data(unsigned char data)
{
LCD_CS(1);
delay_us(30);
lcd_send_byte(0xfa); // 写数据
lcd_send_byte(0xf0 & data); // 写高4位数据
lcd_send_byte(data << 4); // 写低4位数据
LCD_CS(0);
}
/**
* @brief LCD12864初始化
* @param 无
* @retval 无
*/
void lcd_init(void)
{
delay_ms(50); // 上电自检延时
lcd_write_cmd(0x30); // 选择基本指令集,8bit数据流
delay_ms(1);
lcd_write_cmd(0x0c); // 开显示,关闭光标
delay_ms(1);
lcd_write_cmd(0x01); // 清除显示
delay_ms(30);
}
/**
* @brief LCD12864显示字符串
* @param column: 行地址0~3,row: 列地址0~7
* @retval 无
*/
void lcd_draw_str(unsigned char column, unsigned char row, const char *str)
{
/* 设置显示的行/列地址 */
lcd_write_cmd(lcd_str_addr[column][row]);
/* 逐个字符写入 */
while(*str)
{
lcd_write_data(*str );
}
}
/* x轴按位显示的位码表 */
static const unsigned char set_pix_bit[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
/* 显示缓冲区 */
static unsigned char disp_buff[8][64] = {0};
/**
* @brief 设置LCD12864显示坐标
* @param x: x轴坐标0~127, y: y轴坐标0~63
* @retval 无
*/
static void lcd_setXY(unsigned char x, unsigned char y)
{
if (y >= 32)
{
/* 下半屏 */
lcd_write_cmd(0x80 (y - 32)); // y坐标
lcd_write_cmd(0x88 (x>>4)); // x坐标
}
else
{
/* 上半屏 */
lcd_write_cmd(0x80 y);
lcd_write_cmd(0x80 (x>>4));
}
}
/**
* @brief 清空屏幕
* @param 无
* @retval 无
*/
void lcd_clear(void)
{
unsigned char x, y;
lcd_write_cmd(0x34); // 切换到扩展指令集
for(y=0; y<64; y )
{
lcd_setXY(0, y); // 设置显示坐标
for(x=0; x<8; x )
{
/* 因为x轴一个地址对应16个像素点,可以连续发送两个字节数据 */
lcd_write_data(0x00);
lcd_write_data(0x00);
}
}
lcd_write_cmd(0x36); // 打开绘图显示
lcd_write_cmd(0x30); // 回到基本指令集
}
/**
* @brief 显示图片,注意显示起点坐标固定是(0, 0)
* @param 无
* @retval 无
*/
void lcd_draw_picture(const unsigned char *data)
{
unsigned char x, y;
lcd_write_cmd(0x34); // 切换到扩展指令集
for(y=0; y<64; y )
{
lcd_setXY(0, y);
for(x=0; x<8; x )
{
lcd_write_data(*data );
lcd_write_data(*data );
}
}
lcd_write_cmd(0x36); // 打开绘图显示
lcd_write_cmd(0x30); // 回到基本指令集
}
/**
* @brief 在LCD显示范围内绘制任意点
x坐标范围是:0~127,y坐标范围是:0~63
* @param x: x轴坐标, y: y轴坐标, color: 颜色值,1:点亮像素,0:不点亮
* @retval 无
*/
void lcd_draw_dots(unsigned char x, unsigned char y, unsigned char color)
{
lcd_write_cmd(0x34); // 切换到扩展指令集
/* 超出显示范围,退出函数 */
if ((x >= 128) || (y >= 64))
return;
/* 设置x, y坐标 */
lcd_setXY(x, y);
/* 填充显示缓冲区数据 */
if (color == 1)
{
/* 点亮某点像素 */
disp_buff[x>>3][y] |= 0x00;
disp_buff[(x>>3) 1][y] |= set_pix_bit[x & 0x07];
}
else
{
/* 熄灭某点像素 */
disp_buff[x>>3][y] |= 0x00;
disp_buff[(x>>3) 1][y] &= ~set_pix_bit[x & 0x07];
}
/* 输出数据到LCD显示 */
if ((x >> 3) % 2 != 0) // 判断x轴0~15个显示数据的奇偶性
{
/* 奇数 */
lcd_write_data(disp_buff[x>>3][y]);
lcd_write_data(disp_buff[(x>>3) 1][y]);
}
else
{
/* 偶数 */
lcd_write_data(disp_buff[(x>>3) 1][y]);
lcd_write_data(disp_buff[x>>3][y]);
}
lcd_write_cmd(0x36); // 打开绘图显示
lcd_write_cmd(0x30); // 回到基本指令集
}
/**
* @brief 绘制水平线
* @param x0: x轴起点, y0: y0轴起点, x1: x轴结束点, color: 颜色值,1点亮像素,0不点亮
* @retval 无
*/
void lcd_draw_Hline(unsigned char x0, unsigned char y0, unsigned char x1, unsigned char color)
{
/* 超出显示范围,退出函数 */
if ((x0 >= 128) || (y0 >= 64) || (x1 >= 128))
return;
for ( ; x1>=x0; x0 )
lcd_draw_dots(x0, y0, color);
}
/**
* @brief 绘制垂直线
* @param x0: x轴起点, y0: y轴起点, y1: y轴结束点, color: 颜色值,1点亮像素,0不点亮
* @retval 无
*/
void lcd_draw_Vline(unsigned char x0, unsigned char y0, unsigned char y1, unsigned char color)
{
/* 超出显示范围,退出函数 */
if ((x0 >= 128) || (y0 >= 64) || (y1 >= 64))
return;
for ( ; y1>=y0; y0 )
lcd_draw_dots(x0, y0, color);
}
【实例截图】

【核心代码】
/**
* @brief LCD12864串行发送一个字节数据* @param byte: 一个字节数据
* @retval 无
*/
static void lcd_send_byte(unsigned char byte)
{
unsigned char i;
for(i=0; i<8; i )
{
LCD_CLK(0);
LCD_SID(byte & (0x80 >> i)); // 按位发送
delay_us(5);
LCD_CLK(1);
}
}
/**
* @brief LCD12864写命令
* @param cmd: 要发送的命令
* @retval 无
*/
static void lcd_write_cmd(unsigned char cmd)
{
LCD_CS(1);
delay_us(30);
lcd_send_byte(0xf8); // 写命令
lcd_send_byte(0xf0 & cmd); // 写高4位指令
lcd_send_byte(cmd << 4); // 写低4位指令
LCD_CS(0);
}
/**
* @brief LCD12864写数据
* @param data: 要发送的数据
* @retval 无
*/
static void lcd_write_data(unsigned char data)
{
LCD_CS(1);
delay_us(30);
lcd_send_byte(0xfa); // 写数据
lcd_send_byte(0xf0 & data); // 写高4位数据
lcd_send_byte(data << 4); // 写低4位数据
LCD_CS(0);
}
/**
* @brief LCD12864初始化
* @param 无
* @retval 无
*/
void lcd_init(void)
{
delay_ms(50); // 上电自检延时
lcd_write_cmd(0x30); // 选择基本指令集,8bit数据流
delay_ms(1);
lcd_write_cmd(0x0c); // 开显示,关闭光标
delay_ms(1);
lcd_write_cmd(0x01); // 清除显示
delay_ms(30);
}
/**
* @brief LCD12864显示字符串
* @param column: 行地址0~3,row: 列地址0~7
* @retval 无
*/
void lcd_draw_str(unsigned char column, unsigned char row, const char *str)
{
/* 设置显示的行/列地址 */
lcd_write_cmd(lcd_str_addr[column][row]);
/* 逐个字符写入 */
while(*str)
{
lcd_write_data(*str );
}
}
/* x轴按位显示的位码表 */
static const unsigned char set_pix_bit[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
/* 显示缓冲区 */
static unsigned char disp_buff[8][64] = {0};
/**
* @brief 设置LCD12864显示坐标
* @param x: x轴坐标0~127, y: y轴坐标0~63
* @retval 无
*/
static void lcd_setXY(unsigned char x, unsigned char y)
{
if (y >= 32)
{
/* 下半屏 */
lcd_write_cmd(0x80 (y - 32)); // y坐标
lcd_write_cmd(0x88 (x>>4)); // x坐标
}
else
{
/* 上半屏 */
lcd_write_cmd(0x80 y);
lcd_write_cmd(0x80 (x>>4));
}
}
/**
* @brief 清空屏幕
* @param 无
* @retval 无
*/
void lcd_clear(void)
{
unsigned char x, y;
lcd_write_cmd(0x34); // 切换到扩展指令集
for(y=0; y<64; y )
{
lcd_setXY(0, y); // 设置显示坐标
for(x=0; x<8; x )
{
/* 因为x轴一个地址对应16个像素点,可以连续发送两个字节数据 */
lcd_write_data(0x00);
lcd_write_data(0x00);
}
}
lcd_write_cmd(0x36); // 打开绘图显示
lcd_write_cmd(0x30); // 回到基本指令集
}
/**
* @brief 显示图片,注意显示起点坐标固定是(0, 0)
* @param 无
* @retval 无
*/
void lcd_draw_picture(const unsigned char *data)
{
unsigned char x, y;
lcd_write_cmd(0x34); // 切换到扩展指令集
for(y=0; y<64; y )
{
lcd_setXY(0, y);
for(x=0; x<8; x )
{
lcd_write_data(*data );
lcd_write_data(*data );
}
}
lcd_write_cmd(0x36); // 打开绘图显示
lcd_write_cmd(0x30); // 回到基本指令集
}
/**
* @brief 在LCD显示范围内绘制任意点
x坐标范围是:0~127,y坐标范围是:0~63
* @param x: x轴坐标, y: y轴坐标, color: 颜色值,1:点亮像素,0:不点亮
* @retval 无
*/
void lcd_draw_dots(unsigned char x, unsigned char y, unsigned char color)
{
lcd_write_cmd(0x34); // 切换到扩展指令集
/* 超出显示范围,退出函数 */
if ((x >= 128) || (y >= 64))
return;
/* 设置x, y坐标 */
lcd_setXY(x, y);
/* 填充显示缓冲区数据 */
if (color == 1)
{
/* 点亮某点像素 */
disp_buff[x>>3][y] |= 0x00;
disp_buff[(x>>3) 1][y] |= set_pix_bit[x & 0x07];
}
else
{
/* 熄灭某点像素 */
disp_buff[x>>3][y] |= 0x00;
disp_buff[(x>>3) 1][y] &= ~set_pix_bit[x & 0x07];
}
/* 输出数据到LCD显示 */
if ((x >> 3) % 2 != 0) // 判断x轴0~15个显示数据的奇偶性
{
/* 奇数 */
lcd_write_data(disp_buff[x>>3][y]);
lcd_write_data(disp_buff[(x>>3) 1][y]);
}
else
{
/* 偶数 */
lcd_write_data(disp_buff[(x>>3) 1][y]);
lcd_write_data(disp_buff[x>>3][y]);
}
lcd_write_cmd(0x36); // 打开绘图显示
lcd_write_cmd(0x30); // 回到基本指令集
}
/**
* @brief 绘制水平线
* @param x0: x轴起点, y0: y0轴起点, x1: x轴结束点, color: 颜色值,1点亮像素,0不点亮
* @retval 无
*/
void lcd_draw_Hline(unsigned char x0, unsigned char y0, unsigned char x1, unsigned char color)
{
/* 超出显示范围,退出函数 */
if ((x0 >= 128) || (y0 >= 64) || (x1 >= 128))
return;
for ( ; x1>=x0; x0 )
lcd_draw_dots(x0, y0, color);
}
/**
* @brief 绘制垂直线
* @param x0: x轴起点, y0: y轴起点, y1: y轴结束点, color: 颜色值,1点亮像素,0不点亮
* @retval 无
*/
void lcd_draw_Vline(unsigned char x0, unsigned char y0, unsigned char y1, unsigned char color)
{
/* 超出显示范围,退出函数 */
if ((x0 >= 128) || (y0 >= 64) || (y1 >= 64))
return;
for ( ; y1>=y0; y0 )
lcd_draw_dots(x0, y0, color);
}
好例子网口号:伸出你的我的手 — 分享!
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明
网友评论
我要评论