雖然用GPIO會比較快,也可以省卻「如果你的chip不支援FSMC...」的問題
不過多學會點會比較好些,也許哪天會用到也不一定,
NT35510的規格書在此
(別忘了Back Light要On起來,沒有back light,沒有顯示)
先用read ID & color fomat測看看,如果讀出是亂碼,請到上圖的NOR/PSRAME timing for wirte access那裡改一下,有時要多點clock才會正確 (參考上面兩個URL的內文介紹如個推算,因為我是用NT35510的,所以會以第二個link為主)
程式碼如下
---------------------------------------------------
//因為是用base1 第 4區,所以base address是0x6C000000
(即0x60000000~0x6FFFFFFF分成區,第四區起始位址即為0x6C000000,參考「STM32F103 战舰开发指南V1.1.pdf」P365)
(即0x60000000~0x6FFFFFFF分成區,第四區起始位址即為0x6C000000,參考「STM32F103 战舰开发指南V1.1.pdf」P365)
#define FMC_ADDR_CMD ((uint32_t) 0x6C000000)
//而A10做為C/D(或曰register select),又要往左shfit一位,故為00800
#define FMC_ADDR_DATA ((uint32_t) 0x6C000800)
//在 MX_FSMC_Init();後,這些對應建立起來後,就可以直接用位址的方式讀寫,不必再用8080介面操作了...
void lcd_wr_cmd(volatile uint16_t cmd)
{
cmd = cmd;
*(uint16_t *)(FMC_ADDR_CMD) = cmd;
}
void lcd_wr_data(volatile uint16_t data)
{
data = data;
*(uint16_t *)(FMC_ADDR_DATA) = data;
}
uint16_t lcd_rd_data(void)
{
volatile uint16_t ram;
ram = *(uint16_t *)(FMC_ADDR_DATA);
return ram;
}
...
...
main的內容
HAL_Init();
MX_FSMC_Init();
MX_USART1_UART_Init();
//神說,要有光,於是就有了光
HAL_GPIO_WritePin(LCD_BL_GPIO_Port,LCD_BL_Pin,GPIO_PIN_SET);
HAL_Delay(10);
lcd_wr_cmd(0x1100); //Sleep out & booster on
HAL_Delay(10);
lcd_wr_cmd(0x2900); //display memory to frame.
HAL_Delay(10);
//第一步,先試著讀id,如果傳回值不是80h的話,就是錯了
lcd_wr_cmd(0x0401);
HAL_Delay(100);
uint16_t chip_id=0xabcd;
chip_id=lcd_rd_data();
//試著讀寫 color format,原先是8x8x8 RBG格式,如今我們為了測試,用565格式
//0x0C00是read color mode,而0x3A00是write color mode.
uint16_t pix_fomrat_org=0;
lcd_wr_cmd(0x0c00);pix_fomrat_org=lcd_rd_data();
lcd_wr_cmd(0x3A00); lcd_wr_data(0x55);
lcd_wr_cmd(0x0c00);
uint16_t pix_fomrat=lcd_rd_data();
//清除資料一下 (預設尺寸是480*800)
lcd_wr_cmd(0x2c00);; //demo how to do "clear screen"
for(uint32_t i=0;i<(0x01df-1)*(0x03ef-1);i++){
lcd_wr_data(0x07E0);
}
//最後,把大頭照放上去 x,y : 200,200, width& height:140x140
lcd_wr_cmd(0x2A00);lcd_wr_data(0);;
lcd_wr_cmd(0x2A01);lcd_wr_data(200);
lcd_wr_cmd(0x2A02);lcd_wr_data(339>>8);
lcd_wr_cmd(0x2A03);lcd_wr_data(339&0xff);
lcd_wr_cmd(0x2B00);lcd_wr_data(0);
lcd_wr_cmd(0x2B01);lcd_wr_data(200);
lcd_wr_cmd(0x2B02);lcd_wr_data(339>>8);
lcd_wr_cmd(0x2B03);lcd_wr_data(339&0xff);
lcd_wr_cmd(0x2c00); //demo how to do "clear screen"
for(uint32_t i=0;i<(140*140);i++){
lcd_wr_data(g_pexl[i]);
}
//然後就是while(1)...
---------------------------------------------------
耶~ 有看到圖片了(會不會太自戀了?)
------
------
這次的實作基本上只是個小插曲,還是建議用GPIO直接去操作,以清除螢幕這個函數來說好了
-----------
void fill_color(uint16_t color, uint32_t count)
{
//當然以下的HAL_GPIO_WritePin都可以再直接操作BSRR暫存器來最佳化之,
//只是為了實作驗證是否了解正確,直接用HAL程式庫了
set_d0tod7_output();
HAL_GPIO_WritePin(LCD_DC_GPIO_Port,LCD_DC_Pin,GPIO_PIN_RESET);//RS:0
HAL_GPIO_WritePin(LCD_WRITE_GPIO_Port,LCD_WRITE_Pin,GPIO_PIN_SET);//write 1
HAL_GPIO_WritePin(LCD_READ_GPIO_Port,LCD_READ_Pin,GPIO_PIN_SET);//RD 1
HAL_GPIO_WritePin(LCD_CS_GPIO_Port,LCD_CS_Pin,GPIO_PIN_RESET);//CS 0
write_byte_to_gpio(0x2c00);
HAL_GPIO_WritePin(LCD_WRITE_GPIO_Port,LCD_WRITE_Pin,GPIO_PIN_RESET);//write 0
HAL_GPIO_WritePin(LCD_WRITE_GPIO_Port,LCD_WRITE_Pin,GPIO_PIN_SET);//write 1
//set to data mode
HAL_GPIO_WritePin(LCD_DC_GPIO_Port,LCD_DC_Pin,GPIO_PIN_SET);//RS:1
write_byte_to_gpio(color);
uint32_t pin16u=(uint32_t)LCD_WRITE_Pin<< 16u;
for(uint32_t i=0;i<count;i++)
{
LCD_WRITE_GPIO_Port->BSRR = pin16u; //RESET
LCD_WRITE_GPIO_Port->BSRR = LCD_WRITE_Pin;//SET
}
//all done
HAL_GPIO_WritePin(LCD_CS_GPIO_Port,LCD_CS_Pin,GPIO_PIN_SET);//CS 1
HAL_GPIO_WritePin(LCD_DC_GPIO_Port,LCD_DC_Pin,GPIO_PIN_SET);//RS:1
HAL_GPIO_WritePin(LCD_READ_GPIO_Port,LCD_READ_Pin,GPIO_PIN_SET);//read 1
HAL_GPIO_WritePin(LCD_WRITE_GPIO_Port,LCD_WRITE_Pin,GPIO_PIN_SET);//write 1
}
-----------
這比填入FSMC再填入LCD快了點(直接高低電位切換,當然快啊,這樣比很不講武德捏)
而且會看技術規格文件,是這行必備的生存技能
當然FSMC會了也是很好的一件事,畢竟很多時候可以對應到別的設備的,大大節省開發難度
要學的東西真的太多了,一起加油吧.