📄 lcd_driver.c
字号:
# include "LCD_Driver.h"
# include "Delay.h"
# include "LCD_Driver.h"
# include "MyUSART.h"
////////////////////////////////////////////////////////////////////////////////
//数据输出,包括寄存器内容和GRAM数据内容
//将用宏定义代替,说明:
// LCD_DATA_OUT()将一个16位数据输出到数据总线,
//被写寄存器和写GRAM(写像素点)的函数调用,移植时
//根据数据接口是8位或16位更改该函数(或称宏定义)
////////////////////////////////////////////////////////////////////////////////
void LCD_DATA_OUT(u16 data)
{
/*
//默认为8位数据端口写高8位
DATA_L_PORT = (unsigned char)(data>>8);
LCD_WR_L;
LCD_WR_H;
//写低8位
DATA_L_PORT = (unsigned char)data;
LCD_WR_L;
LCD_WR_H;
*/
//16位数据接口
DATAOUT(data);
LCD_WR_L;
LCD_WR_H;
}
////////////////////////////////////////////////////////////////////////////////
//数据输入,包括寄存器内容和GRAM数据内容
//说明:
// LCD_DATA_IN()将一个16位数据从数据总线上读取
//被读寄存器和读GRAM(读像素点)的函数调用,移植时
//根据数据接口是8位或16位更改该函数(可用内联函数)
////////////////////////////////////////////////////////////////////////////////
u16 LCD_DATA_IN(void)
{
u16 temp = 0;
/*
DATA_L_IN;
LCD_RD_L; //读有效
LCD_RD_H;
temp = DATA_L_PIN; //读取高字节
LCD_RD_L; //读有效
LCD_RD_H;
temp <<= 8;
temp |= DATA_L_PIN; //读取低字节
DATA_L_OUT;
*/
//置为输入
GPIOC->CRL = 0x88888888; //PC0-7 上拉输入
GPIOB->CRH = 0X88888888; // PB8-15上拉输入
GPIOB->ODR |= 0XFF00; //全部输出高
GPIOC->ODR |= 0X00FF;
LCD_RD_L; //读有效
LCD_RD_H;
temp = DATAIN;
GPIOC->CRL = 0X33333333; //PC0-7 上拉输出
GPIOB->CRH = 0X33333333; //PB8-15 上拉输出
GPIOB->ODR |= 0XFF00; //全部输出高
GPIOC->ODR |= 0X00FF;
return temp;
}
//写LCD缓存命令,视需要更改0x0022的值,一般LCD驱动
//IC都使用的该命令
void LCD_WriteGRAM_EN(void)
{
LCD_CS_L; //选中片选
LCD_RS_L; //命令读写控制RS->0有效
LCD_DATA_OUT(0x0022); //写入寄存器地址
LCD_RS_H;
}
//读LCD缓存命令,视需要更改0x0022的值,一般LCD驱动
//IC都使用的该命令
void LCD_ReadGRAM_EN(void)
{
LCD_CS_L; //选中片选
LCD_RS_L; //命令读写控制RS->0有效
LCD_DATA_OUT(0x0022); //写入寄存器地址
LCD_RS_H;
}
////////////////////////////////////////////////////////////////////////////////
// LCD_SetCursor ->设置读写指针
// 该函数在移植时视需要修改,一般驱动IC使用了20H
//和21H分别设置GARM的x和y地址
////////////////////////////////////////////////////////////////////////////////
void LCD_SetCursor(u16 x,u16 y)
{ // *-------->x
LCD_WriteRegister(0x0020, x); // 行 | (H 127)
LCD_WriteRegister(0x0021, y); // 列 |
/////////////////////////////// |
//R61514屏没有20H寄存器,xy坐标通过21H寄存器转化 |
//完成,公式:y*256 + x,参见手册R21H寄存器描述 V(V 159)
# if R61514_EN > 0
LCD_WriteRegister(0x0021,(y << 8) + x);
# endif
}
////////////////////////////////////////////////////////////////////////////////
// LCD_WriteRegister()->写寄存器
// 写寄存器,LCD i80接口标准,RS为低时写寄存器IR
//(寄存器指针),将index的值赋给他;RS为高时写数据,
//将data的值赋给IR指向的寄存器,该函数是i80接口上
//层应用,移植时不用修改
////////////////////////////////////////////////////////////////////////////////
void LCD_WriteRegister(u16 index, u16 data)
{
////////////////////////////////////////////////////////////////////////////////
// 对于8位模式,则数据端口要进行两次操作,下图是16位模式情况下的操作 //
// nCS ----\__________________________________________/------- //
// RS ------\____________/----------------------------------- //
// nRD ------------------------------------------------------- //
// nWR --------\_______/--------\_____/----------------------- //
// DB[0:15] ---------[index]----------[data]----------------------- //
// //
////////////////////////////////////////////////////////////////////////////////
LCD_CS_L; //选中片选
LCD_RS_L; //命令读写控制RS->0有效
LCD_DATA_OUT(index); //先写入寄存器地址
LCD_RS_H; //数据读写控制RS->1有效
LCD_DATA_OUT(data);
LCD_CS_H; //关闭片选
}
////////////////////////////////////////////////////////////////////////////////
// LCD_ReadRegister()->读寄存器
// 读寄存器,LCD i80接口标准,RS为低时写寄存器IR
//(寄存器指针),将index的值赋给他;RS为高时读数据,
//将data的值赋给IR指向的寄存器,该函数是i80接口上
//层应用,移植时不用修改
////////////////////////////////////////////////////////////////////////////////
u16 LCD_ReadRegister(u16 index)
{
////////////////////////////////////////////////////////////////////////////////
// 对于8位模式,则数据端口要进行两次操作,下图是16位模式情况下的操作 //
// nCS ----\__________________________________________/------- //
// RS ------\____________/----------------------------------- //
// nRD -------------------------\_____/----------------------- //
// nWR --------\_______/-------------------------------------- //
// DB[0:15] ---------[index]----------[data]----------------------- //
// //
////////////////////////////////////////////////////////////////////////////////
u16 temp = 0;
LCD_CS_L; //选中片选
LCD_RS_L; //命令读写控制RS->0有效
LCD_DATA_OUT(index); //写入寄存器地址
LCD_RS_H; //数据读写控制RS->1有效
temp = LCD_DATA_IN();
LCD_CS_H; //关闭片选
return temp;
}
////////////////////////////////////////////////////////////////////////////////
// LCD_DrawPoint()->画点函数
// 该函数先设置GARM地址,然后发送写命令,接着再将
//color的值赋给GRAM中对应的地址.该函数是上层应用
//移植时不用修改
////////////////////////////////////////////////////////////////////////////////
void LCD_DrawPoint(u16 x, u16 y, u16 color)
{
if ((x > X_END) || (y > Y_END)) //显示不能超过最大坐标值
{
return;
}
LCD_SetCursor(x, y);
LCD_WriteGRAM_EN();
LCD_DATA_OUT(color);
LCD_WR_END();
}
////////////////////////////////////////////////////////////////////////////////
// LCD_GetPoint()->读点函数
// 该函数先设置GARM地址,然后发送写命令,接着是一
//个哑操作,该哑操作根据8位或16位接口需要更改宏定
//义.该函数是上层应用移植时不用修改
////////////////////////////////////////////////////////////////////////////////
u16 LCD_GetPoint(u16 x, u16 y)
{
////////////////////////////////////////////////////////////////////////////////
// 对于8位模式,则数据端口要进行两次操作,下图是16位模式情况下的操作 //
// nCS ----\__________________________________________/------- //
// RS ------\____________/----------------------------------- //
// nRD -------------------------\_____/------\_____/---------- //
// nWR --------\_______/-------------------------------------- //
// DB[0:15] ---------[Address]-------[Dummy]-------[data]---------- //
// 注意:在读GRAM时,要先设置读地址,再写读命令,然后是Dummy Read,最后 //
// 才是数据。同时,在8位模式下,Dummy Read 是一个Word的时间,意味//
// 着RD要产生2次上升沿,最后读回来的数据还要进行转换 //
////////////////////////////////////////////////////////////////////////////////
u16 temp_color = 0;
u16 temp = 0;
LCD_SetCursor(x,y);
LCD_ReadGRAM_EN();
DUMMY_READ(); //第一次不读
temp_color = LCD_DATA_IN();
LCD_WR_END();
temp = temp_color >> 11; //RRRRRGGGGGGBBBBB 改为
temp |= temp_color << 11; //BBBBBGGGGGGRRRRR 格式
temp |= (temp_color & 0x07E0); //0000011111100000 = 0x07E0
return temp;
}
////////////////////////////////////////////////////////////////////////////////
// LCD_SetWindow()->设置GRAM窗口
// 该函数对于块写很有用,用户只需设置好块写区域
//然后一次给设置GRAM区域写数据即可,GC指针会自动
//增加而无需用户更改,这样就提高了写效率.读数据时
//GC不会自动增加(GC->GRAM Counter)
////////////////////////////////////////////////////////////////////////////////
void LCD_SetWindow(u16 start_x,u16 start_y,
u16 end_x,u16 end_y)
{
LCD_WriteRegister(0x0050, start_x);
LCD_WriteRegister(0x0052, start_y);
LCD_WriteRegister(0x0051, end_x);
LCD_WriteRegister(0x0053, end_y);
//驱动ICR61514->设置GARM地址
////////////////////////////////////////
# if R61514_EN > 0
end_x <<= 8; //高8位是垂直结束地址
end_x |= (unsigned char)start_x;//低8位是垂直开始地址(水平GRAM地址也是如此 )
end_y <<= 8;
end_y |= (unsigned char)start_y;
LCD_WriteRegister(0x0044, end_x);
LCD_WriteRegister(0x0045, end_y);
# endif
LCD_SetCursor(start_x, start_y);//设置起始绘图的GRAM地址
}
//LCD清屏函数
void LCD_Clear(u16 color)
{
unsigned long i;
LCD_SetWindow(0, 0, X_END, Y_END);
LCD_WriteGRAM_EN();
for(i=0; i< X_SIZE*Y_SIZE; i++) //R61514为128*160
{
LCD_DATA_OUT(color);
}
LCD_WR_END();
LCD_SetWindow(0,0, X_END, Y_END); //恢复全局作图区
}
//填充一个矩形区域
void LCD_Fill(u16 start_x,u16 start_y,
u16 end_x,u16 end_y,
u16 color)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -