2017-01-22 6 views
1

ILI9341 디스플레이 컨트롤러를 STM32F407vg 마이크로 컨트롤러 (STM32 디스커버리 보드)에 연결하고있다. 디스플레이는 16 비트 병렬 데이터 버스로 STM32에 연결된다.STM32F4Discovery 보드의 디스플레이를 제어하기 위해 빠른 STM32 F4 FSMC를 설정하는 방법은 무엇입니까?

높은 데이터를 얻기 위해 STM32의 FSMC를 사용합니다. FSMC는 정적 RAM 컨트롤러로 구성됩니다. 나는 칩을 선택하거나 읽지 않는다. 인터페이스가 작동하고 디스플레이에 데이터를 전송할 수 있지만 속도가 느립니다.

for 루프로 LCD에 쓰기를 시도했지만 메모리 모드에서 메모리 모드로 DMA를 시도했습니다. 나는 플래시에서 데이터를 쓰려고했지만 RAM에서도 시도했다. 다양한 DMA 설정 최적화. 이러한 모든 변화는 속도에 전혀 영향을 미치지 않았습니다. 그래서 나에게는 어딘가에 커다란 병목 현상이있는 것 같습니다.

아래 그림은 16 비트 워드 전송을 측정 한 것입니다 (처음 8 개 라인 만 측정 됨). 보시다시피, 디스플레이의 WR 라인은 558kHz로 토글됩니다. 참조 매뉴얼에 설명 된대로

Logic analyzer FSMC 558kHz

아래 그림 FSMC 타이밍을 나타낸다. NWE (쓰기 가능)은 WR입니다. A16D/C입니다. enter image description here

ADDSET 및 DATAST는 HCLK (AHB 클럭)주기입니다. AHB 클록은 최대 속도가 168MHz로 구성됩니다. ADDSET과 DATAST는 0과 1로 설정됩니다. 그래서 나는 84MHz의 속도를 설정했습니다. DMA 컨트롤러가 더 느리기 때문에 84MHz를 달성 할 것으로 기대하지는 않습니다 (아래 참조). 하지만 나는 적어도 DMA 속도를 달성 할 것으로 기대합니다. 내가 DMA 구성

void init_fsmc(void){ 
SRAM_HandleTypeDef sram_init_struct; 
FSMC_NORSRAM_TimingTypeDef fsmc_norsram_timing_struct = {0}; 

sram_init_struct.Instance = FSMC_NORSRAM_DEVICE; 
sram_init_struct.Extended = FSMC_NORSRAM_EXTENDED_DEVICE; 

fsmc_norsram_timing_struct.AddressSetupTime  = 0; 
fsmc_norsram_timing_struct.AddressHoldTime  = 1; // n/a for SRAM mode A 
fsmc_norsram_timing_struct.DataSetupTime   = 1; 
fsmc_norsram_timing_struct.BusTurnAroundDuration = 0; 
fsmc_norsram_timing_struct.CLKDivision   = 2; // n/a for SRAM mode A 
fsmc_norsram_timing_struct.DataLatency   = 2; // n/a for SRAM mode A 
fsmc_norsram_timing_struct.AccessMode    = FSMC_ACCESS_MODE_A; 

sram_init_struct.Init.NSBank    = FSMC_NORSRAM_BANK4; 
sram_init_struct.Init.DataAddressMux  = FSMC_DATA_ADDRESS_MUX_DISABLE; 
sram_init_struct.Init.MemoryType   = FSMC_MEMORY_TYPE_SRAM; 
sram_init_struct.Init.MemoryDataWidth = FSMC_NORSRAM_MEM_BUS_WIDTH_16; 
sram_init_struct.Init.BurstAccessMode = FSMC_BURST_ACCESS_MODE_DISABLE; 
sram_init_struct.Init.WaitSignalPolarity = FSMC_WAIT_SIGNAL_POLARITY_LOW; 
sram_init_struct.Init.WrapMode   = FSMC_WRAP_MODE_DISABLE; 
sram_init_struct.Init.WaitSignalActive = FSMC_WAIT_TIMING_BEFORE_WS; 
sram_init_struct.Init.WriteOperation  = FSMC_WRITE_OPERATION_ENABLE; 
sram_init_struct.Init.WaitSignal   = FSMC_WAIT_SIGNAL_DISABLE; 
sram_init_struct.Init.ExtendedMode  = FSMC_EXTENDED_MODE_DISABLE; // maybe enable? 
sram_init_struct.Init.AsynchronousWait = FSMC_ASYNCHRONOUS_WAIT_DISABLE; 
sram_init_struct.Init.WriteBurst   = FSMC_WRITE_BURST_DISABLE; 

__HAL_RCC_FSMC_CLK_ENABLE(); 

HAL_SRAM_Init(&sram_init_struct, &fsmc_norsram_timing_struct, &fsmc_norsram_timing_struct); 
} 

: 나는 FSMC를 초기화

void SystemClock_Config(void) 
{ 

RCC_OscInitTypeDef RCC_OscInitStruct; 
RCC_ClkInitTypeDef RCC_ClkInitStruct; 

__HAL_RCC_PWR_CLK_ENABLE(); 

__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); 

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; 
RCC_OscInitStruct.HSIState = RCC_HSI_ON; 
RCC_OscInitStruct.HSICalibrationValue = 16; 
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; 
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; 
RCC_OscInitStruct.PLL.PLLM = 16; 
RCC_OscInitStruct.PLL.PLLN = 336; 
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; 
RCC_OscInitStruct.PLL.PLLQ = 7; 
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) 
{ 
    Error_Handler(); 
} 

RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK 
          |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; 
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; 
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; 
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; 
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; 
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) 
{ 
    Error_Handler(); 
} 

HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000); 

HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); 

/* SysTick_IRQn interrupt configuration */ 
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0); 
} 

: ST의 HAL의 v1.6.0.0 라이브러리와

는 내가 최고 속도로 시계를 설정

void init_dma(void){ 
    __HAL_RCC_DMA2_CLK_ENABLE(); 

    /*##-2- Select the DMA functional Parameters ###############################*/ 
    dma_handle.Init.Channel = DMA_CHANNEL_0; 
    dma_handle.Init.Direction = DMA_MEMORY_TO_MEMORY; 
    dma_handle.Init.PeriphInc = DMA_PINC_DISABLE;    /* Peripheral increment mode */ 
    dma_handle.Init.MemInc = DMA_MINC_DISABLE;     /* Memory increment mode */ 
    dma_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; /* Peripheral data alignment */ 
    dma_handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; /* memory data alignment */ 
    dma_handle.Init.Mode = DMA_NORMAL;       /* Normal DMA mode */ 
    dma_handle.Init.Priority = DMA_PRIORITY_HIGH;    /* priority level */ 
    dma_handle.Init.FIFOMode = DMA_FIFOMODE_DISABLE;   /* FIFO mode disabled */ 
    dma_handle.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; 
    dma_handle.Init.MemBurst = DMA_MBURST_SINGLE;    /* Memory burst */ 
    dma_handle.Init.PeriphBurst = DMA_PBURST_SINGLE;   /* Peripheral burst */ 

    dma_handle.Instance = DMA2_Stream0; 

    if(HAL_DMA_Init(&dma_handle) != HAL_OK) 
    { 
    // @todo proper error handling. 
    return; 
    } 

    HAL_DMA_RegisterCallback(&dma_handle, HAL_DMA_XFER_CPLT_CB_ID, dma_transfer_complete); 
    // @todo proper error handling 
    HAL_DMA_RegisterCallback(&dma_handle, HAL_DMA_XFER_ERROR_CB_ID, dma_transfer_error); 

    /*##-6- Configure NVIC for DMA transfer complete/error interrupts ##########*/ 
    /* Set Interrupt Group Priority */ 
    HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 1, 0); 

    /* Enable the DMA STREAM global Interrupt */ 
    HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn); 
} 

그러면 다음과 같이 거래를 시작합니다 :

HAL_DMA_Start_IT(&dma_handle, (uint32_t)&data_buffer, (uint32_t)&LCD_RAM, pixelCount); 

이 DMA 구성으로 SRAM1에서 SRAM2로 DMA 전송을 수행하면 ~ 38MHz의 전송 속도를 달성합니다. 이것이 FSMC에서 기대할 수있는 속도입니다.

무엇이 FSMC를 억제하고 있습니까?

+2

당신이 "느린", 그리고 몇 가지 숫자를 우리에게 이미지를 보여 있다고 말한다. 558kHz가 의미하는 것은 무엇입니까? RAM 쓰기 속도? RAM 읽기 속도? 디스플레이 새로 고침 빈도는? 다른 것? 그리고 어떤 숫자를 기대 했습니까? 화면에 무언가를 쓸 때 느리게 재생됩니까? 우리에게 줄 수있는 세부 사항이 많을수록 더 쉽게 당신을 도울 것입니다. –

+1

FSMC 타이밍 설정을 제한하는 요소와 그 주파수가 산출 할 것으로 예상되는 주파수를 자세히 설명 할 수 있습니까? 주변에 대한 지식이 없지만 두각을 드러내고 있습니다. – doynax

+0

STM32F437과 같은 TFT 컨트롤러가있는 마이크로 컨트롤러를 사용하면 수명이 단축 될 수 있습니다. –

답변

1

CMSS만으로 FSMC를 구성하는 방법을 보여주는 매우 짧은 코드 here가 있습니다. HAL의 한 줄의 코드로

시계를 활성화하기 위해,이 코드 조각은 다음과 같습니다

__HAL_RCC_FSMC_CLK_ENABLE(); 

int FSMC_Bank = 0; 
FSMC_Bank1->BTCR[FSMC_Bank+1] = FSMC_BTR1_ADDSET_1 | FSMC_BTR1_DATAST_1; 

// Bank1 NOR/SRAM control register configuration 
FSMC_Bank1->BTCR[FSMC_Bank] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN; 

나는이 코드를 시도하고 지금은 ~는 27MHz의 속도를 달성한다. 이것은 내가 예상 한 범위 내에 있습니다.

지금은이 코드를 계속 사용 하겠지만 근본 원인 분석은 나중을위한 것입니다.

BTW FSMC의 NWE 핀에 연결되어 있고이 0 Ohm 저항으로 STM32에 연결된 회로가 풀업되어 있기 때문에 STM32F4 디스커버리 보드에서 FSMC를 사용하면 디스 솔더 저항 R50이 전송합니다.

-1

어쩌면 당신은 HSI 대신 HSE를 사용해야합니다

/* Enable HSE Oscillator and activate PLL with HSE as source */ 
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; 
    RCC_OscInitStruct.HSEState = RCC_HSE_ON; 
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; 
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; 
    RCC_OscInitStruct.PLL.PLLM = 8; // 8MHz crystal frequency 
    RCC_OscInitStruct.PLL.PLLN = 336; // 2*168, 168MHz PLL_Freq 
    RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; 
    RCC_OscInitStruct.PLL.PLLQ = 7; 
    HAL_RCC_OscConfig(&RCC_OscInitStruct); 

감사

+0

HSI가 HSI보다 더 나은 방법을 자세히 설명해 주실 수 있습니까? –

+0

아야! 맞습니다. 잘못된 PLL 파라미터를 사용했기 때문에 계산 오류가 발생했습니다! 그래서 버스에서 FSMC 성능에 영향을 줄 수있는 저주파를 발견했습니다. 죄송합니다. :) – Ramucho

관련 문제