120|0

1521

帖子

1

TA的资源

五彩晶圆(初级)

楼主
 

【复旦微车规MCU FM32FT0A测评】LCD屏显示驱动 [复制链接]

比较诧异的是开发板上配有一个LCD显示屏,但在例程中却没有它的身影,似乎是在考验使用者的等级水平一般,等级不够似乎就没有使用的权力。

多亏知晓了该显示屏的驱动芯片是ST7789v3,以及它是一款1.47寸、分配率为172X320的屏。

才找到相近的显示屏例程以便进行参考移植,本着GPIO口横行一切的原则,决定以GPIO口来模拟SPI方式驱动这个显示屏。图1是它的接口电路,图2是其引脚占用情况。

 

图1  接口电路

 

 

图  使用引脚

 

为此,对所用引脚的配置为:

#define OLED_INIT()   do{\
                             FL_GPIO_InitTypeDef    GPIO_InitStruct;\
                             GPIO_InitStruct.pin           = FL_GPIO_PIN_0|FL_GPIO_PIN_1|FL_GPIO_PIN_2;\
                             GPIO_InitStruct.mode          = FL_GPIO_MODE_OUTPUT;\
                             GPIO_InitStruct.outputType    = FL_GPIO_OUTPUT_PUSHPULL;\
                             GPIO_InitStruct.pull          = FL_GPIO_BOTH_DISABLE;\
                             GPIO_InitStruct.remapPin      = FL_GPIO_PINREMAP_FUNCTON1;\
                             GPIO_InitStruct.analogSwitch  = FL_DISABLE;\
                             GPIO_InitStruct.driveStrength = FL_GPIO_DRIVESTRENGTH_X3;\
                             (void)FL_GPIO_Init(GPIOE, &GPIO_InitStruct );\
	                           GPIO_InitStruct.pin           = FL_GPIO_PIN_9|FL_GPIO_PIN_14|FL_GPIO_PIN_15;\
                             GPIO_InitStruct.mode          = FL_GPIO_MODE_OUTPUT;\
                             GPIO_InitStruct.outputType    = FL_GPIO_OUTPUT_PUSHPULL;\
                             GPIO_InitStruct.pull          = FL_GPIO_BOTH_DISABLE;\
                             GPIO_InitStruct.remapPin      = FL_GPIO_PINREMAP_FUNCTON1;\
                             GPIO_InitStruct.analogSwitch  = FL_DISABLE;\
                             GPIO_InitStruct.driveStrength = FL_GPIO_DRIVESTRENGTH_X3;\
                             (void)FL_GPIO_Init(GPIOB, &GPIO_InitStruct );\
                         }while(0)

 

对输出高低电平的语句定义为:

#define OLED_SCLK_Set   do{FL_GPIO_SetOutputPin(GPIOE, FL_GPIO_PIN_0);}while(0)
#define OLED_SCLK_Clr   do{FL_GPIO_ResetOutputPin(GPIOE, FL_GPIO_PIN_0);}while(0)

#define OLED_SDIN_Set   do{FL_GPIO_SetOutputPin(GPIOB, FL_GPIO_PIN_14);}while(0)
#define OLED_SDIN_Clr   do{FL_GPIO_ResetOutputPin(GPIOB, FL_GPIO_PIN_14);}while(0)

#define OLED_RST_Set    do{FL_GPIO_SetOutputPin(GPIOB, FL_GPIO_PIN_15);}while(0)
#define OLED_RST_Clr    do{FL_GPIO_ResetOutputPin(GPIOB, FL_GPIO_PIN_15);}while(0)

#define OLED_DC_Set     do{FL_GPIO_SetOutputPin(GPIOE, FL_GPIO_PIN_2);}while(0)
#define OLED_DC_Clr     do{FL_GPIO_ResetOutputPin(GPIOE, FL_GPIO_PIN_2);}while(0)

#define OLED_CS_Set     do{FL_GPIO_SetOutputPin(GPIOE, FL_GPIO_PIN_1);}while(0)
#define OLED_CS_Clr     do{FL_GPIO_ResetOutputPin(GPIOE, FL_GPIO_PIN_1);}while(0)

#define OLED_BLK_Set    do{FL_GPIO_SetOutputPin(GPIOB, FL_GPIO_PIN_9);}while(0)
#define OLED_BLK_Clr    do{FL_GPIO_ResetOutputPin(GPIOB, FL_GPIO_PIN_9);}while(0)

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

void  LCD_Writ_Bus(u8 dat)
{
    u8 i;
    OLED_CS_Clr;
    for(i=0;i<8;i++)
    {
        OLED_SCLK_Clr;
        if(dat&0x80)
        {
			OLED_SDIN_Set;
		}
        else
		{
            OLED_SDIN_Clr;
		}
        OLED_SCLK_Set;
        dat<<=1;
    }
    OLED_CS_Set;
}

考虑到屏幕可能会朝不同的方向使用, LCD_Address_Set()被设计很万能,其内容如下:

void LCD_Address_Set(u16 x1,u16 y1,u16 x2,u16 y2)
{
	if(USE_HORIZONTAL==0)
	{
		LCD_WR_REG(0x2a);
		LCD_WR_DATA(x1+34);
		LCD_WR_DATA(x2+34);
		LCD_WR_REG(0x2b);
		LCD_WR_DATA(y1);
		LCD_WR_DATA(y2);
		LCD_WR_REG(0x2c);
	}
	else if(USE_HORIZONTAL==1)
	{
		LCD_WR_REG(0x2a);
		LCD_WR_DATA(x1+34);
		LCD_WR_DATA(x2+34);
		LCD_WR_REG(0x2b);
		LCD_WR_DATA(y1);
		LCD_WR_DATA(y2);
		LCD_WR_REG(0x2c);
	}
	else if(USE_HORIZONTAL==2)
	{
		LCD_WR_REG(0x2a);
		LCD_WR_DATA(x1);
		LCD_WR_DATA(x2);
		LCD_WR_REG(0x2b);
		LCD_WR_DATA(y1+34);
		LCD_WR_DATA(y2+34);
		LCD_WR_REG(0x2c);
	}
	else
	{
		LCD_WR_REG(0x2a);
		LCD_WR_DATA(x1);
		LCD_WR_DATA(x2);
		LCD_WR_REG(0x2b);
		LCD_WR_DATA(y1+34);
		LCD_WR_DATA(y2+34);
		LCD_WR_REG(0x2c);
	}
}

与之相应的屏幕初始化函数也是具有这个特点的,其内容为:

void Lcd_Init(void)
{
	OLED_INIT();
    OLED_RST_Clr;
    FL_DelayMs(30);
    OLED_RST_Set;
    FL_DelayMs(100);
    OLED_BLK_Set;
	FL_DelayMs(100);
    LCD_WR_REG(0x11);
	LCD_WR_REG(0x36);
	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);
	LCD_WR_REG(0x3A);
    LCD_WR_DATA8(0x05);
	LCD_WR_REG(0xB2);
	LCD_WR_DATA8(0x0C);
	LCD_WR_DATA8(0x0C);
	LCD_WR_DATA8(0x00);
	LCD_WR_DATA8(0x33);
	LCD_WR_DATA8(0x33);
	LCD_WR_REG(0xB7);
	LCD_WR_DATA8(0x35);
	LCD_WR_REG(0xBB);
	LCD_WR_DATA8(0x35);
	LCD_WR_REG(0xC0);
	LCD_WR_DATA8(0x2C);
	LCD_WR_REG(0xC2);
	LCD_WR_DATA8(0x01);
	LCD_WR_REG(0xC3);
	LCD_WR_DATA8(0x13);
	LCD_WR_REG(0xC4);
	LCD_WR_DATA8(0x20);
	LCD_WR_REG(0xC6);
	LCD_WR_DATA8(0x0F);
	LCD_WR_REG(0xD0);
	LCD_WR_DATA8(0xA4);
	LCD_WR_DATA8(0xA1);
	LCD_WR_REG(0xD6);
	LCD_WR_DATA8(0xA1);
	LCD_WR_REG(0xE0);
	LCD_WR_DATA8(0xF0);
	LCD_WR_DATA8(0x00);
	LCD_WR_DATA8(0x04);
	LCD_WR_DATA8(0x04);
	LCD_WR_DATA8(0x04);
	LCD_WR_DATA8(0x05);
	LCD_WR_DATA8(0x29);
	LCD_WR_DATA8(0x33);
	LCD_WR_DATA8(0x3E);
	LCD_WR_DATA8(0x38);
	LCD_WR_DATA8(0x12);
	LCD_WR_DATA8(0x12);
	LCD_WR_DATA8(0x28);
	LCD_WR_DATA8(0x30);
	LCD_WR_REG(0xE1);
	LCD_WR_DATA8(0xF0);
	LCD_WR_DATA8(0x07);
	LCD_WR_DATA8(0x0A);
	LCD_WR_DATA8(0x0D);
	LCD_WR_DATA8(0x0B);
	LCD_WR_DATA8(0x07);
	LCD_WR_DATA8(0x28);
	LCD_WR_DATA8(0x33);
	LCD_WR_DATA8(0x3E);
	LCD_WR_DATA8(0x36);
	LCD_WR_DATA8(0x14);
	LCD_WR_DATA8(0x14);
	LCD_WR_DATA8(0x29);
	LCD_WR_DATA8(0x32);
	LCD_WR_REG(0x21);
	LCD_WR_REG(0x11);
	FL_DelayMs(120);
	LCD_WR_REG(0x29);
}

实现指定色彩清除屏幕的函数为:

void LCD_Clear(u16 Color)
{
    u16 i,j;
    LCD_Address_Set(0,0,LCD_W-1,LCD_H-1);
    for(i=0;i<LCD_W;i++)
    {
        for (j=0;j<LCD_H;j++)
        {
             LCD_WR_DATA(Color);
        }
    }
}

实现字符显示的函数为:

void LCD_ShowChar(u16 x,u16 y,u8 num,u8 mode,u16 color)
{
    u8 temp;
    u8 pos,t;
    u16 x0=x;
    if(x>LCD_W-16||y>LCD_H-16) return;
    num=num-' ';
    LCD_Address_Set(x,y,x+8-1,y+16-1);
    if(!mode)
    {
        for(pos=0;pos<16;pos++)
        {
            temp=asc2_1608[(u16)num*16+pos];
            for(t=0;t<8;t++)
          {
                if(temp&0x01)LCD_WR_DATA(color);
                else LCD_WR_DATA(BLACK);
                temp>>=1;
                x++;
          }
            x=x0;
            y++;
        }
    }
    else
    {
        for(pos=0;pos<16;pos++)
        {
            temp=asc2_1608[(u16)num*16+pos];
            for(t=0;t<8;t++)
            {
                if(temp&0x01)LCD_DrawPoint(x+t,y+pos,color);
                temp>>=1;
            }
        }
    }
}

相应的字符串显示函数为:

void LCD_ShowString(u16 x,u16 y,const u8 *p,u16 color)
{
    while(*p!='\0')
    {
	    LCD_ShowChar(x,y,*p,1,color);
        x+=8;
        p++;
    }
}

实现小图标显示的函数为:

void show_tbh(unsigned int x,unsigned int y)
{  
	unsigned int i,j,k;
	unsigned int da;
	k=0;
	for(i=0;i<50;i++)
	{	
		for(j=0;j<50;j++)
		{
            da=gImage_8[k*2];
			da<<=8;
            da|=gImage_8[k*2+1];
            LCD_DrawPoint(x+j,y+i,da);				
			k++;  
		}
	}
}

在以上函数的支持下,测试显示功能的主程序为:

int main(void)
{   
	  Lcd_Init();
      LCD_Clear(RED);	
	  LCD_ShowString(20,20,"FM33FT0A",YELLOW);  
      LCD_ShowString(20,40,"LCD Test",YELLOW);
	  LCD_ShowString(20,150,"jinglixixi",WHITE);
	  show_tbh(20,70);
      while(1);
}

经程序的编译和下载,其显示效果如图3和图4所示,说明显示驱动成功。

 

图3 整体效果

 

 

图4 显示效果

 

此帖出自汽车电子论坛
点赞 关注

回复
举报
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表