标题:
stm32串行st7920 128*64屏显示字符源程序
[打印本页]
作者:
GAOXIANG123
时间:
2017-7-18 20:10
标题:
stm32串行st7920 128*64屏显示字符源程序
stm32单片机串行方式控制st7920 128*64屏显示字符,附件里面有2个程序,全部都是经过测试ok的
b00d5298a8551fe631848e1e1e5d996a_604.jpg
(31.21 KB, 下载次数: 87)
下载附件
2017-7-19 01:11 上传
单片机源程序如下:
/**********************************************************
* @ File name -> lcd12864.c
* @ Version -> V1.1.2
* @ Date -> 11-30-13
* @ Brief -> LCD12864驱动函数
* 适用于ST7920驱动芯片
V1.1
* @ Revise -> A、修正操作命令宏定义。
* @ -> B、增加串口、并口转换宏定义,增加对高速度MCU控制通讯频率延时函数
* @ -> C、显示字符串函数增加显示长度选择,即显示多少个ASCII可显示字符,汉字x2即可
* @ -> D、去掉显示数组函数,合并在字符串显示里
V1.1.1
* @ Revise -> 增加字符串显示函数,可以从要显示的数组中任意位置显示一定长度字符串
V1.1.2
* @ Revise -> A、增加对低速晶振系统的MCU通讯频率是否使用的宏定义
* @ -> B、增加在检测液晶忙超时退出,预防死循环
**********************************************************/
#include "lcd12864.h"
/**********************************************************
自定义显示字符
**********************************************************/
#define CGRAM_Value 64 //写入CGRAM数量
u8 code CGROM_Code[] = {
//天线图形
0xff,0xff,0x80,0x01,0xbf,0xfd,0xdf,0xfb,0xec,0x37,0xf6,0x6f,0xfb,0xdf,0xfd,0xbf,
0xfe,0x7f,0xfe,0x7f,0xfe,0x7f,0xfe,0x7f,0xfe,0x7f,0xfe,0x7f,0xfe,0x7f,0xff,0xff,
//摄氏图形
// 0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x70,0x14,0xd8,0x1d,0x88,0x01,0x80,0x01,0x80,
// 0x01,0x80,0x01,0x80,0x01,0x88,0x00,0xc8,0x00,0x70,0x00,0x00,0x00,0x00,0x00,0x00,
//蓝牙图形
0x07,0xe0,0x0e,0x70,0x1e,0xb8,0x3e,0xdc,0x36,0xec,0x3a,0xdc,0x3c,0xbc,0x3e,0x7c,
0x3e,0x7c,0x3c,0xbc,0x3a,0xdc,0x36,0xec,0x3e,0xdc,0x1e,0xb8,0x0e,0x70,0x07,0xe0,
//CD图形
0xff,0xff,0xff,0xff,0xff,0xff,0xe3,0x07,0xc9,0xb3,0x9d,0xb9,0x9f,0xb9,0x9f,0xb9,
0x9f,0xb9,0x9f,0xb9,0x9d,0xb9,0xc9,0xb3,0xe3,0x07,0xff,0xff,0xff,0xff,0xff,0xff,
//右指向手型
0x00,0x00,0x1e,0x00,0x12,0x00,0x73,0xfc,0x52,0x02,0x52,0x1c,0x53,0xe0,0x52,0x10,
0x53,0xe0,0x52,0x10,0x53,0xe0,0x52,0x10,0x73,0xe0,0x12,0x00,0x1e,0x00,0x00,0x00
};
//=========================================================
#ifdef LCD_Work_Mode //如果定义了,则使用并口工作模式
//=========================================================
/**********************************************************
* 函数功能 ---> LCD12864判断忙
* 入口参数 ---> none
* 返回数值 ---> none
* 功能说明 ---> none
**********************************************************/
void LCD_Check_Busy(void)
{
static u16 busytimeout; //忙超时
//=====================================================
#ifdef LCD_USE_DELAY /* 定义了则使用延时调整通讯频率 */
//=====================================================
ktdata = 0xf0; //数据口全部置位
do
{
busytimeout++;
if(busytimeout > 300) break;
LCD_RS = 0;
LCD_Delay();
LCD_RW = 1;
LCD_Delay();
LCD_EN = 1;
LCD_Delay();
}while(ktdata & LCD_Busy == LCD_Busy); //等待LCD忙完
LCD_EN = 0;
//=====================================================
#else /* 没定义则不使用 */
//=====================================================
ktdata = 0xf0; //数据口全部置位
do
{
busytimeout++;
if(busytimeout > 300) break;
LCD_RS = 0;
LCD_RW = 1;
LCD_EN = 1;
// LCD_Delay();
}while(ktdata & LCD_Busy == LCD_Busy); //等待LCD忙完
LCD_EN = 0;
//=====================================================
#endif
//=====================================================
if(busytimeout >= 300) printf("LCD Busy TimeOut...\r\n");
busytimeout = 0;
}
/**********************************************************
* 函数功能 ---> LCD写入一个字节命令或者数据,判断忙标志(8位数据一次发送完毕)
* 入口参数 ---> dat:要写入的字节
* ord:判断dat是命令还是数据依据,“0”为命令,“1”为数据
* 返回数值 ---> none
* 功能说明 ---> none
**********************************************************/
void LCD_Write_Byte(u8 dat,u8 ord)
{
//=====================================================
#ifdef LCD_USE_DELAY /* 定义了则使用延时调整通讯频率 */
//=====================================================
LCD_Check_Busy(); //判断是否在忙?
LCD_EN = 0;
LCD_Delay();
LCD_RW = 0;
LCD_Delay();
if(ord & 0x01) LCD_RS = 1; //放上数据或者命令判断位
else LCD_RS = 0;
LCD_EN = 1;
LCD_Delay();
ktdata = dat; //放入数据
LCD_Delay();
LCD_EN = 0;
//=====================================================
#else /* 没定义则不使用 */
//=====================================================
LCD_Check_Busy(); //判断是否在忙?
LCD_EN = 0;
LCD_RW = 0;
if(ord & 0x01) LCD_RS = 1; //放上数据或者命令判断位
else LCD_RS = 0;
LCD_EN = 1;
ktdata = dat; //放入数据
LCD_EN = 0;
//=====================================================
#endif
//=====================================================
}
//=========================================================
#else //没定义则使用串口通讯模式
//=========================================================
/**********************************************************
* 函数功能 ---> LCD启动字节
* 入口参数 ---> dt:传输的字节,高5位在函数内部设定为1
* 只是确定RW和RS为,最后那位也是内部确定
* 返回数值 ---> none
* 功能说明 ---> 首先传送一个启动字节,送入连续5个“1”用来启
* 动一个周期,此时传输计数被重置,并且串行传输
* 被同步,紧接着的两个位指定传输方向(R/W,确
* 定是读还是写)和传输性质(RS,确定是命令寄存
* 器还是数据寄存器),最后的第八位是一个“0”
**********************************************************/
void LCD12864_Start(u8 dt)
{
u8 dat,j;
dat = dt | 0xf8; //高5位设定为“1”,第八位设定为“0”
LCD_SCL = 0;
LCD_Delay();LCD_Delay();
LCD_CS = 1; //选中显示屏,高电平有效
for(j = 0;j < 8;j++)
{
if(dat & 0x80) LCD_SDA = 1; //放数据到数据线
else LCD_SDA = 0;
LCD_Delay();LCD_Delay();LCD_Delay();
LCD_SCL = 1; //发送数据,上升沿有效
LCD_Delay();LCD_Delay();LCD_Delay();
LCD_SCL = 0;
dat <<= 1; //左移一位,先发的是高位
}
LCD_Delay();LCD_Delay();LCD_Delay();
LCD_SCL = 0;
LCD_Delay();LCD_Delay();LCD_Delay(); //等待硬件反应(等待数据发送完全)
}
/**********************************************************
* 函数功能 ---> LCD写入一个字节命令或者数据
* 入口参数 ---> dat:要写入的命令或者数据
* ord:命令或者数据判断为。0为命令,1为数据
* 返回数值 ---> none
* 功能说明 ---> none
**********************************************************/
void LCD_Write_Byte(u8 dat,u8 ord)
{
u8 tem;
u8 i,j;
tem = dat & 0xf0; //先发送高4位
LCD12864_Start((ord << 1) | 0xf0); //置RW为“0”、RS为“ord”并启动串行传输为数据格式
for(j = 0;j < 2;j++) //一个字节数据或者命令分两次发送
{
LCD_SCL = 0; //允许数据线电平变化
LCD_Delay();LCD_Delay();LCD_Delay();
for(i = 0;i < 8;i++)
{
if(tem & 0x80) LCD_SDA = 1; //放上数据,屏蔽低4位
else LCD_SDA = 0;
LCD_Delay();LCD_Delay();LCD_Delay();
LCD_SCL = 1; //发送数据,上升沿有效
LCD_Delay();LCD_Delay();LCD_Delay();
LCD_SCL = 0;
tem <<= 1; //左移一位,先发的是高位
}
tem = (dat << 4) & 0xf0; //发完高4位,再次发送低4位
}
LCD_Delay();LCD_Delay();LCD_Delay();
LCD_SDA = 0;
LCD_Delay();LCD_Delay();LCD_Delay();
LCD_SCL = 0;
LCD_Delay();LCD_Delay();LCD_Delay();
LCD_CS = 0;
LCD_Delay();LCD_Delay();LCD_Delay(); //等待硬件反应(等待数据发送完全)
}
//=========================================================
#endif
//=========================================================
/**********************************************************
* 函数功能 ---> 设置LCD显示位置
* 入口参数 ---> x:行,取值范围:1 ~ 4
* y:列,取值范围:0 ~ 7
* 返回数值 ---> none
* 功能说明 ---> none
**********************************************************/
void LCD_Set_xy(u8 x,u8 y)
{
switch(x)
{
case 1:
LCD_Write_Byte((One_LineAddress + y),0); //写入操作地址
break;
case 2:
LCD_Write_Byte((Two_LineAddress + y),0); //写入操作地址
break;
case 3:
LCD_Write_Byte((Three_LineAddress + y),0); //写入操作地址
break;
case 4:
LCD_Write_Byte((Four_LineAddress + y),0); //写入操作地址
break;
default:
LCD_Write_Byte((One_LineAddress + y),0); //写入操作地址
break;
}
}
/**********************************************************
* 函数功能 ---> 写入自定义字符到LCD的CGRAM
* 入口参数 ---> *data_code:写入的数组
* 返回数值 ---> none
* 功能说明 ---> none
**********************************************************/
void LCD_Write_CGRAM(u8 *data_code)
{
u8 i;
LCD_Write_Byte(0x34,0); //打开字符扩展指令
LCD_Write_Byte(0x02,0); //SR=0,允许输入
LCD_Write_Byte(0x30,0); //恢复基本指令
LCD_Write_Byte(0x40,0); //CGRAM地址
for(i = 0;i < CGRAM_Value;i++)
{
LCD_Write_Byte(data_code[i*2],1);
LCD_Write_Byte(data_code[i*2+1],1);
}
}
/**********************************************************
* 函数功能 ---> 显示一个CGRAM内容
* 入口参数 ---> x:行
* y:列
* *str为要显示的字符串
* add_h:CGRAM高位地址
* add_l:CGRAM低位地址
* 返回数值 ---> none
* 功能说明 ---> none
**********************************************************/
void Display_CGRAM(u8 x,u8 y,u8 add_h,u8 add_l)
{
LCD_Set_xy(x,y); //设置显示地址
LCD_Write_Byte(add_h,1);
LCD_Write_Byte(add_l,1);
}
/**********************************************************
* 函数功能 ---> LCD显示字符串
* 入口参数 ---> x:行
* y:列
* *str:要显示的字符串
* len:显示的长度
* 返回数值 ---> none
* 功能说明 ---> 只能从数组的开头开始显示len长度字符串
**********************************************************/
void Display_String(u8 x,u8 y,u8 *str,u8 len)
{
LCD_Set_xy(x,y); //设置显示地址
while(len--)
{
LCD_Write_Byte(*str,1);
str++;
}
}
/**********************************************************
* 函数功能 ---> LCD显示字符串
* 入口参数 ---> x:行
* y:列
* *str:要显示的字符串
* len:显示的长度
* 返回数值 ---> none
* 功能说明 ---> 可以从显示数组的任意位置starsum开始显示len长度的字符串
**********************************************************/
void Display_String1(u8 x,u8 y,u8 *str,u8 starsum,u8 len)
{
u8 i;
LCD_Set_xy(x,y); //设置显示地址
for(i = starsum;i < starsum + len;i++)
{
LCD_Write_Byte(str[i],1);
}
}
/**********************************************************
* 函数功能 ---> LCD写入GDRAM绘图
* 入口参数 ---> x:行
* y:列
* width:显示图片的宽度
* hieght:显示图片的高度
* *bmp:要显示的字符串
* dis_mode:显示模式,是半屏显示还是全屏显示
* 0:半屏显示。1:全屏显示
* 返回数值 ---> none
* 功能说明 ---> none
**********************************************************/
void Display_GDRAM(u8 x,u8 y,u8 width,u8 height,u8 *bmp,u8 dis_mode)
{
u8 i,j,k;
u8 base_x,base_y; //起始坐标
/******全屏绘图显示******/
if(dis_mode)
{
switch(x)
{
case 1:
base_y = One_LineAddress + y;
break;
case 2:
base_y = Two_LineAddress + y;
break;
case 3:
base_y = Three_LineAddress + y;
break;
case 4:
base_y = Four_LineAddress + y;
break;
default: break;
}
LCD_Write_Byte(MPU_8bit_Expansion_Draw_Close,0); //扩充指令
LCD_Write_Byte(MPU_8bit_Expansion_Draw_Open,0); //打开绘图功能
for(j = 0;j < height;j++) //32
{
LCD_Write_Byte(base_y + j,0); //写入行号,即第几行开始
LCD_Write_Byte(One_LineAddress,0); //横坐标的第几个字节开始写
for(i = 0;i < width;i++) //上半屏
{
LCD_Write_Byte(bmp[width * j + i],1); //开始写入数据
}
for(k = 0;k < width;k++) //下半屏
{
LCD_Write_Byte(bmp[width * (j + height) + k],1); //开始写入数据
}
}
}
/******分开上半屏或者下半屏写******/
else
{
switch(x) //判断显示的横坐标,确定起始行
{
case 1: //上半屏
base_x = One_LineAddress; //起始地址为0x80
break;
case 2: //下半屏
base_x = One_LineAddress; //起始地址为0x80
break;
case 3: //下半屏
base_x = Three_LineAddress; //起始地址为0x88
break;
default:
break;
}
base_y = base_x + y; //x轴方向的偏移,基地址 + 偏移地址
LCD_Write_Byte(MPU_8bit_Expansion_Draw_Close,0); //扩充指令
LCD_Write_Byte(MPU_8bit_Expansion_Draw_Open,0); //打开绘图功能
if(x == 1 || x == 3) //直接在同一个半屏的,直接写完32位数据
{
for(i = 0;i < 32;i++) //写地址有讲究,先写垂直再写水平,详见“设定绘图RAM地址”说明
{
LCD_Write_Byte(One_LineAddress + i,0); //写入垂直地址,不管上半屏还是下半屏
LCD_Write_Byte(base_y,0); //写入水平地址
for(j = 0;j < 2;j++) //两组8bit数据,组成16bit
{
LCD_Write_Byte(*bmp++,1); //写入数据
}
}
}
if(x == 2) //数据显示不在同一半屏上的,先写上半屏,在写下半屏
{
for(i = 0;i < 16;i++) //上半屏16行点阵数据
{
LCD_Write_Byte(Two_LineAddress + i,0); //写入垂直地址
LCD_Write_Byte(base_y,0); //写入水平地址
for(j = 0;j < 2;j++) //两组8bit数据,组成16bit
{
LCD_Write_Byte(*bmp++,1); //写入数据
}
}
for(i = 0;i < 16;i++) //下半屏16行点阵数据
{
LCD_Write_Byte(Three_LineAddress + i,0); //写入垂直地址
LCD_Write_Byte(base_y + 8,0); //写入水平地址
for(j = 0;j < 2;j++) //两组8bit数据,组成16bit
{
LCD_Write_Byte(*bmp++,1); //写入数据
……………………
…………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
STM32F103VCT612864.rar
(263.89 KB, 下载次数: 100)
2017-7-19 01:14 上传
点击文件名下载附件
下载积分: 黑币 -5
lcd12864.zip
(8.03 KB, 下载次数: 83)
2017-7-19 01:14 上传
点击文件名下载附件
下载积分: 黑币 -5
JN12864J使用说明书.pdf
(776.12 KB, 下载次数: 40)
2017-7-19 01:14 上传
点击文件名下载附件
下载积分: 黑币 -5
作者:
by64214
时间:
2017-7-21 19:19
谢谢楼主分享 学习一下 现在能力只能模仿 无力独立完成
作者:
sean0110
时间:
2018-5-13 20:16
谢谢楼主分享 学习一下 现在能力只能模仿 无力独立完成
作者:
lzqs
时间:
2018-11-25 11:53
谢谢楼主分享 学习一下 现在能力只能模仿 无力独立完成
作者:
zhaoxiaolong
时间:
2018-11-26 11:25
谢谢分享 学习一下
作者:
万能的金果果
时间:
2019-7-29 14:16
谢谢楼主分享,新人学习一下
作者:
万能的金果果
时间:
2019-7-29 14:16
谢谢楼主分享,学习一下
作者:
ia88k3
时间:
2020-4-7 00:00
谢谢!刚好需要,下来参考一下
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1