#include "lcd8.h"
#include "stdlib.h"
#include "font.h"
#include "usart.h"
#include "delay.h"
//LCD的画笔颜色和背景色
u16 POINT_COLOR=0x0000; //画笔颜色
u16 BACK_COLOR=0xFFFF; //背景色
//管理LCD重要参数
//默认为竖屏
_lcd_dev lcddev;
//写寄存器函数
//regval:寄存器值
void LCD_WR_REG(vu8 regval)
{
u8 a=0;
LCD_RS=0;//写地址
LCD_CS=0;
a=regval;
GPIOA->ODR|=a;
LCD_WR=0;
LCD_WR=1;
LCD_CS=1;
GPIOA->ODR&=~0x00FF;
}
//写LCD数据
//data:要写入的值
void LCD_WR_DATA(vu8 data)
{
u8 a=0;
LCD_RS=1;
LCD_CS=0;
a=data;
GPIOA->ODR|=a;
LCD_WR=0;
LCD_WR=1;
LCD_CS=1;
GPIOA->ODR&=~0x00FF;
}
void LCD_WR_DATAX(u16 data)
{
u16 a=0;
a=data;
GPIOA->ODR&=~0x00FF;
LCD_RS=1;
LCD_CS=0;
GPIOA->ODR|=a>>8;
LCD_WR=0;
LCD_WR=1;
GPIOA->ODR&=~0x00FF;
GPIOA->ODR|=a;
LCD_WR=0;
LCD_WR=1;
LCD_CS=1;
GPIOA->ODR&=~0x00FF;
}
//读LCD数据
//返回值:读到的值
u16 LCD_RD_DATA(void)
{
u8 t;
GPIO_Set(GPIOA,PIN0|PIN1|PIN2|PIN3|PIN4|PIN5|PIN6|PIN7,GPIO_MODE_IN,0,0,GPIO_PUPD_PU); //设置上拉输入
GPIOA->ODR|=0x0000; //全部输出0
LCD_RS=1;
LCD_CS=0;
LCD_RD=0;
t=GPIOA->IDR&0xff;
LCD_RD=1;
LCD_CS=1;
GPIO_Set(GPIOA,PIN0|PIN1|PIN2|PIN3|PIN4|PIN5|PIN6|PIN7,GPIO_MODE_OUT,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU); //设置上拉输出
GPIOA->ODR|=0x00ff; //全部输出高
return t;
}
//写寄存器
//LCD_Reg:寄存器地址
//LCD_RegValue:要写入的数据
void LCD_WriteReg(u16 LCD_Reg,u16 LCD_RegValue)
{
LCD_WR_REG(LCD_Reg);
LCD_WR_DATA(LCD_RegValue);
}
//读寄存器
//LCD_Reg:寄存器地址
//返回值:读到的数据
u16 LCD_ReadReg(u16 LCD_Reg)
{
LCD_WR_REG(LCD_Reg); //写入要读的寄存器序号
delay_us(5);
return LCD_RD_DATA(); //返回读到的值
}
//开始写GRAM
void LCD_WriteRAM_Prepare(void)
{
LCD_WR_REG(0x2C);
}
//LCD写GRAM
//RGB_Code:颜色值
void LCD_WriteRAM(u16 RGB_Code)
{
LCD_WR_DATAX(RGB_Code);//写十六位GRAM
}
//从ILI93xx读出的数据为GBR格式,而我们写入的时候为RGB格式。
//通过该函数转换
//c:GBR格式的颜色值
//返回值:RGB格式的颜色值
u16 LCD_BGR2RGB(u16 c)
{
u16 r,g,b,rgb;
b=(c>>0)&0x1f;
g=(c>>5)&0x3f;
r=(c>>11)&0x1f;
rgb=(b<<11)+(g<<5)+(r<<0);
return(rgb);
}
//当mdk -O1时间优化时需要设置
//延时i
void opt_delay(u8 i)
{
while(i--);
}
//读取个某点的颜色值
//x,y:坐标
//返回值:此点的颜色
u16 LCD_ReadPoint(u16 x,u16 y)
{
u16 r=0,g=0,b=0;
if(x>=lcddev.width||y>=lcddev.height)return 0; //超过了范围,直接返回
LCD_SetCursor(x,y); //设置光标位置
LCD_WR_REG(0X2E);//9341 发送读GRAM指令
LCD_RD_DATA();
opt_delay(2);
r=LCD_RD_DATA(); //实际坐标颜色
{
opt_delay(2);
b=LCD_RD_DATA();
g=r&0XFF; //对于9341,第一次读取的是RG的值,R在前,G在后,各占8位
g<<=8;
}
return (((r>>11)<<11)|((g>>10)<<5)|(b>>11));//ILI9341需要公式转换一下
}
//LCD开启显示
void LCD_DisplayOn(void)
{
LCD_WR_REG(0X29); //开启显示
}
//LCD关闭显示
void LCD_DisplayOff(void)
{
LCD_WR_REG(0X28); //关闭显示
}
//设置光标位置
//Xpos:横坐标
//Ypos:纵坐标
void LCD_SetCursor(u16 Xpos, u16 Ypos)
{
LCD_WR_REG(0x2A);
LCD_WR_DATA(Xpos>>8);
LCD_WR_DATA(Xpos&0XFF);
LCD_WR_REG(0x2B);
LCD_WR_DATA(Ypos>>8);
LCD_WR_DATA(Ypos&0XFF);
LCD_WriteReg(0x2A, Xpos);
LCD_WriteReg(0x2B, Ypos);
}
//设置LCD的自动扫描方向
//注意:其他函数可能会受到此函数设置的影响(尤其是9341/6804这两个奇葩),
//所以,一般设置为L2R_U2D即可,如果设置为其他扫描方式,可能导致显示不正常.
//dir:0~7,代表8个方向(具体定义见lcd.h)
//9320/9325/9328/4531/4535/1505/b505/5408/9341/5310/5510/1963等IC已经实际测试
void LCD_Scan_Dir(u8 dir)
{
u16 regval=0;
u16 dirreg=0;
switch(dir)
{
case L2R_U2D://从左到右,从上到下
regval|=(0<<7)|(0<<6)|(0<<5);
break;
case L2R_D2U://从左到右,从下到上
regval|=(1<<7)|(0<<6)|(0<<5);
break;
case R2L_U2D://从右到左,从上到下
regval|=(0<<7)|(1<<6)|(0<<5);
break;
case R2L_D2U://从右到左,从下到上
regval|=(1<<7)|(1<<6)|(0<<5);
break;
case U2D_L2R://从上到下,从左到右
regval|=(0<<7)|(0<<6)|(1<<5);
break;
case U2D_R2L://从上到下,从右到左
regval|=(0<<7)|(1<<6)|(1<<5);
break;
case D2U_L2R://从下到上,从左到右
regval|=(1<<7)|(0<<6)|(1<<5);
break;
case D2U_R2L://从下到上,从右到左
regval|=(1<<7)|(1<<6)|(1<<5);
break;
}
dirreg=0X03;
regval|=1<<12;
LCD_WriteReg(dirreg,regval);
}
//画点
//x,y:坐标
//POINT_COLOR:此点的颜色
void LCD_DrawPoint(u16 x,u16 y)
{
LCD_SetCursor(x,y); //设置光标位置
LCD_WriteRAM_Prepare(); //开始写入GRAM
LCD_WR_DATAX(POINT_COLOR);
}
//快速画点
//x,y:坐标
//color:颜色
void LCD_Fast_DrawPoint(u16 x,u16 y,u16 color)
{
LCD_WR_REG(0x2A);
LCD_WR_DATA(x>>8);
LCD_WR_DATA(x&0XFF);
LCD_WR_REG(0x2B);
LCD_WR_DATA(y>>8);
LCD_WR_DATA(y&0XFF);
LCD_WR_REG(0x2C);
LCD_WR_DATAX(color);
}
//设置LCD显示方向
//dir:0,竖屏;1,横屏
void LCD_Display_Dir(u8 dir)
{
lcddev.width=240;//宽
lcddev.height=320;//高
LCD_Scan_Dir(DFT_SCAN_DIR); //默认扫描方向
}
//设置窗口,并自动设置画点坐标到窗口左上角(sx,sy).
//sx,sy:窗口起始坐标(左上角)
//width,height:窗口宽度和高度,必须大于0!!
//窗体大小:width*height.
void LCD_Set_Window(u16 sx,u16 sy,u16 width,u16 height)
{
u8 hsareg,heareg,vsareg,veareg;
u16 hsaval,heaval,vsaval,veaval;
u16 twidth,theight;
twidth=sx+width-1;
theight=sy+height-1;
LCD_WR_REG(0x2A);
LCD_WR_DATA(sx>>8);
LCD_WR_DATA(sx&0XFF);
LCD_WR_DATA(twidth>>8);
LCD_WR_DATA(twidth&0XFF);
LCD_WR_REG(0x2B);
LCD_WR_DATA(sy>>8);
LCD_WR_DATA(sy&0XFF);
LCD_WR_DATA(theight>>8);
LCD_WR_DATA(theight&0XFF);
hsareg=0X50;heareg=0X51;//水平方向窗口寄存器
vsareg=0X52;veareg=0X53;//垂直方向窗口寄存器
//设置寄存器值
LCD_WriteReg(hsareg,hsaval);
LCD_WriteReg(heareg,heaval);
LCD_WriteReg(vsareg,vsaval);
LCD_WriteReg(veareg,veaval);
LCD_SetCursor(sx,sy); //设置光标位置
}
//初始化lcd
//该初始化函数可以初始化各种型号的LCD(详见本.c文件最前面的描述)
void LCD_Init(void)
{
RCC->AHB1ENR|=1<<0; //使能PA时钟
RCC->AHB1ENR|=1<<1; //使能PB时钟
RCC->AHB1ENR|=1<<2; //使能PC时钟
GPIO_Set(GPIOA,PIN0|PIN1|PIN2|PIN3|PIN4|PIN5|PIN6|PIN7,GPIO_MODE_OUT,GPIO_OTYPE_PP,GPIO_SPEED_50M,GPIO_PUPD_PU); //PA设置
GPIO_Set(GPIOB,PIN6|PIN7|PIN10,GPIO_MODE_OUT,GPIO_OTYPE_PP,GPIO_SPEED_50M,GPIO_PUPD_PU);
GPIO_Set(GPIOC,PIN0|PIN1|PIN13,GPIO_MODE_OUT,GPIO_OTYPE_PP,GPIO_SPEED_50M,GPIO_PUPD_PU);
delay_ms(50); // delay 50 ms
LCD_WR_REG(0x01);
LCD_WR_REG(0x00);
delay_ms(50); // delay 50 ms
{
//尝试9341 ID的读取
LCD_WR_REG(0XD3);
LCD_RD_DATA(); //dummy read
LCD_RD_DATA(); //读到0X00
lcddev.id=LCD_RD_DATA(); //读取93
lcddev.id<<=8;
lcddev.id|=LCD_RD_DATA(); //读取41
}
printf(" LCD ID:%x\r\n",lcddev.id); //打印LCD ID
{
LCD_WR_REG(0xCF); //功耗控制B
LCD_WR_DATA(0x00);
LCD_WR_DATA(0xC1);
LCD_WR_DATA(0X30);
LCD_WR_REG(0xED); //电源序列控制
LCD_WR_DATA(0x64);
LCD_WR_DATA(0x03);
LCD_WR_DATA(0X12);
LCD_WR_DATA(0X81);
LCD_WR_REG(0xE8); //驱动时序控制A
LCD_WR_DATA(0x85);
LCD_WR_DATA(0x10);
LCD_WR_DATA(0x7A);
LCD_WR_REG(0xCB); //功耗控制A
LCD_WR_DATA(0x39);
LCD_WR_DATA(0x2C);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x34);
LCD_WR_DATA(0x02);
LCD_WR_REG(0xF7); //泵比控制
LCD_WR_DATA(0x20);
LCD_WR_REG(0xEA); //驱动时序控制B
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_REG(0xC0); //Power control 功耗控制1
LCD_WR_DATA(0x1B); //VRH[5:0]
LCD_WR_REG(0xC1); //Power control 功耗控制2
LCD_WR_DATA(0x01); //SAP[2:0];BT[3:0]
LCD_WR_REG(0xC5);
评论4