写在前面
MCU:RP2040,双核M0+,默频125MHz
屏幕:ST7735驱动芯片,8080 8bit时序
驱动板:自制
关于PIO详见官方的rp2040-datasheet: Chapter 3. PIO
部分代码
PIO代码
将八位数据送到八个并行数据口,同时WR信号产生上升沿
其他控制信号(CS、RD、RS)由内核操作GPIO控制
增加一些延时确保数据能正确送入驱动芯片
.program lcd_8080_8bit
lp1:
pull block
set pins, 0
out pins, 8 [5]
set pins, 1 [5]
jmp lp1
DMA初始化
配置DMA通道
DMA的DRQE配置为PIO产生
void dma_init(PIO pio, uint8_t sm) {
// TX DMA channel
dma_chan = dma_claim_unused_channel(true);
dma_channel_config c = dma_channel_get_default_config(dma_chan);
channel_config_set_transfer_data_size(&c, DMA_SIZE_8);
channel_config_set_read_increment(&c, true);
channel_config_set_write_increment(&c, false);
channel_config_set_dreq(&c, pio_get_dreq(pio, sm, true)); // Dreq from PIO
dma_channel_configure(
dma_chan,
&c,
&pio0_hw->txf[sm],
NULL,
H_RESOLUTION*V_RESOLUTION*2,
false // Not start yet
);
}
DMA中断
每次刷新LCD后,在中断中重新发送写显存命令
void dma_irq_handler() {
st7735_set_cs_pin(1);
dma_hw->ints0 = 1u << dma_chan;
fps_calculate();
st7735_pio_pixel_start(pio, sm);
dma_channel_set_trans_count(dma_chan, H_RESOLUTION*V_RESOLUTION*2, false);
dma_channel_set_read_addr(dma_chan, image_array, true); // Start trans
}
帧率计算
取60次LCD刷新时间的平均值计算帧率
void fps_calculate() {
uint64_t current_time = time_us_64();
uint64_t delta_time = current_time - last_time;
last_time = current_time;
if (delta_time > 0) {
fps += 1000000.0f / (float)delta_time;
}
count++;
if (count == 60) {
count = 0;
printf("CORE1: FPS: %.2f ", fps / 60.0f);
printf("FREQ: %u\n", clock_get_hz(clk_sys));
fps = 0.0f;
}
}
结果
显示彩条的情况下,信息输出如下:
不使用DMA,由内核发送数据给PIO时的帧率并没有低太多,刷新速率的瓶颈还是在驱动芯片上
RP2040超频到150MHz时,帧率能提高到270fps,但是LCD显示出现错误并且自己重启