開(kāi)發(fā)環(huán)境:
STM32F103ZET6? ? ? STM32CubeMX? ? ? Keil5
使用STM32CubeMx創(chuàng)建FSMC工程,生成后使用keil5創(chuàng)建TFT-LCD驅(qū)動(dòng)程序留搔,實(shí)現(xiàn)在LCD上顯示。
網(wǎng)上有一些配置FSMC的技掏,有驅(qū)動(dòng)TFT-LCD的程序,不過(guò)大多是標(biāo)準(zhǔn)庫(kù)的项鬼,有一些找到的驅(qū)動(dòng)程序可是試了試哑梳,沒(méi)有效果,所以自己修改绘盟。
現(xiàn)在有四塊屏鸠真,1602(顯示一些數(shù)字)悯仙,128604(顯示字符,簡(jiǎn)單圖片)吠卷,2.4寸TFT液晶屏(ili9325驅(qū)動(dòng)锡垄,可觸摸,240*320)祭隔,3.5寸TFT(hx8357驅(qū)動(dòng)货岭,可觸摸),此篇只寫(xiě)2.4寸TFT液晶屏疾渴,基本方法是修改廠(chǎng)家提供的使用FSMC的驅(qū)動(dòng)文件千贯,將標(biāo)準(zhǔn)庫(kù)文件修改為在HAL庫(kù)中可以運(yùn)行的文件,因?yàn)橹皩?2864的標(biāo)準(zhǔn)庫(kù)程序修改為HAL庫(kù)程序成功搞坝,所以可以借鑒搔谴。
在網(wǎng)上使用STM32CubeMx配置FSMC的工程有一些,不過(guò)存在問(wèn)題
使用STM32CubeMx配置FSMC桩撮,GPIO
1. STM32CubeMx如何配置FSMC
按照上一篇的方法創(chuàng)建一個(gè)工程后敦第,在引腳設(shè)置頁(yè)面的左側(cè)有FSMC的配置,不過(guò)STM32CubeMx的版本不同距境,STM芯片的選擇不同申尼,F(xiàn)SMC配置選項(xiàng)也不同垮卓,
FSMC(16位)主要配置的引腳為
? ? ? CS 液晶屏片選? ? NE4
? ? ? RS? 即LCD Register Select? PG0? (A10)
? ? ? WR? 寫(xiě)信號(hào)? ? PD5
? ? ? RD 讀信號(hào)? ? PD4
? ? ? 以及16位數(shù)據(jù)總線(xiàn)垫桂,高八位和第八位
不過(guò)液晶屏?xí)蠦L背光控制和RST復(fù)位引腳,需要在配置完FSMC后再添加兩個(gè)輸出引腳粟按。
那么問(wèn)題來(lái)了诬滩,F(xiàn)SMC配置中的內(nèi)存類(lèi)型怎么選,是選SRAM還是其他灭将?
? ? ? 我覺(jué)得選圖中所示可以直接選擇寄存器數(shù)據(jù)選擇信號(hào)引腳為A10即PG0,這符合我的彩屏的實(shí)際情況疼鸟,具體怎么選要先看一下自己彩屏正常工作時(shí)配置了那些引腳。
在配置了FSMC后再經(jīng)過(guò)一些小的修改就可以生成工程庙曙,添加自己的代碼空镜。
注意:
使用不同驅(qū)動(dòng)的彩屏在初始化時(shí)對(duì)寄存器的操作都是不同的,一定要找到可以在自己彩屏上正常運(yùn)行的程序捌朴,因?yàn)樵诔跏蓟瘮?shù)中都會(huì)對(duì)很多寄存器寫(xiě)入不同的值吴攒,錯(cuò)一個(gè)可能就無(wú)法初始化成功。
使用NOR/SRAM的 Bank1.sector4,地址位HADDR[27,26]=11砂蔽,A10作為數(shù)據(jù)命令區(qū)分線(xiàn)洼怔,注意設(shè)置時(shí)STM32內(nèi)部會(huì)右移一位對(duì)其! 111110=0X3E。
因?yàn)樵跇?biāo)準(zhǔn)庫(kù)中和HAL庫(kù)中數(shù)據(jù)類(lèi)型本質(zhì)相同左驾,但表示不同镣隶,比如在標(biāo)準(zhǔn)庫(kù)中為u16,不過(guò)在HAL庫(kù)中卻是uint16_t极谊,需要注意。
在標(biāo)準(zhǔn)庫(kù)中GPIO和FSMC相關(guān)結(jié)構(gòu)體具體定義是不同的安岂,也需要修改轻猖。
基本步驟:
修改向寄存器地址寫(xiě)數(shù)據(jù)和命令的函數(shù)
注意是否在STM32CUBEMX中配置好時(shí)鐘,時(shí)鐘配置是很重要的
修改LCD的初始化函數(shù)
修改GPIO初始化函數(shù)嗜闻,還要使能相關(guān)引腳時(shí)鐘
注意除了FSMC相關(guān)引腳配置為復(fù)用推挽輸出外蜕依,PB0和PC5需要配置為推挽輸出
修改FSMC初始函數(shù),需要使能FSMC時(shí)鐘
需要注意的是在標(biāo)準(zhǔn)庫(kù)中和在HAL庫(kù)中FSMC的配置有不小的不同琉雳,首先是FSMC相關(guān)結(jié)構(gòu)體和標(biāo)準(zhǔn)庫(kù)中不同样眠,有一些在標(biāo)準(zhǔn)庫(kù)中可以配置的選項(xiàng)在HAL庫(kù)中并不存在,還有FSMC配置完成后初始化FSMC的函數(shù)和標(biāo)準(zhǔn)庫(kù)中也有很大不同翠肘,如果使用了兩個(gè)FSMC_NORSRAM_TimingTypeDef檐束,則要使用HAL_SRAM_Init()函數(shù)進(jìn)行初始化。還需要注意的是要使能BANK1束倍。
修改復(fù)位函數(shù)
還有其他一些修改被丧,改動(dòng)不大
rebuild工程,如果沒(méi)有錯(cuò)誤绪妹,在main函數(shù)中調(diào)用LCD初始化函數(shù)甥桂,就可以直接使用標(biāo)準(zhǔn)庫(kù)中可以使用的繪制函數(shù)了。
修改后的GPIO初始化函數(shù)
void LCD_GPIOInit(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
//FSMC_NORSRAM_InitTypeDef? FSMC_NORSRAMInitStructure;
FSMC_NORSRAM_TimingTypeDef? readWriteTiming;
FSMC_NORSRAM_TimingTypeDef? writeTiming;
hsram2.Instance = FSMC_NORSRAM_DEVICE;
hsram2.Extended = FSMC_NORSRAM_EXTENDED_DEVICE;
__HAL_RCC_FSMC_CLK_ENABLE();//ê1?üFSMCê±?ó
//RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC,ENABLE); //ê1?üFSMCê±?ó
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
//RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOE|RCC_APB2Periph_GPIOG|RCC_APB2Periph_AFIO,ENABLE);//ê1?üPORTB,D,E,Gò??°AFIO?′ó?1|?üê±?ó
/*Configure GPIO pin : PC5 */
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/*Configure GPIO pin : PB0 */
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* GPIO_InitStruct */
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
/* GPIO_InitStruct */
GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10
|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14
|GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
/* GPIO_InitStruct */
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_14
|GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_4
|GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
readWriteTiming.AddressSetupTime = 0x01; //μ??·?¨á¢ê±??£¨ADDSET£??a2??HCLK 1/36M=27ns
readWriteTiming.AddressHoldTime = 0x00; //μ??·±£3?ê±??£¨ADDHLD£??£ê?A?′ó?μ?
readWriteTiming.DataSetupTime = 0x0f; // êy?Y±£′?ê±???a16??HCLK,òò?aòo?§?y?ˉICμ??áêy?Yμ?ê±oò£??ù?è2??üì??ì£?óè????1289?a??IC?£
readWriteTiming.BusTurnAroundDuration = 0x00;
readWriteTiming.CLKDivision = 0x00;
readWriteTiming.DataLatency = 0x00;
readWriteTiming.AccessMode = FSMC_ACCESS_MODE_A; //?£ê?A
writeTiming.AddressSetupTime = 0x02; //0x01 μ??·?¨á¢ê±??£¨ADDSET£??a1??HCLK
writeTiming.AddressHoldTime = 0x00; //μ??·±£3?ê±??£¨A
writeTiming.DataSetupTime = 0x05; ////0x03 êy?Y±£′?ê±???a4??HCLK
writeTiming.BusTurnAroundDuration = 0x00;
writeTiming.CLKDivision = 0x00;
writeTiming.DataLatency = 0x00;
writeTiming.AccessMode = FSMC_ACCESS_MODE_A; //?£ê?A
hsram2.Init.NSBank = FSMC_NORSRAM_BANK4;//? ?aà??ò??ê1ó?NE4 £?ò2?í??ó|BTCR[6],[7]?£
hsram2.Init.DataAddressMux = FSMC_DATA_ADDRESS_MUX_DISABLE; // 2??′ó?êy?Yμ??·
hsram2.Init.MemoryType =FSMC_MEMORY_TYPE_SRAM;// FSMC_MemoryType_SRAM;? //SRAM
hsram2.Init.MemoryDataWidth = FSMC_NORSRAM_MEM_BUS_WIDTH_16;//′?′¢?÷êy?Y?í?è?a16bit
hsram2.Init.BurstAccessMode =FSMC_BURST_ACCESS_MODE_DISABLE;// FSMC_BurstAccessMode_Disable;
hsram2.Init.WaitSignalPolarity = FSMC_WAIT_SIGNAL_POLARITY_LOW;
hsram2.Init.AsynchronousWait=FSMC_ASYNCHRONOUS_WAIT_DISABLE;
hsram2.Init.WrapMode = FSMC_WRAP_MODE_DISABLE;
hsram2.Init.WaitSignalActive = FSMC_WAIT_TIMING_BEFORE_WS;
hsram2.Init.WriteOperation = FSMC_WRITE_OPERATION_ENABLE; //? ′?′¢?÷D′ê1?ü
hsram2.Init.WaitSignal = FSMC_WAIT_SIGNAL_DISABLE;
hsram2.Init.ExtendedMode = FSMC_EXTENDED_MODE_ENABLE; // ?áD′ê1ó?2?í?μ?ê±Dò
hsram2.Init.WriteBurst = FSMC_WRITE_BURST_DISABLE;
//FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &readWriteTiming; //?áD′ê±Dò
//FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &writeTiming;? //D′ê±Dò
if (HAL_SRAM_Init(&hsram2, &readWriteTiming, &writeTiming) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
__FSMC_NORSRAM_ENABLE(FSMC_NORSRAM_DEVICE,FSMC_NORSRAM_BANK4);
}
修改后的LCD初始化函數(shù)
void LCD_Init(void)
{
LCD_GPIOInit();
LCD_RESET();
//************* Start Initial Sequence **********//
LCD_WriteReg(0x00E5,0x78F0);
LCD_WriteReg(0x0001,0x0100);
LCD_WriteReg(0x0002,0x0700);
LCD_WriteReg(0x0003,0x1030);
LCD_WriteReg(0x0004,0x0000);
LCD_WriteReg(0x0008,0x0202);
LCD_WriteReg(0x0009,0x0000);
LCD_WriteReg(0x000A,0x0000);
LCD_WriteReg(0x000C,0x0000);
LCD_WriteReg(0x000D,0x0000);
LCD_WriteReg(0x000F,0x0000);
//power on sequence VGHVGL
LCD_WriteReg(0x0010,0x0000);
LCD_WriteReg(0x0011,0x0007);
LCD_WriteReg(0x0012,0x0000);
LCD_WriteReg(0x0013,0x0000);
LCD_WriteReg(0x0007,0x0000);
//vgh
LCD_WriteReg(0x0010,0x1690);
LCD_WriteReg(0x0011,0x0227);
//delay_ms(100);
//vregiout
LCD_WriteReg(0x0012,0x009D); //0x001b
//delay_ms(100);
//vom amplitude
LCD_WriteReg(0x0013,0x1900);
//delay_ms(100);
//vom H
LCD_WriteReg(0x0029,0x0025);
LCD_WriteReg(0x002B,0x000D);
//gamma
LCD_WriteReg(0x0030,0x0007);
LCD_WriteReg(0x0031,0x0303);
LCD_WriteReg(0x0032,0x0003);// 0006
LCD_WriteReg(0x0035,0x0206);
LCD_WriteReg(0x0036,0x0008);
LCD_WriteReg(0x0037,0x0406);
LCD_WriteReg(0x0038,0x0304);//0200
LCD_WriteReg(0x0039,0x0007);
LCD_WriteReg(0x003C,0x0602);// 0504
LCD_WriteReg(0x003D,0x0008);
//ram
LCD_WriteReg(0x0050,0x0000);
LCD_WriteReg(0x0051,0x00EF);
LCD_WriteReg(0x0052,0x0000);
LCD_WriteReg(0x0053,0x013F);
LCD_WriteReg(0x0060,0xA700);
LCD_WriteReg(0x0061,0x0001);
LCD_WriteReg(0x006A,0x0000);
//
LCD_WriteReg(0x0080,0x0000);
LCD_WriteReg(0x0081,0x0000);
LCD_WriteReg(0x0082,0x0000);
LCD_WriteReg(0x0083,0x0000);
LCD_WriteReg(0x0084,0x0000);
LCD_WriteReg(0x0085,0x0000);
//
LCD_WriteReg(0x0090,0x0010);
LCD_WriteReg(0x0092,0x0600);
LCD_WriteReg(0x0007,0x0133);
LCD_WriteReg(0x00,0x0022);//
LCD_SetParam();//éè??LCD2?êy
//LCD_LED=1;//μ?áá±31a
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);
LCD_Clear(WHITE);
}
修改后在main函數(shù)中使用繪圖函數(shù)時(shí)要注釋掉原有的GPIO和FSMC初始化函數(shù)邮旷。
測(cè)試結(jié)果:
修改后即可以在STM32CubeMX中配置后就可以將之前修改好的文件直接添加到工程中使用黄选,這樣即可在LCD上顯示其他功能的狀態(tài)信息。