日韩一区二区三区精品,欧美疯狂xxxxbbbb牲交,热99re久久免费视精品频,人妻互换 综合,欧美激情肉欲高潮视频

歷史上的今天

今天是:2025年07月26日(星期六)

2021年07月26日 | STM32CubeMX | 35-使用硬件FSMC驅(qū)動TFT-LCD屏幕

發(fā)布者:敬亭山人 來源: eefocus關(guān)鍵字:STM32CubeMX 手機看文章 掃描二維碼
隨時隨地手機看文章

本篇詳細的記錄了如何使用STM32CubeMX配置 STM32f407ZGT6 的硬件FSMC外設(shè)驅(qū)動TFT-LCD屏幕。


1. 準備工作

硬件準備

  • 開發(fā)板
    首先需要準備一個開發(fā)板,這里我準備的是STM32F407ZGT6的開發(fā)板。

  • TFT-LCD
    開發(fā)板底板接正點原子4.3寸TFT-LCD。

2. STM32 FSMC外設(shè)概述

2.1. 什么是FSMC

FSMC全稱 Flexible static memory controller,靈活的靜態(tài)內(nèi)存控制器,顧名思義,其主要作用是:負責向外部擴展的存儲類設(shè)備提供控制信號。


FSMC內(nèi)存控制器支持的存儲設(shè)備有:

  • Nor Flash、SRAM、PSRAM

  • Nand Flash

  • 類SRAM設(shè)備

2.2. FSMC外設(shè)的功能框圖

在這里插入圖片描述

2.3. 外部設(shè)備的地址映射(重點)

從FSMC的角度來看,外部的存儲設(shè)備被分為幾個固定大小的Bank,每個bank 256 MB。

整個FSMC外設(shè)映射地址的劃分如圖:

2.3.1. Bank1

Bank1的地址空間為:0x6000 0000 - 0x6FFF FFFF,支持外接Nor Flash、PSRAM、SRAM等設(shè)備,還可以外接DM9000等類存儲設(shè)備。


整個Bank1的地址空間被劃分為四個子bank,每個子bank的大小為64MB,剛好對應(yīng)FSMC外設(shè)的地址總線(FSMC_A[0:25])有26條(2^26=64MB)。


FSMC還有兩條內(nèi)部總線ADDR[27:26],用這兩路控制片選信號,如下表:

BANK1控制時序模型

接下來講述BANK1控制外部存儲器的時序模式,BANK1又稱為Nor Flash/SRAM/PSRAM控制器,后續(xù)暫且叫它SRAM控制器。


SRAM控制器支持兩種控制模式:

  • 同步模式

  • 異步模式

對于異步模式,F(xiàn)SMC主要設(shè)置三個時序參數(shù):

  • 地址建立時間:ADDSET

  • 數(shù)據(jù)建立時間:DATASET

  • 地址保持時間:ADDHLD

根據(jù)SRAM、PSRAM、Nor Flash的綜合特點,F(xiàn)MC定義了四種不同的異步時序模型,如下表:

本文中控制TFT-LCD使用的就是異步ModeA時序模型。


異步ModeA時序模型

模式A時序模型的優(yōu)勢在于:支持獨立的讀寫時序控制。這一點對于控制TFT-LCD來說,非常符合。因為TFT-LCD在讀的時候,一般比較慢,而在寫入的時候一般比較快。

模式A的讀操作時序如圖:

模式A的寫操作時序如圖:

圖中ADDSET和DATASET兩個時序的值,后續(xù)配置的時候會詳細講述。


2.3.2. Bank2、3/4

只能外接Nand Flash設(shè)備和PC Card設(shè)備:

3. 使用STM32CubeMX生成工程

選擇芯片型號

打開STM32CubeMX,打開MCU選擇器:

搜索并選中芯片STM32F407ZGT6:

配置時鐘源

  • 如果選擇使用外部高速時鐘(HSE),則需要在System Core中配置RCC;

  • 如果使用默認內(nèi)部時鐘(HSI),這一步可以略過;

這里我都使用外部時鐘:

調(diào)試選項配置

默認沒有配置下載引腳,燒錄之后下載器將無法再檢測到,這里我使用ST-Link,所以配置為SW選項:

配置串口

開發(fā)板板載了一個CH340換串口,連接到USART1,但是引腳不是默認引腳,需要手動修改。


接下來開始配置USART1:

配置FSMC外設(shè)

本文所使用的開發(fā)板中,將TFT-LCD當做SRAM來操作,連接在FSMC的BANK1的第4個區(qū)域。
知識點:為什么TFT-LCD可以當做SRAM來控制?
因為TFT-LCD和SRAM相比,同樣需要D0-D15數(shù)據(jù)線,WR、RD、CS控制線,唯一不同的就是TFT-LCD需要一條RS信號線(用于控制傳輸?shù)氖敲钸€是數(shù)據(jù)),而SRAM則需要一堆地址線,所以可以巧妙的使用任意一條地址線來當做RS信號。

FSMC配置

開發(fā)板上 TFT-LCD 的原理圖如下:

通過原理圖可以看出:

  • LCD D0-D15:使用了16bit:FSMC D0 - FSMC D15;

  • LCD_RS:使用FSMC A6來控制向LCD寫入數(shù)據(jù)還是命令(0-命令,1-數(shù)據(jù));

  • LCD_BL:背光控制,對應(yīng)PB5;

  • LCD_CS:LCD片選信號,F(xiàn)MC_NE4,表示使用Bank1的Bank4子區(qū)域

  • LCD_WR :LCD寫使能,F(xiàn)SMC_NWE;

  • LCD_RD:LCD讀使能,F(xiàn)SMC_NOE;

  • RESET:LCD復(fù)位信號,直接與單片機復(fù)位信號接在一起;

根據(jù)這些信息,在STM32CubeMX中先配置SRAM4的基本設(shè)置:

此處如果選擇LCD接口類型和SRAM類型的區(qū)別在于:
LCD接口類型只會配置用到的那一個地址引腳,而SRAM類型則會配置所有的地址引腳。

SRAM基本參數(shù)配置

首先設(shè)置基本的參數(shù),允許讀與寫使用不同的模式:

SRAM時序參數(shù)配置

本文中使用的LCD控制器為NT35510控制器,找到其數(shù)據(jù)手冊,查看:

其中主要的時序參數(shù)配置方法如下。

讀時序配置

① HCLK

時序參數(shù)都是以HCLK的周期為單位的,在本文中HCLK=168Mhz,所以一個周期為5.95ns。

② 地址建立時間:Address setup time(ADDSET)

該時序的最大值的15個HCLK,從圖中可以看出,NT35110控制器要求讀的時候最小為10ns,,所以設(shè)為2即可,2x5.95=11.9ns。

③ 數(shù)據(jù)持續(xù)時間:Data setup time(DATASET)

讀時序比較慢,該時序的最大值為255個HCLK,從圖中可以看出,NT35510控制器要求的數(shù)據(jù)建立時間最小為15ns,但因為讀時序比較慢,所以設(shè)為4,4x5.95=23.8ns。

寫時序配置

① HCLK

時序參數(shù)都是以HCLK的周期為單位的,在本文中HCLK=168Mhz,所以一個周期為5.95ns。

② 地址建立時間:Address setup time(ADDSET)

該時序的最大值為15個HCLK,NT35110控制器要求寫的時候最小為0,,所以設(shè)為0即可。

③ 數(shù)據(jù)持續(xù)時間:Data setup time(DATASET)

寫時序比較快,該時序的最大值為255個HCLK,圖中可以看出,NT35510控制器要求的數(shù)據(jù)建立時間最小為15ns,但因為讀時序比較慢,所以設(shè)為3,3x5.95=17.85ns。

綜合上述計算,配置情況如下:

配置背光引腳

配置時鐘樹

STM32F407ZGT6的最高主頻到168M,使HCLK = 168Mhz即可:
在這里插入圖片描述

生成工程設(shè)置

代碼生成設(shè)置

最后設(shè)置生成獨立的初始化文件:

生成代碼

點擊GENERATE CODE即可生成MDK-V5工程:

4. 編寫TFT-LCD驅(qū)動(測試是否可以正常讀寫ID)

特別提醒:STM32CubeMX生成的工程默認開啟了-O3優(yōu)化,編寫的驅(qū)動太菜了,會出問題,所以遇到玄學Bug請改為-O0優(yōu)化!


封裝底層發(fā)送/讀取函數(shù)

LCD的底層無非就是兩個API:發(fā)送命令、發(fā)送數(shù)據(jù),(有的還需要從屏幕讀取數(shù)據(jù)),接下來封裝出這兩(三)個底層API。


之前查看原理圖的時候,表示命令或者數(shù)據(jù)的LCD_RS控制引腳接在FMC_A6上,也就是說地址數(shù)據(jù)的第6位,所以在頭文件lcd-fsmc.h中先定義:


/* 通過地址線控制RS引腳 */

#define LCD_CMD_ADDR            0x6c00007E

#define LCD_DAT_ADDR            0x6c000080


接著開始封裝兩個(三個)底層操作函數(shù):


① 發(fā)送命令函數(shù):


/**

 * @brief    向LCD寫入命令

 * @param    cmd 待寫入命令

 * @retval   none

*/

static void lcd_write_cmd(__IO uint16_t cmd)

{

    *(uint16_t *)(LCD_CMD_ADDR) = cmd;

}


② 發(fā)送數(shù)據(jù)函數(shù):


/**

 * @brief    向LCD寫入數(shù)據(jù)

 * @param    data 待寫入數(shù)據(jù)

 * @retval   none

*/

static void lcd_write_data(__IO uint16_t data)

{

    *(uint16_t *)(LCD_DAT_ADDR) = data;

}


③ 讀取數(shù)據(jù)函數(shù):


/**

 * @brief    從LCD讀取數(shù)據(jù)

 * @param    none

 * @retval   讀取到的數(shù)據(jù)

*/

static uint16_t lcd_read_data(void)

{

    __IO uint16_t data;

    

    data = *(uint16_t *)(LCD_DAT_ADDR);

    

    return data;

}


基于這三個底層API,還可以封裝出讀寫LCD內(nèi)部寄存器的函數(shù):


/**

 * @brief    寫LCD中的寄存器

 * @param    reg  寄存器序號

 * @param    data 要寫入寄存器的值

 * @retval   none

*/

static void lcd_write_reg(__IO uint16_t reg, __IO uint16_t data)

{

    lcd_write_cmd(reg);

    lcd_write_data(data);

}


LCD控制參數(shù)結(jié)構(gòu)體

為了方便驅(qū)動不同的IC,保存不同的控制參數(shù),在lcd_fmc.h中封裝如下數(shù)據(jù)類型:


/**

 * @brief    保存LCD屏幕參數(shù)

 * @param    lcd_width     LCD屏幕寬度

 * @param    lcd_height    LCD屏幕高度

 * @param    lcd_id        LCD 驅(qū)動IC ID

 * @param    lcd_direction LCD橫屏顯示還是豎屏顯示,0-豎屏,1-橫屏

 * @param    wram_cmd      開始寫gram指令

 * @param    set_x_cmd     設(shè)置x坐標指令

 * @param    set_y_cmd     設(shè)置y坐標指令

*/

typedef struct lcd_params_st {

    uint16_t lcd_width;

    uint16_t lcd_height;

    uint16_t lcd_id;

    uint8_t  lcd_direction;

    uint16_t wram_cmd;

    uint16_t set_x_cmd;

    uint16_t set_y_cmd;

} lcd_params_t;


然后在頭文件中聲明外部變量定義,方便其他程序訪問:


extern lcd_params_t lcd_params;


在lcd_fsmc.c中定義此變量為全局變量:


lcd_params_t lcd_params;


LCD驅(qū)動打印日志的處理

為了方便程序開發(fā),難免要打印一些日志,但是如果printf沒有被重定向,則會導致LCD驅(qū)動卡死。為了避免這個問題,我們使用宏開關(guān)的方式來控制是否打印。


在lcd_fsmc.h中定義此宏開關(guān):


/* 使能此驅(qū)動是否打印調(diào)試日志(需要printf支持) */

#define LCD_LOG_ENABLE          1


接著可以定義一個日志打印函數(shù):


#if LCD_LOG_ENABLE

#include

#define LCD_LOG printf

#else

#define LCD_LOG(format,...)

#endif


之后所以需要打印的地方使用LCD_LOG代替printf即可。


編寫LCD控制器ID讀取函數(shù)

通過主動讀取此控制器ID,可以自動檢測出是哪種類型的控制器,然后執(zhí)行不同的驅(qū)動代碼:


static int lcd_read_id(void)

{

    /* 嘗試執(zhí)行ILI9341控制器ID的讀取流程 */

    lcd_write_cmd(0XD3);    

lcd_params.lcd_id = lcd_read_data();

lcd_params.lcd_id = lcd_read_data();

lcd_params.lcd_id = lcd_read_data();    

lcd_params.lcd_id <<= 8;

lcd_params.lcd_id |= lcd_read_data();

    /* 如果正常讀到,則返回成功 */

    if (lcd_params.lcd_id == 0x9341) {

        return 0;

    }

    

    /* 嘗試執(zhí)行NT35310控制器ID的讀取流程 */

    lcd_write_cmd(0XD4);    

    lcd_params.lcd_id = lcd_read_data();

    lcd_params.lcd_id = lcd_read_data();

    lcd_params.lcd_id = lcd_read_data();

    lcd_params.lcd_id <<= 8;  

    lcd_params.lcd_id |= lcd_read_data();

    /* 如果正常讀到,則返回成功 */

    if (lcd_params.lcd_id == 0x5310) {

        return 0;

    }

    

    /* 嘗試執(zhí)行NT35510控制器ID的讀取流程 */

    lcd_write_cmd(0XDA00);

    lcd_params.lcd_id = lcd_read_data();

    lcd_write_cmd(0XDB00);

    lcd_params.lcd_id = lcd_read_data();

    lcd_params.lcd_id <<= 8;  

    lcd_write_cmd(0XDC00);

    lcd_params.lcd_id |= lcd_read_data();

    /* 如果正常讀到,則返回成功 */

    if (lcd_params.lcd_id == 0x8000) {

        lcd_params.lcd_id = 0x5510;

        return 0;

    }

   

    /* 驅(qū)動IC不支持 */

    lcd_params.lcd_id = 0;

    return -1;

}


編寫LCD初始化函數(shù)

LCD初始化需要發(fā)送大量的命令和數(shù)據(jù),本文限于篇幅,只給出讀LCD 控制IC的ID的部分,用來測試LCD是否能正常讀寫足矣。


void lcd_init(void)

{

    /* 初始化FMC接口 */

    //MX_FSMC_Init();

    

    /* 開啟背光 */

    HAL_GPIO_WritePin(LCD_BL_GPIO_Port, LCD_BL_Pin, GPIO_PIN_SET);

    

  HAL_Delay(50); 

  /* 讀取LCD控制器IC */

    if (lcd_read_id() == -1) {

        LCD_LOG("Not Support LCD IC!rn");

        return;

    } else {

        LCD_LOG("LCD IC ID is:%#xrn", lcd_params.lcd_id);  

    }

return;

}


在lcd_fsmc.h中聲明該函數(shù):


void lcd_init(void);


測試是否可以正常操作LCD

在main.c中包含進來頭文件:


/* Private includes ----------------------------------------------------------*/

/* USER CODE BEGIN Includes */

#include

#include "lcd_fsmc.h"

/* USER CODE END Includes */


然后在man函數(shù)中調(diào)用:


/* USER CODE BEGIN 2 */

printf("4.3' TFT-LCD Test By Mculover666rn");

lcd_init();

/* USER CODE END 2 */


編譯,下載,在串口助手中查看結(jié)果:


5. 編寫TFT-LCD驅(qū)動(初始化、刷屏測試)

可以正常讀取ID之后,接下來的工作是:


發(fā)送一堆一堆的命令,初始化屏幕;

設(shè)置坐標

清屏

刷屏測試

① LCD開顯示、關(guān)顯示、LCD設(shè)置掃描方向、 LCD設(shè)置顯示方向、LCD設(shè)置光標位置這些函數(shù)代碼不多,需要的話請查看源碼。


② 清屏函數(shù):



static void lcd_write_ram_start(void)

{

    lcd_write_cmd(lcd_params.wram_cmd);

}


static void lcd_write_ram(uint16_t rgb_color)

{

    lcd_write_data(rgb_color);

}


void lcd_clear(uint16_t color)

{

uint32_t index = 0;      

uint32_t totalpoint = lcd_params.lcd_width;

    

    /* 計算得到總點數(shù) */

totalpoint *= lcd_params.lcd_height;

    

    /* 設(shè)置光標位置 */

lcd_set_cursor(0x00,0x0000);

    

    /* 開始寫入GRAM */

lcd_write_ram_start();

    

    /* 寫入數(shù)據(jù)到GRAM */

for (index = 0; index < totalpoint; index++) {

lcd_write_ram(color);

}

}


③ 初始化函數(shù):代碼過長,請查看源碼。


這三類函數(shù)實現(xiàn)完之后,就可以編寫一個如下的刷屏測試函數(shù):


void lcd_auto_clear(uint16_t period_ms)

{

    lcd_clear(BLACK);

    HAL_Delay(period_ms);

    lcd_clear(BLUE);

    HAL_Delay(period_ms);

    lcd_clear(GREEN);

    HAL_Delay(period_ms);

    lcd_clear(GBLUE);

    HAL_Delay(period_ms);

    lcd_clear(CYAN);

    HAL_Delay(period_ms);

    lcd_clear(GRAY);

    HAL_Delay(period_ms);

    lcd_clear(BROWN);

    HAL_Delay(period_ms);

    lcd_clear(RED);

    HAL_Delay(period_ms);

    lcd_clear(BRED);

    HAL_Delay(period_ms);

    lcd_clear(BRRED);

    HAL_Delay(period_ms);

    lcd_clear(YELLOW);

    HAL_Delay(period_ms);

    lcd_clear(WHITE);

    HAL_Delay(period_ms);

}


在main函數(shù)中調(diào)用此函數(shù),分別給予不同的刷新頻率,測試刷屏速度和效果。


6. 實現(xiàn)打點、畫線、填充函數(shù)(重點)

打點函數(shù)

/**

 * @brief    LCD打點函數(shù)

 * @param    x_pos x方向坐標

 * @param    y_pos y方向坐標

 * @retval   none

*/

void lcd_draw_point(uint16_t x_pos, uint16_t y_pos, uint16_t color)

[1] [2]
關(guān)鍵字:STM32CubeMX 引用地址:STM32CubeMX | 35-使用硬件FSMC驅(qū)動TFT-LCD屏幕

上一篇:STM32CubeMX | 33-使用GPIO讀取溫度傳感器數(shù)據(jù)(DS18B20)
下一篇:移植uc/OS-III最新版到小熊派開發(fā)板(STM32L431)

推薦閱讀

人機混合體或?qū)砼R,因為日本科學家已成功地將肌肉與機器人骨骼融合。 以前的這種嘗試都曇花一現(xiàn)且往往以失敗告終。報道稱,新的研究采用了不同的方法,從零開始培育肌肉、而不是摘取在動物體內(nèi)長出的肌肉。 這一發(fā)現(xiàn)可能會為制造類似超人的生化人鋪平道路,但科學家表示,大規(guī)模應(yīng)用至少要再過十年。 報道稱,這個交叉項目是生物機器人領(lǐng)域的一個突...
小米創(chuàng)始人、小米集團董事長兼CEO雷軍宣布,三家調(diào)研公司數(shù)據(jù)顯示,小米成為唯一半年度出貨量和銷量全部突破400萬臺的電視品牌,斬獲中國電視市場第一名。 小米集團副總裁、紅米Redmi品牌總經(jīng)理盧偉冰轉(zhuǎn)發(fā)微博表示祝賀,同時向廣大米粉征求建議:“Redmi要不要做電視?” 這不是盧偉冰第一次向網(wǎng)友提問,就Redmi要不要做電視,網(wǎng)友留言有支持也有反對。 ...
  在全球工業(yè)革命、技術(shù)創(chuàng)新大背景環(huán)境影響下,我國機器人產(chǎn)業(yè)得以蓬勃發(fā)展,工業(yè)機器人應(yīng)用空間進一步擴大,服務(wù)機器人產(chǎn)品百花齊放,特種機器人智能化技術(shù)水平也在不斷提升。同時,在國家相關(guān)政策引導下,機器人、機器人用芯片、機器人用等產(chǎn)業(yè)園區(qū)遍地開花,整個機器人研發(fā)熱度居高不下。   然而,中國機器人產(chǎn)業(yè)70%以上的市場份額已經(jīng)被美國ABB...
本篇詳細的記錄了如何使用STM32CubeMX配置 STM32G070RBT6 的硬件SPI外設(shè)與 SPI Flash 通信(W25Q64)。1. 準備工作硬件準備開發(fā)板首先需要準備一個開發(fā)板,這里我準備的是STM32G070RB的開發(fā)板SPI Flash開發(fā)板板載一片SPI Flash,型號為 W25Q64JV,大小為 8 MB。軟件準備需要安裝好Keil - MDK及芯片對應(yīng)的包,以便編譯和下載生成的代碼;準備一...

史海拾趣

問答坊 | AI 解惑

LabVIEW在大眾寶來A4轎車雨刮電機生產(chǎn)中的應(yīng)用1

大眾汽車公司生產(chǎn)的寶來A4轎車雨刮器電機為永磁式直流電機,電機工作電壓為13V,額定輸出功率為40W,電機引線為4線制,分別為高速端、低速端、復(fù)位端及接地端。雨刮器電機自帶減速箱,減速箱內(nèi)部有一開關(guān),當復(fù)位端接有13VDC電壓時,電機將先慢速旋 ...…

查看全部問答∨

開關(guān)電容梳狀濾波器幅頻特性的深入分析

最基本的開關(guān)電容電路是由電子開關(guān)和電容組成的,主要應(yīng)用是構(gòu)成各種低通、高通、帶通、帶阻等開關(guān)電容濾波器(Switched-Capacitor Filter,SCF)。將開關(guān)電容電路與運算放大器結(jié)合,組成的開關(guān)電容有源濾波器具有很多奇特的性質(zhì),但由于引入了電子開 ...…

查看全部問答∨

鍵盤的檢測與消抖

FPGA學習真在進行中,有很多值得分享的東西! 按鍵的檢測與消抖是處理非編碼鍵盤必須考慮的一部分。 在單片機中主要通過延時來消抖,通過while循環(huán)不斷讀 端口,確保鍵盤被松開。但是這樣會影響系統(tǒng)的效率。 在FPGA中鍵盤的消抖與檢測主要通過 ...…

查看全部問答∨

招驅(qū)動開發(fā)方面的兼職人員

本公司現(xiàn)在招驅(qū)動開發(fā)方面書籍的作者 待遇豐厚 有興趣的可以和我聯(lián)系  進行詳談 QQ878298915 請注明  驅(qū)動 Email pyq_1985@163.com…

查看全部問答∨

請問一下,有沒有增加P0、P2驅(qū)動能力的方法

如題。。。 除了加上拉電阻,還有沒有其它的辦法 有沒有專用的芯片之類的 麻煩各位了…

查看全部問答∨

avr studio 連接USB下載線老是 connect failed

裝了avrstudio 發(fā)現(xiàn)用USB連接不上開發(fā)板,看視頻教程里面,他實現(xiàn)裝了一個驅(qū)動,誰有這樣的驅(qū)動,在線等…

查看全部問答∨

PID問題

在使用PID增量算法時,我有這樣的疑惑,用公式求到增量后,怎么辦?   要解決這個問題,我認為必須明確增量反映的是什么?為什么用增量?     懇請大神指導一二    …

查看全部問答∨

自己(新手)編寫的ds1302 +數(shù)碼管顯示時間的程序,發(fā)現(xiàn)了一點點問題

問題 1.是寫入單片機仿真版的時候顯示000000,但是重新接入電腦的時候就可以顯示時間了, 2.在進入調(diào)分鐘的時候調(diào)節(jié)不了 要求;顯示時間,如果P3.1可以進入分調(diào)節(jié)(進入調(diào)節(jié)分所顯示的時間是0.5秒閃爍,并在沒按下p3.2進行增加1會在10s內(nèi)退出調(diào)節(jié) ...…

查看全部問答∨
小廣播
設(shè)計資源 培訓 開發(fā)板 精華推薦

最新單片機文章

 
EEWorld訂閱號

 
EEWorld服務(wù)號

 
汽車開發(fā)圈

 
機器人開發(fā)圈

電子工程世界版權(quán)所有 京ICP證060456號 京ICP備10001474號-1 電信業(yè)務(wù)審批[2006]字第258號函 京公網(wǎng)安備 11010802033920號 Copyright ? 2005-2025 EEWORLD.com.cn, Inc. All rights reserved