一,LCD是什么?LCD干嘛用的?
由以下构成
用处:显示你想显示的东西。(对不起,是废话)
二,LCD怎么用?
备注:使用的就是COG LCD液晶屏,它只能显示黑白图像和文字,显示的像素大小为128*128。
LCD显示点阵与DD RAM(显示数据存储器)地址的对应关系:
其一行有128个像素点,可通过向存储器写入数据来点亮/熄灭该点阵
接下来我们将用LCD屏幕来显示简单的中英文字符和图片,通过以上介绍,我们可以得出COG LCD液晶显示需要的相关设置步骤如下:
三、实际操作
/**
****************************************************************************
* @文件名 : lcd.c
* @作者 : Apana
* @文件版本 : V1.0.0
* @编写日期 : 2020-08-17
* @说明 : lcd源文件
* @备注 : lcd使用JTAG引脚,在使用之前需要禁用JTAG,使能SW
******************************************************************************/
/*----------------------------------------------------------------------------
更新日志:
2020-08-17 V1.0.0:初始版本
----------------------------------------------------------------------------*/
/* 包含的头文件 --------------------------------------------------------------*/
#include "lcd.h"
#include "gbhz.h"
#include "ascii.h"
#include "delay.h"
u8 LCD_GRAM[16][128]; //显示缓存
//初始化LCD_GPIO
void LCD_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure; //GPIO结构体定义
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC, ENABLE); //使能端口时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //开启复用时钟
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE); //禁用JTAG,使能SW
//数据引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_12 | GPIO_Pin_14 | GPIO_Pin_15 ; //PC
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
GPIO_Init(GPIOC,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_8 ; //PB
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
GPIO_Init(GPIOB,&GPIO_InitStructure);
//控制引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
GPIO_Init(GPIOC,&GPIO_InitStructure);
GPIO_SetBits(GPIOC,GPIO_Pin_9); //将引脚置
GPIO_ResetBits(GPIOC,GPIO_Pin_8 | GPIO_Pin_10 | GPIO_Pin_11); //将引脚复位
//LCD-RD
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_Init(GPIOB, &GPIO_InitStructure); //根据设定参数初始化
GPIO_SetBits(GPIOB,GPIO_Pin_13); //输出高
//背光灯初始化
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能PA端口时钟
//释放JTAG的IO口保留SWD
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //引脚PA8
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //时钟频率
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化
GPIO_SetBits(GPIOA,GPIO_Pin_8); //输出高电平,开启背光灯
}
//lcd写模式
void LCD_WRITE(u8 x)
{
if(x&0x01)PCout(14) = 1;else PCout(14) = 0;
if(x&0x02)PCout(15) = 1;else PCout(15) = 0;
if(x&0x04)PBout(4) = 1;else PBout(4) = 0;
if(x&0x08)PBout(3) = 1;else PBout(3) = 0;
if(x&0x10)PCout(12) = 1;else PCout(12) = 0;
if(x&0x20)PBout(8) = 1;else PBout(8) = 0;
if(x&0x40)PCout(6) = 1;else PCout(6) = 0;
if(x&0x80)PCout(7) = 1;else PCout(7) = 0;
}
//写命令
void LCD_WR_CMD(u8 cmd)
{
LCD_CS = 0;
LCD_RS = 0;
LCD_RD = 0;
LCD_WR = 0;
LCD_WRITE(cmd);
LCD_RD = 1;
LCD_CS = 1;
LCD_RD = 0;
}
//写数据
void LCD_WR_DATA(u8 data)
{
LCD_CS = 0;
LCD_RS = 1;
LCD_RD = 0;
LCD_WR = 0;
LCD_WRITE(data);
LCD_RD = 1;
LCD_CS = 1;
LCD_RD = 0;
}
//LCD模块初始化
void LCD_Init(void)
{
LCD_GPIO_Init(); /*GPIO初始化*/
//lcd硬件复位
LCD_RESET = 0;
delay_ms(20);
LCD_RESET = 1;
delay_ms(20);
LCD_WR_CMD(0xae); //关显示
LCD_WR_CMD(0xa9); //a9
LCD_WR_CMD(0xc8);
LCD_WR_CMD(0xa0); //a0
LCD_WR_CMD(0xab);
LCD_WR_CMD(0xa6);
LCD_WR_CMD(0xa4);
LCD_WR_CMD(0x4c); //n-line
LCD_WR_CMD(0x00); //0a
LCD_WR_CMD(0x38); //frame
LCD_WR_CMD(0x08);
LCD_WR_CMD(0x48); //duty
LCD_WR_CMD(0x80); //128
LCD_WR_CMD(0xb0);
LCD_WR_CMD(0x40);
LCD_WR_CMD(0x00);
LCD_WR_CMD(0x44); //com0
LCD_WR_CMD(0x00);
LCD_WR_CMD(0x52); //bias 54
LCD_WR_CMD(0x25); //27
LCD_WR_CMD(0x81); //
LCD_WR_CMD(0x22); //18
LCD_WR_CMD(0xa8); //
LCD_WR_CMD(0x2c);
delay_ms(200);
LCD_WR_CMD(0x2e);
delay_ms(200);
LCD_WR_CMD(0x2f);
delay_ms(200);
LCD_WR_CMD(0x7B); //Enter Test Command Set 3
LCD_WR_CMD(0x10); //Set Color Mode(0x11Black/White mode),0x10=Gray mode (default)
LCD_WR_CMD(0x00); //Exit Test Command Set 3
LCD_WR_CMD(0xaf);
}
//更新显存到LCD
void LCD_RefreshGram(void)
{
u8 i,n;
for(i=0;i<16;i++)
{
LCD_WR_CMD(0xb0+i);
LCD_WR_CMD(0x10);
LCD_WR_CMD(0x00);
for(n=0;n<128;n++)
{
LCD_WR_DATA(LCD_GRAM[i][n]);
LCD_WR_DATA(LCD_GRAM[i][n]);
}
}
}
//清除显示缓存
void LCD_ClearGram(void)
{
u8 i,n;
for(i=0;i<16;i++)
{
for(n=0;n<128;n++)
{
LCD_GRAM[i][n]=0x00;
}
}
}
//清除显示缓存
void LCD_ClearGramLine(u8 line1,u8 line2)
{
u8 i,n;
for(i=line1;i127||y>127) return;//超出范围了
temp=1<<(y%8);
if(t) LCD_GRAM[y/8][x]|=temp;
else LCD_GRAM[y/8][x]&=~temp;
}
//画线
void LCD_DrawLine(u16 sx,u16 sy,u16 ex,u16 ey)
{
u16 t;
int xerr=0,yerr=0,delta_x,delta_y,distance;
int incx,incy,uRow,uCol;
delta_x=ex-sx; //计算坐标增量
delta_y=ey-sy;
uRow=sx;
uCol=sy;
if(delta_x>0)incx=1; //设置单步方向
else if(delta_x==0)incx=0;//垂直线
else {incx=-1;delta_x=-delta_x;}
if(delta_y>0)incy=1;
else if(delta_y==0)incy=0;//水平线
else{incy=-1;delta_y=-delta_y;}
if( delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴
else distance=delta_y;
for(t=0;t<=distance+1;t++ )//画线输出
{
LCD_DrawPoint(uRow,uCol,1);//画点
xerr+=delta_x ;
yerr+=delta_y ;
if(xerr>distance)
{
xerr-=distance;
uRow+=incx;
}
if(yerr>distance)
{
yerr-=distance;
uCol+=incy;
}
}
}
//画矩形
void LCD_DrawRect(u16 sx,u16 sy,u16 width,u16 height)
{
u16 ex = sx + width -1;
u16 ey = sy + height -1;
LCD_DrawLine(sx,sy,ex,sy);
LCD_DrawLine(sx,sy,sx,ey);
LCD_DrawLine(sx,ey,ex,ey);
LCD_DrawLine(ex,sy,ex,ey);
}
//画圆
void LCD_DrawCircle(u16 x0,u16 y0,u8 r)
{
int a,b;
int di;
a=0;b=r;
di=3-(r<<1); //判断下个点位置的标志
while(a<=b)
{
LCD_DrawPoint(x0+b,y0-a,1); //1
LCD_DrawPoint(x0+a,y0-b,1); //2
LCD_DrawPoint(x0-a,y0-b,1); //3
LCD_DrawPoint(x0-b,y0-a,1); //4
LCD_DrawPoint(x0-b,y0+a,1); //5
LCD_DrawPoint(x0-a,y0+b,1); //6
LCD_DrawPoint(x0+a,y0+b,1); //7
LCD_DrawPoint(x0+b,y0+a,1); //8
a++;
//使用Bresenham算法画圆
if(di<0)di +=4*a+6;
else
{
di+=10+4*(a-b);
b--;
}
}
}
//显示一个字符
//x,y 点坐标
//mode:0,反白显示;1,正常显示
//size:选择字体 8、16
void LCD_ShowOneChar(u8 x,u8 y,u8 chr,u8 size,u8 mode)
{
u8 temp,t,t1;
u8 y0=y;
u8 csize=16;
u8* pdata=NULL;
chr=chr-' ';//得到偏移后的值
if(chr > 94) return; //超出范围
//确定字符点阵起始地址和数据个数
if(size == 8)
{
csize = 5;
pdata = (u8*)ascii_table_5x8[chr]; //调用0805字体
}
else if(size == 16)
{
csize = 16;
pdata = (u8*)ascii_table_8x16[chr]; //调用1608字体
}
else return;
//显示字符
for(t=0;t 127) break; //超出范围了
if((str[i] >= 0x20) && (str[i] <= 0x7f))
{
LCD_ShowOneChar(x,y,str[i],size,mode); //是可见字符
}
else
{
LCD_ShowOneChar(x,y,' ',size,mode);//非可见字符显示空格
}
x += xlen; //下一个位置
i++; // 下一个字符
}
}
//显示一个汉字
void LCD_ShowOneHz(u8 x,u8 y,uc8* ptr,u8 size,u8 mode)
{
u8 temp,t1,t;
u16 num=0;
u16 y0=y;
uc8 *pdata=NULL;
u8 csize=(size/8+((size%8)?1:0))*size; //得到字体一个字符对应点阵集所占的字节数
//查找点阵数据
if(size==16)
{
while(GB_1616[num].Index[0] > 0x80)
{
if((*ptr==GB_1616[num].Index[0])&&(*(ptr+1)==GB_1616[num].Index[1])) break;
num++;
if(num > (sizeof(GB_1616) / sizeof(FNT_GB16) - 1)) return; //搜索下标约束
}
pdata = GB_1616[num].Msk;
}
else if(size==32)
{
while(GB_3232[num].Index[0] > 0x80)
{
if((*ptr==GB_3232[num].Index[0])&&(*(ptr+1)==GB_3232[num].Index[1])) break;
num++;
if(num > (sizeof(GB_3232) / sizeof(FNT_GB3211) - 1)) return; //搜索下标约束
}
pdata= GB_3232[num].Msk;
}
else return;
//显示
for(t=0;t0x80))//判断是汉字
{
LCD_ShowOneHz(x,y,pcStr,size,mode);
x+=size;
pcStr+=2;
}
}
/************************************************
函数名称 : LCD_ShowAllString
功 能 : 自适应显示字符和汉字
参 数 : x,y,* ptr,size,mode
x,y:显示坐标
* ptr:显示内容
size:显示尺寸 支持08*05和16*08字符,16*16和32*32汉字
mode:显示模式,1-正常 0-反白
返 回 值 : 无
作 者 : andyLuo
*************************************************/
//显示所有字符和汉字
void LCD_ShowAllString(u8 x,u8 y,uc8* ptr,u8 size,u8 mode)
{
uc8 *pcStr = ptr;
while(*pcStr != '\0')
{
if(*pcStr > 0x7f)
{
LCD_ShowOneHz(x,y,pcStr,size,mode);
pcStr += 2;
x += size;
}else
{
LCD_ShowOneChar(x,y,*pcStr,size,mode);
pcStr++;
x += size/2;
}
}
}
//画单色图标
void LCD_DrawIcon(u8 x,u8 y,uc8* icon,u8 mode)
{
u16 xlen,ylen,csize;
u16 y0=y,i,j;
u8 temp;
if(icon != NULL)
{
xlen = icon[0];
ylen = icon[1];
csize=(ylen/8+((ylen%8)?1:0))*xlen+2;
}
for(i=2;i 127 || y_start > 127 || y_end > 127) return;
if(y_end < y_start)
{
temp = y_end;
y_end = y_start;
y_start = temp;
}
for(;y_start <= y_end;y_start++) LCD_DrawPoint(x,y_start,mode);
}
void LCD_DrawLineY(u8 x_start,u8 x_end,u8 y,u8 mode) //画垂直线
{
u8 temp;
if(x_start > 127 || x_end > 127 || y > 127) return;
if(x_end < x_start)
{
temp = x_end;
x_end = x_start;
x_start = temp;
}
for(;x_start <= x_end;x_start++) LCD_DrawPoint(x_start,y,mode);
}
void LCD_Fill(u8 x_start,u8 y_start,u8 x_end,u8 y_end,u8 mode) //填充
{
u8 i,j;
u8 temp;
if(x_start > 127 || y_start > 127 || x_end > 127 || y_end > 127) return;
if(x_start > x_end)
{
temp = x_start;
x_start = x_end;
x_end = temp;
}
if(y_start > y_end)
{
temp = y_start;
y_start = y_end;
y_end = temp;
}
if(x_start == x_end && y_start == y_end) {LCD_DrawPoint(x_start,y_start,mode);return;}
if(x_start == x_end) {LCD_DrawLineX(x_start,y_start,y_end,mode);return;}
if(y_start == y_end) {LCD_DrawLineY(x_start,x_end,y_start,mode);return;}
for(i = 0;i <= (x_end - x_start);i++)
{
for(j = 0;j <= (y_end - y_start);j++)
{
LCD_DrawPoint(x_start + i,y_start + j,mode);
}
}
}
/**** Copyright (C)2019-2029 中科智博. All Rights Reserved. **** END OF FILE ****/
对应的头文件,h
/**
******************************** STM32F10x *********************************
* @文件名 : lcd.h
* @作者 : Apana
* @库版本 : V3.5.0
* @文件版本 : V1.0.0
* @日期 : 2020-08-17
* @摘要 : lcd驱动库头文件
******************************************************************************/
/* 定义防止递归包含 ----------------------------------------------------------*/
#include "sys.h"
#ifndef __LCD_H_
#define __LCD_H_
/* 定义引脚 ------------------------------------------------------------------*/
#define LCD_RD PBout(13) //LCD读信号
#define LCD_WR PCout(11) //LCD写信号
#define LCD_RS PCout(10) //LCD指令数据控制信号
#define LCD_RESET PCout(9) //LCD复位信号
#define LCD_CS PCout(8) //LCD片选信号
#define LCD_BACK PAout(8) //LCD背光控制
#define LCD_BACK_ON PAout(8)=1 //LCD背光开
#define LCD_BACK_OFF PAout(8)=0 //LCD背光关
void LCD_WRITE(u8 x);//LCD写
void LCD_RefreshGram(void); //更新显存到lcd
void LCD_ClearGram(void); //清除显存
void LCD_ClearGramLine(u8 line1,u8 line2);//清除显存
void LCD_Init(void); //LCD模块初始化
void LCD_DrawPoint(u8 x,u8 y,u8 t); //画点
void LCD_DrawLine(u16 sx,u16 sy,u16 ex,u16 ey); //画线
void LCD_DrawRect(u16 sx,u16 sy,u16 width,u16 height); //画矩形
void LCD_DrawCircle(u16 x0,u16 y0,u8 r); //画圆
void LCD_ShowOneChar(u8 x,u8 y,u8 chr,u8 size,u8 mode); //显示一个字符
void LCD_ShowStrChar(u8 x,u8 y,uc8* str,u8 size,u8 mode); //显示一串字符
void LCD_ShowOneHz(u8 x,u8 y,uc8* ptr,u8 size,u8 mode); //显示一个汉字
void LCD_ShowStrHz(u8 x,u8 y,uc8* ptr,u8 size,u8 mode); //显示一串汉字
void LCD_ShowAllString(u8 x,u8 y,uc8* ptr,u8 size,u8 mode); //显示所有字符和汉字
void LCD_DrawIcon(u8 x,u8 y,uc8* icon,u8 mode); //画单色图标
void LCD_Fill(u8 x_start,u8 y_start,u8 x_end,u8 y_end,u8 mode); //填充
#endif
/**** Copyright (C)2019-2029 中科智博. All Rights Reserved. **** END OF FILE ****/
其中,#include "gbhz.h" 包含了我用取模软件得到的汉字
(不仅可以展示汉字数字等也可以进行显示图案)
#ifndef _GBHZ_H_
#define _GBHZ_H_
//结构体定义
typedef struct typFNT_GB16 // 汉字字模数据结构
{
unsigned char Index[2]; // 汉字内码索引
unsigned char Msk[32]; // 点阵码数据
}FNT_GB16;
typedef struct typeFNT_GB32
{ /* 汉字字模数据结构 */
unsigned char Index[2]; /* 汉字内码索引 */
unsigned char Msk[128]; /* 点阵码数据 */
}FNT_GB32;
// ------------------ 汉字字模的数据结构定义 ------------------------ //
typedef struct typFNT_GB32 // 汉字字模数据结构
{
unsigned char Index[2]; // 汉字内码索引
unsigned char Msk[128]; // 点阵码数据
}FNT_GB3211 ;
/
// 汉字字模表 //
// Font:宋体32, 纵向取模上高位,数据排列:从上到下从左到右 //
/
const FNT_GB3211 GB_3232[] = // 数据表
{
"院", 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x1F,0xFF,0xFF,0xFE,
0x0F,0xFF,0xFF,0xFC,0x08,0x00,0x00,0x00,
0x08,0x00,0x00,0x00,0x08,0x18,0x04,0x00,
0x08,0xE4,0x06,0x00,0x0F,0x83,0x06,0x04,
0x1E,0x01,0xFC,0x04,0x08,0x00,0x78,0x04,
0x00,0xC0,0x80,0x08,0x07,0xC0,0x80,0x10,
0x02,0x08,0x80,0x30,0x02,0x08,0x80,0xE0,
0x02,0x08,0x87,0xC0,0x02,0x08,0xFE,0x00,
0x22,0x08,0x80,0x00,0x12,0x08,0x80,0x00,
0x1E,0x08,0x80,0x00,0x0A,0x08,0xFF,0xF8,
0x02,0x08,0xFF,0xFC,0x02,0x18,0x80,0x0C,
0x02,0x18,0x80,0x04,0x02,0x48,0x80,0x04,
0x03,0x81,0x80,0x04,0x07,0x01,0x80,0x0C,
0x02,0x00,0x01,0xFC,0x00,0x00,0x00,0x08,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
// 汉字表:
const FNT_GB16 GB_1616[] = // 数据表
{
"同", 0x00,0x00,0x7F,0xFF,0x40,0x00,0x48,0x00,
0x49,0xFC,0x49,0x08,0x49,0x08,0x49,0x08,
0x49,0x08,0x49,0x08,0x5B,0xFC,0x49,0x02,
0x40,0x01,0xFF,0xFE,0x40,0x00,0x00,0x00,
"学", 0x02,0x20,0x0C,0x20,0x88,0x20,0x69,0x20,
0x09,0x20,0x09,0x22,0x89,0x21,0x69,0x7E,
0x09,0x60,0x09,0xA0,0x19,0x20,0x28,0x20,
0xC8,0x20,0x0A,0x60,0x0C,0x20,0x00,0x00,
"们", 0x02,0x00,0x04,0x00,0x1F,0xFF,0xE0,0x00,
0x00,0x00,0x1F,0xFF,0x40,0x00,0x20,0x00,
0x10,0x00,0x20,0x00,0x20,0x00,0x20,0x02,
0x20,0x01,0x7F,0xFE,0x20,0x00,0x00,0x00,
"好", 0x08,0x02,0x08,0x44,0x0F,0xA8,0xF8,0x10,
0x08,0x28,0x0F,0xC6,0x01,0x00,0x41,0x00,
0x41,0x02,0x41,0x01,0x47,0xFE,0x49,0x00,
0x51,0x00,0x63,0x00,0x01,0x00,0x00,0x00,
"呀", 0x00,0x00,0x3F,0xF8,0x20,0x10,0x20,0x10,
0x7F,0xF0,0x20,0x08,0x41,0x08,0x47,0x10,
0x59,0x10,0x41,0x22,0x41,0x41,0x7F,0xFE,
0xC1,0x00,0x43,0x00,0x01,0x00,0x00,0x00
};
此为本人学校实训所学习的知识,欢迎大佬指点!