发新帖本帖赏金 30.00元(功能说明)我要提问
返回列表
打印
[AT32F421]

快速实现移植LCD驱动到F425

[复制链接]
2605|17
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
51xlf|  楼主 | 2022-6-1 23:20 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 51xlf 于 2022-7-1 17:40 编辑

#申请原创#  @21小跑堂 近期又购置了一个arduino接口的TFT LCD,可以兼容arduino接口。而且芯片还自动SD卡,后期可以通过这个SD卡加载汉字库。

需要在arduino上测试了一下,感觉效果还是可以的。突然想起来,AT-START-F425的板子也是自带arduino的接口的。
这个板子可以完全和AT-START-F425板子完美的融合起来的。奔着说干就干的原则,先看看需要用到哪些接口?
屏幕的接口就是暂时用到的是绿色框中的几个引脚。

而对应在屏幕上的几个端,就需要看原理图了。完美的arduino的接口,不错。

看一下屏幕和AT-START-F425的契合的图片。

就是刷新的速度有限,不能发挥出AT32F425的能力,不过这个的速度还是可以的。
这个需要用到的几个引脚。先在程序里面配置一下,因为不是连续的引脚,所以这个只能是按照位进行操作了。
程序的配置有点繁琐了,不如直接给寄存器赋值来的直接。先把引脚全部的配置为输出了。
crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
    crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
    crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE);
    /* set default parameter */
    gpio_default_para_init(&gpio_init_struct);

    /* configure button pin as input with pull-up/pull-down */
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
    gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
    gpio_init_struct.gpio_pins = GPIO_PINS_0 |GPIO_PINS_1|GPIO_PINS_4|GPIO_PINS_8|GPIO_PINS_9|GPIO_PINS_10;
    gpio_init_struct.gpio_pull = GPIO_PULL_UP;
    gpio_init(GPIOA, &gpio_init_struct);

    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
    gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
    gpio_init_struct.gpio_pins = GPIO_PINS_0 |GPIO_PINS_4|GPIO_PINS_3|GPIO_PINS_5|GPIO_PINS_10;
    gpio_init_struct.gpio_pull = GPIO_PULL_UP;
    gpio_init(GPIOB, &gpio_init_struct);

    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
    gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
    gpio_init_struct.gpio_pins = GPIO_PINS_1 |GPIO_PINS_7;
    gpio_init_struct.gpio_pull = GPIO_PULL_UP;
    gpio_init(GPIOC, &gpio_init_struct);
后面就是对IO口进行赋值操作了,习惯了使用了stm32的HAL了,所以这里还是使用的宏定义对LCD的控制引脚(例如复位 读写 片选)进行操作的,
这样好操作,而且后期移植到其他的程序上也是非常的方便的。
#define LCD_RD_GPIO_Port GPIOA
#define LCD_RD_Pin GPIO_PINS_0

#define LCD_WR_GPIO_Port GPIOA
#define LCD_WR_Pin  GPIO_PINS_1

#define LCD_RS_GPIO_Port GPIOA
#define LCD_RS_Pin   GPIO_PINS_4

#define LCD_CS_GPIO_Port GPIOB
#define LCD_CS_Pin GPIO_PINS_0

#define LCD_RST_GPIO_Port GPIOC
#define LCD_RST_Pin GPIO_PINS_1

#define LCD_D0_GPIO_Port  GPIOA
#define LCD_D0_Pin   GPIO_PINS_9
#define LCD_D1_GPIO_Port  GPIOC
#define LCD_D1_Pin   GPIO_PINS_7
#define LCD_D2_GPIO_Port  GPIOA
#define LCD_D2_Pin   GPIO_PINS_10
#define LCD_D3_GPIO_Port  GPIOB
#define LCD_D3_Pin   GPIO_PINS_3
#define LCD_D4_GPIO_Port GPIOB
#define LCD_D4_Pin   GPIO_PINS_5
#define LCD_D5_GPIO_Port GPIOB
#define LCD_D5_Pin   GPIO_PINS_4
#define LCD_D6_GPIO_Port GPIOB
#define LCD_D6_Pin   GPIO_PINS_10
#define LCD_D7_GPIO_Port   GPIOA
#define LCD_D7_Pin   GPIO_PINS_8
#define                LCD_CS_LOW()                LCD_CS_GPIO_Port->clr =LCD_CS_Pin         //
#define                LCD_CS_HIGH()                LCD_CS_GPIO_Port->scr = LCD_CS_Pin                //

#define                LCD_RST_LOW()                LCD_RST_GPIO_Port->clr = LCD_RST_Pin         //
#define                LCD_RST_HIGH()        LCD_RST_GPIO_Port->scr = LCD_RST_Pin                //
这里需要对屏幕进行操作了,需要用到的按照位进行操作了。
使用右键查询到使用寄存器赋值的方法。
对IO进行赋值需要对scr进行操作,如果是需要置0则对clr进行操作。
具体的代码如下所示,保障了屏幕的刷新速度了。最快的实现置位和置0的操作。
 LCD_WR_GPIO_Port->clr = (uint32_t)LCD_WR_Pin ;        
    if(dat&0x01)        LCD_D0_GPIO_Port->scr = (uint32_t)LCD_D0_Pin;        
    else                LCD_D0_GPIO_Port->clr = (uint32_t)LCD_D0_Pin ;        
    if(dat&0x02)        LCD_D1_GPIO_Port->scr = (uint32_t)LCD_D1_Pin;               
    else                LCD_D1_GPIO_Port->clr = (uint32_t)LCD_D1_Pin ;        
    if(dat&0x04)        LCD_D2_GPIO_Port->scr = (uint32_t)LCD_D2_Pin;        
    else                LCD_D2_GPIO_Port->clr = (uint32_t)LCD_D2_Pin;        
    if(dat&0x08)        LCD_D3_GPIO_Port->scr = (uint32_t)LCD_D3_Pin;        
    else                LCD_D3_GPIO_Port->clr = (uint32_t)LCD_D3_Pin;        
    if(dat&0x10)        LCD_D4_GPIO_Port->scr = (uint32_t)LCD_D4_Pin;               
    else                LCD_D4_GPIO_Port->clr = (uint32_t)LCD_D4_Pin ;        
    if(dat&0x20)        LCD_D5_GPIO_Port->scr = (uint32_t)LCD_D5_Pin;               
    else                LCD_D5_GPIO_Port->clr = (uint32_t)LCD_D5_Pin ;
    if(dat&0x40)        LCD_D6_GPIO_Port->scr = (uint32_t)LCD_D6_Pin;        
    else                LCD_D6_GPIO_Port->clr = (uint32_t)LCD_D6_Pin ;        
    if(dat&0x80)        LCD_D7_GPIO_Port->scr = (uint32_t)LCD_D7_Pin;               
    else                LCD_D7_GPIO_Port->clr = (uint32_t)LCD_D7_Pin ;        
    LCD_WR_GPIO_Port->scr = (uint32_t)LCD_WR_Pin;               
具体怎么配置寄存器,这里就不再赘述了。就是跟配置正常的LCD一样了,主要的实现对数据寄存器的写入。
再根据需要配置的形式,自己实现数据和命令的控制,这个具体的代码,在购买屏幕的时候,他就直接给出了。
自己根据提供的例程,选择一下,自己要实现的方式就行了。屏幕的配置很简单,都是固定的代码。
主要的实现函数就是现实一个点的绘制,点动成线,线动成面。
这样就会绘制出来想要的效果了。这个代码使用的就是淘宝店家的提供的例程了。
void lcd_point(uint16_t x, uint16_t y,uint16_t color){
    if ((x >= LCD_W) || (y >= LCD_H))        return ;
    LCD_CS_LOW();        //HAL_GPIO_WritePin(LCD_CS,LOW);
    lcd_address_set(x, y, x, y);
    lcd_write_data(color >> 8);
    lcd_write_data(color);
    LCD_CS_HIGH();        //HAL_GPIO_WritePin(LCD_CS,HIGH);
}
有了这个点,后面就是现实的文字输出,根据自己的字库实现字符和汉字的输出了
字符很简单,就是根据字模输出屏幕了就行了。
这里移植了一个oled的显示程序,里面很简单,可以根据自己的需要选择需要的字符。具体的字库,可以看后面的代码了。
这个代码做的就是非常好,可选择性很高。
  u8 i,m,temp,size2,chr1;
    u8 x0=x,y0=y;
    if(size1==8)size2=6;
    else size2=(size1/8+((size1%8)?1:0))*(size1/2);  //得到字体一个字符对应点阵集所占的字节数
    chr1=chr-' ';  //计算偏移后的值
    for(i=0; i<size2; i++)
    {
        if(size1==8)
        {
            temp=asc2_0806[chr1][i];   //调用0806字体
        }
        else if(size1==12)
        {
            temp=asc2_1206[chr1][i];   //调用1206字体
        }
        else if(size1==16)
        {
            temp=asc2_1608[chr1][i];   //调用1608字体
        }
        else if(size1==24)
        {
            temp=asc2_2412[chr1][i];   //调用2412字体
        }
        else return;
        for(m=0; m<8; m++)
        {
            if(temp&0x01)lcd_point(x,y,f_color);
            else lcd_point(x,y,b_color);
            temp>>=1;
            y++;
        }
        x++;
        if((size1!=8)&&((x-x0)==size1/2))
        {
            x=x0;
            y0=y0+8;
        }
        y=y0;
    }
至于字符串就是逐个对字符进行输出实现。
这里说明一下如何实现汉字的输出。参考正点原子的方法。
实现字符的取模用的是PC2LCD2000,因为软件的原因,获取的数据,需要修改的内容很多,太麻烦,所以我将正点原子的变量修改了一下,
这样就可以直接实现把内容复制到字模文件中了。
struct typFNT_GB162
{char Msk[32];
        unsigned char Index[2];        
        unsigned char no;
};




这样对比一下就行了,直接复制粘贴的效果还是比较好的。省去了,调换字符位置,删除字符内容等一系列的复杂操作。
接下来实现的就是汉字和字符的混合输出了。
根据字符的大小判断是字符还是汉字,如果是字符调用上述的方法就可以实现,如果是汉字,就根据汉字字模,赋值前景色和背景色就行了。
while(*chr) {
        if((*chr) < 128)
        {
            OLED_ShowChar(x,y,*chr,size1, f_color,b_color);
            if(size1==8)x+=6;
            else x+=size1/2;
            chr++;
        } else {
            for (k=0; k<hz16_num; k++)
            {
                if ((hz16[k].Index[0]==*(chr))&&(hz16[k].Index[1]==*(chr+1)))
                {
                    for(i=0; i<16; i++)
                    {
                        for(j=0; j<8; j++)
                        {
                            if(hz16[k].Msk[i*2]&(0x80>>j))        lcd_point(x+j,y+i,f_color);//lcd_point(x,y,f_color);
                            else {
                                lcd_point(x+j,y+i,b_color);
                            }
                        }
                        for(j=0; j<8; j++)
                        {
                            if(hz16[k].Msk[i*2+1]&(0x80>>j))        lcd_point(x+j+8,y+i,f_color);//lcd_point(x+j,y+i,f_color);
                            else
                            {
                                lcd_point(x+j+8,y+i,b_color);
                            }
                        }
                    }
                }
            }
            chr+=2;
            x+=16;
        }
    }

主要的一些代码已经实现了
 OLED_ShowStringCN(0,20,"bbs.21ic.com",16,GREEN,BLACK);
        OLED_ShowStringCN(0,40,"雅特力AT32 MCU",16,RED,BLACK);
        lcd_show_image(0,60,160,27,gImage_ic21);        
        lcd_show_image(0,90,120,80,gImage_at);



让我们来欣赏一下,演示的效果。









1.jpg (118.58 KB )

1.jpg

使用特权

评论回复

打赏榜单

21小跑堂 打赏了 30.00 元 2022-07-04
理由:恭喜通过原创文章审核!请多多加油哦!

评论
forgot 2023-6-29 13:39 回复TA
感谢分享,MARK一下,学习了 
21小跑堂 2022-7-4 10:03 回复TA
雅特力开发板驱动Arduino接口的LCD屏幕,作者实现效果较好,可尝试用硬件外设代替IO模拟提高刷新率。 
沙发
caigang13| | 2022-6-2 08:19 | 只看该作者
刷新频率咋样?

使用特权

评论回复
板凳
51xlf|  楼主 | 2022-6-2 08:37 | 只看该作者

不怎么快,写入数据的速度太慢了。  

使用特权

评论回复
地板
koala889| | 2022-6-3 10:41 | 只看该作者
真不错啊

使用特权

评论回复
5
trucyw| | 2022-7-6 15:06 | 只看该作者
赞赞赞

使用特权

评论回复
6
geraldbetty| | 2022-10-5 19:29 | 只看该作者
哪位仁兄帮我介绍一本关于LCD的书  

使用特权

评论回复
7
janewood| | 2022-10-5 19:43 | 只看该作者
一个屏,两个驱动板,怎么实现切换  

使用特权

评论回复
8
mollylawrence| | 2022-10-5 20:00 | 只看该作者
如何使F425的启动信息显示到LCD 上面

使用特权

评论回复
9
maqianqu| | 2022-11-1 11:06 | 只看该作者
能不能实现读取LCD的触摸数据吗

使用特权

评论回复
10
dspmana| | 2022-11-1 15:05 | 只看该作者
这个lcd的刷屏速度比较慢了              

使用特权

评论回复
11
bestwell| | 2022-11-1 15:25 | 只看该作者
可以是用dma写入数据吗              

使用特权

评论回复
12
pentruman| | 2022-11-1 16:12 | 只看该作者
模拟spi的效果很一般,写入的速度不快,lcd比较慢了。

使用特权

评论回复
13
yangxiaor520| | 2023-7-1 11:56 | 只看该作者
SP刷新I速度有限

使用特权

评论回复
14
georgeliu2016| | 2023-7-1 15:27 | 只看该作者
动手能力强。

使用特权

评论回复
15
Jon495323976| | 2023-7-12 14:02 | 只看该作者
SRAM够用吗

使用特权

评论回复
16
guijial511| | 2023-7-12 19:25 | 只看该作者
arduino编程确定方便,不用过多关注底层驱动。

使用特权

评论回复
发新帖 本帖赏金 30.00元(功能说明)我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

534

主题

9559

帖子

23

粉丝