本系列教程配套出有視頻教程,觀看地址:https://www.bilibili.com/video/BV1gV4y1e7Sg
4. 驅(qū)動(dòng)LCD屏(SPI)
本次實(shí)驗(yàn)我們?cè)谏弦淮螌?shí)驗(yàn)的基礎(chǔ)上驅(qū)動(dòng) LCD屏(SPI)。
上次實(shí)驗(yàn)我們已經(jīng)能驅(qū)動(dòng)觸摸屏(I2C)并打印觸摸點(diǎn)坐標(biāo),這次實(shí)驗(yàn)我們的目標(biāo)是點(diǎn)亮LCD屏,向屏幕依次刷寫紅綠藍(lán)三種不同的顏色,并在串口終端打印當(dāng)前刷新的顏色文本信息。
4.1 復(fù)制工程
上次實(shí)驗(yàn)得出的工程我們可以通過復(fù)制在原有的基礎(chǔ)上得到一個(gè)新的工程。
如果你不清楚復(fù)制工程的步驟,請(qǐng)參考閱讀第2章實(shí)驗(yàn)的步驟教程。
本次實(shí)驗(yàn)我們的項(xiàng)目命名為:02_dshanmcu_ra6m5_spi_display
4.2 配置FSP
4.2.1 查看硬件資料
打開位于 03硬件資料\1_開發(fā)板原理圖\ DshanMCU_RA6M5_V4.0.pdf
的開發(fā)板原理圖,確認(rèn)SPI引腳,電路圖如下:

可以看到原理圖并沒有像之前那樣直接就能確定使用的是哪一路spi,因此需要打開位于 03硬件資料\5_官方資料\RA6M5 Group User's Manual Hardware.pdf
的文檔,跳轉(zhuǎn)到下圖所示的兩個(gè)位置,確定使用的是 spi1:


03硬件資料\5_官方資料\RA6M5 Group User's Manual Hardware.pdf
的文檔,跳轉(zhuǎn)到下圖所示的位置,確定SPI時(shí)鐘頻率計(jì)算公式:
打開 e2studio 如下窗口,確定當(dāng)前的 PCLKA:
由下圖可知 PCLKA 為 200MHz,因此可得出支持的SPI最大時(shí)鐘頻率為:100/ (2*(0+1) * 2^0) = 100 / 2 = 50Mbps

打開位于 4_模塊資料\01_ST7796顯示器芯片手冊(cè)\ST7796U2_SPEC_V1.0.pdf
的文檔,跳轉(zhuǎn)到下圖所示的位置:

通過換算可得出時(shí)鐘頻率: 1000000000 / 15= 66,666,666.66666667 ≈ 66.5Mhz
接下來我們根據(jù)這些信息對(duì) r_spi
進(jìn)行配置。
4.2.2 添加 Stacks(r_spi_master)
- 打開
FSP Configuration
視圖:雙擊項(xiàng)目文件夾中的configuration.xml
文件。 - 按照下圖所示,添加
r_spi
模塊:

-
點(diǎn)擊剛剛添加的
r_spi
在底部窗口的Properties
選項(xiàng)卡中對(duì)其進(jìn)行配置,將其配置為與下圖一致:- Name: g_spi1
- Channel: 1
- Callback: spi1_callback
- Bitrate: 50000000

配置完成之后,如果馬上編譯會(huì)發(fā)現(xiàn)編譯出錯(cuò)、可以根據(jù)錯(cuò)誤信息進(jìn)行解決,也可以在編譯前參考下圖解決:

點(diǎn)擊剛剛添加的 r_dmac
在底部窗口的 Properties
選項(xiàng)卡中對(duì)其進(jìn)行配置,將其配置為與下圖一致:
- Name: g_transfer1
- Channel:1

4.2.3 配置RS、RESET、PWM引腳
這三個(gè)引腳,在上面的原理圖中有標(biāo)注,負(fù)責(zé)的功能分別是:
- RS引腳(P104):低電平代表發(fā)送的是指令,高電平代表發(fā)送的是數(shù)據(jù)
- RESET引腳(P105):控制LCD屏的復(fù)位
- PWM引腳(P608):可以自由調(diào)節(jié)背光亮度調(diào)節(jié),給高電平常亮
根據(jù)他們負(fù)責(zé)的功能特性,在FSP對(duì)其進(jìn)行配置:
- 按下圖所示操作,打開配置IO引腳頁面:

- 按下圖所示操作,配置RS引腳(P104)

- 按下圖所示操作,配置RESET引腳(P105)

- 按下圖所示操作,配置PWM引腳(P608)

最后檢查確認(rèn)無誤,點(diǎn)擊右上角的 “Generate Project Content”
e2studio就會(huì)根據(jù)我們對(duì)FSP的配置自動(dòng)配置項(xiàng)目、生成相應(yīng)的代碼。

4.3 編寫LCD驅(qū)動(dòng)代碼
在e2studio中進(jìn)入 02_dshanmcu_ra6m5_spi_display\dshanmcu_ra6m5\drivers
目錄,新建如下兩個(gè)文件 drv_spi_display.c
和 drv_spi_display.h
:
在e2studio中點(diǎn)擊打開 02_dshanmcu_ra6m5_spi_display\dshanmcu_ra6m5\drivers\drv_spi_display.c
添加下面的代碼:
/***********************************************************************************************************************
* Includes
**********************************************************************************************************************/
#include "drv_spi_display.h"
#include <stdio.h>
/**********************************************************************************************************************
* Macro definitions
**********************************************************************************************************************/
#define LCD_DC_PIN BSP_IO_PORT_01_PIN_04
#define LCD_RESET_PIN BSP_IO_PORT_01_PIN_05
#define LCD_PWM_PIN BSP_IO_PORT_06_PIN_08
#define SPI_SEND_DATA BSP_IO_LEVEL_HIGH
#define SPI_SEND_CMD BSP_IO_LEVEL_LOW
/* ST7796S部分寄存器定義 */
#define LCD_DISPLAY_CMD_RAMCTRL 0xb0 // RAM Control
#define LCD_DISPLAY_CMD_CASET 0x2a // Column address set
#define LCD_DISPLAY_CMD_RASET 0x2b // Row address set
#define LCD_DISPLAY_CMD_RAMWR 0x2c // Memory write
/**********************************************************************************************************************
* Typedef definitions
**********************************************************************************************************************/
/***********************************************************************************************************************
* Private function prototypes
**********************************************************************************************************************/
static void spi1_wait_for_tx(void);
static void spi_display_init(void);
static fsp_err_t spi_send_data_cmd(uint8_t * uc_data, bsp_io_level_t uc_cmd, uint32_t len);
static fsp_err_t spi_display_backlight_opt(bsp_io_level_t opt);
static fsp_err_t spi_display_reset(void);
/***********************************************************************************************************************
* Private global variables
**********************************************************************************************************************/
/* Event flags for master */
static volatile spi_event_t g_master_event_flag; // Master Transfer Event completion flag
/***********************************************************************************************************************
* Functions
**********************************************************************************************************************/
fsp_err_t drv_spi_display_init(void)
{
fsp_err_t err;
/* 初始化I2C驅(qū)動(dòng) */
err = g_spi1.p_api->open(&g_spi1_ctrl, &g_spi1_cfg);
if (FSP_SUCCESS != err)
{
printf ("%s %d\r\n", __FUNCTION__, __LINE__);
return err;
}
spi_display_init();
return err;
}
void spi_display_set_window(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
{
uint8_t caset[4];
uint8_t raset[4];
caset[0] = (uint8_t)(x1 >> 8) & 0xFF;
caset[1] = (uint8_t)(x1 & 0xff);
caset[2] = (uint8_t)(x2 >> 8) & 0xFF;
caset[3] = (uint8_t)(x2 & 0xff) ;
raset[0] = (uint8_t)(y1 >> 8) & 0xFF;
raset[1] = (uint8_t)(y1 & 0xff);
raset[2] = (uint8_t)(y2 >> 8) & 0xFF;
raset[3] = (uint8_t)(y2 & 0xff);
spi_send_data_cmd((uint8_t []){LCD_DISPLAY_CMD_CASET}, SPI_SEND_CMD, 1); // Horiz
spi_send_data_cmd(caset, SPI_SEND_DATA, 4);
spi_send_data_cmd((uint8_t []){LCD_DISPLAY_CMD_RASET}, SPI_SEND_CMD, 1); // Vert
spi_send_data_cmd(raset, SPI_SEND_DATA, 4);
spi_send_data_cmd((uint8_t []){LCD_DISPLAY_CMD_RAMWR}, SPI_SEND_CMD, 1); // Memory write
}
fsp_err_t drv_spi_display_flush_data(uint8_t * data, uint32_t len)
{
fsp_err_t err;
err = spi_send_data_cmd(data, SPI_SEND_DATA, len);
if (FSP_SUCCESS != err)
{
printf ("%s %d\r\n", __FUNCTION__, __LINE__);
return err;
}
return err;
}
void spi1_callback(spi_callback_args_t *p_args)
{
/* 判斷是否是發(fā)送完成觸發(fā)的中斷 */
/* 如果是的話就將發(fā)送完成標(biāo)志位置1 */
if (SPI_EVENT_TRANSFER_COMPLETE == p_args->event)
{
g_master_event_flag = SPI_EVENT_TRANSFER_COMPLETE;
}
else
{
g_master_event_flag = SPI_EVENT_TRANSFER_ABORTED;
}
}
/***********************************************************************************************************************
* Private Functions
**********************************************************************************************************************/
static void spi1_wait_for_tx(void)
{
while(!g_master_event_flag);
g_master_event_flag = false;
}
static void spi_display_init(void)
{
spi_display_reset();
spi_display_backlight_opt(BSP_IO_LEVEL_HIGH); // backlight on
#if 1
spi_send_data_cmd((uint8_t []){0x11}, SPI_SEND_CMD, 1); // Sleep out
spi_send_data_cmd((uint8_t []){0x20}, SPI_SEND_CMD, 1); // 關(guān)閉顯示反轉(zhuǎn)
spi_send_data_cmd((uint8_t []){0x36}, SPI_SEND_CMD, 1); // 內(nèi)存數(shù)據(jù)訪問控制設(shè)置
spi_send_data_cmd((uint8_t []){0x48}, SPI_SEND_DATA, 1); // 顯示方向:左->右,上->下(不旋轉(zhuǎn)); BGR
spi_send_data_cmd((uint8_t []){0x3a}, SPI_SEND_CMD, 1); // 設(shè)置像素格式(bpp)
spi_send_data_cmd((uint8_t []){0x55}, SPI_SEND_DATA, 1); // RGB接口顏色格式:16bit/pixel;控制接口的顏色格式:16bit/pixel
spi_send_data_cmd((uint8_t []){0x13}, SPI_SEND_CMD, 1); // 普通顯示模式
spi_send_data_cmd((uint8_t []){0x29}, SPI_SEND_CMD, 1); // 開啟顯示
#elif
spi_send_data_cmd((uint8_t []){0x11}, SPI_SEND_CMD, 1);
spi_send_data_cmd((uint8_t []){0x00}, SPI_SEND_DATA, 1);
R_BSP_SoftwareDelay(120, BSP_DELAY_UNITS_MILLISECONDS); //延時(shí)120ms
spi_send_data_cmd((uint8_t []){0xf0}, SPI_SEND_CMD, 1);
spi_send_data_cmd((uint8_t []){0xc3}, SPI_SEND_DATA, 1);
spi_send_data_cmd((uint8_t []){0xf0}, SPI_SEND_CMD, 1);
spi_send_data_cmd((uint8_t []){0x96}, SPI_SEND_DATA, 1);
spi_send_data_cmd((uint8_t []){0x36}, SPI_SEND_CMD, 1);
spi_send_data_cmd((uint8_t []){0x48}, SPI_SEND_DATA, 1); // RGB
spi_send_data_cmd((uint8_t []){0xb4}, SPI_SEND_CMD, 1);
spi_send_data_cmd((uint8_t []){0x01}, SPI_SEND_DATA, 1);
spi_send_data_cmd((uint8_t []){0xb7}, SPI_SEND_CMD, 1);
spi_send_data_cmd((uint8_t []){0xc6}, SPI_SEND_DATA, 1);
spi_send_data_cmd((uint8_t []){0xe8}, SPI_SEND_CMD, 1);
spi_send_data_cmd((uint8_t []){0x40, 0x8A, 0x00, 0x00, 0x29, 0x19, 0xA5, 0x33}, SPI_SEND_DATA, 8);
spi_send_data_cmd((uint8_t []){0xc1}, SPI_SEND_CMD, 1);
spi_send_data_cmd((uint8_t []){0x06}, SPI_SEND_DATA, 1);
spi_send_data_cmd((uint8_t []){0xc2}, SPI_SEND_CMD, 1);
spi_send_data_cmd((uint8_t []){0xa7}, SPI_SEND_DATA, 1);
spi_send_data_cmd((uint8_t []){0xc5}, SPI_SEND_CMD, 1);
spi_send_data_cmd((uint8_t []){0x18}, SPI_SEND_DATA, 1);
spi_send_data_cmd((uint8_t []){0xe0}, SPI_SEND_CMD, 1);
spi_send_data_cmd((uint8_t []){0xF0, 0x09, 0x0B, 0x06, 0x04, 0x15, 0x2F, 0x54, 0x42, 0x3C, 0x17, 0x14, 0x18, 0x1B}, SPI_SEND_DATA, 14);
spi_send_data_cmd((uint8_t []){0xe1}, SPI_SEND_CMD, 1);
spi_send_data_cmd((uint8_t []){0xF0, 0x09, 0x0B, 0x06, 0x04, 0x03, 0x2D, 0x43, 0x42, 0x3B, 0x16, 0x14, 0x17, 0x1B}, SPI_SEND_DATA, 14);
spi_send_data_cmd((uint8_t []){0xf0}, SPI_SEND_CMD, 1);
spi_send_data_cmd((uint8_t []){0x3c}, SPI_SEND_DATA, 1);
spi_send_data_cmd((uint8_t []){0xf0}, SPI_SEND_CMD, 1);
spi_send_data_cmd((uint8_t []){0x69}, SPI_SEND_DATA, 1);
spi_send_data_cmd((uint8_t []){0x3a}, SPI_SEND_CMD, 1);
spi_send_data_cmd((uint8_t []){0x55}, SPI_SEND_DATA, 1);
R_BSP_SoftwareDelay(120, BSP_DELAY_UNITS_MILLISECONDS); //延時(shí)120ms
spi_send_data_cmd((uint8_t []){0x29}, SPI_SEND_CMD, 1);
/*rotation*/
spi_send_data_cmd((uint8_t []){0x36}, SPI_SEND_CMD, 1);
spi_send_data_cmd((uint8_t []){0x48}, SPI_SEND_DATA, 1); // 0
#endif
}
static fsp_err_t spi_send_data_cmd(uint8_t * uc_data, bsp_io_level_t uc_cmd, uint32_t len)
{
fsp_err_t err = FSP_SUCCESS; // Error status
/* Master send data to device */
err = g_ioport.p_api->pinWrite(g_ioport.p_ctrl, LCD_DC_PIN, uc_cmd);
if(FSP_SUCCESS != err)
{
printf ("%s %d\r\n", __FUNCTION__, __LINE__);
return err;
}
err = g_spi1.p_api->write(g_spi1.p_ctrl, uc_data, len, SPI_BIT_WIDTH_8_BITS);
if(FSP_SUCCESS != err)
{
printf ("%s %d\r\n", __FUNCTION__, __LINE__);
return err;
}
spi1_wait_for_tx();
return err;
}
static fsp_err_t spi_display_backlight_opt(bsp_io_level_t opt)
{
fsp_err_t err = FSP_SUCCESS; // Error status
g_ioport.p_api->pinWrite((ioport_ctrl_t * const )&g_ioport.p_ctrl, LCD_PWM_PIN, opt);
return err;
}
static fsp_err_t spi_display_reset(void)
{
fsp_err_t err = FSP_SUCCESS; // Error status
g_ioport.p_api->pinWrite((ioport_ctrl_t * const )&g_ioport.p_ctrl, LCD_RESET_PIN, BSP_IO_LEVEL_LOW);
R_BSP_SoftwareDelay(120, BSP_DELAY_UNITS_MILLISECONDS); //延時(shí)120ms
g_ioport.p_api->pinWrite((ioport_ctrl_t * const )&g_ioport.p_ctrl, LCD_RESET_PIN, BSP_IO_LEVEL_HIGH);
R_BSP_SoftwareDelay(120, BSP_DELAY_UNITS_MILLISECONDS); //延時(shí)120ms
return err;
}
在e2studio中點(diǎn)擊打開 02_dshanmcu_ra6m5_spi_display\dshanmcu_ra6m5\drivers\drv_spi_display.h
添加下面的代碼:
#ifndef DRV_SPI_DISPLAY_H
#define DRV_SPI_DISPLAY_H
/***********************************************************************************************************************
* Includes
**********************************************************************************************************************/
#include "hal_data.h"
/**********************************************************************************************************************
* Macro definitions
**********************************************************************************************************************/
#define LCD_SCREEN_WIDTH (320)
#define LCD_SCREEN_HEIGHT (480)
#define LCD_COLOR_RED (0xF800)
#define LCD_COLOR_GREEN (0x07E0)
#define LCD_COLOR_BLUE (0x001F)
/**********************************************************************************************************************
* Typedef definitions
**********************************************************************************************************************/
/***********************************************************************************************************************
* Exported global variables
**********************************************************************************************************************/
/***********************************************************************************************************************
* Exported global functions (to be accessed by other files)
**********************************************************************************************************************/
fsp_err_t drv_spi_display_init(void);
void spi_display_set_window(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
fsp_err_t drv_spi_display_flush_data(uint8_t * data, uint32_t len);
#endif /*DRV_SPI_DISPLAY_H*/
4.4 編寫app
在 02_dshanmcu_ra6m5_spi_display\dshanmcu_ra6m5\applications
目錄下新建 app_spi_display_test.c
文件,如下圖所示:
打開 app_spi_display_test.c
添加如下代碼:
/***********************************************************************************************************************
* Includes
**********************************************************************************************************************/
#include "app.h"
#include "drv_uart.h"
#include "drv_spi_display.h"
#include <stdio.h>
/**********************************************************************************************************************
* Macro definitions
**********************************************************************************************************************/
/**********************************************************************************************************************
* Typedef definitions
**********************************************************************************************************************/
/***********************************************************************************************************************
* Private function prototypes
**********************************************************************************************************************/
static void spi_display_show_color(uint16_t color_le);
/***********************************************************************************************************************
* Private global variables
**********************************************************************************************************************/
/***********************************************************************************************************************
* Functions
**********************************************************************************************************************/
void app_spi_display_test(void)
{
fsp_err_t err;
err = drv_uart_init();
if(FSP_SUCCESS != err) __BKPT();
err = drv_spi_display_init();
if(FSP_SUCCESS != err)
{
printf ("%s %d\r\n", __FUNCTION__, __LINE__);
__BKPT();
}
while(1)
{
spi_display_show_color((uint16_t)LCD_COLOR_RED);
printf ("Full screen display in red\r\n");
R_BSP_SoftwareDelay(500, BSP_DELAY_UNITS_MILLISECONDS); //延時(shí)500ms
spi_display_show_color((uint16_t)LCD_COLOR_GREEN);
printf ("Full screen display in green\r\n");
R_BSP_SoftwareDelay(500, BSP_DELAY_UNITS_MILLISECONDS); //延時(shí)500ms
spi_display_show_color((uint16_t)LCD_COLOR_BLUE);
printf ("Full screen display in blue\r\n");
R_BSP_SoftwareDelay(500, BSP_DELAY_UNITS_MILLISECONDS); //延時(shí)500ms
}
}
static void spi_display_show_color(uint16_t color_le)
{
uint8_t color_be[2];
color_be [0] = (uint8_t)((color_le & 0xff00) >> 8);
color_be [1] = (uint8_t)(color_le & 0xff);
spi_display_set_window(0, 0, LCD_SCREEN_WIDTH, LCD_SCREEN_HEIGHT);
for(uint16_t x = 0; x < LCD_SCREEN_WIDTH; x++)
for(uint16_t y = 0; y < LCD_SCREEN_HEIGHT; y++)
drv_spi_display_flush_data(color_be, 2);
}
/***********************************************************************************************************************
* Private Functions
**********************************************************************************************************************/
將 app.h
改為如下代碼:
#ifndef APP_TEST_H
#define APP_TEST_H
/***********************************************************************************************************************
* Includes
**********************************************************************************************************************/
#include "hal_data.h"
/**********************************************************************************************************************
* Macro definitions
**********************************************************************************************************************/
/**********************************************************************************************************************
* Typedef definitions
**********************************************************************************************************************/
/***********************************************************************************************************************
* Exported global variables
**********************************************************************************************************************/
/***********************************************************************************************************************
* Exported global functions (to be accessed by other files)
**********************************************************************************************************************/
void app_uart_test(void);
void app_i2c_touchpad_test(void);
void app_spi_display_test(void);
#endif /*APP_TEST_H*/
4.5 調(diào)用app
打開 02_dshanmcu_ra6m5_spi_display\src\hal_entry.c
,按照如下步驟進(jìn)行修改:
將 hal_entry
函數(shù)修改為如下所示的代碼:
void hal_entry(void)
{
/* TODO: add your own code here */
//app_uart_test();
//app_i2c_touchpad_test();
app_spi_display_test();
#if BSP_TZ_SECURE_BUILD
/* Enter non-secure code */
R_BSP_NonSecureEnter();
#endif
}
4.6 驗(yàn)證效果
點(diǎn)擊編譯按鈕,再點(diǎn)擊 debug 按鈕,將程序燒寫到開發(fā)板中。會(huì)看到屏幕依次循環(huán)刷紅、綠、藍(lán)三種顏色。文章來源:http://www.zghlxwxcb.cn/news/detail-704760.html
【拓展】為什么要交換RGB565顏色數(shù)據(jù)兩個(gè)字節(jié)的順序
文章來源地址http://www.zghlxwxcb.cn/news/detail-704760.html
到了這里,關(guān)于04_瑞薩GUI(LVGL)移植實(shí)戰(zhàn)教程之驅(qū)動(dòng)LCD屏(SPI)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!