硬汉嵌入式论坛

 找回密码
 立即注册
查看: 3060|回复: 10
收起左侧

[有问必答] TFT屏幕刷新慢

[复制链接]

13

主题

27

回帖

66

积分

初级会员

积分
66
发表于 2022-11-21 16:51:36 | 显示全部楼层 |阅读模式
STM32F407驱动ILI9488,使用8080时序,刷一次屏幕要接近300ms,有什么办法吗?
image.png
回复

使用道具 举报

0

主题

12

回帖

12

积分

新手上路

积分
12
发表于 2022-11-22 22:29:11 来自手机 | 显示全部楼层
差不多,之前用f1也有400ms
回复

使用道具 举报

0

主题

22

回帖

22

积分

新手上路

积分
22
发表于 2022-11-23 08:44:10 | 显示全部楼层
屏幕多少乘多少?试过240*320在F103 emwin下从w25qxx读取再显示才62ms
回复

使用道具 举报

356

主题

2180

回帖

3253

积分

版主

Rank: 7Rank: 7Rank: 7

积分
3253
发表于 2022-11-23 09:49:38 | 显示全部楼层
如果逐点刷新,屏幕又是800X480这种高分辨率的话,确实需要这么久。 但是,0.3秒的切换整屏的话,普通应用也是够的。
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
发表于 2022-11-23 10:25:39 | 显示全部楼层
你的显示屏分辨率多少。

我记得F407的驱动9488的emWin跑分是600万像素,可以简单换算下你的显示屏。

回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
发表于 2022-11-23 10:25:50 | 显示全部楼层
你的显示屏分辨率多少。

我记得F407的驱动9488的emWin跑分是600万像素,可以简单换算下你的显示屏。

回复

使用道具 举报

3

主题

432

回帖

441

积分

高级会员

积分
441
发表于 2022-11-24 15:55:22 | 显示全部楼层
本帖最后由 glory 于 2022-11-24 15:57 编辑

我用FSMC+DMA刷ILI9488,总线速度可达18Mhz,逻辑分析仪可以看出来。
emWin色块测试也是18000000.可以计算得到480x320的屏可以刷到100fps(全屏单色刷屏,不考虑渲染成本)
[C] 纯文本查看 复制代码
#include "efxinc.h"
#include "ili9488_FSMC.h"

static volatile bool_t isOpen = 0;
static void __gpioConfig(void) __attribute__((noinline));
static void __fsmcConfig(void) __attribute__((noinline));
////////////////////////////////////////////////////////////////////////////////
//|          |
//| 函数名称 |: LCM_InitFSMC
//| 功能描述 |: 配置连接LCM的FSMC硬件
//|          |:
//| 参数列表 |:
//|          |:
//| 返    回 |:
//|          |:
//| 备注信息 |:
//|          |:
////////////////////////////////////////////////////////////////////////////////
void LCM_InitFSMC(void)
{
  if (!isOpen) {
    DBG_PUTS("FSMC init\n");
    __gpioConfig();
    __fsmcConfig();
    isOpen = true;
  }
}

////////////////////////////////////////////////////////////////////////////////
//|          |
//| 函数名称 |: __gpioConfig
//| 功能描述 |: 配置FSMC的GPIO
//|          |:
//| 参数列表 |:
//|          |:
//| 返    回 |:
//|          |:
//| 备注信息 |:
//|          |:
////////////////////////////////////////////////////////////////////////////////
static void __gpioConfig(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE, ENABLE);

  /* GPIOD configuration */
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_FSMC);
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_FSMC);
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource4, GPIO_AF_FSMC);
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource5, GPIO_AF_FSMC);
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource7, GPIO_AF_FSMC);
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource8, GPIO_AF_FSMC);
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource9, GPIO_AF_FSMC);
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource10, GPIO_AF_FSMC);
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource11, GPIO_AF_FSMC);
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource14, GPIO_AF_FSMC);
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource15, GPIO_AF_FSMC);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0  | GPIO_Pin_1  | GPIO_Pin_4 | GPIO_Pin_5  |
                                GPIO_Pin_7  | GPIO_Pin_8  | GPIO_Pin_9 | GPIO_Pin_10 |
                                GPIO_Pin_11 | GPIO_Pin_14 | GPIO_Pin_15;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOD, &GPIO_InitStructure);

  /* GPIOE configuration */
  GPIO_PinAFConfig(GPIOE, GPIO_PinSource7, GPIO_AF_FSMC);
  GPIO_PinAFConfig(GPIOE, GPIO_PinSource8, GPIO_AF_FSMC);
  GPIO_PinAFConfig(GPIOE, GPIO_PinSource9, GPIO_AF_FSMC);
  GPIO_PinAFConfig(GPIOE, GPIO_PinSource10, GPIO_AF_FSMC);
  GPIO_PinAFConfig(GPIOE, GPIO_PinSource11, GPIO_AF_FSMC);
  GPIO_PinAFConfig(GPIOE, GPIO_PinSource12, GPIO_AF_FSMC);
  GPIO_PinAFConfig(GPIOE, GPIO_PinSource13, GPIO_AF_FSMC);
  GPIO_PinAFConfig(GPIOE, GPIO_PinSource14, GPIO_AF_FSMC);
  GPIO_PinAFConfig(GPIOE, GPIO_PinSource15, GPIO_AF_FSMC);

  GPIO_InitStructure.GPIO_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_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOE, &GPIO_InitStructure);
}

////////////////////////////////////////////////////////////////////////////////
//|          |
//| 函数名称 |: __fsmcConfig
//| 功能描述 |: 配置FSMC的细节
//|          |:
//| 参数列表 |:
//|          |:
//| 返    回 |:
//|          |:
//| 备注信息 |:
//|          |:
////////////////////////////////////////////////////////////////////////////////
static void __fsmcConfig(void)
{
  FSMC_NORSRAMTimingInitTypeDef timing;
  FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure;

  RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC, ENABLE);

  timing.FSMC_AddressSetupTime = 3;       /* (n+0) HCLK */
  timing.FSMC_AddressHoldTime = 3;        /* (n+0) HCLK */
  timing.FSMC_DataSetupTime = 5;          /* (n+0) HCLK */
  timing.FSMC_BusTurnAroundDuration = 0;  /* (n+0) HCLK */
  timing.FSMC_CLKDivision = 1;            /* (n+1) HCLK */
  timing.FSMC_DataLatency = 0;            /* (n+2) FSMC_CLK */
  timing.FSMC_AccessMode = FSMC_AccessMode_A;

  FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM1;
  FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
  FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM;
  FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
  FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
  FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable;
  FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
  FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
  FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
  FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
  FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
  FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
  FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
  FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &timing;
  FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &timing;

  FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);
  FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE);
}


////////////////////////////////////////////////////////////////////////////////


回复

使用道具 举报

3

主题

432

回帖

441

积分

高级会员

积分
441
发表于 2022-11-24 16:00:12 | 显示全部楼层
这是DMA使用的代码:
[C] 纯文本查看 复制代码
#include "efxinc.h"
#include "lcm_DEV.h"
#include "ili9488_FSMC.h"

#ifndef MEM_PI_HARDWARE
#define MEM_PI_HARDWARE
#endif


/* 发送数据到外围设备的DMA配置 */
#define TEMPL_TX_CR (DMA_Channel_0\
                     | DMA_MemoryBurst_Single\
                     | DMA_PeripheralBurst_Single\
                     | DMA_Priority_Low\
                     | DMA_MemoryDataSize_HalfWord\
                     | DMA_PeripheralDataSize_HalfWord\
                     | DMA_MemoryInc_Disable\
                     | DMA_PeripheralInc_Disable\
                     | DMA_DIR_MemoryToMemory\
                     | DMA_FlowCtrl_Memory)
#define LCM_DMA_MAX  (32*1024UL)

#define RST_H()   do{GPIOC->BSRR = GPSET(GPIO_Pin_2);}while(0)
#define RST_L()   do{GPIOC->BSRR = GPCLR(GPIO_Pin_2);}while(0)
#define BL_ON()   do{GPIOD->BSRR = GPSET(GPIO_Pin_12);}while(0)
#define BL_OFF()  do{GPIOD->BSRR = GPCLR(GPIO_Pin_12);}while(0)

#define LCM_H36_MY    (1<<7)
#define LCM_H36_MX    (1<<6)
#define LCM_H36_MV    (1<<5)
#define LCM_H36_ML    (1<<4)
#define LCM_H36_RGB   (1<<3)
#define LCM_H36_MH    (1<<2)

uint16_t lcm_lbuf[LCM_LBUF_SIZE] MEM_PI_HARDWARE;

static struct {
  uint32_t foreColor;
  uint32_t backColor;
  uint16_t blValue;
} ctx = {
  .foreColor = LCM_WHITE,
  .backColor = LCM_BLACK,
};

static uint16_t lcm_args[16] MEM_PI_HARDWARE;
static uint8_t const _zheng[8] = {
  0x00, 0x7e, 0x08, 0x2e, 0x28, 0x7e, 0x00
};

static void lcm_write_reg(uint16_t reg, const uint16_t data[], size_t num)
{
  LCM_FSMC_REG = reg;
  for (; num; num--) {
    LCM_FSMC_DAT = *data++;
  }
}

////////////////////////////////////////////////////////////////////////////////
//|          |
//| 函数名称 |: lcm_init_dma
//| 功能描述 |: 配置DMA
//|          |:
//| 参数列表 |:
//|          |:
//| 返    回 |:
//|          |:
//| 备注信息 |: 只有DMA2允许Memory-to-Memory传输!
//|          |:
////////////////////////////////////////////////////////////////////////////////
static void lcm_init_dma(void) __attribute__((noinline));
static void lcm_init_dma(void)
{
  NVIC_DisableIRQ(DMA2_Stream7_IRQn);
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
  DMA2_Stream7->CR = 0;
}

////////////////////////////////////////////////////////////////////////////////
//|          |
//| 函数名称 |: lcm_send_dma
//| 功能描述 |: 用DMA向LCM发送一种颜色
//|          |:
//| 参数列表 |:
//|          |:
//| 返    回 |:
//|          |:
//| 备注信息 |:
//|          |:
////////////////////////////////////////////////////////////////////////////////
static void lcm_send_dma_fixed(uint16_t color, unsigned num)
{
  static uint16_t src_buffer[1] MEM_PI_HARDWARE;
  unsigned nTrans;

  src_buffer[0] = color;
  while (num > 0) {
    nTrans = num;
    if (nTrans > LCM_DMA_MAX) {
      nTrans = LCM_DMA_MAX;
    } else if (nTrans < 32) {
      for (; nTrans; nTrans--) {
        LCM_FSMC_DAT = color;
      }
      break;
    }
    DMA2->HIFCR = (DMA_HIFCR_CTCIF7 | DMA_HIFCR_CHTIF7 | DMA_HIFCR_CTEIF7 | DMA_HIFCR_CDMEIF7 | DMA_HIFCR_CFEIF7);
    DMA2_Stream7->CR = (TEMPL_TX_CR | 0);
    DMA2_Stream7->PAR  = (uint32_t)src_buffer;
    DMA2_Stream7->M0AR = (uint32_t)&LCM_FSMC_DAT;
    DMA2_Stream7->NDTR = (uint16_t)nTrans;
    DMA2_Stream7->CR  |= DMA_SxCR_EN;
    while (!(DMA2->HISR & DMA_HISR_TCIF7));
    num -= nTrans;
  }
}

////////////////////////////////////////////////////////////////////////////////
//|          |
//| 函数名称 |: lcm_send_dma_line
//| 功能描述 |: 用DMA向LCM发送一行颜色序列
//|          |:
//| 参数列表 |:
//|          |:
//| 返    回 |:
//|          |:
//| 备注信息 |:
//|          |:
////////////////////////////////////////////////////////////////////////////////
static void lcm_send_dma_line(const uint16_t data[], unsigned num)
{
  DMA2->HIFCR = (DMA_HIFCR_CTCIF7 | DMA_HIFCR_CHTIF7 | DMA_HIFCR_CTEIF7 | DMA_HIFCR_CDMEIF7 | DMA_HIFCR_CFEIF7);
  DMA2_Stream7->CR = (TEMPL_TX_CR | DMA_PeripheralInc_Enable);
  DMA2_Stream7->PAR  = (uint32_t)data;
  DMA2_Stream7->M0AR = (uint32_t)&LCM_FSMC_DAT;
  DMA2_Stream7->NDTR = (uint16_t)num;
  DMA2_Stream7->CR  |= DMA_SxCR_EN;
  while (!(DMA2->HISR & DMA_HISR_TCIF7));
}

////////////////////////////////////////////////////////////////////////////////
//|          |
//| 函数名称 |: DMA2_Stream7_IRQHandler
//| 功能描述 |: DMA中断处理函数
//|          |:
//| 参数列表 |:
//|          |:
//| 返    回 |:
//|          |:
//| 备注信息 |:
//|          |:
////////////////////////////////////////////////////////////////////////////////
void DMA2_Stream7_IRQHandler(void)
{

}

////////////////////////////////////////////////////////////////////////////////
//|          |
//| 函数名称 |: LCM_Init
//| 功能描述 |: 初始化LCM
//|          |:
//| 参数列表 |:
//|          |:
//| 返    回 |:
//|          |:
//| 备注信息 |:
//|          |:
////////////////////////////////////////////////////////////////////////////////
bool_t LCM_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  uint32_t reg_val;
  unsigned i;

  DBG_PUTS("LCM init.\n");
  lcm_init_dma();
  LCM_InitFSMC();

  /* Enable GPIOB clock */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD, ENABLE);

  RST_L();
  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_2;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
  GPIO_Init(GPIOC, &GPIO_InitStructure);

  BL_OFF();
  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_12;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
  GPIO_Init(GPIOD, &GPIO_InitStructure);

  /* 执行复位信号电平 */
  LCM_SetBacklight(LCM_BL_OFF);
  RST_L();
  sys_delay(5);   // 低电平5ms
  RST_H();
  sys_delay(20);  // 等待20ms

#if 1 /* 执行LCM初始化配置 */
  /* Read ID4 */
  do {
    reg_val = 0;
    LCM_FSMC_REG = 0xD3;
    reg_val = ((reg_val << 8) | (LCM_FSMC_DAT & 0xFF));
    reg_val = ((reg_val << 8) | (LCM_FSMC_DAT & 0xFF));
    reg_val = ((reg_val << 8) | (LCM_FSMC_DAT & 0xFF));
    reg_val = ((reg_val << 8) | (LCM_FSMC_DAT & 0xFF));
  } while ((reg_val & 0xFFFF) != 0x9488);

  /* PGAMCTRL (Positive Gamma Control) (E0h) */
  i = 0;
  lcm_args[i++] = 0x00;
  lcm_args[i++] = 0x03;
  lcm_args[i++] = 0x0C;
  lcm_args[i++] = 0x09;
  lcm_args[i++] = 0x17;
  lcm_args[i++] = 0x09;
  lcm_args[i++] = 0x3E;
  lcm_args[i++] = 0x89;
  lcm_args[i++] = 0x49;
  lcm_args[i++] = 0x08;
  lcm_args[i++] = 0x0D;
  lcm_args[i++] = 0x0A;
  lcm_args[i++] = 0x13;
  lcm_args[i++] = 0x15;
  lcm_args[i++] = 0x0F;
  lcm_write_reg(0xE0, lcm_args, i);

  /* NGAMCTRL (Negative Gamma Control) (E1h) */
  i = 0;
  lcm_args[i++] = 0x00;
  lcm_args[i++] = 0x11;
  lcm_args[i++] = 0x15;
  lcm_args[i++] = 0x03;
  lcm_args[i++] = 0x0F;
  lcm_args[i++] = 0x05;
  lcm_args[i++] = 0x2D;
  lcm_args[i++] = 0x34;
  lcm_args[i++] = 0x41;
  lcm_args[i++] = 0x02;
  lcm_args[i++] = 0x0B;
  lcm_args[i++] = 0x0A;
  lcm_args[i++] = 0x33;
  lcm_args[i++] = 0x37;
  lcm_args[i++] = 0x0F;
  lcm_write_reg(0xE1, lcm_args, i);

  /* Power Control 1 (C0h) */
  i = 0;
  lcm_args[i++] = 0x17;
  lcm_args[i++] = 0x15;
  lcm_write_reg(0xC0, lcm_args, i);

  /* Power Control 2 (C1h) */
  i = 0;
  lcm_args[i++] = 0x41;
  lcm_write_reg(0xC1, lcm_args, i);

  /* VCOM Control (C5h) */
  i = 0;
  lcm_args[i++] = 0x00;
  lcm_args[i++] = 0x12;
  lcm_args[i++] = 0x80;
  lcm_write_reg(0xC5, lcm_args, i);

  /* Memory Access Control (36h) */
  i = 0;
  lcm_args[i++] = 0x48;
  lcm_write_reg(0x36, lcm_args, i);

  /* Interface Pixel Format (3Ah) */
  i = 0;
  lcm_args[i++] = 0x55;
  lcm_write_reg(0x3A, lcm_args, i);

  /* Interface Mode Control (B0h) */
  i = 0;
  lcm_args[i++] = 0x00;
  lcm_write_reg(0xB0, lcm_args, i);

  /* Frame Rate Control (In Normal Mode/Full Colors) (B1h) */
  i = 0;
  lcm_args[i++] = 0xA0;
  lcm_write_reg(0xB1, lcm_args, i);

  /* Display Inversion Control (B4h) */
  i = 0;
  lcm_args[i++] = 0x02;
  lcm_write_reg(0xB4, lcm_args, i);

  /* Display Function Control (B6h) */
  i = 0;
  lcm_args[i++] = 0x02;
  lcm_args[i++] = 0x02;
  lcm_write_reg(0xB6, lcm_args, i);

  /* Set Image Function (E9h) */
  i = 0;
  lcm_args[i++] = 0x00;
  lcm_write_reg(0xE9, lcm_args, i);

  /* Adjust Control 3 (F7h) */
  i = 0;
  lcm_args[i++] = 0xA9;
  lcm_args[i++] = 0x51;
  lcm_args[i++] = 0x2C;
  lcm_args[i++] = 0x82;
  lcm_write_reg(0xF7, lcm_args, i);

  /* Sleep OUT (11h) */
  lcm_write_reg(0x11, lcm_args, 0);
  sys_delay(100);

  /* Display ON (29h) */
  lcm_write_reg(0x29, lcm_args, 0);
#endif

#if (LCM_DEGREE == LCM_DEGREE_D0)
  LCM_FSMC_REG = 0x36;
  LCM_FSMC_DAT = LCM_H36_RGB | LCM_H36_MX;
#elif (LCM_DEGREE == LCM_DEGREE_D90)
  LCM_FSMC_REG = 0x36;
  LCM_FSMC_DAT = LCM_H36_RGB | LCM_H36_MV;
#elif (LCM_DEGREE == LCM_DEGREE_D180)
  LCM_FSMC_REG = 0x36;
  LCM_FSMC_DAT = LCM_H36_RGB | LCM_H36_MY;
#elif (LCM_DEGREE == LCM_DEGREE_D270)
  LCM_FSMC_REG = 0x36;
  LCM_FSMC_DAT = LCM_H36_RGB | LCM_H36_MV | LCM_H36_MX | LCM_H36_MY;
#endif

  LCM_Clear();
  sys_delay(100);

#if 0
  LCM_SetForeColor(LCM_WHITE);
  LCM_FillHLine(0, 0, 40);
  LCM_FillVLine(0, 0, 40);
  LCM_FillHLine(LCM_LOG_HSIZE - 40, LCM_LOG_VSIZE - 1, 40);
  LCM_FillVLine(LCM_LOG_HSIZE - 1, LCM_LOG_VSIZE - 40, 40);
  LCM_ShowTest();
  LCM_SetForeColor(LCM_GREEN);
  LCM_FillHLine(10, 10, 20);
  LCM_FillVLine(10, 10, 20);
  LCM_SetForeColor(LCM_RED);
  LCM_FillRect(12, 12, 18, 30);
#endif
  return true;
}

////////////////////////////////////////////////////////////////////////////////
//|          |
//| 函数名称 |: LCM_SetBacklight
//| 功能描述 |: 设置LCM背光亮度
//|          |:
//| 参数列表 |: value 亮度值,已定义的:LCM_BL_OFF,LCM_BL_ON,LCM_BL_MAX
//|          |:
//| 返    回 |:
//|          |:
//| 备注信息 |:
//|          |:
////////////////////////////////////////////////////////////////////////////////
void LCM_SetBacklight(unsigned value)
{
  if (value > LCM_BL_MAX) {
    value = LCM_BL_MAX;
  }
  ctx.blValue = value;
  if (value == 0) {
    BL_OFF();
  } else {
    BL_ON();
  }
}

////////////////////////////////////////////////////////////////////////////////
//|          |
//| 函数名称 |: LCM_SetWindowEx
//| 功能描述 |: 设置像素块传输的矩形窗口
//|          |:
//| 参数列表 |:
//|          |:
//| 返    回 |:
//|          |:
//| 备注信息 |:
//|          |:
////////////////////////////////////////////////////////////////////////////////
void LCM_SetWindowEx(unsigned x0, unsigned y0, unsigned x1, unsigned y1)
{
  /* Column Address Set (2Ah) */
  LCM_FSMC_REG = 0x2A;
  LCM_FSMC_DAT = (x0 >> 8);
  LCM_FSMC_DAT = x0;
  LCM_FSMC_DAT = (x1 >> 8);
  LCM_FSMC_DAT = x1;

  /* Page Address Set (2Bh) */
  LCM_FSMC_REG = 0x2B;
  LCM_FSMC_DAT = (y0 >> 8);
  LCM_FSMC_DAT = y0;
  LCM_FSMC_DAT = (y1 >> 8);
  LCM_FSMC_DAT = y1;

  /* Memory Write (2Ch) */
  LCM_FSMC_REG = 0x2C;
}

////////////////////////////////////////////////////////////////////////////////
//|          |
//| 函数名称 |: LCM_SetWindow
//| 功能描述 |: 设置像素块传输的矩形窗口
//|          |:
//| 参数列表 |:
//|          |:
//| 返    回 |:
//|          |:
//| 备注信息 |:
//|          |:
////////////////////////////////////////////////////////////////////////////////
void LCM_SetWindow(unsigned x, unsigned y, unsigned w, unsigned h)
{
  LCM_SetWindowEx(x, y, x + w - 1, y + h - 1);
}

////////////////////////////////////////////////////////////////////////////////
//|          |
//| 函数名称 |: LCM_SetCursor
//| 功能描述 |: 设置光标位置
//|          |:
//| 参数列表 |:
//|          |:
//| 返    回 |:
//|          |:
//| 备注信息 |:
//|          |:
////////////////////////////////////////////////////////////////////////////////
void LCM_SetCursor(unsigned x, unsigned y)
{
  /* Column Address Set (2Ah) */
  LCM_FSMC_REG = 0x2A;
  LCM_FSMC_DAT = (x >> 8);
  LCM_FSMC_DAT = x;
  LCM_FSMC_DAT = (LCM_LOG_HSIZE >> 8);
  LCM_FSMC_DAT = (LCM_LOG_HSIZE & 0xFF);

  /* Page Address Set (2Bh) */
  LCM_FSMC_REG = 0x2B;
  LCM_FSMC_DAT = (y >> 8);
  LCM_FSMC_DAT = y;
  LCM_FSMC_DAT = (LCM_LOG_VSIZE >> 8);
  LCM_FSMC_DAT = (LCM_LOG_VSIZE & 0xFF);

  /* Memory Write (2Ch) */
  LCM_FSMC_REG = 0x2C;
}

////////////////////////////////////////////////////////////////////////////////
//|          |
//| 函数名称 |: LCM_ReadRect
//| 功能描述 |: 读取指定矩形区域内的像素值
//|          |:
//| 参数列表 |: pixels[] 返回的像素值(不必须MEM_PI_HARDWARE)
//|          |:
//| 返    回 |: 返回已经读取的像素数量
//|          |:
//| 备注信息 |: ILI9488读出的像素,每3个Hword带2个像素,分别是:
//|          |: [R1,G1][B1,R2][G2,B2]...[Rm,Gm][Bm,Rn][Gn,Bn]
//|          |: 其中每Hword表示为[Hbyte,Lbyte]
////////////////////////////////////////////////////////////////////////////////
unsigned LCM_ReadRect(LCM_RECT const* pRect, uint16_t pixels[])
{
  unsigned tmpval1, tmpval2;
  unsigned count;
  uint32_t color;

  tmpval1 = pRect->x0;
  tmpval2 = pRect->x1;
  count = (tmpval2 - tmpval1 + 1);
  /* Column Address Set (2Ah) */
  LCM_FSMC_REG = 0x2A;
  LCM_FSMC_DAT = (tmpval1 >> 8);
  LCM_FSMC_DAT = tmpval1;
  LCM_FSMC_DAT = (tmpval2 >> 8);
  LCM_FSMC_DAT = tmpval2;

  tmpval1 = pRect->y0;
  tmpval2 = pRect->y1;
  count *= (tmpval2 - tmpval1 + 1);
  /* Page Address Set (2Bh) */
  LCM_FSMC_REG = 0x2B;
  LCM_FSMC_DAT = (tmpval1 >> 8);
  LCM_FSMC_DAT = tmpval1;
  LCM_FSMC_DAT = (tmpval2 >> 8);
  LCM_FSMC_DAT = tmpval2;

  /* Memory Read (2Eh) */
  LCM_FSMC_REG = 0x2E;
  tmpval1 = LCM_FSMC_DAT;
  for (unsigned i = 0; i < count; i += 2) {
    tmpval1 = LCM_FSMC_DAT;
    tmpval2 = LCM_FSMC_DAT;
    color = (tmpval1 & 0xF800);
    color |= (tmpval1 & 0xFC) << 3;
    color |= (tmpval2 & 0xF800) >> 11;
    pixels[i + 0] = color;
    if (i + 1 == count) {
      /* 最后的像素,跳出 */
      break;
    }
    tmpval1 = LCM_FSMC_DAT;
    color = (tmpval2 << 8);
    color |= (tmpval1 & 0xFC00) >> 5;
    color |= (tmpval1 & 0xF8) >> 3;
    pixels[i + 1] = color;
  }
  return count;
}

////////////////////////////////////////////////////////////////////////////////
//|          |
//| 函数名称 |: LCM_Clear
//| 功能描述 |: 用背景色填充整个屏幕
//|          |:
//| 参数列表 |:
//|          |:
//| 返    回 |:
//|          |:
//| 备注信息 |:
//|          |:
////////////////////////////////////////////////////////////////////////////////
void LCM_Clear(void)
{
  LCM_SetWindow(0, 0, LCM_LOG_HSIZE, LCM_LOG_VSIZE);
  LCM_PutColor(ctx.backColor, LCM_LOG_HSIZE * LCM_LOG_VSIZE);
}

////////////////////////////////////////////////////////////////////////////////
//|          |
//| 函数名称 |: LCM_SetBackColor
//| 功能描述 |: 设置背景色
//|          |:
//| 参数列表 |:
//|          |:
//| 返    回 |:
//|          |:
//| 备注信息 |:
//|          |:
////////////////////////////////////////////////////////////////////////////////
void LCM_SetBackColor(uint32_t color)
{
  ctx.backColor = color;
}

////////////////////////////////////////////////////////////////////////////////
//|          |
//| 函数名称 |: LCM_SetForeColor
//| 功能描述 |: 设置前景色
//|          |:
//| 参数列表 |:
//|          |:
//| 返    回 |:
//|          |:
//| 备注信息 |:
//|          |:
////////////////////////////////////////////////////////////////////////////////
void LCM_SetForeColor(uint32_t color)
{
  ctx.foreColor = color;
}

////////////////////////////////////////////////////////////////////////////////
//|          |
//| 函数名称 |: LCM_FillHLine
//| 功能描述 |: 填充水平线
//|          |:
//| 参数列表 |:
//|          |:
//| 返    回 |:
//|          |:
//| 备注信息 |:
//|          |:
////////////////////////////////////////////////////////////////////////////////
void LCM_FillHLine(unsigned x, unsigned y, unsigned len)
{
  LCM_SetWindow(x, y, len, 1);
  LCM_PutColor(ctx.foreColor, len);
}

////////////////////////////////////////////////////////////////////////////////
//|          |
//| 函数名称 |: LCM_FillVLine
//| 功能描述 |: 填充垂直线
//|          |:
//| 参数列表 |:
//|          |:
//| 返    回 |:
//|          |:
//| 备注信息 |:
//|          |:
////////////////////////////////////////////////////////////////////////////////
void LCM_FillVLine(unsigned x, unsigned y, unsigned len)
{
  LCM_SetWindow(x, y, 1, len);
  LCM_PutColor(ctx.foreColor, len);
}

////////////////////////////////////////////////////////////////////////////////
//|          |
//| 函数名称 |: LCM_FillRect
//| 功能描述 |: 填充矩形色块
//|          |:
//| 参数列表 |:
//|          |:
//| 返    回 |:
//|          |:
//| 备注信息 |:
//|          |:
////////////////////////////////////////////////////////////////////////////////
void LCM_FillRect(unsigned x, unsigned y, unsigned w, unsigned h)
{
  LCM_SetWindow(x, y, w, h);
  LCM_PutColor(ctx.foreColor, w * h);
}

////////////////////////////////////////////////////////////////////////////////
//|          |
//| 函数名称 |: LCM_DrawRect
//| 功能描述 |: 绘制矩形方框
//|          |:
//| 参数列表 |:
//|          |:
//| 返    回 |:
//|          |:
//| 备注信息 |:
//|          |:
////////////////////////////////////////////////////////////////////////////////
void LCM_DrawRect(unsigned x, unsigned y, unsigned w, unsigned h)
{
  LCM_FillHLine(x, y, w);
  LCM_FillVLine(x, y, h);
  LCM_FillHLine(x, y + h - 1, w);
  LCM_FillVLine(x + w - 1, y, h);
}

////////////////////////////////////////////////////////////////////////////////
//|          |
//| 函数名称 |: LCM_PutColor
//| 功能描述 |: 向LCM输入大量相同颜色值
//|          |:
//| 参数列表 |:
//|          |:
//| 返    回 |:
//|          |:
//| 备注信息 |:
//|          |:
////////////////////////////////////////////////////////////////////////////////
void LCM_PutColor(uint32_t color, unsigned len)
{
  lcm_send_dma_fixed(color, len);
}

////////////////////////////////////////////////////////////////////////////////
//|          |
//| 函数名称 |: LCM_PutPixel
//| 功能描述 |: 向LCM写入一个像素值
//|          |:
//| 参数列表 |:
//|          |:
//| 返    回 |:
//|          |:
//| 备注信息 |:
//|          |:
////////////////////////////////////////////////////////////////////////////////
void LCM_PutPixel(uint16_t data)
{
  LCM_FSMC_DAT = data;
}

////////////////////////////////////////////////////////////////////////////////
//|          |
//| 函数名称 |: LCM_PutPixels
//| 功能描述 |: 向LCM输入大量像素值(会拷贝到DMA内存,再DMA发送)
//|          |:
//| 参数列表 |: pixels[] 每个pixel的bit15先发送,bit0最后发送
//|          |: len      表示pixels[]数组的长度,不是字节数!
//| 返    回 |:
//|          |:
//| 备注信息 |: 该函数比LCM_PutData16多了中间缓存的拷贝,以便对数据预处理
//|          |:
////////////////////////////////////////////////////////////////////////////////
void LCM_PutPixels(const uint16_t pixels[], unsigned len)
{
  unsigned size = LCM_LBUF_SIZE;

__again:
  while (len >= size) {
    for (unsigned i = 0; i < size; i++) {
      lcm_lbuf[i] = pixels[i];
    }
    lcm_send_dma_line(lcm_lbuf, size);
    pixels += size;
    len -= size;
  }
  if (len > 0) {
    size = len;
    goto __again;
  }
}

////////////////////////////////////////////////////////////////////////////////
//|          |
//| 函数名称 |: LCM_PutData16
//| 功能描述 |: 向LCM输入大量Raw数据(直接DMA发送)
//|          |:
//| 参数列表 |: data[] 每个data的bit15先发送,bit0最后发送
//|          |: len    表示data[]数组的长度,不是字节数!
//| 返    回 |:
//|          |:
//| 备注信息 |: !!注意!!参数data[]必须是DMA可访问的存储器
//|          |:
////////////////////////////////////////////////////////////////////////////////
void LCM_PutData16(const uint16_t data[], unsigned len)
{
  unsigned size = LCM_DMA_MAX;

__again:
  while (len >= size) {
    lcm_send_dma_line(data, size);
    data += size;
    len -= size;
  }
  if (len > 0) {
    size = len;
    goto __again;
  }
}

////////////////////////////////////////////////////////////////////////////////
//|          |
//| 函数名称 |: LCM_ShowTest
//| 功能描述 |: 在屏幕上写一个蓝底黄字的“正”字,以测试屏幕旋转角度
//|          |:
//| 参数列表 |:
//|          |:
//| 返    回 |:
//|          |:
//| 备注信息 |:
//|          |:
////////////////////////////////////////////////////////////////////////////////
void LCM_ShowTest(void)
{
  uint8_t mask;

  LCM_SetWindow(1, 1, 8, 7);
  for (unsigned i = 0; i < 7; i++) {
    mask = 0x80;
    while (mask) {
      if (mask & _zheng[i]) {
        LCM_PutColor(LCM_YELLOW, 1);
      } else {
        LCM_PutColor(LCM_BLUE, 1);
      }
      mask >>= 1;
    }
  }
}



回复

使用道具 举报

13

主题

27

回帖

66

积分

初级会员

积分
66
 楼主| 发表于 2023-1-6 16:11:50 | 显示全部楼层
谢谢各位大佬,已经找到问题解决了,是FSMC的地址设置错误的问题;不过还没搞清楚为什么地址错了仍然能使用?
[C] 纯文本查看 复制代码
	TFTSRAM_Handler.Init.NSBank=FSMC_NORSRAM_BANK1;     				//使用NE1
	TFTSRAM_Handler.Init.DataAddressMux=FSMC_DATA_ADDRESS_MUX_DISABLE; 	//地址/数据线不复用
	TFTSRAM_Handler.Init.MemoryType=FSMC_MEMORY_TYPE_SRAM;   			//SRAM
	TFTSRAM_Handler.Init.MemoryDataWidth=FSMC_NORSRAM_MEM_BUS_WIDTH_16; //16位数据宽度
	TFTSRAM_Handler.Init.BurstAccessMode=FSMC_BURST_ACCESS_MODE_DISABLE; //是否使能突发访问,仅对同步突发存储器有效,此处未用到
	TFTSRAM_Handler.Init.WaitSignalPolarity=FSMC_WAIT_SIGNAL_POLARITY_LOW;//等待信号的极性,仅在突发模式访问下有用
	TFTSRAM_Handler.Init.WaitSignalActive=FSMC_WAIT_TIMING_BEFORE_WS;   //存储器是在等待周期之前的一个时钟周期还是等待周期期间使能NWAIT
	TFTSRAM_Handler.Init.WriteOperation=FSMC_WRITE_OPERATION_ENABLE;    //存储器写使能
	TFTSRAM_Handler.Init.WaitSignal=FSMC_WAIT_SIGNAL_DISABLE;           //等待使能位,此处未用到
	TFTSRAM_Handler.Init.ExtendedMode=FSMC_EXTENDED_MODE_ENABLE;        //读写使用不同的时序
	TFTSRAM_Handler.Init.AsynchronousWait=FSMC_ASYNCHRONOUS_WAIT_DISABLE;//是否使能同步传输模式下的等待信号,此处未用到
	TFTSRAM_Handler.Init.WriteBurst=FSMC_WRITE_BURST_DISABLE;           //禁止突发写
	TFTSRAM_Handler.Init.ContinuousClock=FSMC_CONTINUOUS_CLOCK_SYNC_ASYNC;[attach]83421[/attach]
回复

使用道具 举报

13

主题

27

回帖

66

积分

初级会员

积分
66
 楼主| 发表于 2023-1-6 16:25:41 | 显示全部楼层
找到问题了,是FSMC的地址设置错误:改成FSMC_NORSRAM_BANK1就恢复了正常的刷新率;但很奇怪为什么设置错误却也能刷新
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
发表于 2023-1-7 00:41:04 | 显示全部楼层
13450334834 发表于 2023-1-6 16:25
找到问题了,是FSMC的地址设置错误:改成FSMC_NORSRAM_BANK1就恢复了正常的刷新率;但很奇怪为什么设置错误 ...

FSMC_NORSRAM_BANK1影响的是片选,他的数据和地址线是一直有输出的。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-8-12 20:44 , Processed in 0.064587 second(s), 27 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表