开发环境
- Keil MDK: 5.42.0
- ARM-GCC: 10.3.1
- FSP: 5.1.0
- FreeRTOS: 10.6.1
承接上文
在上文中测试的RA4M2使用SCI SPI 驱动小屏的效果,本文使用RA4M2仅有的一个专用SPI接口来驱动小屏,得到最为极限的驱动速度,仍然使用自己绘制的arduino接口的小屏幕底板

在RASC软件中设置使用SPI0接口,在Pins中设置管脚后可以看到使用的SCLK管脚为P111,MOSI管脚为P109,其余IO仍使用之前的管脚,并且设置SPI速度为50Mbps

可以得到硬件IO的连接如下
| IO |
功能 |
|---|
| P111 |
SCK |
| P109 |
MOSI |
| P603 |
CS |
| P114 |
DC |
| P601 |
BLK |
| P102 |
RES |
硬件连接大致如下,对于SCLK和MOSI需要使用较短的杜邦线,避免50Mbps信号传输不稳定

点亮屏幕
同上文的思路,根据手册编写初始化序列的代码并编写了一个简单的fps计算程序,大致流程如下:
- 向屏幕发送初始化序列,完成屏幕的初始化
- 拉低CS、拉高DC,进入全刷模式,不断填充红、绿、蓝三色
- 在lcd_thread中fps变量不断自增
- 在1s的定时器中断内记录fps的大小
区别于上文的DTC配置,本次测试将DTC的配置改为了2Bytes的传输模式,避免出现65536的最大包长的限制问题

修改代码如下,将屏幕的全屏刷新缓冲区改为了uint16_t类型,在使用lcd_push_buff函数将屏幕色彩缓存推到屏幕上时使用16bit模式
#include "common_data.h"
#include "lcd_thread.h"
#include "r_ioport.h"
#define RED 0xF800
#define BLUE 0x001F
#define GREEN 0x07E0
#define WHITE 0xFFFF
#define BLACK 0x0000
#define GRAY 0x8430
#define PINK 0xFE19
#define PIN_RES BSP_IO_PORT_01_PIN_02
#define PIN_DC BSP_IO_PORT_01_PIN_14
#define PIN_CS BSP_IO_PORT_06_PIN_03
#define PIN_BL BSP_IO_PORT_06_PIN_01
#define LCD_W 240
#define LCD_H 240
uint16_t lcd_buff[LCD_H][LCD_W];
static volatile bool transfer_complete = false;
volatile uint32_t fps;
void lcd_reset(void);
void lcd_spisend(uint8_t data);
void lcd_sendcmd(uint8_t cmd);
void lcd_senddata(int data);
void lcd_push_buff(void);
void lcd_init(void);
void lcd_setPos(uint16_t Xstart, uint16_t Ystart, uint16_t Xend, uint16_t Yend);
void lcd_clear_buff(uint16_t color);
void lcd_clear(uint16_t color);
void lcd_enter_brushmode(void);
void lcd_setup(void);
void lcd_loop(void);
void lcd_reset(void)
{
R_IOPORT_PinWrite(g_ioport.p_ctrl, PIN_RES, BSP_IO_LEVEL_LOW);
vTaskDelay(pdMS_TO_TICKS(100));
R_IOPORT_PinWrite(g_ioport.p_ctrl, PIN_RES, BSP_IO_LEVEL_HIGH);
vTaskDelay(pdMS_TO_TICKS(100));
}
void lcd_spisend(uint8_t data) {
fsp_err_t err = FSP_SUCCESS;
transfer_complete = false;
R_IOPORT_PinWrite(g_ioport.p_ctrl, PIN_CS, BSP_IO_LEVEL_LOW);
err = R_SPI_Write(spilcd_spi0.p_ctrl, &data, 1, SPI_BIT_WIDTH_8_BITS);
assert(FSP_SUCCESS == err);
while (transfer_complete == false) {
}
R_IOPORT_PinWrite(g_ioport.p_ctrl, PIN_CS, BSP_IO_LEVEL_HIGH);
}
void lcd_sendcmd(uint8_t cmd) {
R_IOPORT_PinWrite(g_ioport.p_ctrl, PIN_DC, BSP_IO_LEVEL_LOW);
lcd_spisend(cmd);
R_IOPORT_PinWrite(g_ioport.p_ctrl, PIN_DC, BSP_IO_LEVEL_HIGH);
}
void lcd_senddata(int data) { lcd_spisend((uint8_t)data); }
void lcd_push_buff(void) {
transfer_complete = false;
R_SPI_Write(spilcd_spi0.p_ctrl, lcd_buff, LCD_W * LCD_H, SPI_BIT_WIDTH_16_BITS);
while (transfer_complete == false) { }
}
void lcd_init(void) {
lcd_reset();
lcd_sendcmd(0x11);
vTaskDelay(pdMS_TO_TICKS(100));
lcd_sendcmd(0x09);
lcd_senddata(0x00);
lcd_senddata(0x00);
lcd_sendcmd(0xB1);
lcd_senddata(0x05);
lcd_senddata(0x3C);
lcd_senddata(0x3C);
lcd_sendcmd(0xB2);
lcd_senddata(0x05);
lcd_senddata(0x3C);
lcd_senddata(0x3C);
lcd_sendcmd(0xB3);
lcd_senddata(0x05);
lcd_senddata(0x3C);
lcd_senddata(0x3C);
lcd_senddata(0x05);
lcd_senddata(0x3C);
lcd_senddata(0x3C);
lcd_sendcmd(0xB4);
lcd_senddata(0x03);
lcd_sendcmd(0xC0);
lcd_senddata(0x28);
lcd_senddata(0x08);
lcd_senddata(0x04);
lcd_sendcmd(0xC1);
lcd_senddata(0XC0);
lcd_sendcmd(0xC2);
lcd_senddata(0x0D);
lcd_senddata(0x00);
lcd_sendcmd(0xC3);
lcd_senddata(0x8D);
lcd_senddata(0x2A);
lcd_sendcmd(0xC4);
lcd_senddata(0x8D);
lcd_senddata(0xEE);
lcd_sendcmd(0xC5);
lcd_senddata(0x1A);
lcd_sendcmd(0x36);
lcd_senddata(0x00);
lcd_sendcmd(0xE0);
lcd_senddata(0x04);
lcd_senddata(0x22);
lcd_senddata(0x07);
lcd_senddata(0x0A);
lcd_senddata(0x2E);
lcd_senddata(0x30);
lcd_senddata(0x25);
lcd_senddata(0x2A);
lcd_senddata(0x28);
lcd_senddata(0x26);
lcd_senddata(0x2E);
lcd_senddata(0x3A);
lcd_senddata(0x00);
lcd_senddata(0x01);
lcd_senddata(0x03);
lcd_senddata(0x13);
lcd_sendcmd(0xE1);
lcd_senddata(0x04);
lcd_senddata(0x16);
lcd_senddata(0x06);
lcd_senddata(0x0D);
lcd_senddata(0x2D);
lcd_senddata(0x26);
lcd_senddata(0x23);
lcd_senddata(0x27);
lcd_senddata(0x27);
lcd_senddata(0x25);
lcd_senddata(0x2D);
lcd_senddata(0x3B);
lcd_senddata(0x00);
lcd_senddata(0x01);
lcd_senddata(0x04);
lcd_senddata(0x13);
lcd_sendcmd(0x3A);
lcd_senddata(0x05);
lcd_sendcmd(0x21);
lcd_sendcmd(0x29);
}
void lcd_setPos(uint16_t Xstart, uint16_t Ystart, uint16_t Xend, uint16_t Yend) {
lcd_sendcmd(0x2a);
lcd_senddata((Xstart) >> 8);
lcd_senddata((Xstart) & 0xff);
lcd_senddata((Xend) >> 8);
lcd_senddata((Xend) & 0xff);
lcd_sendcmd(0x2b);
lcd_senddata((Ystart) >> 8);
lcd_senddata((Ystart) & 0xff);
lcd_senddata((Yend) >> 8);
lcd_senddata((Yend)&0xff);
lcd_sendcmd(0x2C);
}
void lcd_clear_buff(uint16_t color) {
for (size_t j = 0; j < LCD_H; j++) {
for (size_t i = 0; i < LCD_W; i++) {
lcd_buff[j][i] = color;
}
}
}
void lcd_clear(uint16_t color) {
lcd_clear_buff(color);
lcd_push_buff();
}
void lcd_enter_brushmode(void) {
lcd_setPos(0, 0, LCD_W-1, LCD_H-1);
R_IOPORT_PinWrite(g_ioport.p_ctrl, PIN_CS, BSP_IO_LEVEL_LOW);
}
void lcd_setup(void) {
fsp_err_t err = FSP_SUCCESS;
err = R_SPI_Open(spilcd_spi0.p_ctrl, spilcd_spi0.p_cfg);
err += R_AGT_Open(spilcd_timer0.p_ctrl, spilcd_timer0.p_cfg);
err += R_AGT_Start(spilcd_timer0.p_ctrl);
assert(FSP_SUCCESS == err);
lcd_init();
lcd_enter_brushmode();
}
void lcd_loop(void) {
static uint16_t rgb;
rgb++;
rgb %= 3;
if (rgb == 1)
{
lcd_clear_buff(RED);
} else if (rgb == 2)
{
lcd_clear_buff(GREEN);
} else
{
lcd_clear_buff(BLUE);
}
lcd_push_buff();
}
void lcd_thread_entry(void* pvParameters) {
FSP_PARAMETER_NOT_USED(pvParameters);
R_IOPORT_Open(g_ioport.p_ctrl, g_ioport.p_cfg);
R_AGT_Open(spilcd_timer0.p_ctrl, spilcd_timer0.p_cfg);
R_AGT_Start(spilcd_timer0.p_ctrl);
lcd_setup();
while (1) {
lcd_loop();
fps++;
}
}
void spi_callback(spi_callback_args_t* p_args) {
if (SPI_EVENT_TRANSFER_COMPLETE == p_args->event) {
transfer_complete = true;
}
}
static uint32_t fps_record = 0;
void spilcd_timer0_callback(timer_callback_args_t* p_args) {
if (TIMER_EVENT_CYCLE_END == p_args->event) {
fps_record = fps;
fps = 0;
static uint8_t state = 0;
state = !state;
R_IOPORT_PinWrite(g_ioport.p_ctrl, BSP_IO_PORT_04_PIN_05, state);
}
}
烧录到开发板中后可以看到屏幕上面已经不断的刷新三种颜色,用逻辑分析仪抓包查看波形可以看到SPI的输出,稳定的50Mbps

拍摄原因所以不是单色的,可以看到屏幕的刷新也是非常快

在keil MDK的debug界面可以看出来fps稳定在29左右,比25Mbps的SCI SPI驱动的16fps效果快了近一倍之多
