瑞萨单片机论坛
直播中

jinglixixi

9年用户 1911经验值
擅长:嵌入式技术 光电显示 接口/总线/驱动 控制/MCU
私信 关注

【RA-Eco-RA6M4开发板评测】+LCD屏显示驱动

相较于OLED屏,LCD屏在色彩表现力和显示规格上都有较大的优势,对于LCD屏来说多采用SPI接口的方式工作。在显示驱动方面,除采用硬件的驱动方式,也可以模拟的方式来进行。该显示屏是一款1.8寸显示屏,其控制芯片为ST7735。

为此,需在RASC中先对所用的引脚加以配置,并生成以KEIL工程。

然后,在回到KEIL中进行程序的设计。

LCD屏的引脚连接关系为:

CS ----P209

REST----P206

DC ----P207

SDI ----P211

SCK ----P210

BL ----P208

为便于高低电平的输出控制,所进行的语句定义有:

#define LCD_CS_Set() R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_02_PIN_09,BSP_IO_LEVEL_HIGH)

#define LCD_CS_Reset() R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_02_PIN_09,BSP_IO_LEVEL_LOW)

#define LCD_REST_Set() R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_02_PIN_06,BSP_IO_LEVEL_HIGH)

#define LCD_REST_Reset() R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_02_PIN_06,BSP_IO_LEVEL_LOW)

#define LCD_DC_Set() R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_02_PIN_07,BSP_IO_LEVEL_HIGH)

#define LCD_DC_Reset() R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_02_PIN_07,BSP_IO_LEVEL_LOW)

#define LCD_SDI_Set() R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_02_PIN_11,BSP_IO_LEVEL_HIGH)

#define LCD_SDI_Reset() R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_02_PIN_11,BSP_IO_LEVEL_LOW)

#define LCD_SCK_Set() R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_02_PIN_10,BSP_IO_LEVEL_HIGH)

#define LCD_SCK_Reset() R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_02_PIN_10,BSP_IO_LEVEL_LOW)

#define LCD_BL_Set() R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_02_PIN_08,BSP_IO_LEVEL_HIGH)

#define LCD_BL_Reset() R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_02_PIN_08,BSP_IO_LEVEL_LOW)

模拟SPI发送字节数据的函数为:

void LCD_SendByte(unsigned char com)   
{	
     unsigned char i;
     for(i=0;i<8;i++)
     {
		if(com & 0x80)
		{
			LCD_SDI_Set();
	        }
		else
		{
			LCD_SDI_Reset();
	        }
		com = com << 1;
		R_BSP_SoftwareDelay (3, BSP_DELAY_UNITS_MICROSECONDS);//delay_1us(1);
		LCD_SCK_Reset();
		LCD_SCK_Set();  
    }  
}

显示屏的初始化函数为:

void LCD_Init(void)
{
    LCD_WR_REG(0x11);
    R_BSP_SoftwareDelay(120 ,BSP_DELAY_UNITS_MILLISECONDS); 
    LCD_WR_REG(0xB1);
    LCD_WR_DATA8(0x01);
    LCD_WR_DATA8(0x2C);
    LCD_WR_DATA8(0x2D);
    LCD_WR_REG(0xB2);
    LCD_WR_DATA8(0x01);
    LCD_WR_DATA8(0x2C);
    LCD_WR_DATA8(0x2D);
    LCD_WR_REG(0xB3);
    LCD_WR_DATA8(0x01);
    LCD_WR_DATA8(0x2C);
    LCD_WR_DATA8(0x2D);
    LCD_WR_DATA8(0x01);
    LCD_WR_DATA8(0x2C);
    LCD_WR_DATA8(0x2D);
    LCD_WR_REG(0xB4);
    LCD_WR_DATA8(0x07);
    LCD_WR_REG(0xC0);
    LCD_WR_DATA8(0xA2);
    LCD_WR_DATA8(0x02);
    LCD_WR_DATA8(0x84);
    LCD_WR_REG(0xC1);
    LCD_WR_DATA8(0xC5);
    LCD_WR_REG(0xC2);
    LCD_WR_DATA8(0x0A);
    LCD_WR_DATA8(0x00);
    LCD_WR_REG(0xC3);
    LCD_WR_DATA8(0x8A);
    LCD_WR_DATA8(0x2A);
    LCD_WR_REG(0xC4);
    LCD_WR_DATA8(0x8A);
    LCD_WR_DATA8(0xEE);		
    LCD_WR_REG(0xC5); 
    LCD_WR_DATA8(0x0E);
    LCD_WR_REG(0x36); 
    LCD_WR_DATA8(0xC0);
    LCD_WR_REG(0xe0);
    LCD_WR_DATA8(0x0f);
    LCD_WR_DATA8(0x1a);
    LCD_WR_DATA8(0x0f);
    LCD_WR_DATA8(0x18);
    LCD_WR_DATA8(0x2f);
    LCD_WR_DATA8(0x28);
    LCD_WR_DATA8(0x20);
    LCD_WR_DATA8(0x22);
    LCD_WR_DATA8(0x1f);		
    LCD_WR_DATA8(0x1b);
    LCD_WR_DATA8(0x23);
    LCD_WR_DATA8(0x37);
    LCD_WR_DATA8(0x00);
    LCD_WR_DATA8(0x07);
    LCD_WR_DATA8(0x02);
    LCD_WR_DATA8(0x10);
    LCD_WR_REG(0xe1);
    LCD_WR_DATA8(0x0f);
    LCD_WR_DATA8(0x1b);
    LCD_WR_DATA8(0x0f);
    LCD_WR_DATA8(0x17);
    LCD_WR_DATA8(0x33);
    LCD_WR_DATA8(0x2c);
    LCD_WR_DATA8(0x29);
    LCD_WR_DATA8(0x2e);
    LCD_WR_DATA8(0x30);
    LCD_WR_DATA8(0x30);
    LCD_WR_DATA8(0x39);
    LCD_WR_DATA8(0x3f);
    LCD_WR_DATA8(0x00);
    LCD_WR_DATA8(0x07);
    LCD_WR_DATA8(0x03);
    LCD_WR_DATA8(0x10);
    LCD_WR_REG(0x2a);
    LCD_WR_DATA8(0x00);
    LCD_WR_DATA8(0x00);
    LCD_WR_DATA8(0x00);
    LCD_WR_DATA8(0x7f);		
    LCD_WR_REG(0x2b);
    LCD_WR_DATA8(0x00);
    LCD_WR_DATA8(0x00); 
    LCD_WR_DATA8(0x00);
    LCD_WR_DATA8(0x9f); 		
    LCD_WR_REG(0xF0);
    LCD_WR_DATA8(0x01);
    LCD_WR_REG(0xF6);
    LCD_WR_DATA8(0x00);
    LCD_WR_REG(0x3A);
    LCD_WR_DATA8(0x05);
    LCD_WR_REG(0x29); 
}

以色彩填充显示屏的函数为:

void LCD_Fill(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_DATA16(color);
        }
    }
}

字符串的显示函数为:

void LCD_ShowString(uint16_t x,uint16_t y,const uint8_t *p,uint16_t fc,uint16_t bc,uint8_t sizey,uint8_t mode)
{
    while(*p!='\\\\0')
    {
        LCD_ShowChar(x,y,*p,fc,bc,sizey,mode);
        x+=sizey/2;
        p++;
    }
}

数值的显示函数为:

void LCD_ShowIntNum(uint16_t x,uint16_t y,uint16_t num,uint8_t len,uint16_t fc,uint16_t bc,uint8_t sizey)
{
    uint8_t t,temp;
    uint8_t enshow=0;
    uint8_t sizex=sizey/2;
    for(t=0;t<len;t++)
    {
        temp = (num/mypow(10, (uint8_t)(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, (uint8_t)(temp+48),fc,bc,sizey,0);
    }
}

汉字的显示函数为:

void LCD_Showhanzi16(unsigned int x,unsigned int y,unsigned char index,uint16_t fc,uint16_t bc)
{  
	unsigned char i,j,k;
	const unsigned char *temp=hanzi16;    
	temp+=index*32;	
	LCD_Address_Set(x,y,x+16-1,y+16-1); //Address_set(x,y,x+16-1,y+16-1);
	for(j=0;j<16;j++)
	{
		for(k=0;k<2;k++)
		{
			for(i=0;i<8;i++)
			{ 		     
			 	if((*temp&(1<<i))!=0)
				{
					  LCD_WR_DATA16(fc);
				} 
				else
				{
					  LCD_WR_DATA16(bc);
				}   
			}
			temp++;
		}
	 }
}

图标的显示函数为:

void LCD_ShowPicture(uint16_t x,uint16_t y,uint16_t length,uint16_t width, uint8_t *pic)
{
	uint16_t i,j,c;
	uint32_t k=0;
	LCD_Address_Set(x,y,length-1,width-1); 
	for(i=0;i<length;i++)
	{
		for(j=0;j<width;j++)
		{
			   c=pic[k*2]*256+pic[k*2+1];
			   LCD_WR_DATA16(c);
			   k++;
		}
	}	
}

实现驱动测试的主程序为:

void hal_entry(void)
{
	LCD_REST_Reset();
        R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_MILLISECONDS);
        LCD_REST_Set(); 
        R_BSP_SoftwareDelay(150, BSP_DELAY_UNITS_MILLISECONDS);
        LCD_LED_Set();
	LCD_Init();
	LCD_Fill(0,0,LCD_W,LCD_H,BLUE);
        R_BSP_SoftwareDelay(500, BSP_DELAY_UNITS_MILLISECONDS);
        LCD_Fill(0,0,LCD_W,LCD_H,YELLOW);
        R_BSP_SoftwareDelay(500, BSP_DELAY_UNITS_MILLISECONDS);
        LCD_Fill(0,0,LCD_W,LCD_H,BLACK);
        LCD_ShowString(32,50,(uint8_t *)"RA6M4",RED,BLACK,24,0);
        LCD_ShowString(0,80,(uint8_t *)"SPI-LCD",BLUE,BLACK,32,0);
	LCD_ShowIntNum(60,20,123,3,YELLOW,BLACK,16);
	LCD_Showhanzi16(100,20,4,GREEN,BLACK); 
	LCD_Showhanzi16(100,40,5,GREEN,BLACK); 
	LCD_ShowPicture(0,0,40,40, Image_1);
        while(1);
}

经程序的编译和下载,其测试效果如图2所示,说明驱动控制有效。
image.png

图1 器件连接

image.png

图2 显示效果

在此基础上,要实现硬件方式的驱动就有了一定的基础。

先在RASC的Stack中加入SPI,见图3所示。
image.png

图3 加入SPI

随后,按图4所示加以配参数置。在点击“Generate Project Content”后,即可生成Keil工程。

image.png

图4 配置参数

在完成引脚配置后,即可在生成的Keil工程中进行编程。

在硬件驱动方式下,它与模拟SPI方式的主要区别集中在数据的发送上面。

其替代的函数为:

void  LCD_SendByte(uint8_t dat)
{
    LCD_CS_Reset();
    g_transfer_complete = false;
    err = R_SPI_Write(&g_spi1_ctrl, &dat, 1, SPI_BIT_WIDTH_8_BITS);
    assert(err == FSP_SUCCESS);
    while(g_transfer_complete == false)
    {
    }
    LCD_CS_Set();
}

此外,在初始化方面也有一些变化,就是在初始化显示屏之前,要先打开SPI,其语句为:

err = R_SCI_UART_Open(&g_uart9_ctrl, &g_uart9_cfg);

应注意的是,由于LCD显示屏在使用SPI硬件驱动后,在所引脚上会出现稍许的变动,要要调整引脚的连接。此时,所使用的引脚全集中在J5盒J6上,见图5所示。

image.png

图5 所用接口

更多回帖

发帖
×
20
完善资料,
赚取积分