搜索
bottom↓
回复: 0

《ATK-DFPGL22G之FPGA开发指南_V1.0》第二十五章 TFTLCD(MCU屏)实验

[复制链接]

出0入234汤圆

发表于 2023-6-28 10:41:33 | 显示全部楼层 |阅读模式
本帖最后由 正点原子 于 2023-6-28 10:41 编辑

1)实验平台:正点原子 DFZU2EG_4EV MPSoC开发板
2)购买链接:https://item.taobao.com/item.htm?&id=692368045899
3)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-340252-1-1.html
4)正点原子官方B站:https://space.bilibili.com/394620890
5)正点原子FPGA交流群:994244016 lQLPJxaFi2zaB4UWWrDAMgIsFEW2pwLb3abnwDMA_90_22.png
lQDPJxaFi2nfFizMjM0CbLCPlxn_FVheIQLb3aGrwFQA_620_140.jpg

lQLPJxaFi2nfFhLMkM0BXrDNvOUyeU_FPgLb3aGvQNIA_350_144.png

第二十五章 TFTLCD(MCU屏)实验


本章将介绍使用APM32E103驱动TFTLCD(MCU屏)进行显示。通过本章的学习,读者将学习到EMMC(外部存储器控制器)中SMC(静态存储控制器)的使用。
本章分为如下几个小节:
25.1硬件设计
25.2 程序设计
25.3 下载验证


25.1 硬件设计
25.1.1 例程功能

1. TFTLCD模块显示实验信息和LCD驱动器的ID,同时不停地切换底色
2. LED0闪烁,指示程序正在运行
25.1.2 硬件资源
1. LED
        LED0 - PB5
2. 正点原子 2.8/3.5/4.3/7/10寸TFTLCD模块(仅限MCU屏,16位8080并口驱动)
25.1.3 原理图
本章实验使用了正点原子的TFTLCD模块(兼容正点原子2.8/3.5/4.3/7/10寸的TFTLCD模块),该模块需通过LCD转接板与板载的TFTLCD接口进行连接,该接口与板载MCU的连接原理图,如下图所示:
第二十五章 TFTLCD428.png
图25.1.3.1 TFTLCD模块与MCU的连接原理图



从上图中可以看到,TFTLCD模块连接至SMC的存储块1的区域块4,并且使用了地址线A10作为TFTLCD模块命令或数据的选择信号,结合《APM32E103xCxE用户手册》,便可计算出配置好SMC后,TFTLCD模块的命令访问地址被映射到0x6C00007E,TFTLCD模块的数据访问地址被映射到0x6C000080。
25.2 程序设计
25.2.1 Geehy标准库的SMC驱动

本章实验通过SMC驱动8080并口的TFTLCD模块,通过SMC可以将TFTLCD模块的命令和数据寄存器映射为两个地址,往这两个地址写入或读取数据就可直接与TFTLCD模块进行通讯,因此需要对SMC做相应的配置,,具体的步骤如下:
①:配置SMC存储块1的区域块4
②:使能SMC存储块1的区域块4
在Geehy标准库中对应的驱动函数如下:
①:配置SMC存储块1的区域块
该函数用于配置SMC存储块1的区域块,其函数原型如下所示:
void SMC_ConfigNORSRAM(SMC_NORSRAMConfig_T* smcNORSRAMConfig);
该函数的形参描述,如下表所示:
lQLPJxVvvUIPYipLzQHesJg-e8EvY7uwBJGVDnvA4gA_478_75.png
表25.2.1.1 函数SMC_ConfigNORSRAM()形参描述

该函数的返回值描述,如下表所示:
lQLPJw4VFd_znOonzQHcsN-K1pT3oTS8BJGVe3VA4gA_476_39.png
表25.2.1.2 函数SMC_ConfigNORSRAM()返回值描述

该函数使用SMC_NORSRAMConfig_T类型的结构体变量传入SMC存储块1区域块的配置参数,该结构体的定义如下所示:
typedef enum
{
    SMC_BANK1_NORSRAM_1,                                                /* SMC存储块1区域块1 */
    SMC_BANK1_NORSRAM_2,                                                /* SMC存储块1区域块2 */
    SMC_BANK1_NORSRAM_3,                                                /* SMC存储块1区域块3 */
    SMC_BANK1_NORSRAM_4                                                        /* SMC存储块1区域块4 */
} SMC_BANK1_NORSRAM_T;

typedef enum
{
    SMC_DATA_ADDRESS_MUX_DISABLE,                                /* 禁止数据地址总线复用 */
    SMC_DATA_ADDRESS_MUX_ENABLE                                        /* 使能数据地址总线复用 */
} SMC_DATA_ADDRESS_MUX_T;

typedef enum
{
    SMC_MEMORY_TYPE_SRAM,                                                /* SRAM */
    SMC_MEMORY_TYPE_PSRAM,                                                /* PSRAM */
    SMC_MEMORY_TYPE_NOR                                                        /* NORFlash */
} SMC_MEMORY_TYPE_T;

typedef enum
{
    SMC_MEMORY_DATA_WIDTH_8BIT,                                        /* 8位数据宽度 */
    SMC_MEMORY_DATA_WIDTH_16BIT                                        /* 16位数据宽度 */
} SMC_MEMORY_DATA_WIDTH_T;

typedef enum
{
    SMC_BURST_ACCESS_MODE_DISABLE,                                /* 禁用突发访问模式 */
    SMC_BURST_ACCESS_MODE_ENABLE                                /* 使能突发访问模式 */
} SMC_BURST_ACCESS_MODE_T;

typedef enum
{
    SMC_ASYNCHRONOUS_WAIT_DISABLE,                                /* 禁用异步等待 */
    SMC_ASYNCHRONOUS_WAIT_ENABLE                                /* 使能异步等待 */
} SMC_ASYNCHRONOUS_WAIT_T;

typedef enum
{
    SMC_WAIT_SIGNAL_POLARITY_LOW,                                /* 低电平有效 */
    SMC_WAIT_SIGNAL_POLARITY_HIGH                                /* 高电平有效 */
} SMC_WAIT_SIGNAL_POLARITY_T;

typedef enum
{
    SMC_WRAP_MODE_DISABLE,                                                /* 禁止非对齐的突发访问 */
    SMC_WRAP_MODE_ENABLE                                                /* 使能非对齐的突发访问 */
} SMC_WRAP_MODE_T;

typedef enum
{
    SMC_WAIT_SIGNAL_ACTIVE_BEFORE_WAIT_STATE,        /* 在等待前有效 */
    SMC_WAIT_SIGNAL_ACTIVE_DURING_WAIT_STATE        /* 在等在阶段有效 */
} SMC_WAIT_SIGNAL_ACTIVE_T;

typedef enum
{
    SMC_WRITE_OPERATION_DISABLE,                                /* 禁止写操作 */
    SMC_WRITE_OPERATION_ENABLE                                        /* 使能写操作  */
} SMC_WRITE_OPERATION_T;

typedef enum
{
    SMC_WAITE_SIGNAL_DISABLE,                                        /* 禁止等待信号 */
    SMC_WAITE_SIGNAL_ENABLE                                                /* 使能等待信号 */
} SMC_WAITE_SIGNAL_T;

typedef enum
{
    SMC_EXTENDEN_MODE_DISABLE,                                        /* 禁止扩展模式 */
    SMC_EXTENDEN_MODE_ENABLE                                        /* 使能扩展模式 */
} SMC_EXTENDEN_MODE_T;

typedef enum
{
    SMC_WRITE_BURST_DISABLE,                                        /* 禁止突发写 */
    SMC_WRITE_BURST_ENABLE                                                /* 使能突发写 */
} SMC_WRITE_BURST_T;

typedef enum
{
    SMC_ACCESS_MODE_A,                                                        /* 访问模式A */
    SMC_ACCESS_MODE_B,                                                        /* 访问模式B */
    SMC_ACCESS_MODE_C,                                                        /* 访问模式C */
    SMC_ACCESS_MODE_D                                                        /* 访问模式D */
} SMC_ACCESS_MODE_T;

typedef struct
{
    uint8_t addressSetupTime;                                        /* 地址建立时间 */
    uint8_t addressHodeTime;                                        /* 地址保持时间 */
    uint8_t dataSetupTime;                                                /* 数据建立时间 */
    uint8_t busTurnaroundTime;                                        /* 总线恢复时间 */
    uint8_t clockDivision;                                                /* 时钟分频系数 */
    uint8_t dataLatency;                                                /* 数据保持时间 */
    SMC_ACCESS_MODE_T accessMode;                                /* 访问模式 */
} SMC_NORSRAMTimingConfig_T;

typedef struct
{
    SMC_BANK1_NORSRAM_T                        bank;                                        /* SMC存储块1区域块 */
    SMC_DATA_ADDRESS_MUX_T                dataAddressMux;                        /* 数据地址总线复用 */
    SMC_MEMORY_TYPE_T                        memoryType;                                /* 存储器类型 */
    SMC_MEMORY_DATA_WIDTH_T                memoryDataWidth;                /* 数据宽度 */
    SMC_BURST_ACCESS_MODE_T                burstAcceesMode;                /* 突发访问模式 */
    SMC_ASYNCHRONOUS_WAIT_T                asynchronousWait;                /* 异步等待 */
    SMC_WAIT_SIGNAL_POLARITY_T        waitSignalPolarity;                /* 等待信号极性    */
    SMC_WRAP_MODE_T                                wrapMode;                                /* 非对齐的突发访问 */
    SMC_WAIT_SIGNAL_ACTIVE_T        waitSignalActive;                /* 等待时序 */
    SMC_WRITE_OPERATION_T                writeOperation;                        /* 写操作 */
    SMC_WAITE_SIGNAL_T                        waiteSignal;                        /* 等待信号 */
    SMC_EXTENDEN_MODE_T                        extendedMode;                        /* 扩展模式 */
    SMC_WRITE_BURST_T                        writeBurst;                                /* 突发写 */
    SMC_NORSRAMTimingConfig_T        *readWriteTimingStruct;        /* 读写时序 */
    SMC_NORSRAMTimingConfig_T        *writeTimingStruct;                /* 写时序 */
} SMC_NORSRAMConfig_T;
该函数的使用示例,如下所示:
#include "apm32e10x.h"
#include "apm32e10x_smc.h"

void example_fun(void)
{
    SMC_NORSRAMConfig_T smc_norsram_init_struct;
    SMC_NORSRAMTimingConfig_T smc_read_timing_struct;
    SMC_NORSRAMTimingConfig_T smc_write_timing_struct;
   
    /* 配置SMC读时序 */
    smc_read_timing_struct.addressSetupTime        = 0x0F;
    smc_read_timing_struct.addressHodeTime                = 0x00;
    smc_read_timing_struct.dataSetupTime                = 0x3C;
    smc_read_timing_struct.busTurnaroundTime        = 0;
    smc_read_timing_struct.clockDivision                = 0;
    smc_read_timing_struct.dataLatency                        = 0;
    smc_read_timing_struct.accessMode                        = SMC_ACCESS_MODE_A;
   
    /* 配置SMC写时序 */
    smc_write_timing_struct.addressSetupTime        = 0x09;
    smc_write_timing_struct.addressHodeTime        = 0x00;
    smc_write_timing_struct.dataSetupTime                = 0x09;
    smc_write_timing_struct.busTurnaroundTime        = 0;
    smc_write_timing_struct.clockDivision                = 0;
    smc_write_timing_struct.dataLatency                = 0;
    smc_write_timing_struct.accessMode                        = SMC_ACCESS_MODE_A;
   
    /* 配置SMC存储块1区域块1 */
    smc_norsram_init_struct.bank                                = SMC_BANK1_NORSRAM_1;
    smc_norsram_init_struct.dataAddressMux                = SMC_DATA_ADDRESS_MUX_DISABLE;
    smc_norsram_init_struct.memoryType                        = SMC_MEMORY_TYPE_SRAM;
    smc_norsram_init_struct.memoryDataWidth        = SMC_MEMORY_DATA_WIDTH_16BIT;
    smc_norsram_init_struct.burstAcceesMode        = SMC_BURST_ACCESS_MODE_DISABLE;
    smc_norsram_init_struct.asynchronousWait        = SMC_ASYNCHRONOUS_WAIT_DISABLE;
    smc_norsram_init_struct.waitSignalPolarity        = SMC_WAIT_SIGNAL_POLARITY_LOW;
    smc_norsram_init_struct.wrapMode                        = SMC_WRAP_MODE_DISABLE;
    smc_norsram_init_struct.waitSignalActive        =
           SMC_WAIT_SIGNAL_ACTIVE_BEFORE_WAIT_STATE;
    smc_norsram_init_struct.writeOperation                = SMC_WRITE_OPERATION_ENABLE;
    smc_norsram_init_struct.waiteSignal                = SMC_WAITE_SIGNAL_DISABLE;
    smc_norsram_init_struct.extendedMode                = SMC_EXTENDEN_MODE_ENABLE;
    smc_norsram_init_struct.writeBurst                        = SMC_WRITE_BURST_DISABLE;
    smc_norsram_init_struct.readWriteTimingStruct        = &smc_read_timing_struct;
    smc_norsram_init_struct.writeTimingStruct        = &smc_write_timing_struct;
    SMC_ConfigNORSRAM(&smc_norsram_init_struct);
}
②:使能SMC存储块1的区域块
该函数用于使能SMC存储块1的区域块,其函数原型如下所示:
void SMC_EnableNORSRAM(SMC_BANK1_NORSRAM_T bank);
该函数的形参描述,如下表所示:
lQLPJx9iUwmHw2pLzQHfsEXaUG7EtbWzBJGVb01AxgA_479_75.png
表25.2.1.3 函数SMC_EnableNORSRAM()形参描述

该函数的返回值描述,如下表所示:
lQLPJwnbsiCk0qonzQHdsDEbj65R9negBJGVKTuAaAA_477_39.png
表25.2.1.4 函数SMC_EnableNORSRAM()返回值描述

该函数的使用示例,图下所示:
#include "apm32e10x.h"
#include "apm32e10x_smc.h"

void example_fun(void)
{
    /* 使能SMC存储块1区域块1 */
    SMC_EnableNORSRAM(SMC_BANK1_NORSRAM_1);
}
25.2.2 TFTLCD驱动
本章实验的TFTLCD驱动主要负责向应用层提供TFTLCD的初始化和各种TFTLCD显示的操作函数。本章实验中,TFTLCD的驱动代码包括lcd.c、lcd_ex.c、lcd.h和字体文件lcdfont.h四个文件。
由于TFTLCD模块需要使用到打量的GPIO引脚,因此对于GPIO的相关定义,请读者自行查看lcd.c和lcd.h这两个文件。
TFTLCD驱动中,TFTLCD的初始化函数,如下所示:
/**
* @brief       初始化LCD
* @param       无
* @retval      无
*/
void lcd_init(void)
{
    GPIO_Config_T gpio_init_struct;
    SMC_NORSRAMConfig_T smc_norsram_init_struct;
    SMC_NORSRAMTimingConfig_T smc_read_timing_struct;
    SMC_NORSRAMTimingConfig_T smc_write_timing_struct;
   
    /* 使能时钟 */
    LCD_WR_GPIO_CLK_ENABLE();                        /* 使能SMC_NWE引脚端口时钟 */
    LCD_RD_GPIO_CLK_ENABLE();                        /* 使能SMC_NOE引脚端口时钟 */
    LCD_BL_GPIO_CLK_ENABLE();                        /* 使能LCD_BL引脚端口时钟 */
    LCD_CS_GPIO_CLK_ENABLE();                        /* 使能SMC_NE4引脚端口时钟 */
    LCD_RS_GPIO_CLK_ENABLE();                        /* 使能SMC_A6引脚端口时钟 */
RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_SMC);    /* 使能EMMC时钟 */
/* 使能SMC_D0/1/2/3/13/14/15引脚端口时钟 */
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOD);
/* 使能SMC_D4/5/6/7/8/9/10/11/12引脚端口时钟 */
    RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOD);
   
    /* 配置SMC_NWE引脚 */
    gpio_init_struct.pin = LCD_WR_GPIO_PIN;          /* SMC_NWE引脚 */
    gpio_init_struct.mode = GPIO_MODE_AF_PP;         /* 复用功能模式 */
    gpio_init_struct.speed = GPIO_SPEED_50MHz;       /* 高速 */
    GPIO_Config(LCD_WR_GPIO_PORT, &gpio_init_struct);/* 配置SMC_NWE引脚 */
   
    /* 配置SMC_NOE引脚 */
    gpio_init_struct.pin = LCD_RD_GPIO_PIN;          /* SMC_NOE引脚 */
    GPIO_Config(LCD_RD_GPIO_PORT, &gpio_init_struct);/* 配置SMC_NOE引脚 */
   
    /* 配置SMC_NEx引脚 */
    gpio_init_struct.pin = LCD_CS_GPIO_PIN;          /* SMC_NEx引脚 */
    GPIO_Config(LCD_CS_GPIO_PORT, &gpio_init_struct);/* 配置SMC_NEx引脚 */
   
    /* 配置SMC_Ay引脚 */
    gpio_init_struct.pin = LCD_RS_GPIO_PIN;          /* SMC_Ay引脚 */
    GPIO_Config(LCD_RS_GPIO_PORT, &gpio_init_struct);/* 配置SMC_Ay引脚 */
   
    /* 配置SMC_Dn引脚 */
    gpio_init_struct.pin =  GPIO_PIN_14 |            /* SMC_D0 */
                            GPIO_PIN_15 |            /* SMC_D1 */
                            GPIO_PIN_0 |             /* SMC_D2 */
                            GPIO_PIN_1 |             /* SMC_D3 */
                            GPIO_PIN_8 |             /* SMC_D13 */
                            GPIO_PIN_9 |             /* SMC_D14 */
                            GPIO_PIN_10;             /* SMC_D15 */
    GPIO_Config(GPIOD, &gpio_init_struct);                                                  /* 配置SMC_Dn引脚 */
    gpio_init_struct.pin =  GPIO_PIN_7 |             /* SMC_D4 */
                            GPIO_PIN_8 |             /* SMC_D5 */
                            GPIO_PIN_9 |             /* SMC_D6 */
                            GPIO_PIN_10 |            /* SMC_D7 */
                            GPIO_PIN_11 |            /* SMC_D8 */
                            GPIO_PIN_12 |            /* SMC_D9 */
                            GPIO_PIN_13 |            /* SMC_D10 */
                            GPIO_PIN_14 |            /* SMC_D11 */
                            GPIO_PIN_15;             /* SMC_D12 */
    GPIO_Config(GPIOE, &gpio_init_struct);           /* 配置SMC_Dn引脚 */
   
    /* 配置LCD_BL引脚 */
    gpio_init_struct.pin = LCD_BL_GPIO_PIN;          /* LCD_BL引脚 */
    gpio_init_struct.mode = GPIO_MODE_OUT_PP;        /* 通用输出模式 */
    GPIO_Config(LCD_BL_GPIO_PORT, &gpio_init_struct);/* 配置LCD_BL引脚 */
   
    /* 配置SMC读时序 */
    smc_read_timing_struct.addressSetupTime = 1;     /* 地址建立时间 */
    smc_read_timing_struct.addressHodeTime = 0;      /* 地址保持时间 */
smc_read_timing_struct.dataSetupTime = 26;       /* 数据建立时间 */
/* 访问模式 */
    smc_read_timing_struct.accessMode = SMC_ACCESS_MODE_A;
    /* 配置SMC写时序 */
    smc_write_timing_struct.addressSetupTime = 1;    /* 地址建立时间 */
    smc_write_timing_struct.addressHodeTime = 0;     /* 地址保持时间 */
smc_write_timing_struct.dataSetupTime = 3;       /* 数据建立时间 */
/* 访问模式 */
    smc_write_timing_struct.accessMode = SMC_ACCESS_MODE_A;
   
/* 配置SMC */
smc_norsram_init_struct.bank = SMC_BANK1_NORSRAM_4;/* 使用SMC_NE4 */
/* 禁止数据、地址总线复用 */
smc_norsram_init_struct.dataAddressMux     = SMC_DATA_ADDRESS_MUX_DISABLE;
/* SRAM类型 */
smc_norsram_init_struct.memoryType         = SMC_MEMORY_TYPE_SRAM;
/* 16位数据宽度 */
smc_norsram_init_struct.memoryDataWidth    = SMC_MEMORY_DATA_WIDTH_16BIT;
/* 禁止突发访问 */
smc_norsram_init_struct.burstAcceesMode    = SMC_BURST_ACCESS_MODE_DISABLE;
/* 禁止异步传输期间的等待信号 */
smc_norsram_init_struct.asynchronousWait   = SMC_ASYNCHRONOUS_WAIT_DISABLE;
/* 配置等待信号极性,仅在突发访问模式下有效 */
    smc_norsram_init_struct.waitSignalPolarity = SMC_WAIT_SIGNAL_POLARITY_LOW;
   /* 禁止非对齐的突发访问 */
smc_norsram_init_struct.wrapMode = SMC_WRAP_MODE_DISABLE;
/* 配置等待时序 */
    smc_norsram_init_struct.waitSignalActive = SMC_WAIT_SIGNAL_ACTIVE_BEFORE_WAIT_STATE;
/* 使能写存储器 */
smc_norsram_init_struct.writeOperation = SMC_WRITE_OPERATION_ENABLE;
/* 禁止等待信号 */
smc_norsram_init_struct.waiteSignal    = SMC_WAITE_SIGNAL_DISABLE;
/* 使能扩展模式 */
smc_norsram_init_struct.extendedMode   = SMC_EXTENDEN_MODE_ENABLE;
/* 使能突发写 */
smc_norsram_init_struct.writeBurst     = SMC_WRITE_BURST_DISABLE;
/* 读时序 */
smc_norsram_init_struct.readWriteTimingStruct = &smc_read_timing_struct;
/* 写时序 */
smc_norsram_init_struct.writeTimingStruct = &smc_write_timing_struct;
/* 配置SMC */
SMC_ConfigNORSRAM(&smc_norsram_init_struct);
/* 使能存储块1区域块4 */
    SMC_EnableNORSRAM(SMC_BANK1_NORSRAM_4);
    delay_ms(50);
   
    /* 尝试读取ILI9341的ID */
    lcd_wr_regno(0xD3);
    lcddev.id = lcd_rd_data();                    /* 无效数据 */
    lcddev.id = lcd_rd_data();                    /* 读取到0x00 */
    lcddev.id = lcd_rd_data() << 8;               /* 读取到0x93 */
    lcddev.id |= lcd_rd_data();                   /* 读取到0x41 */
    if (lcddev.id != 0x9341)                                                                /* 尝试读取ST7789的ID */
    {
        lcd_wr_regno(0x04);
        lcddev.id = lcd_rd_data();                /* 无效数据 */
        lcddev.id = lcd_rd_data();                /* 读取到0x85 */
        lcddev.id = lcd_rd_data() << 8;           /* 读取到0x85 */
        lcddev.id |= lcd_rd_data();               /* 读取到0x52 */
        if (lcddev.id == 0x8552)                  /* 将ST7789的ID记为0x7789 */
        {
            lcddev.id = 0x7789;
        }
        if (lcddev.id != 0x7789)                  /* 尝试读取NT35310的ID */
        {
            lcd_wr_regno(0xD4);
            lcddev.id = lcd_rd_data();            /* 无效数据 */
            lcddev.id = lcd_rd_data();            /* 读取到0x01 */
            lcddev.id = lcd_rd_data() << 8;       /* 读取到0x53 */
            lcddev.id |= lcd_rd_data();           /* 读取到0x10 */
            if (lcddev.id != 0x5310)              /* 尝试读取NT35510的ID */
            {
                /* 发送密钥(厂家提供) */
                lcd_write_reg(0xF000, 0x0055);
                lcd_write_reg(0xF001, 0x00AA);
                lcd_write_reg(0xF002, 0x0052);
                lcd_write_reg(0xF003, 0x0008);
                lcd_write_reg(0xF004, 0x0001);
               
                lcd_wr_regno(0xC500);
                lcddev.id = lcd_rd_data() << 8;   /* 读取到0x80 */
                lcd_wr_regno(0xC501);
                lcddev.id |= lcd_rd_data();       /* 读取到0x00 */
/* 因为此NT5510的指令恰好为SSD1963的软件复位指令 */
                delay_ms(5);

                if (lcddev.id != 0x5510)          /* 尝试读取SSD1963的ID */
                {
                    lcd_wr_regno(0xA1);
                    lcddev.id = lcd_rd_data();
                    lcddev.id = lcd_rd_data()<<8; /* 读取到0x57 */
                    lcddev.id |= lcd_rd_data();   /* 读取到0x61 */
                    if (lcddev.id == 0x5761)      /* 将SSD1963的ID记为0x1963 */
                    {
                        lcddev.id = 0x1963;
                    }
                }
            }
        }
    }
   
    if (lcddev.id == 0x7789)
    {
        lcd_ex_st7789_reginit();                  /* 执行ST7789初始化 */
    }
    else if (lcddev.id == 0x9341)
    {
        lcd_ex_ili9341_reginit();                 /* 执行ILI9341初始化 */
    }
    else if (lcddev.id == 0x5310)
    {
        lcd_ex_nt35310_reginit();                 /* 执行NT35310初始化 */
    }
    else if (lcddev.id == 0x5510)
    {
        lcd_ex_nt35510_reginit();                 /* 执行NT35510初始化 */
    }
    else if (lcddev.id == 0x1963)
    {
        lcd_ex_ssd1963_reginit();                 /* 执行SSD1963初始化 */
        lcd_ssd_backlight_set(100);               /* 背光设置为最亮 */
    }
    lcd_display_dir(0);                           /* 默认设置为竖屏 */
    LCD_BL(1);                                    /* 点亮背光 */
    lcd_clear(WHITE);                             /* 清屏 */
}
从上的代码中可以看出,本章实验的TFTLCD驱动是兼容了正点原子的多款TFTLCD模块的,因此在初始化完SMC后,会与TFTLCD进行通讯,确定TFTLCD的型号,然后根据型号针对性地对TFTLCD模块进行配置。
TFTLCD驱动中与TFTLCD模块通讯的函数,如下所示:
/**
* @brief       LCD写数据
* @param       data: 要写入的数据
* @retval      无
*/
void lcd_wr_data(volatile uint16_t data)
{
    data = data;
    LCD->LCD_RAM = data;
}

/**
* @brief       LCD写寄存器编号或地址
* @param       regno: 寄存器编号或地址
* @retval      无
*/
void lcd_wr_regno(volatile uint16_t regno)
{
    regno = regno;
    LCD->LCD_REG = regno;
}

/**
* @brief       LCD写寄存器
* @param       regno: 寄存器编号
* @param       data : 要写入的数据
* @retval      无
*/
void lcd_write_reg(uint16_t regno, uint16_t data)
{
    LCD->LCD_REG = regno;
    LCD->LCD_RAM = data;
}

/**
* @brief       LCD读数据
* @param       无
* @retval      读取到的数据
*/
static uint16_t lcd_rd_data(void)
{
    volatile uint16_t ram;
    ram = LCD->LCD_RAM;
    return ram;
}
从上面的代码中可以看出,与TFTLCD的通讯都是通过LCD这一结构体对象来完成的,对于LCD结构体的相关定义,如下所示:
#define LCD_SMC_NEX    4
#define LCD_SMC_AX     10

typedef struct
{
    volatile uint16_t LCD_REG;
    volatile uint16_t LCD_RAM;
} LCD_TypeDef;
从LCD结构体的相关定义中可以看出,与TFTLCD模块的通讯地址是与TFTLCD连接的SMC存储块1的区域块和TFTLCD模块命令、数据选择信号所连接的SMC地址线是有关的。通过上面宏定义的计算,可以算出LCD_BASE宏定义的值为0x6C00007E,因此访问LCD->LCD_REG就是访问0x6C00007E这一地址,访问LCD->LCD_RAM就是访问0x6C000080这一地址,这两个地址也就是通过SMC映射的TFTLCD命令和数据寄存器的访问地址。
通过上面介绍的驱动函数就能够与TFTLCD模块进行通讯了,而在TFTLCD模块的显示屏上显示出特定的图案或字符或设置TFTLCD模块的显示方向等等的操作都是能够通过TFTLCD模块规定的特定命令来完成的,想深究的读者可以产看正点原子TFTLCD模块的用户手册或查看实际使用的TFTLCD模块的相关文档。
25.2.3 实验应用代码
本实验的应用代码,如下所示:
int main(void)
{
    uint8_t x = 0;
    uint8_t lcd_id[12];
   
    NVIC_ConfigPriorityGroup(NVIC_PRIORITY_GROUP_4);  /* 设置中断优先级分组为组4 */
    sys_apm32_clock_init(15);                         /* 配置系统时钟 */
    delay_init(120);                                  /* 初始化延时功能 */
    usart_init(115200);                               /* 初始化串口 */
    led_init();                                       /* 初始化LED */
    lcd_init();                                       /* 初始化LCD */
    /* 显示LCD屏ID信息 */
    sprintf((char *)lcd_id, "LCD ID: %04X", lcddev.id);
   
    while (1)
    {
        switch (x)
        {
            case 0:
            {
                lcd_clear(WHITE);
                break;
            }
            case 1:
            {
                lcd_clear(BLACK);
                break;
            }
            case 2:
            {
                lcd_clear(BLUE);
                break;
            }
            case 3:
            {
                lcd_clear(RED);
                break;
            }
            case 4:
            {
                lcd_clear(MAGENTA);
                break;
            }
            case 5:
            {
                lcd_clear(GREEN);
                break;
            }
            case 6:
            {
                lcd_clear(CYAN);
                break;
            }
            case 7:
            {
                lcd_clear(YELLOW);
                break;
            }
            case 8:
            {
                lcd_clear(BRRED);
                break;
            }
            case 9:
            {
                lcd_clear(GRAY);
                break;
            }
            case 10:
            {
                lcd_clear(LGRAY);
                break;
            }
            case 11:
            {
                lcd_clear(BROWN);
                break;
            }
        }
        
        lcd_show_string(10, 40, 240, 32, 32, "APM32", RED);
        lcd_show_string(10, 80, 240, 24, 24, "TFTLCD TEST", RED);
        lcd_show_string(10, 110, 240, 16, 16, "ATOM@ALIENTEK", RED);
        lcd_show_string(10, 130, 240, 16, 16, (char *)lcd_id, RED);
        
        x++;
        
        if (x == 12)
        {
            x = 0;
        }
        LED0_TOGGLE();
        delay_ms(1000);
    }
}
从上面的代码中可以看出,在初始化完LCD后,便在LCD上显示一些本实验的相关信息,随后便每间隔1000毫秒就更换一次LCD屏幕显示的背景色。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-6 13:56

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表