STM32F4VE LCD ili9341 16bit Keil

Опубликовано stm32 - чт, 03/05/2020 - 19:31

 STM32F4VE LCD ili9341 16bit Keil 

Всем привет! 

В этой статье хочу рассказать о выводе информации на LCD ili9341 в режиме 16bit. Ранее в статье  ссылка мною был уже представлен этот LCD и его присоединение к плате STM32F4VE  , а также  в другой статье - ссылка выводил информацию - STM32F4VE LCD ili9341 16bit CubeMx_Keil . Программа создавалась с помощью генератора начального кода CubeMx. В этой статье мы выведем информацию на  LCD ili9341  с помощью Keil Vision и библиотек. Создадим проект, сгенерируем файл  с помощью  System Clock Configuration. Подключим библиотеки в выведем информацию на экран. Программу будем создавать в Keil µVision® версии v5.29.0.0.

Что мы получим в результате 

1. Вывод информации на LCD ili9341 16 bit

2. Возможно регулировать подсветку LCD ili9341 !!

И так приступим..

Запускаем Keil и создаем проект с микроконтроллером STM32F407Vx 

b6 

В появившемся окне выбираем путь для проекта и название

b7

Нажимаем Сохранить и выходит окно выбора микроконтроллера.

b8

Выбираем STM32F407VETx и OK и попадаем в следующее окно.

bb9

Выбираем в нем следующие пункты 

bb10

bb11

 

Нажимаем OK и выходим в основное окно которое получает следующий вид

bb12

И далее два пути:

1. Для тех, кто пока сам не может с нуля собрать проект - статья Первый проект на STM32F407VE Keil до пункта где добавляется в файл main управление светодиодами потом пункт 2.

2. Взять мой пустой проект и наполнить его содержимым. Это быстрее.  Ссылка.

Я не буду плодить одинаковые статьи и исправлю (дополню) проект по ссылке выше.

Итак скачиваем, распаковываем в папку, открываем проект в Keil.

bb13

 

Переходим к файлу main.c. Убираем все, что идет после  while (1) . Файл main.c получает вид 

#include "main.h"
//*******************************************************

int main(void)
{    
  SysTick_Config(SystemCoreClock / 1000);
    
    //  Настраиваем порты
        GPIO_init();
    //  Настраиваем кнопки установленные на плате    
        button_ini();
    //
    // Настраиваем связь 
    USART2_Configuration();
    //
    
      while (1)
     {      
    
    

         }    
    
}

***********************************************************************

Проверяем все ли нормально - собираем проект

bb14

Ошибок быть не должно. 

Далее необходимо настроить частоту работы микроконтроллера STM32F407 и его основной периферии.

Для этого ищем архив с файлами файл от фирмы ST под названием en.stsw-stm32091.zip его можно найти в интернете  можно скачать у меня - ссылка.  Распаковываем его в папку. В папке будут присутствовать файлы 

bb15

Запускаем файл STM32F4xx_Clock_Configuration_V1.1.0.xls. Для открытия файла должен быть установлен пакет программ - Microsoft Office.

Запускаем файл.

При первом запуске  выйдет оно 

bb16

Включаем содержимое.

И получаем следующее окно

bb17

Идея использовать Excel на мой взгляд очень не плохая. Конечно, Excel, он не у всех установлен. И скорее всего этот файл поддерживаться не будет в связи с CubeMx.  Но на сегодня файл есть и он работает. И я этим воспользуюсь.. 

Устанавливаем в нем следующую конфигурацию - ставим все по max !!!

bb18 по схеме ниже 

bb19

 

bb20

 

bb21

И в результате полный вид картинки

bb22

Маленький CubeMx такой получается .... 

Когда нужная картинка с конфигурацией создана  нажимаем 

bb23

И результатом будет создание файла в той же папке где лежит файл STM32F4xx_Clock_Configuration_V1.1.0.xls 

bb24

bb25

Закрываем Keil !!!

Переходим в папку проекта !!! 

bb26

У меня это 

D:\Keil_pj\Work\407\RTE\Device\STM32F407VETx

Созданный файл  копируем  в папку STM32F407VETx  заменяя тот который там лежит. 

Заменяем его на созданный. Если файл по каким-то причинам не получился берем мой ссылка. Файл в архиве. Скачиваем распаковываем и копируем с заменой файл из папки см.выше.

Далее ..

В папке проекта создаем папку Lib для удобства

b33

Заходим в нее и создаем в ней папку с названием ILI9341 

bb34

 

Скачиваем папку с библиотекой  - ссылка.  В архиве файлы

colors.h

font8.c

....

fonts.h

ili9341.c

ili9341.h

image.h

registers.h

 

Открываем архив и все файлы из архива копируем в ранее созданную ILI9341 

bb35

Запускаем Keil.  И проверяем сначала  

b27

Файл самый нижний два раза тыкаем мышкой - когда он откроется - мы увидим следующее 

bb28 Это заголовок где видно дату создания и где в какой программе он создан и конечно все необходимые нам настройки.

Далее ..

bb29

Устанавливаем как на фото ниже 

 bb30

bb31

Переходим 

bb32

bb36

В этом окне необходимо!!!

1. Поправить пути к указанным библиотекам - в том случае когда вы скачали МОЙ проект с моими указанными путями для файлов!!!!!

2. Добавить путь к папке  ILI9341 

Исправляем и добавляем.. в итоге будет вид

bb37

Нажимаем OK два раза и выходим в основное окно и добавить наши библиотеки

Для этого 

bb39

 

И создаем новую группу

bb40

Переименовываем ее

b41

Два раза тыкаем мышкой на созданной папке и откроется окно добавления файлов. 

Переходим в окне в папку Lib -> ILI9341 - выделяем в ней мышкой все файлы и жмем Add.

bb42

 

Все файлы пропишутся у нас в проекте

bb43

Дальше начинаем наполнять файлы проекта содержимым 

Начнем с файла port_ini.c - добавим в него следующие строки сразу после 170 строчки 

bb44

void LCD_CtrlLinesConfig()
{
      // Настраиваем порт D
        GPIO_InitTypeDef GPIO_InitStructure;
        RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE, ENABLE);
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7
             | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_13 | GPIO_Pin_1
        | GPIO_Pin_0 | GPIO_Pin_15 | GPIO_Pin_14;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
         GPIO_Init(GPIOD, &GPIO_InitStructure);
    
    /* Конфигурируем D как альтернативную функцию - 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_PinSource13, GPIO_AF_FSMC); 
        GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_FSMC); 
        GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_FSMC); 
        GPIO_PinAFConfig(GPIOD, GPIO_PinSource15, GPIO_AF_FSMC); 
        GPIO_PinAFConfig(GPIOD, GPIO_PinSource14, GPIO_AF_FSMC); 
    
    /* // Настраиваем порт E */
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13
            | GPIO_Pin_14 | GPIO_Pin_15 | GPIO_Pin_7 | GPIO_Pin_8
            | GPIO_Pin_9 | GPIO_Pin_10;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
         GPIO_Init(GPIOE, &GPIO_InitStructure);
    
    /* Конфигурируем E как альтернативную функцию - FSMC */
    
        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); // 

return;
}

/* Конфигурируем FSMC */
void LCD_FSMCConfig()
{
        FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure;
        FSMC_NORSRAMTimingInitTypeDef FSMC_NORSRAMTimingInitStructureRead;
        FSMC_NORSRAMTimingInitTypeDef FSMC_NORSRAMTimingInitStructureWrite;

        /* Enable FSMC Clock */
        RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC, ENABLE);

        /* Define Read timing parameters */
        FSMC_NORSRAMTimingInitStructureRead.FSMC_AddressSetupTime = 2;
        FSMC_NORSRAMTimingInitStructureRead.FSMC_AddressHoldTime = 0; 
        FSMC_NORSRAMTimingInitStructureRead.FSMC_DataSetupTime = 5;  
        FSMC_NORSRAMTimingInitStructureRead.FSMC_BusTurnAroundDuration = 0;
        FSMC_NORSRAMTimingInitStructureRead.FSMC_CLKDivision =  0; 
        FSMC_NORSRAMTimingInitStructureRead.FSMC_DataLatency = 0;
        FSMC_NORSRAMTimingInitStructureRead.FSMC_AccessMode = FSMC_AccessMode_B;

        /* Define Write Timing parameters */
        FSMC_NORSRAMTimingInitStructureWrite.FSMC_AddressSetupTime = 3;
        FSMC_NORSRAMTimingInitStructureWrite.FSMC_AddressHoldTime = 0;
        FSMC_NORSRAMTimingInitStructureWrite.FSMC_DataSetupTime = 6;
        FSMC_NORSRAMTimingInitStructureWrite.FSMC_BusTurnAroundDuration = 0;
        FSMC_NORSRAMTimingInitStructureWrite.FSMC_CLKDivision = 1;
        FSMC_NORSRAMTimingInitStructureWrite.FSMC_DataLatency = 0;
        FSMC_NORSRAMTimingInitStructureWrite.FSMC_AccessMode = FSMC_AccessMode_A;

        /* Define protocol type */
        FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM1; //Bank1
        FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable; //No mux
        FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM; //SRAM type
        FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b; //16 bits wide
        FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable; //No Burst
        FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable; // No wait
        FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low; //Don'tcare
        FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable; //No wrap mode
        FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState; //Don't care
        FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
        FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable; //Don't care
        FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Enable; //Allow distinct Read/Write parameters
        FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable; //Don't care

        // Set read timing structure
        FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = 
            &FSMC_NORSRAMTimingInitStructureRead;

        // Set write timing structure
         FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct =
            &FSMC_NORSRAMTimingInitStructureWrite;

        // Initialize FSMC for read and write
        FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);

        // Enable FSMC
        FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE);

        return;
 
}

void LCD_Configuration(void)
{
    // Настраиваем порты для работы с индикатором
  LCD_CtrlLinesConfig();

  // Настраиваем FSMC 
  LCD_FSMCConfig();
}

// Для того чтобы была возможность управлять уровнем яркости от 0-max до 100 - min
// Настроим Таймер3 канал 4  и используем PWM

void LCD_SetBackLight(unsigned short level)
{
  
  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_OCInitTypeDef TIM_OCInitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;
    uint16_t CCR1_Val = level;
    uint16_t PrescalerValue;
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
    // Конфигурируем ПОРТ В1 на выход и настраиваем PWM
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource1, GPIO_AF_TIM3);

    PrescalerValue = (uint16_t)((SystemCoreClock) / 100000) - 1;

    TIM_TimeBaseStructure.TIM_Period = 100;
    TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = CCR1_Val;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low ;

    TIM_OC4Init(TIM3, &TIM_OCInitStructure);
    TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);
    TIM_ARRPreloadConfig(TIM3, ENABLE);

    /* TIM1 enable counter */
    TIM_Cmd(TIM3, ENABLE);
    TIM_CtrlPWMOutputs(TIM3, ENABLE);

}
 

 Далее ....

Дополним его - выделю те строчки которые дополнил.

port_ini.h

void GPIO_init(void); 
void LCD_Configuration(void);
void LCD_SetBackLight(unsigned short level);
void button_ini(void);
void delay_ms(uint32_t ms);
void delay_us(uint32_t us);
void USART2_Configuration(void);

 

Перейдем в main.c

Дополним его - выделю те строчки которые дополнил.

#include "main.h"

#include <stdio.h>
#include <string.h>
#include "ili9341.h"

 

char str1[60];
char str2[60];

 

USART2_Configuration();
    //

   LCD_Configuration();

   //
    lcdInit();
    //

 

    lcdSetOrientation(LCD_ORIENTATION_LANDSCAPE);
     lcdFillRGB(COLOR_WHITE);
     LCD_SetBackLight(50);  //Включаем подсветку на нужную яркость. 0 -max 100- min
    // Пишем текст сверху экрана
     lcdSetTextFont(&Font24);
     lcdSetTextColor(COLOR_BLACK, COLOR_WHITE);
     lcdSetCursor(40, 5);   // xy
     lcdPrintf("www.stm32res.ru");
    
    lcdSetTextColor(COLOR_BLUE , COLOR_WHITE);
    lcdSetCursor(80, 65);   
    lcdPrintf("STM32F4VE");
    
    lcdSetTextColor(COLOR_MAROON , COLOR_WHITE);
    lcdSetCursor(20, 100);   
    lcdPrintf("LCD ili9341 16bit");
    
    lcdSetTextColor(COLOR_RED , COLOR_WHITE);
    lcdSetCursor(110, 140);   
   lcdPrintf("No Hal");

    while (1)
     {      
         
            GPIO_ResetBits(GPIOA, GPIO_Pin_7); //Подаем «0» на PA
           delay_ms(450);            
           GPIO_SetBits(GPIOA, GPIO_Pin_7); //Подаем «1» на PA     
           delay_ms(450);

       }    
    
}

Отлично почти закончили!!  Осталось добавить только стандартные библиотеки которые не использовались ранее!! 

Для этого 

b45

В открывшемся окне 

bb47

В группу User1 справа добавляем Add Files  следующие файлы -  это стандартные библиотеки для работы с 

FSMC и TIM  Добавляем файлы с расширением .с и .h которые находятся соответственно в папках src и inc 

bb47

Выбрали нажали Add 

bb48

Выбрали нажали Add 

Перешли в папку inc 

bb49

bb50

Выбрали нажали Add 

bb51

Жмем два раза Ok и выходим в основное окно Keil 

Собираем проект 

bb52

 

Если все сделано правильно то Error быть не должно !!!

Настраиваем программатор !!!

Я использую ULINK - у меня настройки остаются от проекта.

Прошиваем микроконтроллер!!

bb53

 

В результате на экране появиться изображение. Т.к у нас установлено ~ 50% свечения - экран будет затемненный!!!!

b3_3

 

Ура !! Все получилось!!! 

Если есть вопросы или необходим исходник проекта  из статьи - пишите по адресу stm32@stm32res.ru или Website feedback

 

Яндекс.Метрика