4060 views|3 replies

565

Posts

0

Resources
The OP
 

【BLE 5.3 wireless MCU CH582】9. Hardware SPI driver LCD [Copy link]

 

Series of articles:

【BLE 5.3 wireless MCU CH582】1. Getting to know the CH582 development board (unboxing)

【BLE 5.3 wireless MCU CH582】2. MounRiver IDE first experience

【BLE 5.3 wireless MCU CH582】3. Non-blocking lighting

【BLE 5.3 wireless MCU CH582】4. Serial port variable length data reception

【BLE 5.3 wireless MCU CH582】5. Hardware I2C drive 0.96-inch OLED

【BLE 5.3 wireless MCU CH582】6. PWM breathing light

[BLE 5.3 wireless MCU CH582] 7. Button - GPIO external interrupt

【BLE 5.3 wireless MCU CH582】8. ADC sampling (internal bat, internal temperature, external input)

1. spi of ch582

There is only one set of spi, which can be used as master and slave.

2. SPI pin

3. Hardware connection

/*
GND GND
3.3V VCC
PA13 SCL
PA14 SDA
PA12 CS (chip select)

PA7 ERS (reset)
PA8 DC (command data selection)
PA6 BL (backlight)
*/

4. Code Implementation

(1) Macro definition

#define LCD_RES_LOW()   GPIOA_ResetBits(GPIO_Pin_7)//RES  rst
#define LCD_RES_HIGH()  GPIOA_SetBits(GPIO_Pin_7)

#define LCD_DC_LOW()    GPIOA_ResetBits(GPIO_Pin_8)//DC  data command select
#define LCD_DC_HIGH()   GPIOA_SetBits(GPIO_Pin_8)
 		     
#define LCD_BLK_LOW()   GPIOA_ResetBits(GPIO_Pin_6)//BLK
#define LCD_BLK_HIGH()  GPIOA_SetBits(GPIO_Pin_6)

#define LCD_CS_LOW()    GPIOA_ResetBits(GPIO_Pin_12)//CS
#define LCD_CS_HIGH()   GPIOA_SetBits( GPIO_Pin_12 );

(2) IO and spi initialization

void LcdIoInit(void)
{
    GPIOA_ModeCfg(  GPIO_Pin_6 |GPIO_Pin_7 | GPIO_Pin_8 , GPIO_ModeOut_PP_5mA );
	
	/*  SPI0 :
		PA12/CS
		PA13/SCK
		PA14/MOSI
		PA15/MISO
	*/

	GPIOA_SetBits( GPIO_Pin_12 );
	GPIOA_ModeCfg( GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14|GPIO_Pin_15, GPIO_ModeOut_PP_5mA );
	SPI0_MasterDefInit();
}

(3) SPI write data

void LCD_Writ_Bus(uint8_t dat) 
{	
	LCD_CS_LOW();
	
	SPI0_MasterSendByte( dat );

	LCD_CS_HIGH();	
}

(3) LCD driver related code

/******************************************************************************
函数说明:LCD写入数据
入口数据:dat 写入的数据
返回值:  无
******************************************************************************/
void LCD_WR_DATA8(uint8_t dat)
{
	LCD_Writ_Bus(dat);
}


/******************************************************************************
函数说明:LCD写入数据
入口数据:dat 写入的数据
返回值:  无
******************************************************************************/
void LCD_WR_DATA(uint16_t dat)
{
	LCD_Writ_Bus(dat>>8);
	LCD_Writ_Bus(dat);
}


/******************************************************************************
函数说明:LCD写入命令
入口数据:dat 写入的命令
返回值:  无
******************************************************************************/
void LCD_WR_REG(uint8_t  dat)
{
	LCD_DC_LOW();//写命令
	LCD_Writ_Bus(dat);
	LCD_DC_HIGH();//写数据
}


/******************************************************************************
函数说明:设置起始和结束地址
入口数据:x1,x2 设置列的起始和结束地址
		  y1,y2 设置行的起始和结束地址
返回值:  无
******************************************************************************/
void LCD_Address_Set(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2)
{
	if(USE_HORIZONTAL==0)
	{
		LCD_WR_REG(0x2a);//列地址设置
		LCD_WR_DATA(x1+2);
		LCD_WR_DATA(x2+2);
		LCD_WR_REG(0x2b);//行地址设置
		LCD_WR_DATA(y1+1);
		LCD_WR_DATA(y2+1);
		LCD_WR_REG(0x2c);//储存器写
	}
	else if(USE_HORIZONTAL==1)
	{
		LCD_WR_REG(0x2a);//列地址设置
		LCD_WR_DATA(x1+2);
		LCD_WR_DATA(x2+2);
		LCD_WR_REG(0x2b);//行地址设置
		LCD_WR_DATA(y1+1);
		LCD_WR_DATA(y2+1);
		LCD_WR_REG(0x2c);//储存器写
	}
	else if(USE_HORIZONTAL==2)
	{
		LCD_WR_REG(0x2a);//列地址设置
		LCD_WR_DATA(x1+1);
		LCD_WR_DATA(x2+1);
		LCD_WR_REG(0x2b);//行地址设置
		LCD_WR_DATA(y1+2);
		LCD_WR_DATA(y2+2);
		LCD_WR_REG(0x2c);//储存器写
	}
	else
	{
		LCD_WR_REG(0x2a);//列地址设置
		LCD_WR_DATA(x1+1);
		LCD_WR_DATA(x2+1);
		LCD_WR_REG(0x2b);//行地址设置
		LCD_WR_DATA(y1+2);
		LCD_WR_DATA(y2+2);
		LCD_WR_REG(0x2c);//储存器写
	}
}

/******************************************************************************
函数说明:LCD初始化,包含硬件IO
入口数据:无
返回值:  无
******************************************************************************/
void LcdInit(void)
{
	LcdIoInit();//初始化GPIO
	
	LCD_RES_LOW();//复位
	DelayMs(100);
	LCD_RES_HIGH();
	DelayMs(100);
	
	LCD_BLK_HIGH();//打开背光
    DelayMs(100);
	
	//************* Start Initial Sequence **********//
	LCD_WR_REG(0x11); //Sleep out 
	DelayMs(120);              //Delay 120ms 
	//------------------------------------ST7735S Frame Rate-----------------------------------------// 
	LCD_WR_REG(0xB1); 
	LCD_WR_DATA8(0x05); 
	LCD_WR_DATA8(0x3C); 
	LCD_WR_DATA8(0x3C); 
	LCD_WR_REG(0xB2); 
	LCD_WR_DATA8(0x05);
	LCD_WR_DATA8(0x3C); 
	LCD_WR_DATA8(0x3C); 
	LCD_WR_REG(0xB3); 
	LCD_WR_DATA8(0x05); 
	LCD_WR_DATA8(0x3C); 
	LCD_WR_DATA8(0x3C); 
	LCD_WR_DATA8(0x05); 
	LCD_WR_DATA8(0x3C); 
	LCD_WR_DATA8(0x3C); 
	//------------------------------------End ST7735S Frame Rate---------------------------------// 
	LCD_WR_REG(0xB4); //Dot inversion 
	LCD_WR_DATA8(0x03); 
	//------------------------------------ST7735S Power Sequence---------------------------------// 
	LCD_WR_REG(0xC0); 
	LCD_WR_DATA8(0x28); 
	LCD_WR_DATA8(0x08); 
	LCD_WR_DATA8(0x04); 
	LCD_WR_REG(0xC1); 
	LCD_WR_DATA8(0XC0); 
	LCD_WR_REG(0xC2); 
	LCD_WR_DATA8(0x0D); 
	LCD_WR_DATA8(0x00); 
	LCD_WR_REG(0xC3); 
	LCD_WR_DATA8(0x8D); 
	LCD_WR_DATA8(0x2A); 
	LCD_WR_REG(0xC4); 
	LCD_WR_DATA8(0x8D); 
	LCD_WR_DATA8(0xEE); 
	//---------------------------------End ST7735S Power Sequence-------------------------------------// 
	LCD_WR_REG(0xC5); //VCOM 
	LCD_WR_DATA8(0x1A); 
	LCD_WR_REG(0x36); //MX, MY, RGB mode 
	
	if(USE_HORIZONTAL==0)
		LCD_WR_DATA8(0x00);
	else if(USE_HORIZONTAL==1)
		LCD_WR_DATA8(0xC0);
	else if(USE_HORIZONTAL==2)
		LCD_WR_DATA8(0x70);
	else 
		LCD_WR_DATA8(0xA0); 
	//------------------------------------ST7735S Gamma Sequence---------------------------------// 
	LCD_WR_REG(0xE0); 
	LCD_WR_DATA8(0x04); 
	LCD_WR_DATA8(0x22); 
	LCD_WR_DATA8(0x07); 
	LCD_WR_DATA8(0x0A); 
	LCD_WR_DATA8(0x2E); 
	LCD_WR_DATA8(0x30); 
	LCD_WR_DATA8(0x25); 
	LCD_WR_DATA8(0x2A); 
	LCD_WR_DATA8(0x28); 
	LCD_WR_DATA8(0x26); 
	LCD_WR_DATA8(0x2E); 
	LCD_WR_DATA8(0x3A); 
	LCD_WR_DATA8(0x00); 
	LCD_WR_DATA8(0x01); 
	LCD_WR_DATA8(0x03); 
	LCD_WR_DATA8(0x13); 
	LCD_WR_REG(0xE1); 
	LCD_WR_DATA8(0x04); 
	LCD_WR_DATA8(0x16); 
	LCD_WR_DATA8(0x06); 
	LCD_WR_DATA8(0x0D); 
	LCD_WR_DATA8(0x2D); 
	LCD_WR_DATA8(0x26); 
	LCD_WR_DATA8(0x23); 
	LCD_WR_DATA8(0x27); 
	LCD_WR_DATA8(0x27); 
	LCD_WR_DATA8(0x25); 
	LCD_WR_DATA8(0x2D); 
	LCD_WR_DATA8(0x3B); 
	LCD_WR_DATA8(0x00); 
	LCD_WR_DATA8(0x01); 
	LCD_WR_DATA8(0x04); 
	LCD_WR_DATA8(0x13); 
	//------------------------------------End ST7735S Gamma Sequence-----------------------------// 
	LCD_WR_REG(0x3A); //65k mode 
	LCD_WR_DATA8(0x05); 
	LCD_WR_REG(0x29); //Display on 
} 


/******************************************************************************
函数说明:在指定区域填充颜色
入口数据:xsta,ysta   起始坐标
		  xend,yend   终止坐标
		  color       要填充的颜色
返回值:  无
******************************************************************************/
void LcdFill(uint16_t xsta,uint16_t ysta,uint16_t xend,uint16_t yend,uint16_t color)
{          
	uint16_t 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);
		}
	} 					  	    
}

/******************************************************************************
函数说明:在指定位置画点
入口数据:x,y 画点坐标
		  color 点的颜色
返回值:  无
******************************************************************************/
void LcdDrawPoint(uint16_t x,uint16_t y,uint16_t color)
{
	LCD_Address_Set(x,y,x,y);//设置光标位置 
	LCD_WR_DATA(color);
} 


/******************************************************************************
函数说明:画线
入口数据:x1,y1   起始坐标
		  x2,y2   终止坐标
		  color   线的颜色
返回值:  无
******************************************************************************/
void LcdDrawLine(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2,uint16_t color)
{
	uint16_t 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;//画线起点坐标
	uCol=y1;
	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++)
	{
		LcdDrawPoint(uRow,uCol,color);//画点
		xerr+=delta_x;
		yerr+=delta_y;
		if(xerr>distance)
		{
			xerr-=distance;
			uRow+=incx;
		}
		if(yerr>distance)
		{
			yerr-=distance;
			uCol+=incy;
		}
	}
}


/******************************************************************************
函数说明:画矩形
入口数据:x1,y1   起始坐标
		  x2,y2   终止坐标
		  color   矩形的颜色
返回值:  无
******************************************************************************/
void LcdDrawRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2,uint16_t color)
{
	LcdDrawLine(x1,y1,x2,y1,color);
	LcdDrawLine(x1,y1,x1,y2,color);
	LcdDrawLine(x1,y2,x2,y2,color);
	LcdDrawLine(x2,y1,x2,y2,color);
}


/******************************************************************************
函数说明:画圆
入口数据:x0,y0   圆心坐标
		  r       半径
		  color   圆的颜色
返回值:  无
******************************************************************************/
void LcdDrawCircle(uint16_t x0,uint16_t y0,uint8_t r,uint16_t color)
{
	int a,b;
	
	a=0;b=r;	  
	while(a<=b)
	{
		LcdDrawPoint(x0-b,y0-a,color);             //3           
		LcdDrawPoint(x0+b,y0-a,color);             //0           
		LcdDrawPoint(x0-a,y0+b,color);             //1                
		LcdDrawPoint(x0-a,y0-b,color);             //2             
		LcdDrawPoint(x0+b,y0+a,color);             //4               
		LcdDrawPoint(x0+a,y0-b,color);             //5
		LcdDrawPoint(x0+a,y0+b,color);             //6 
		LcdDrawPoint(x0-b,y0+a,color);             //7
		a++;
		if((a*a+b*b)>(r*r))//判断要画的点是否过远
		{
			b--;
		}
	}
}


/******************************************************************************
函数说明:显示单个字符
入口数据:x,y显示坐标
		  ch 要显示的字符
		  fc 字的颜色
		  bc 字的背景色
		  csize 字号
返回值:  无
******************************************************************************/
void LcdShowChar(uint16_t x,uint16_t y,uint8_t ch,uint16_t fc,uint16_t bc,uint8_t csize)
{
	const unsigned char  *temp;
	uint8_t i,j,k;
	uint16_t x0=x,y0=y;
	uint8_t row=0,column=0;
	
	row=(csize/8+((csize%8)?1:0));  //计算行
	column=csize/2;                 //列
	ch=ch-' ';                      //得到偏移后的值
		
	switch(csize)
	{
		case 12:temp=Ascii_6x12[ch]; break;
		case 16:temp=Ascii_8x16[ch]; break;
		case 24:temp=Ascii_12x24[ch]; break;
		case 32:temp=Ascii_16x32[ch]; break;
		default: temp=Ascii_6x12[ch]; break;
	}
	
	//显示要与取模方式保持一致
	for(i=0;i<row;i++)
	{
		for(j=0;j<column;j++)
		{ 
			for(k=0;k<8;k++)
			{
				if((*temp)&(0x01<<k))
				{
					LcdDrawPoint(x,y,fc);//画一个点,字体色
				}
				else
				{
					LcdDrawPoint(x,y,bc);//画一个点,背景色
				}
				y++;
			}
			y=y0;
			x++;
			temp++;
		}
		x=x0;
		y0+=8;
		y=y0;
	}
}

/******************************************************************************
函数说明:显示字符串
入口数据:x,y显示坐标
		  *p 要显示的字符串
		  fc 字的颜色
		  bc 字的背景色
		  csize 字号
返回值:  无
******************************************************************************/
void LcdShowString(uint16_t x,uint16_t y,const char *p,uint16_t fc,uint16_t bc,uint8_t csize)
{         
	while(*p!='\0')
	{       
		LcdShowChar(x,y,*p,fc,bc,csize);
		x+=csize/2;
		p++;
	}  
}


/******************************************************************************
函数说明:显示汉字字符
入口数据:x,y显示坐标
		  index 汉字字符索引
		  fc 字的颜色
		  bc 字的背景色
返回值:  无
******************************************************************************/
void LcdShow16x16Hz(uint32_t x, uint32_t y, uint8_t index, uint16_t fc, uint16_t bc)	
{  
	const char *temp=Hzk[index];              // 获取字体数据在数组中的的起始位置 
	uint8_t y0=y,x0=x;
	uint8_t i,j,k;
	uint8_t row=0,column=0;

	row=16/8;
	column=16;
	
	//显示要与取模方式保持一致
	for(i=0;i<row;i++)
	{
		for(j=0;j<column;j++)
		{
			for( k=0;k<8;k++)
			{ 	
				if(*temp&(0x01<<k))
				{
					LcdDrawPoint(x,y,fc);//画一个点,字体色
				}
				else
				{
					LcdDrawPoint(x,y,bc);//画一个点,背景色
				}
				y++;
			}
			temp++;
			x++;
			y=y0;
		}
		x=x0;
		y0+=8;
		y=y0;
	}
}	


/******************************************************************************
函数说明:显示图片
入口数据:x,y显示坐标
		  width   图片宽度
		  height  图片高度
		  image   图片数据
返回值:  无
******************************************************************************/
void LcdShowImage(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint8_t *image) 
{  	
	uint16_t colorData=0;
	uint32_t cnt=0;
	uint16_t i,j;
	
 	for( i=0; i<height; i++)                // 一行一行地显示
	{
 		LCD_Address_Set(x, y+i, x+width, y+height);  // 重新设置光标位置 
		for( j=0; j<width; j++)             // 一行中,从左到事,逐个像素处理
		{		    
		    colorData=(image[cnt*2+1]<<8) | image[cnt*2]; 
		    LCD_WR_DATA(colorData);              // 写入16位颜色数据 
			cnt++;	
		}
	}	  
}

(4) Test code

/******************************************************************************
函数说明:LCD显示测试
入口数据:无
返回值:  无
******************************************************************************/
void LcdTest(void)
{
	LcdInit();//LCD初始化
	LcdFill(0,0,LCD_W,LCD_H,BLACK);
	
	LcdShow16x16Hz(32, 0, 0, YELLOW, BLACK);
	LcdShow16x16Hz(48, 0, 1, YELLOW, BLACK);
	LcdShow16x16Hz(64, 0, 2, YELLOW, BLACK);
	LcdShow16x16Hz(80, 0, 3, YELLOW, BLACK);

	LcdShowImage (14,40, 100, 93, gImage_zan);//winxin_gImage_x
}

5. Display test

Note: The driver code of this LCD has been ported to multiple platforms, such as: gd32, at32, etc.

This post is from Domestic Chip Exchange

Latest reply

You got up so early, you must be writing a review report! I admire you!   Details Published on 2022-3-26 07:31
Personal signaturestm32/LoRa物联网:304350312
 
 

6818

Posts

11

Resources
2
 
Thanks for sharing. It is better to indicate which chip the screen is driven by, because the initialization code of different LCD screens is different. It seems that the screen is ST7735 bought from Hezhou.
This post is from Domestic Chip Exchange

Comments

Yes  Details Published on 2022-3-26 07:27
 
 
 

565

Posts

0

Resources
3
 
lugl4313820 posted on 2022-3-26 07:20 Thanks for sharing. It is better to indicate which chip the screen is driven by, because the initialization code of different LCD screens is different. It seems that it is in Hezhou...

Yes

This post is from Domestic Chip Exchange

Comments

You got up so early, you must be writing a review report! I admire you!  Details Published on 2022-3-26 07:31
Personal signaturestm32/LoRa物联网:304350312
 
 
 

6818

Posts

11

Resources
4
 

You got up so early, you must be writing a review report! I admire you!

This post is from Domestic Chip Exchange
 
 
 

Guess Your Favourite
Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

Featured Posts
Homemade STEVAL-IPM05F 3Sh board: FOC motor control 400V/8A non-sensing/sensing Hall/sensing encoder and other reference programs...

This post was last edited by music_586 on 2019-4-4 19:06 This content was originally created by EEWORLD forum user musi ...

Based on IPM05F 3Sh board: FOC motor control 400V non-sensing sensory encoder all design data summary (schematic diagram/BOM table...

Based on IPM05F 3Sh board: FOC motor control 400V sensorless and sensory encoder all design data summary (schematic diag ...

"Recommend Chinese chips" + domestic chips

I have used or seen quite a lot of domestic chips. I won't mention Shenwei and Loongson. Basically, anyone who works wit ...

Two highlights of EFM32PG22

I think the M33 core and 16-bit ADC are pretty good.

[HPM-DIY] HPM6750 uses cherryusb to read UVC camera to display VGA resolution

I received the display module from EE last week and finally used it tonight. HPM6750 acts as a host to read the UVC came ...

Is it possible to perform socket communication without IP and port number?

When using socket communication, whether it is internal communication within the local machine or communication betwee ...

全志V853 NPU 转换部署 YOLO V5 模型

# NPU conversion and deployment of YOLO V5 model This article takes the YOLO v5s model as an example to detail the conve ...

What is light load mode?

The technique of improving efficiency when using less output current is called light load mode. It is also called burst ...

[ST NUCLEO-U5A5ZJ-Q development board review] 2. EXTI, PWM and serial port printf

Serial port printf output The serial port 1 of Nucleo-U5A5 is connected to the serial port of STlinkV3 to output the pri ...

What are the functions of the five pins INT, MOSI, MISO, SCK, and NCS of the MPU attitude sensor? Is the waveform correct?

What are the functions of the five pins INT, MOSI, MISO, SCK, and NCS of the MPU attitude sensor? Is the waveform correc ...

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list