Today I want to touch a screen, and originally wanted to use SPI driver, but considering whether it can be driven, I still choose analog pin driver. Because my screen has some fragmented things, which cannot be done by pure SPI.
My pin assignment is printed on the back of the screen, so I had to figure out the pin correspondence:
CS ------------ P5.7
DC------------- P0.5
RES------------ P0.2
MOS------------ P0.3
CLK------------- P0.4
BLK------------- P5.6
Another power ground, connect the 3.3V power supply and GND of the development board
Here is the procedure:
lcd.h:
#ifndef __LCD_INIT_H
#define __LCD_INIT_H
#include <rtthread.h>
#include <rtdevice.h>
#include "drv_gpio.h"
#define USE_HORIZONTAL 1 //设置横屏或者竖屏显示 0或1为竖屏 2或3为横屏
#if USE_HORIZONTAL==0||USE_HORIZONTAL==1
#define LCD_W 128
#define LCD_H 160
#else
#define LCD_W 160
#define LCD_H 128
#endif
#define u8 unsigned char
#define u16 unsigned int
#define LCD_CS GET_PIN(5, 7)//SCLK
#define LCD_SDA GET_PIN(0, 3)//MOSI
#define LCD_RES GET_PIN(0, 2)//RES
#define LCD_DC GET_PIN(0, 5)//DC
#define LCD_CLK GET_PIN(0, 4)
#define LCD_BLK GET_PIN(5, 6)
//sbit LCD_BLK=P0^4; //BLK
//sbit LCD_CS =P0^6; //CS1
//-----------------LCD端口定义----------------
#define LCD_SCLK_Clr() rt_pin_write(LCD_CLK, PIN_LOW)
#define LCD_SCLK_Set() rt_pin_write(LCD_CLK, PIN_HIGH)
#define LCD_MOSI_Clr() rt_pin_write(LCD_SDA, PIN_LOW)
#define LCD_MOSI_Set() rt_pin_write(LCD_SDA, PIN_HIGH)
#define LCD_RES_Clr() rt_pin_write(LCD_RES, PIN_LOW)//RES
#define LCD_RES_Set() rt_pin_write(LCD_RES, PIN_HIGH)
#define LCD_DC_Clr() rt_pin_write(LCD_DC, PIN_LOW)//DC
#define LCD_DC_Set() rt_pin_write(LCD_DC, PIN_HIGH)
#define LCD_BLK_Clr() rt_pin_write(LCD_BLK, PIN_LOW)//BLK
#define LCD_BLK_Set() rt_pin_write(LCD_BLK, PIN_HIGH)
#define LCD_CS_Clr() rt_pin_write(LCD_CS, PIN_LOW)//CS1
#define LCD_CS_Set() rt_pin_write(LCD_CS, PIN_HIGH)
void delay_ms(unsigned int ms);//不准确延时函数
void LCD_GPIO_Init(void);//初始化GPIO
void LCD_Writ_Bus(u8 dat);//模拟SPI时序
void LCD_WR_DATA8(u8 dat);//写入一个字节
void LCD_WR_DATA(u16 dat);//写入两个字节
void LCD_WR_REG(u8 dat);//写入一个指令
void LCD_Address_Set(u16 x1,u16 y1,u16 x2,u16 y2);//设置坐标函数
void LCD_Init(void);//LCD初始化
#endif
lcd.c
include "lcd.h"
#include "lcd_init.h"
#include "lcdfont.h"
#include "delay.h"
/******************************************************************************
oˉêyμ÷£oú¨óòì3é
èúêyY£oxsta,ysta eê×±ê
xend,yend 1×±ê
color òaì3μé
·μμ£o T
******************************************************************************/
void LCD_Fill(u16 xsta,u16 ysta,u16 xend,u16 yend,u16 color)
{
u16 i,j;
LCD_Address_Set(xsta,ysta,xend-1,yend-1);//éèê·§
for(i=ysta;i<yend;i++)
{
for(j=xsta;j<xend;j++)
{
LCD_WR_DATA(color);
}
}
}
/******************************************************************************
oˉêyμ÷£oú¨-μ
èúêyY£ox,y -μ×±ê
color μμé
·μμ£o T
******************************************************************************/
void LCD_DrawPoint(u16 x,u16 y,u16 color)
{
LCD_Address_Set(x,y,x,y);//éè1a±ê
LCD_WR_DATA(color);
}
/******************************************************************************
oˉêyμ÷£o-
èúêyY£ox1,y1 eê×±ê
x2,y2 1×±ê
color μé
·μμ£o T
******************************************************************************/
void LCD_DrawLine(u16 x1,u16 y1,u16 x2,u16 y2,u16 color)
{
u16 t;
int xerr=0,yerr=0,delta_x,delta_y,distance;
int incx,incy,uRow,uCol;
delta_x=x2-x1; //×±êá
delta_y=y2-y1;
uRow=x1;//-eμ×±ê
uCol=y1;
if(delta_x>0)incx=1; //éèμ¥2·ò
else if (delta_x==0)incx=0;//′1±
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,color);//-μ
xerr+=delta_x;
yerr+=delta_y;
if(xerr>distance)
{
xerr-=distance;
uRow+=incx;
}
if(yerr>distance)
{
yerr-=distance;
uCol+=incy;
}
}
}
/******************************************************************************
oˉêyμ÷£o-D
èúêyY£ox1,y1 eê×±ê
x2,y2 1×±ê
color Dμé
·μμ£o T
******************************************************************************/
void LCD_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2,u16 color)
{
LCD_DrawLine(x1,y1,x2,y1,color);
LCD_DrawLine(x1,y1,x1,y2,color);
LCD_DrawLine(x1,y2,x2,y2,color);
LCD_DrawLine(x2,y1,x2,y2,color);
}
/******************************************************************************
oˉêyμ÷£o-2
èúêyY£ox0,y0 2D×±ê
r °
color 2μé
·μμ£o T
******************************************************************************/
void Draw_Circle(u16 x0,u16 y0,u8 r,u16 color)
{
int a,b;
a=0;b=r;
while(a<=b)
{
LCD_DrawPoint(x0-b,y0-a,color); //3
LCD_DrawPoint(x0+b,y0-a,color); //0
LCD_DrawPoint(x0-a,y0+b,color); //1
LCD_DrawPoint(x0-a,y0-b,color); //2
LCD_DrawPoint(x0+b,y0+a,color); //4
LCD_DrawPoint(x0+a,y0-b,color); //5
LCD_DrawPoint(x0+a,y0+b,color); //6
LCD_DrawPoint(x0-b,y0+a,color); //7
a++;
if((a*a+b*b)>(r*r))//Dòa-μμê·1y
{
b--;
}
}
}
/******************************************************************************
oˉêyμ÷£oêoo×′
èúêyY£ox,yê×±ê
*s òaêμoo×′
fc ×μé
bc ×μ±3°é
sizey ×o é 16 24 32
mode: 0·μtó£ê 1μtó£ê
·μμ£o T
******************************************************************************/
void LCD_ShowChinese(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode)
{
while(*s!=0)
{
if(sizey==12) LCD_ShowChinese12x12(x,y,s,fc,bc,sizey,mode);
else if(sizey==16) LCD_ShowChinese16x16(x,y,s,fc,bc,sizey,mode);
else if(sizey==24) LCD_ShowChinese24x24(x,y,s,fc,bc,sizey,mode);
else if(sizey==32) LCD_ShowChinese32x32(x,y,s,fc,bc,sizey,mode);
else return;
s+=2;
x+=sizey;
}
}
/******************************************************************************
oˉêyμ÷£oêμ¥12x12oo×
èúêyY£ox,yê×±ê
*s òaêμoo×
fc ×μé
bc ×μ±3°é
sizey ×o
mode: 0·μtó£ê 1μtó£ê
·μμ£o T
******************************************************************************/
void LCD_ShowChinese12x12(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode)
{
u8 i,j,m=0;
u16 k;
u16 HZnum;//oo×êy
u16 TypefaceNum;//ò×·ù×ú′óD
u16 x0=x;
TypefaceNum=(sizey/8+((sizey%8)?1:0))*sizey;
HZnum=sizeof(tfont12)/sizeof(typFNT_GB12); //í3oo×êy
for(k=0;k<HZnum;k++)
{
if((tfont12[k].Index[0]==*(s))&&(tfont12[k].Index[1]==*(s+1)))
{
LCD_Address_Set(x,y,x+sizey-1,y+sizey-1);
for(i=0;i<TypefaceNum;i++)
{
for(j=0;j<8;j++)
{
if(!mode)//·μtó·ê
{
if(tfont12[k].Msk[i]&(0x01<<j))LCD_WR_DATA(fc);
else LCD_WR_DATA(bc);
m++;
if(m%sizey==0)
{
m=0;
break;
}
}
else//μtó·ê
{
if(tfont12[k].Msk[i]&(0x01<<j)) LCD_DrawPoint(x,y,fc);//-òμ
x++;
if((x-x0)==sizey)
{
x=x0;
y++;
break;
}
}
}
}
}
continue; //2éòμó|μó×aá¢′í3£·à1àoo×′è£′à′ó°ì
}
}
/******************************************************************************
oˉêyμ÷£oêμ¥16x16oo×
èúêyY£ox,yê×±ê
*s òaêμoo×
fc ×μé
bc ×μ±3°é
sizey ×o
mode: 0·μtó£ê 1μtó£ê
·μμ£o T
******************************************************************************/
void LCD_ShowChinese16x16(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode)
{
u8 i,j,m=0;
u16 k;
u16 HZnum;//oo×êy
u16 TypefaceNum;//ò×·ù×ú′óD
u16 x0=x;
TypefaceNum=(sizey/8+((sizey%8)?1:0))*sizey;
HZnum=sizeof(tfont16)/sizeof(typFNT_GB16); //í3oo×êy
for(k=0;k<HZnum;k++)
{
if ((tfont16[k].Index[0]==*(s))&&(tfont16[k].Index[1]==*(s+1)))
{
LCD_Address_Set(x,y,x+sizey-1,y+sizey-1);
for(i=0;i<TypefaceNum;i++)
{
for(j=0;j<8;j++)
{
if(!mode)//·μtó·ê
{
if(tfont16[k].Msk[i]&(0x01<<j))LCD_WR_DATA(fc);
else LCD_WR_DATA(bc);
m++;
if(m%sizey==0)
{
m=0;
break;
}
}
else//μtó·ê
{
if(tfont16[k].Msk[i]&(0x01<<j)) LCD_DrawPoint(x,y,fc);//-òμ
x++;
if((x-x0)==sizey)
{
x=x0;
y++;
break;
}
}
}
}
}
continue; //2éòμó|μó×aá¢′í3£·à1àoo×′è£′à′ó°ì
}
}
/******************************************************************************
oˉêyμ÷£oêμ¥24x24oo×
èúêyY£ox,yê×±ê
*s òaêμoo×
fc ×μé
bc ×μ±3°é
sizey ×o
mode: 0·μtó£ê 1μtó£ê
·μμ£o T
******************************************************************************/
void LCD_ShowChinese24x24(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode)
{
u8 i,j,m=0;
u16 k;
u16 HZnum;//oo×êy
u16 TypefaceNum;//ò×·ù×ú′óD
u16 x0=x;
TypefaceNum=(sizey/8+((sizey%8)?1:0))*sizey;
HZnum=sizeof(tfont24)/sizeof(typFNT_GB24); //í3oo×êy
for(k=0;k<HZnum;k++)
{
if ((tfont24[k].Index[0]==*(s))&&(tfont24[k].Index[1]==*(s+1)))
{
LCD_Address_Set(x,y,x+sizey-1,y+sizey-1);
for(i=0;i<TypefaceNum;i++)
{
for(j=0;j<8;j++)
{
if(!mode)//·μtó·ê
{
if(tfont24[k].Msk[i]&(0x01<<j))LCD_WR_DATA(fc);
else LCD_WR_DATA(bc);
m++;
if(m%sizey==0)
{
m=0;
break;
}
}
else//μtó·ê
{
if(tfont24[k].Msk[i]&(0x01<<j)) LCD_DrawPoint(x,y,fc);//-òμ
x++;
if((x-x0)==sizey)
{
x=x0;
y++;
break;
}
}
}
}
}
continue; //2éòμó|μó×aá¢′í3£·à1àoo×′è£′à′ó°ì
}
}
/******************************************************************************
oˉêyμ÷£oêμ¥32x32oo×
èúêyY£ox,yê×±ê
*s òaêμoo×
fc ×μé
bc ×μ±3°é
sizey ×o
mode: 0·μtó£ê 1μtó£ê
·μμ£o T
******************************************************************************/
void LCD_ShowChinese32x32(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode)
{
u8 i,j,m=0;
u16 k;
u16 HZnum;//oo×êy
u16 TypefaceNum;//ò×·ù×ú′óD
u16 x0=x;
TypefaceNum=(sizey/8+((sizey%8)?1:0))*sizey;
HZnum=sizeof(tfont32)/sizeof(typFNT_GB32); //í3oo×êy
for(k=0;k<HZnum;k++)
{
if ((tfont32[k].Index[0]==*(s))&&(tfont32[k].Index[1]==*(s+1)))
{
LCD_Address_Set(x,y,x+sizey-1,y+sizey-1);
for(i=0;i<TypefaceNum;i++)
{
for(j=0;j<8;j++)
{
if(!mode)//·μtó·ê
{
if(tfont32[k].Msk[i]&(0x01<<j))LCD_WR_DATA(fc);
else LCD_WR_DATA(bc);
m++;
if(m%sizey==0)
{
m=0;
break;
}
}
else//μtó·ê
{
if(tfont32[k].Msk[i]&(0x01<<j)) LCD_DrawPoint(x,y,fc);//-òμ
x++;
if((x-x0)==sizey)
{
x=x0;
y++;
break;
}
}
}
}
}
continue; //2éòμó|μó×aá¢′í3£·à1àoo×′è£′à′ó°ì
}
}
/******************************************************************************
oˉêyμ÷£oêμ¥×·
èúêyY£ox,yê×±ê
num òaêμ×·
fc ×μé
bc ×μ±3°é
sizey ×o
mode: 0·μtó£ê 1μtó£ê
·μμ£o T
******************************************************************************/
void LCD_ShowChar(u16 x,u16 y,u8 num,u16 fc,u16 bc,u8 sizey,u8 mode)
{
u8 temp,sizex,t,m=0;
u16 i,TypefaceNum;//ò×·ù×ú′óD
u16 x0=x;
sizex=sizey/2;
TypefaceNum=(sizex/8+((sizex%8)?1:0))*sizey;
num=num-' '; //μμòoóμμ
LCD_Address_Set(x,y,x+sizex-1,y+sizey-1); //éè1a±ê
for(i=0;i<TypefaceNum;i++)
{
if(sizey==12)temp=ascii_1206[num][i]; //μ÷ó6x12×ì
else if(sizey==16)temp=ascii_1608[num][i]; //μ÷ó8x16×ì
else if(sizey==24)temp=ascii_2412[num][i]; //μ÷ó12x24×ì
else if(sizey==32)temp=ascii_3216[num][i]; //μ÷ó16x32×ì
else return;
for(t=0;t<8;t++)
{
if(!mode)//·μtó£ê
{
if(temp&(0x01<<t))LCD_WR_DATA(fc);
else LCD_WR_DATA(bc);
m++;
if(m%sizex==0)
{
m=0;
break;
}
}
else//μtó£ê
{
if(temp&(0x01<<t))LCD_DrawPoint(x,y,fc);//-òμ
x++;
if((x-x0)==sizex)
{
x=x0;
y++;
break;
}
}
}
}
}
/******************************************************************************
oˉêyμ÷£oê×·′
èúêyY£ox,yê×±ê
*p òaêμ×·′
fc ×μé
bc ×μ±3°é
sizey ×o
mode: 0·μtó£ê 1μtó£ê
·μμ£o T
******************************************************************************/
void LCD_ShowString(u16 x,u16 y,const u8 *p,u16 fc,u16 bc,u8 sizey,u8 mode)
{
while(*p!='\0')
{
LCD_ShowChar(x,y,*p,fc,bc,sizey,mode);
x+=sizey/2;
p++;
}
}
/******************************************************************************
oˉêyμ÷£oêêy×
èúêyY£omμ×êy£nêy
·μμ£o T
******************************************************************************/
u32 mypow(u8 m,u8 n)
{
u32 result=1;
while(n--)result*=m;
return result;
}
/******************************************************************************
oˉêyμ÷£oêêy±á
èúêyY£ox,yê×±ê
num òaêêy±á
len òaêμêy
fc ×μé
bc ×μ±3°é
sizey ×o
·μμ£o T
******************************************************************************/
void LCD_ShowIntNum(u16 x,u16 y,u16 num,u8 len,u16 fc,u16 bc,u8 sizey)
{
u8 t,temp;
u8 enshow=0;
u8 sizex=sizey/2;
for(t=0;t<len;t++)
{
temp=(num/mypow(10,len-t-1))%10;
if(enshow==0&&t<(len-1))
{
if(temp==0)
{
LCD_ShowChar(x+t*sizex,y,' ',fc,bc,sizey,0);
continue;
}else enshow=1;
}
LCD_ShowChar(x+t*sizex,y,temp+48,fc,bc,sizey,0);
}
}
/******************************************************************************
oˉêyμ÷£oêáDêy±á
èúêyY£ox,yê×±ê
num òaêDêy±á
len òaêμêy
fc ×μé
bc ×μ±3°é
sizey ×o
·μμ£o T
******************************************************************************/
void LCD_ShowFloatNum1(u16 x,u16 y,float num,u8 len,u16 fc,u16 bc,u8 sizey)
{
u8 t,temp,sizex;
u16 num1;
sizex=sizey/2;
num1=num*100;
for(t=0;t<len;t++)
{
temp=(num1/mypow(10,len-t-1))%10;
if(t==(len-2))
{
LCD_ShowChar(x+(len-2)*sizex,y,'.',fc,bc,sizey,0);
t++;
len+=1;
}
LCD_ShowChar(x+t*sizex,y,temp+48,fc,bc,sizey,0);
}
}
/******************************************************************************
oˉêyμ÷£oêí
èúêyY£ox,yeμ×±ê
length í3¤è
width ííè
pic[] íêy×é
·μμ£o T
******************************************************************************/
void LCD_ShowPicture(u16 x,u16 y,u16 length,u16 width,const u8 pic[])
{
u16 i,j;
u32 k=0;
LCD_Address_Set(x,y,x+length-1,y+width-1);
for(i=0;i<length;i++)
{
for(j=0;j<width;j++)
{
LCD_WR_DATA8(pic[k*2]);
LCD_WR_DATA8(pic[k*2+1]);
k++;
}
}
}
main.c
#include <rtthread.h>
#include <rtdevice.h>
#include "drv_gpio.h"
#include "lcd.h"
#define RED 0xF800
#define LED_PIN GET_PIN(0, 0)
void LCD_Fill(u16 xsta,u16 ysta,u16 xend,u16 yend,u16 color)
{
u16 i,j;
LCD_Address_Set(xsta,ysta,xend-1,yend-1);//设置显示范围
for(i=ysta;i<yend;i++)
{
for(j=xsta;j<xend;j++)
{
LCD_WR_DATA(color);
}
}
}
int main(void)
{
LCD_Init();
delay_ms(100);
LCD_Fill(0,0,128,160,RED);
delay_ms(100);
rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT);
for (;;)
{
rt_pin_write(LED_PIN, PIN_HIGH);
rt_thread_mdelay(500);
rt_pin_write(LED_PIN, PIN_LOW);
rt_thread_mdelay(500);
}
}
Running results: