基于HAL库STM32的FSMC驱动8位TFTLCD屏

先上代码。

main.c:

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */

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

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "ili9341.h"
#include "ctype.h"
#include "stdlib.h"
#include "INA226.h"
#include "INA3221.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;

TIM_HandleTypeDef htim2;

UART_HandleTypeDef huart1;

SRAM_HandleTypeDef hsram1;

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_USART1_UART_Init(void);
static void MX_FSMC_Init(void);
static void MX_ADC1_Init(void);
static void MX_TIM2_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
    float adc0,adc1,adc2,adc3,adc4,adc5,adc6,\
                    adc7,adc8,adc9,adc10,adc11,adc12,adc13,adc14,adc15,adc16,adc17,adc18,adc19,adc13a,adc14a,adc15a,adc16a,adc17a,adc18a,adc19a;
    uint32_t adc_0,adc_1,adc_2,adc_3,adc_4,adc_5,adc_6,\
              adc_7,adc_8,adc_9,adc_10,adc_11,adc_12,adc_13,adc_14,adc_15,adc_16,adc_17,adc_18,adc_19,adc_13a,adc_14a,adc_15a,adc_16a,adc_17a,adc_18a,adc_19a;
        uint32_t AD_DMA[13];
    
    char SStr[10];
    char SStr_A[10];
    uint8_t x = 0;
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
    uint8_t key = 0;
  /* USER CODE END 1 */
  

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART1_UART_Init();
  MX_FSMC_Init();
  MX_ADC1_Init();
  MX_TIM2_Init();
  /* USER CODE BEGIN 2 */
    INA226_Init();
    INA3221_Init();
    
    //HAL_Delay(20);
    
    
    LCD_REG_Config();
    Lcd_data_start();  

    for(long z=0; z<76800; z++)                 
    {
        LCD_WR_Data(WHITE); 
    }
//    printf("主函数测试 \r\n");
    LCD_Str_O_BK(2,5,80,16,"LEDA_1 VOL =       V",RED,WHITE,20);
        LCD_Str_O_BK(2,21,80,16,"LEDA_1A VOL =        V",RED,WHITE,20);
        LCD_Str_O_BK(2,37,80,16,"LEDA_2 VOL =       V",RED,WHITE,20);
        LCD_Str_O_BK(2,53,80,16,"LEDA_2A VOL =       V",RED,WHITE,20);
        LCD_Str_O_BK(2,69,80,16,"LEDK_1 VOL =       V",RED,WHITE,20);
        LCD_Str_O_BK(2,85,80,16,"LEDK_2 VOL =       V",RED,WHITE,20);
        LCD_Str_O_BK(2,101,80,16,"LEDK_3 VOL =       V",RED,WHITE,20);
        LCD_Str_O_BK(2,117,80,16,"LEDK_4 VOL =       V",RED,WHITE,20);
        LCD_Str_O_BK(2,133,80,16,"OUT_VSN VOL =       V",RED,WHITE,20);
        LCD_Str_O_BK(2,146,80,16,"CURRENT_LEDK1 VOL =       V",RED,WHITE,20);
        LCD_Str_O_BK(2,159,80,16,"CURRENT_LEDK2 VOL =       V",RED,WHITE,20);
        LCD_Str_O_BK(2,172,80,16,"CURRENT_LEDK3 VOL =       V",RED,WHITE,20);
        LCD_Str_O_BK(2,185,80,16,"CURRENT_LEDK4 VOL =       V",RED,WHITE,20);
        LCD_Str_O_BK(2,201,80,16,"226_VSN V =        V       A",RED,WHITE,20);
    LCD_Str_O_BK(2,217,80,16,"3221_VSPA =       V        A",RED,WHITE,20);
    LCD_Str_O_BK(2,233,80,16,"3221_VCIA =       V        A",RED,WHITE,20);
    LCD_Str_O_BK(2,249,80,16,"3221_3VA =       V         A",RED,WHITE,20);
    LCD_Str_O_BK(2,265,80,16,"3221_1V8A =       V        A",RED,WHITE,20);
    LCD_Str_O_BK(2,281,80,16,"3221_5VA =       V         A",RED,WHITE,20);
    LCD_Str_O_BK(2,297,80,16,"3221_VDDA =       V        A",RED,WHITE,20);
    //    LCD_Str_O_BK(2,5,80,16,"LEDA_1 VOL =      V",RED,WHITE,20);
    //    LCD_Num_6x12_P(88,319-8-16,key,RED);
    
    char cStr[10];
    
//    sprintf(cStr,"%d", key);
//                LCD_Str_O_BK(188,75,80,16,cStr,RED,WHITE,20);
    
        HAL_TIM_Base_Start_IT(&htim2);
        //HAL_ADCEx_Calibration_Start(&hadc1);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
         HAL_ADC_Start_DMA(&hadc1, AD_DMA, 13);
        
        adc0 = (float)AD_DMA[0];
        adc1 = (float)AD_DMA[1];
        adc2 = (float)AD_DMA[2];
        adc3 = (float)AD_DMA[3];
        adc4 = (float)AD_DMA[4];
        adc5 = (float)AD_DMA[5];
        adc6 = (float)AD_DMA[6];
        adc7 = (float)AD_DMA[7];
        adc8 = (float)AD_DMA[8];
        adc9 = (float)AD_DMA[9];
        adc10 = (float)AD_DMA[10];
        adc11 = (float)AD_DMA[11];
        adc12 = (float)AD_DMA[12];
        
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
        key = KEY_Scan(0);
        sprintf(cStr,"%d", key);
        //    LCD_Str_O_BK(2,181,80,16,cStr,RED,WHITE,20);
            //LCD_Num_6x12_P(88,319-8-16,atoi(),RED);
            switch(key)
        {            
            case KEY1_PRES:
//                    sprintf(cStr,"%d", key);
//                LCD_Str_O_BK(168,75,80,16,cStr,RED,WHITE,20);
            HAL_GPIO_TogglePin(O_LEDA_1_POWER_ON_GPIO_Port, O_LEDA_1_POWER_ON_Pin);//测试MOS开关
                //printf("LCD屏幕第一个按键, LEDA_1电压 = %.3f V \r\n", (adc0 * 3.3)/4096);
            break;    
        case KEY2_PRES:
//                sprintf(cStr,"%d", key);
//                LCD_Str_O_BK(168,75,80,16,cStr,RED,WHITE,20);
                //printf("LCD屏幕第二个按键\r\n");
        HAL_GPIO_TogglePin(O_OUT_VSN_POWER_ON_GPIO_Port, O_OUT_VSN_POWER_ON_Pin);//测试MOS开关
                break;    
            case KEY3_PRES:
//                    sprintf(cStr,"%d", key);
//                LCD_Str_O_BK(168,75,80,16,cStr,RED,WHITE,20);
                //printf("LCD屏幕第三个按键\r\n");
            HAL_GPIO_TogglePin(O_OUT_VSP_POWER_ON_GPIO_Port, O_OUT_VSP_POWER_ON_Pin);//测试MOS开关
            HAL_GPIO_TogglePin(O_VCI_3_8V_OUT_POWER_ON_GPIO_Port, O_VCI_3_8V_OUT_POWER_ON_Pin);//测试MOS开关
            HAL_GPIO_TogglePin(O__3_0V_OUT_POWER_ON_GPIO_Port, O__3_0V_OUT_POWER_ON_Pin);//测试MOS开关
                //    LCD_Rectangle(217,109,12,40,WHITE);//3221_vsp


            break;    
        case KEY4_PRES:
//                sprintf(cStr,"%d", key);
//                LCD_Str_O_BK(168,295,80,16,cStr,RED,WHITE,20);
                //printf("LCD屏幕第四个按键\r\n");
            HAL_GPIO_TogglePin(O_IOVCC_1_8V_OUT_POWER_ON_GPIO_Port, O_IOVCC_1_8V_OUT_POWER_ON_Pin);//测试MOS开关
        HAL_GPIO_TogglePin(O__5V_POWER_ON_GPIO_Port, O__5V_POWER_ON_Pin);//测试MOS开关
        HAL_GPIO_TogglePin(O_AVDD_POWER_ON_GPIO_Port, O_AVDD_POWER_ON_Pin);//测试MOS开关
        //    HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_11);            //喇叭
            break;    
            default:
                HAL_Delay(10);    
        } 
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;
  PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV2;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief ADC1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_ADC1_Init(void)
{

  /* USER CODE BEGIN ADC1_Init 0 */

  /* USER CODE END ADC1_Init 0 */

  ADC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN ADC1_Init 1 */

  /* USER CODE END ADC1_Init 1 */
  /** Common config 
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 13;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel 
  */
  sConfig.Channel = ADC_CHANNEL_0;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel 
  */
  sConfig.Channel = ADC_CHANNEL_1;
  sConfig.Rank = ADC_REGULAR_RANK_2;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel 
  */
  sConfig.Channel = ADC_CHANNEL_2;
  sConfig.Rank = ADC_REGULAR_RANK_3;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel 
  */
  sConfig.Channel = ADC_CHANNEL_3;
  sConfig.Rank = ADC_REGULAR_RANK_4;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel 
  */
  sConfig.Channel = ADC_CHANNEL_4;
  sConfig.Rank = ADC_REGULAR_RANK_5;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel 
  */
  sConfig.Channel = ADC_CHANNEL_5;
  sConfig.Rank = ADC_REGULAR_RANK_6;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel 
  */
  sConfig.Channel = ADC_CHANNEL_6;
  sConfig.Rank = ADC_REGULAR_RANK_7;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel 
  */
  sConfig.Channel = ADC_CHANNEL_7;
  sConfig.Rank = ADC_REGULAR_RANK_8;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel 
  */
  sConfig.Channel = ADC_CHANNEL_8;
  sConfig.Rank = ADC_REGULAR_RANK_9;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel 
  */
  sConfig.Channel = ADC_CHANNEL_10;
  sConfig.Rank = ADC_REGULAR_RANK_10;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel 
  */
  sConfig.Channel = ADC_CHANNEL_11;
  sConfig.Rank = ADC_REGULAR_RANK_11;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel 
  */
  sConfig.Channel = ADC_CHANNEL_12;
  sConfig.Rank = ADC_REGULAR_RANK_12;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel 
  */
  sConfig.Channel = ADC_CHANNEL_13;
  sConfig.Rank = ADC_REGULAR_RANK_13;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC1_Init 2 */

  /* USER CODE END ADC1_Init 2 */

}

/**
  * @brief TIM2 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM2_Init(void)
{

  /* USER CODE BEGIN TIM2_Init 0 */

  /* USER CODE END TIM2_Init 0 */

  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};

  /* USER CODE BEGIN TIM2_Init 1 */

  /* USER CODE END TIM2_Init 1 */
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 10000-1;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 800-1;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM2_Init 2 */

  /* USER CODE END TIM2_Init 2 */

}

/**
  * @brief USART1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_USART1_UART_Init(void)
{

  /* USER CODE BEGIN USART1_Init 0 */

  /* USER CODE END USART1_Init 0 */

  /* USER CODE BEGIN USART1_Init 1 */

  /* USER CODE END USART1_Init 1 */
  huart1.Instance = USART1;
  huart1.Init.BaudRate = 9600;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART1_Init 2 */

  /* USER CODE END USART1_Init 2 */

}

/** 
  * Enable DMA controller clock
  */
static void MX_DMA_Init(void) 
{

  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_ENABLE();

  /* DMA interrupt init */
  /* DMA1_Channel1_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);

}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOE_CLK_ENABLE();
  __HAL_RCC_GPIOF_CLK_ENABLE();
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOG_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOF, O_OUT_VSP_POWER_ON_Pin|O_VCI_3_8V_OUT_POWER_ON_Pin|O__3_0V_OUT_POWER_ON_Pin|O_IOVCC_1_8V_OUT_POWER_ON_Pin 
                          |O__5V_POWER_ON_Pin|O_AVDD_POWER_ON_Pin|O_OUT_VSN_POWER_ON_Pin|O_LEDA_1_POWER_ON_Pin 
                          |O_LEDA_2_POWER_ON_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(PF11_SPEAKER_GPIO_Port, PF11_SPEAKER_Pin, GPIO_PIN_SET);

  /*Configure GPIO pins : KEY3_Pin KEY4_Pin KEY1_Pin KEY2_Pin */
  GPIO_InitStruct.Pin = KEY3_Pin|KEY4_Pin|KEY1_Pin|KEY2_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

  /*Configure GPIO pins : O_OUT_VSP_POWER_ON_Pin O_VCI_3_8V_OUT_POWER_ON_Pin O__3_0V_OUT_POWER_ON_Pin O_IOVCC_1_8V_OUT_POWER_ON_Pin 
                           O__5V_POWER_ON_Pin O_AVDD_POWER_ON_Pin O_OUT_VSN_POWER_ON_Pin O_LEDA_1_POWER_ON_Pin 
                           O_LEDA_2_POWER_ON_Pin */
  GPIO_InitStruct.Pin = O_OUT_VSP_POWER_ON_Pin|O_VCI_3_8V_OUT_POWER_ON_Pin|O__3_0V_OUT_POWER_ON_Pin|O_IOVCC_1_8V_OUT_POWER_ON_Pin 
                          |O__5V_POWER_ON_Pin|O_AVDD_POWER_ON_Pin|O_OUT_VSN_POWER_ON_Pin|O_LEDA_1_POWER_ON_Pin 
                          |O_LEDA_2_POWER_ON_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLDOWN;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

  /*Configure GPIO pin : PF11_SPEAKER_Pin */
  GPIO_InitStruct.Pin = PF11_SPEAKER_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(PF11_SPEAKER_GPIO_Port, &GPIO_InitStruct);

}

/* FSMC initialization function */
static void MX_FSMC_Init(void)
{

  /* USER CODE BEGIN FSMC_Init 0 */

  /* USER CODE END FSMC_Init 0 */

  FSMC_NORSRAM_TimingTypeDef Timing = {0};
  FSMC_NORSRAM_TimingTypeDef ExtTiming = {0};

  /* USER CODE BEGIN FSMC_Init 1 */

  /* USER CODE END FSMC_Init 1 */

  /** Perform the SRAM1 memory initialization sequence
  */
  hsram1.Instance = FSMC_NORSRAM_DEVICE;
  hsram1.Extended = FSMC_NORSRAM_EXTENDED_DEVICE;
  /* hsram1.Init */
  hsram1.Init.NSBank = FSMC_NORSRAM_BANK4;
  hsram1.Init.DataAddressMux = FSMC_DATA_ADDRESS_MUX_DISABLE;
  hsram1.Init.MemoryType = FSMC_MEMORY_TYPE_SRAM;
  hsram1.Init.MemoryDataWidth = FSMC_NORSRAM_MEM_BUS_WIDTH_16;
  hsram1.Init.BurstAccessMode = FSMC_BURST_ACCESS_MODE_DISABLE;
  hsram1.Init.WaitSignalPolarity = FSMC_WAIT_SIGNAL_POLARITY_LOW;
  hsram1.Init.WrapMode = FSMC_WRAP_MODE_DISABLE;
  hsram1.Init.WaitSignalActive = FSMC_WAIT_TIMING_BEFORE_WS;
  hsram1.Init.WriteOperation = FSMC_WRITE_OPERATION_ENABLE;
  hsram1.Init.WaitSignal = FSMC_WAIT_SIGNAL_DISABLE;
  hsram1.Init.ExtendedMode = FSMC_EXTENDED_MODE_ENABLE;
  hsram1.Init.AsynchronousWait = FSMC_ASYNCHRONOUS_WAIT_DISABLE;
  hsram1.Init.WriteBurst = FSMC_WRITE_BURST_DISABLE;
  /* Timing */
  Timing.AddressSetupTime = 15;
  Timing.AddressHoldTime = 15;
  Timing.DataSetupTime = 24;
  Timing.BusTurnAroundDuration = 0;
  Timing.CLKDivision = 16;
  Timing.DataLatency = 17;
  Timing.AccessMode = FSMC_ACCESS_MODE_A;
  /* ExtTiming */
  ExtTiming.AddressSetupTime = 8;
  ExtTiming.AddressHoldTime = 15;
  ExtTiming.DataSetupTime = 8;
  ExtTiming.BusTurnAroundDuration = 0;
  ExtTiming.CLKDivision = 16;
  ExtTiming.DataLatency = 17;
  ExtTiming.AccessMode = FSMC_ACCESS_MODE_A;

  if (HAL_SRAM_Init(&hsram1, &Timing, &ExtTiming) != HAL_OK)
  {
    Error_Handler( );
  }

  /** Disconnect NADV
  */

  __HAL_AFIO_FSMCNADV_DISCONNECTED();

  /* USER CODE BEGIN FSMC_Init 2 */

  /* USER CODE END FSMC_Init 2 */
}

/* USER CODE BEGIN 4 */
struct __FILE 
{ 
int handle;

};

FILE __stdout; 
//定义_sys_exit()以避免使用半主机模式 
void _sys_exit(int x) 
{ 
x = x; 
} 
//重定义fputc函数 
int fputc(int ch, FILE *f)
{ 
while((USART1->SR&0X40)==0);//循环发送,直到发送完毕 
USART1->DR = (uint8_t) ch; 
return ch;
}

uint8_t KEY_Scan(uint8_t mode)
{
     static uint8_t key_up=1;     //按键松开标志
    if(mode==1)key_up=1;    //支持连按
    if(key_up&&(KEY1==0||KEY2==0||KEY3==0||KEY4==0))
    {
        HAL_Delay(10);
        key_up=0;
             if(KEY1==0)       return KEY1_PRES;
            else if(KEY2==0)       return KEY2_PRES;
            else if(KEY3==0)       return KEY3_PRES;
            else if(KEY4==0)       return KEY4_PRES;
                   
    }
        else if(KEY1==1&&KEY2==1&&KEY3==1&&KEY4==1)
            key_up=1;
        
    return 0;   //无按键按下
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
 {
     if(x == 0)
     {
         LCD_Str_O_BK(180,30,80,16,"....",BLUE,WHITE,20);
         x = 1;
     }
     else if(x == 1)
     {
          LCD_Str_O_BK(180,30,80,16,"     ",BLUE,WHITE,20);
        x = 0;
     }
        
     //LEDA_1
     adc0 = (adc0 * 3.3)/4096;     
        sprintf(SStr, "%.4f", adc0);
     LCD_Str_O_BK(100,5,80,16,SStr,BLUE,WHITE,20);
         
     //LEDA_1A
      adc1 = (adc1 * 3.3)/4096;
         sprintf(SStr,"%.4f", adc1);
             LCD_Str_O_BK(107,21,80,16,SStr,BLUE,WHITE,20);
         
     
             //LEDA_2
     adc2 = (adc2 * 3.3)/4096;
         sprintf(SStr,"%.4f", adc2);
         LCD_Str_O_BK(100,37,80,16,SStr,BLUE,WHITE,20);
    
            
                 //LEDA_2A
      adc3 = (adc3 * 3.3)/4096;

         sprintf(SStr,"%.4f", adc3);
             LCD_Str_O_BK(107,53,80,16,SStr,BLUE,WHITE,20);

            
                 //LEDK_1
      adc4 = (adc4 * 3.3)/4096;

         sprintf(SStr,"%.4f", adc4);
             LCD_Str_O_BK(100,69,80,16,SStr,BLUE,WHITE,20);

            
                 //LEDK_2
      adc5 = (adc5 * 3.3)/4096;
         sprintf(SStr,"%.4f", adc5);
             LCD_Str_O_BK(100,85,80,16,SStr,BLUE,WHITE,20);

            
                 //LEDK_3
      adc6 = (adc6 * 3.3)/4096;
         sprintf(SStr,"%.4f", adc6);
             LCD_Str_O_BK(100,101,80,16,SStr,BLUE,WHITE,20);

            
                 //LEDK_4
      adc7 = (adc7 * 3.3)/4096;
         sprintf(SStr,"%.4f", adc7);
             LCD_Str_O_BK(100,117,80,16,SStr,BLUE,WHITE,20);

            
                 //O_OUT_VSN
         //printf("adc8 = %.2f\r\n",adc8);
      adc8 = (adc8 * 3.3)/4096;

         sprintf(SStr,"%.4f", adc8);
             LCD_Str_O_BK(107,133,80,16,SStr,BLUE,WHITE,20);

                 //CURRENT_LEDK1_ADC
      adc9 = (adc9 * 3.3)/4096;

         sprintf(SStr,"%.4f", adc_9);
             LCD_Str_O_BK(157,146,80,16,SStr,BLUE,WHITE,20);

            
                 //CURRENT_LEDK2_ADC
      adc10 = (adc10 * 3.3)/4096;
         sprintf(SStr,"%.4f", adc_10);
             LCD_Str_O_BK(157,159,80,16,SStr,BLUE,WHITE,20);

            
                 //CURRENT_LEDK3_ADC
      adc11 = (adc11 * 3.3)/4096;
         sprintf(SStr,"%.4f", adc_11);
             LCD_Str_O_BK(157,172,80,16,SStr,BLUE,WHITE,20);

            
                 //CURRENT_LEDK4_ADC
      adc12 = (adc12 * 3.3)/4096;
         sprintf(SStr,"%.4f", adc_12);
             LCD_Str_O_BK(157,185,80,16,SStr,BLUE,WHITE,20);

            
                         //226_VSN_V
      adc13 = (((float)INA226_GetVoltage(0x80)*1.25) / 1000) - 8.948;     
         sprintf(SStr,"%.4f", adc13);
         LCD_Str_O_BK(94,201,80,16,SStr,BLUE,WHITE,20);

                
                 adc13a = ((float)(INA226_GetShunt_Current(0x80)  * 2.5)) * 0.001f ;  //A    
                if(adc13a < 0){adc13a = -adc13a;}
             sprintf(SStr_A, "%.4f", adc13a);
                 LCD_Str_O_BK(167,201,80,16,SStr_A,BLUE,WHITE,20);

         
//3221_VSP_V
      adc14 = ((float)(INA3221_GetVoltage(0x82, 1)  * 0.001f));    
         sprintf(SStr,"%.4f", adc14);        
             LCD_Str_O_BK(92,217,80,16,SStr,BLUE,WHITE,20);

            
            adc14a = ((float)(INA3221_GetShuntVoltage(0x82, 1)  * 1)) * 5 * 10 * 0.000001f;  //A
             sprintf(SStr_A, "%.4f", adc14a);
                 LCD_Str_O_BK(165,217,80,16,SStr_A,BLUE,WHITE,20);

            
     //3221_VCI_V
      adc15 = ((float)(INA3221_GetVoltage(0x82, 2)  * 0.001f));        
         sprintf(SStr,"%.4f", adc15);
             LCD_Str_O_BK(92,233,80,16,SStr,BLUE,WHITE,20);

            
        adc15a = ((float)(INA3221_GetShuntVoltage(0x82, 2)  * 1)) * 5 * 10 * 0.000001f;  //A
             sprintf(SStr_A, "%.4f", adc15a);
                 LCD_Str_O_BK(165,233,80,16,SStr_A,BLUE,WHITE,20);

            
                             //3221_3V_V
      adc16 = ((float)(INA3221_GetVoltage(0x82, 3)  * 0.001f));    
         sprintf(SStr,"%.4f", adc16);
             LCD_Str_O_BK(84,249,80,16,SStr,BLUE,WHITE,20);

            
            adc16a = ((float)(INA3221_GetShuntVoltage(0x82, 3)  * 1)) * 5 * 10 * 0.000001f;  //A
             sprintf(SStr_A, "%.4f", adc16a);
                 LCD_Str_O_BK(165,249,80,16,SStr_A,BLUE,WHITE,20);

            
                             //3221_1.8_V
      adc17 = ((float)(INA3221_GetVoltage(0x84, 1)  * 0.001f));
         sprintf(SStr,"%.4f", adc17);
             LCD_Str_O_BK(92,265,80,16,SStr,BLUE,WHITE,20);

            
            adc17a = ((float)(INA3221_GetShuntVoltage(0x84, 1)  * 1)) * 5 * 10 * 0.000001f;  //A
             sprintf(SStr_A, "%.4f", adc17a);
                LCD_Str_O_BK(165,265,80,16,SStr_A,BLUE,WHITE,20);

            
                             //3221_5_V
      adc18 = ((float)(INA3221_GetVoltage(0x84, 2)  * 0.001f));
         sprintf(SStr,"%.4f", adc18);
             LCD_Str_O_BK(84,281,80,16,SStr,BLUE,WHITE,20);

            
                    adc18a = ((float)(INA3221_GetShuntVoltage(0x84, 2)  * 1)) * 5 * 10 * 0.000001f;  //A
             sprintf(SStr_A, "%.4f", adc18a);
                 LCD_Str_O_BK(165,281,80,16,SStr_A,BLUE,WHITE,20);

            
                             //3221_VDD_V
      adc19 = ((float)(INA3221_GetVoltage(0x84, 3)  * 1));
         sprintf(SStr,"%.4f", adc19);
             LCD_Str_O_BK(92,297,80,16,SStr,BLUE,WHITE,20);

            
            adc19a = ((float)(INA3221_GetShuntVoltage(0x84, 3)  * 1)) * 5 * 10 * 0.000001f;  //A
             sprintf(SStr_A, "%.4f", adc19a);
                 LCD_Str_O_BK(165,297,80,16,SStr_A,BLUE,WHITE,20);

            //
}
     
/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */

  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{ 
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
View Code

ili9341.c:

#include "ili9341.h"
#include "stm32f1xx_hal_sram.h"
#include "asc_font.h"
uint8_t display_direction = 1;

  //写寄存器函数
//regval:寄存器值
void LCD_WR_REG(vu16 regval)
{   
    regval=regval;        //使用-O2优化的时候,必须插入的延时
    LCD->LCD_REG=regval;//写入要写的寄存器序号     
}                                                
//写LCD数据
//data:要写入的值
void LCD_WR_DATA(vu16 data)
{      
    data=data;            //使用-O2优化的时候,必须插入的延时
    LCD->LCD_RAM=data;         
}

void LCD_WR_Data(uint16_t u16Date)
{
    LCD_WR_DATA(u16Date>>8);
    LCD_WR_DATA(u16Date);
}                                                                                                    


void Lcd_data_start(void)
{
    LCD_WR_REG(0x2C);//开始写
}

/**
 * @brief  配置lcd初始化寄存器
 * @param  无
 * @retval 无
 */
void LCD_REG_Config(void)
{  
    LCD_WR_REG(0x01);
    HAL_Delay(100);
    
    LCD_WR_REG(0x11);     

    LCD_WR_REG(0x36);     
    LCD_WR_DATA(0x00);   

    LCD_WR_REG(0x3A);     
    LCD_WR_DATA(0x05);   

    LCD_WR_REG(0xB2);     
    LCD_WR_DATA(0x0C);   
    LCD_WR_DATA(0x0C);   
    LCD_WR_DATA(0x00);   
    LCD_WR_DATA(0x33);   
    LCD_WR_DATA(0x33);   

    LCD_WR_REG(0xB7);     
    LCD_WR_DATA(0x75);   //VGH=14.97V, VGL=-10.43V  

    LCD_WR_REG(0xBB);   //VCOM  
    LCD_WR_DATA(0x19);   

    LCD_WR_REG(0xC0);     
    LCD_WR_DATA(0x0C); // D5----RGB/BGR  

    LCD_WR_REG(0xC2);     
    LCD_WR_DATA(0x01);   

    LCD_WR_REG(0xC3);   //GVDD    VRH
    LCD_WR_DATA(0x1D);   //GVDD=5V   

    LCD_WR_REG(0xC4);     
    LCD_WR_DATA(0x20);   

    LCD_WR_REG(0xC6);  //??   
    LCD_WR_DATA(0x0F);   

    LCD_WR_REG(0xD0);     
    LCD_WR_DATA(0xA4);   
    LCD_WR_DATA(0xA1);   

    LCD_WR_REG(0xE0);     
    LCD_WR_DATA(0xD0);   
    LCD_WR_DATA(0x03);   
    LCD_WR_DATA(0x0B);   
    LCD_WR_DATA(0x14);   
    LCD_WR_DATA(0x17);   
    LCD_WR_DATA(0x1D);   
    LCD_WR_DATA(0x3F);   
    LCD_WR_DATA(0x44);   
    LCD_WR_DATA(0x4E);   
    LCD_WR_DATA(0x0A);   
    LCD_WR_DATA(0x13);   
    LCD_WR_DATA(0x13);   
    LCD_WR_DATA(0x1E);   
    LCD_WR_DATA(0x20);   

    LCD_WR_REG(0xE1);     
    LCD_WR_DATA(0xD0);   
    LCD_WR_DATA(0x03);   
    LCD_WR_DATA(0x0B);   
    LCD_WR_DATA(0x12);   
    LCD_WR_DATA(0x14);   
    LCD_WR_DATA(0x1C);   
    LCD_WR_DATA(0x3F);   
    LCD_WR_DATA(0x44);   
    LCD_WR_DATA(0x4E);   
    LCD_WR_DATA(0x0B);   
    LCD_WR_DATA(0x17);   
    LCD_WR_DATA(0x15);   
    LCD_WR_DATA(0x1E);   
    LCD_WR_DATA(0x21);   

    LCD_WR_REG(0x29);  
}

/**********************************
 * 函数名:Set_direction
 * 描述  :设置ILI9341GRAM指针扫描方向
 * 输入  : 0: 横向扫描
            1: 纵向扫描
 * 输出  :无
 * 举例  :无
 * 注意  :无
*************************************/
void Set_direction(uint8_t option)
{
    switch(option)
    {
    case 0:
    /*横屏*/
        LCD_WR_REG(0x36); 
        LCD_WR_DATA(0x68);    //横屏
        LCD_WR_REG(0X2A); 
        LCD_WR_DATA(0x00);    //start  00
        LCD_WR_DATA(0x00);
        LCD_WR_DATA(0x01);    //end  319
        LCD_WR_DATA(0x3F);

        LCD_WR_REG(0X2B); 
        LCD_WR_DATA(0x00);   //start  00
        LCD_WR_DATA(0x00);
        LCD_WR_DATA(0x00);   //end    239
        LCD_WR_DATA(0xEF);
        display_direction = 0;        
        break;
    case 1:
        /*竖屏*/
        LCD_WR_REG(0x36); 
        LCD_WR_DATA(0x08);    //竖屏 
        LCD_WR_REG(0X2A); 
        LCD_WR_DATA(0x00);    //00
        LCD_WR_DATA(0x00);
        LCD_WR_DATA(0x00);
        LCD_WR_DATA(0xEF);    //239

        LCD_WR_REG(0X2B); 
        LCD_WR_DATA(0x00);    //00
        LCD_WR_DATA(0x00);
        LCD_WR_DATA(0x01);
        LCD_WR_DATA(0x3F);    //319
        display_direction = 1;
        break;
    }
}

/**********************************
 * 函数名:LCD_open_windows
 * 描述  :开窗(以x,y为坐标起点,长为len,高为wid)
 * 输入  : -x    窗户起点
           -y       窗户起点
           -len  窗户长 
           -wid 窗户宽
 * 输出  :无
 * 举例  :无
 * 注意  :无
*************************************/
void LCD_open_windows(uint16_t x,uint16_t y,uint16_t len,uint16_t wid)
{                    
    if(display_direction == 0)        /*如果是横屏选项*/
    {
        LCD_WR_REG(0X2A); 
        LCD_WR_DATA(x>>8);    //start 
        LCD_WR_DATA(x-((x>>8)<<8));
        LCD_WR_DATA((x+len-1)>>8);    //end
        LCD_WR_DATA((x+len-1)-(((x+len-1)>>8)<<8));
        
        LCD_WR_REG(0X2B); 
        LCD_WR_DATA(y>>8);   //start
        LCD_WR_DATA(y-((y>>8)<<8));
        LCD_WR_DATA((y+wid-1)>>8);   //end
        LCD_WR_DATA((y+wid-1)-(((y+wid-1)>>8)<<8));
    }
    else
    {
        LCD_WR_REG(0X2A); 
        LCD_WR_DATA(x>>8);
        LCD_WR_DATA(x-((x>>8)<<8));
        LCD_WR_DATA((x+len-1)>>8);
        LCD_WR_DATA((x+len-1)-(((x+len-1)>>8)<<8));

        LCD_WR_REG(0X2B); 
        LCD_WR_DATA(y>>8);
        LCD_WR_DATA(y-((y>>8)<<8));
        LCD_WR_DATA((y+wid-1)>>8);
        LCD_WR_DATA((y+wid-1)-(((y+wid-1)>>8)<<8));    
    }
    LCD_WR_REG(0x2c);     
}

void LCD_Redraw(uint16_t Color)
{
    unsigned long i;            
    Lcd_data_start();   
    for(i=0; i<(240*320); i++)                 
    {
        LCD_WR_Data(Color);                         
    }   
}



/***************************************/
void LCD_Str_O_BK(uint16_t x, uint16_t y,uint16_t w,uint16_t h,const uint8_t *str,uint16_t Color,uint16_t BkColor,uint8_t u8StrSize)
{
    uint16_t u16x,u16y,u16w,u16h;
    
       Set_direction(1);     
    
        u16w=u8StrSize*8;
    //u16w=5*8;
    
    if(u16w<w)
    {
        u16x=x+(w-u16w)/2;
    }
    else
    {
        u16x=x;
    }
    
    u16h=16;
    
    if(u16h<h)
    {
        u16y=y+(h-u16h)/2;
    }
    else
    {
        u16y=y;
    }
    

    while(*str != '\0')
    {       
            if(u16x > (240-8)) 
            {    
                //换行
                 u16x = 0;
                 u16y += 16;
            }
            if(u16y > (320-16)) 
            {    
                //一屏
                 u16x = u16y = 0;
            }
            
            LCD_Char_O_BK(u16x ,u16y, *str,Color,BkColor); // LCD_Char_O
            u16x += 8;
            str ++ ;
    }
        
}

void LCD_Char_O_BK(uint16_t x, uint16_t y, uint8_t acsii,uint16_t Color,uint16_t BkColor)
{       
#define MAX_CHAR_POSX (240-8)
#define MAX_CHAR_POSY (320-16)
    uint8_t temp, t, pos;     
    if(x > MAX_CHAR_POSX || y > MAX_CHAR_POSY)
        return;
       
    LCD_open_windows(x,y,8,16); 
    
    for (pos=0;pos<16;pos++)
    {
        temp=ascii_8x16[((acsii-0x20)*16)+pos];
        
        for(t=0; t<8; t++)
        {
            if(temp & 0x80)
            {
                            if(t==0)                                       /*如果是一行起点--则重新开启一个矩形*/
                            {
                                LCD_open_windows(x,y+pos,8,16-pos);
                                LCD_WR_Data(Color);
                            }
                            else
                            {
                                LCD_WR_Data(Color);    
                            }
            }
                        else     
            {
                            if(t==7)                                    /*如果是末尾点--则直接开启下一个矩形*/
                            {    
                                    LCD_WR_Data(BkColor);    
                                    LCD_open_windows(x,y+pos+1,8,16-pos-1);         
                            }
                            else
                            {
                                    LCD_WR_Data(BkColor);    
                                    LCD_open_windows(x+t+1,y+pos,8-t,1);/*前进一位 开启一行线*/    
                            }
            } 
            
            temp <<= 1;    
        }        
    }
#undef MAX_CHAR_POSX
#undef MAX_CHAR_POSY   
}
void LCD_Rectangle(uint16_t x,uint16_t y,uint16_t len,uint16_t wid,uint16_t rgb565)
{                    
   uint32_t n, temp;
     Set_direction(0);                             /*设定方向为横向*/
   LCD_open_windows(x,y,len,wid);   
   temp = (uint32_t)len*wid;    
   for(n=0; n<temp; n++)
     {
        LCD_WR_Data( rgb565 );
     }
}
void LCD_Num_6x12_P(uint16_t x,uint16_t y,uint32_t num, uint16_t Color)      
{      
    uint32_t res=num;          
    uint8_t t=0;

        Set_direction(1);  
      if( num == 0 )
        {
            LCD_Char_6x12_O(x, y, '0',Color);
                    return;
        }    
       while( res )  /*得到数字长度t*/
    {
        res/=10;
        t++;
    }

        while(num)
        {
             LCD_Char_6x12_O(x+(6*(t--)-6), y, (num%10)+'0',Color);/*先显示低位在显示高位*/
             num /= 10 ;
        }                 
} 

void LCD_Char_6x12_O(uint16_t x, uint16_t y, uint8_t acsii, uint16_t Color)    
{       
#define MAX_CHAR_POSX (240-6)
#define MAX_CHAR_POSY (320-12)
    uint8_t temp, t, pos;  
 
     if(x > MAX_CHAR_POSX || y > MAX_CHAR_POSY)
     {
             return;
         }

    LCD_open_windows(x,y,6,12);
   
    acsii = acsii - ' ';                                             /*得到偏移后的值*/
    for(pos=0; pos<12; pos++)
    {
        temp = asc2_1206[acsii][pos];
        for(t=0; t<6; t++)                                            /* 低位开始,丢弃高两位*/
        {                 
            if(temp & 0x01)
             {
                if(t==0)
                {
                    LCD_open_windows(x,y+pos,6,12-pos);
                    LCD_WR_Data(Color);
                }
                else
                {
                    LCD_WR_Data(Color);    
                }
             }
            else     
            {
                if(t==5)                                            /*如果是末尾点--开启剩下窗户*/
                {
                        LCD_open_windows(x,y+pos+1,6,12-pos-1);         
                }
                else
                {
                        LCD_open_windows(x+t+1,y+pos,6-t,1);          /*前进一位 开启一行线*/    
                }                
            }   
            temp >>= 1; 
        }
    }
    
#undef MAX_CHAR_POSX
#undef MAX_CHAR_POSY   
}
View Code

ili9341.h:

#ifndef __ILI9341_H
#define __ILI9341_H

#include "stm32f1xx_hal.h"

typedef struct
{
    __IO uint16_t LCD_REG;
    __IO uint16_t LCD_RAM;
} LCD_TypeDef;

//使用NOR/SRAM的 Bank1.sector4,地址位HADDR[27,26]=11 A23作为数据命令区分线 
//注意设置时STM32内部会右移一位对其!                 
#define LCD_BASE        ((uint32_t)(0x6C000000 | 0x007FFFFE))
#define LCD             ((LCD_TypeDef *) LCD_BASE)
#define vu16                         __IO uint16_t

/******常用颜色*****/
#define RED      0XF800
#define GREEN 0X07E0
#define BLUE  0X001F  
#define BRED  0XF81F
#define GRED  0XFFE0
#define GBLUE 0X07FF
#define BLACK 0X0000
#define WHITE 0XFFFF
#define YELLOW 0XFFE0
#define BK_COLOR 0XFFFF//0xC618
#define Navy            0x000F      /*   0,   0, 128 */
#define DarkGreen       0x03E0      /*   0, 128,   0 */
#define DarkCyan        0x03EF      /*   0, 128, 128 */
#define Maroon          0x7800      /* 128,   0,   0 */
#define Purple          0x780F      /* 128,   0, 128 */
#define Olive           0x7BE0      /* 128, 128,   0 */
#define LightGrey       0xC618      /* 192, 192, 192 */
#define DarkGrey        0x7BEF      /* 128, 128, 128 */
#define Cyan            0x07FF      /*   0, 255, 255 */
#define Red             0xF800      /* 255,   0,   0 */
#define Magenta         0xF81F      /* 255,   0, 255 */
#define Orange          0xFD20      /* 255, 165,   0 */
#define GreenYellow     0xAFE5      /* 173, 255,  47 */
#define Pink            0xF81F

void LCD_WR_REG(vu16 regval);
void LCD_WR_DATA(vu16 data);
void LCD_WR_Data(uint16_t u16Date);
void Lcd_data_start(void);
void LCD_REG_Config(void);
    
    
    
void LCD_Rectangle(uint16_t x,uint16_t y,uint16_t len,uint16_t wid,uint16_t rgb565);    
void LCD_Char_O_BK(uint16_t x, uint16_t y, uint8_t acsii,uint16_t Color,uint16_t BkColor);
void LCD_Str_O_BK(uint16_t x, uint16_t y,uint16_t w,uint16_t h,const uint8_t *str,uint16_t Color,uint16_t BkColor,uint8_t u8StrSize);
void LCD_Char_6x12_O(uint16_t x, uint16_t y, uint8_t acsii, uint16_t Color);
void LCD_Num_6x12_P(uint16_t x,uint16_t y,uint32_t num, uint16_t Color);      
#endif
View Code

 

在使用FSMC之前,要看看使用芯片的规格是否支持到到16位的fsmc总线,少Pin脚的IC应该是没有的。

然后就是了解FSMC大概情况,我们使用FSMC驱动LCD,相比8080驱动,速度更快,我对它的理解其实就是一个外部总线,且是一个可以自己定义时序的总线并且速度不慢,当驱动8080接口的器件是时,由于STM32没有自带硬件8080接口的控制器,如果只是使用GPIO来实现此时序的话,会占用大量的CPU资源,所以这个时候就可以考虑采用FSMC功能。

当设置好FSMC接口后,不用手动设置时序,方便快捷。

参考:https://blog.csdn.net/jxnu_xiaobing/article/details/8719897?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1

 

 

CubeMX中的设置:

 

 

根据自己项目原理图接口,选择了A22作为RS口。

cubemx设置后有:

static void MX_FSMC_Init(void)
{

  /* USER CODE BEGIN FSMC_Init 0 */

  /* USER CODE END FSMC_Init 0 */

  FSMC_NORSRAM_TimingTypeDef Timing = {0};
  FSMC_NORSRAM_TimingTypeDef ExtTiming = {0};

  /* USER CODE BEGIN FSMC_Init 1 */

  /* USER CODE END FSMC_Init 1 */

  /** Perform the SRAM1 memory initialization sequence
  */
  hsram1.Instance = FSMC_NORSRAM_DEVICE;
  hsram1.Extended = FSMC_NORSRAM_EXTENDED_DEVICE;
  /* hsram1.Init */
  hsram1.Init.NSBank = FSMC_NORSRAM_BANK4;
  hsram1.Init.DataAddressMux = FSMC_DATA_ADDRESS_MUX_DISABLE;
  hsram1.Init.MemoryType = FSMC_MEMORY_TYPE_SRAM;
  hsram1.Init.MemoryDataWidth = FSMC_NORSRAM_MEM_BUS_WIDTH_16;
  hsram1.Init.BurstAccessMode = FSMC_BURST_ACCESS_MODE_DISABLE;
  hsram1.Init.WaitSignalPolarity = FSMC_WAIT_SIGNAL_POLARITY_LOW;
  hsram1.Init.WrapMode = FSMC_WRAP_MODE_DISABLE;
  hsram1.Init.WaitSignalActive = FSMC_WAIT_TIMING_BEFORE_WS;
  hsram1.Init.WriteOperation = FSMC_WRITE_OPERATION_ENABLE;
  hsram1.Init.WaitSignal = FSMC_WAIT_SIGNAL_DISABLE;
  hsram1.Init.ExtendedMode = FSMC_EXTENDED_MODE_ENABLE;
  hsram1.Init.AsynchronousWait = FSMC_ASYNCHRONOUS_WAIT_DISABLE;
  hsram1.Init.WriteBurst = FSMC_WRITE_BURST_DISABLE;
  /* Timing */
  Timing.AddressSetupTime = 15;
  Timing.AddressHoldTime = 15;
  Timing.DataSetupTime = 24;
  Timing.BusTurnAroundDuration = 0;
  Timing.CLKDivision = 16;
  Timing.DataLatency = 17;
  Timing.AccessMode = FSMC_ACCESS_MODE_A;
  /* ExtTiming */
  ExtTiming.AddressSetupTime = 8;
  ExtTiming.AddressHoldTime = 15;
  ExtTiming.DataSetupTime = 8;
  ExtTiming.BusTurnAroundDuration = 0;
  ExtTiming.CLKDivision = 16;
  ExtTiming.DataLatency = 17;
  ExtTiming.AccessMode = FSMC_ACCESS_MODE_A;

  if (HAL_SRAM_Init(&hsram1, &Timing, &ExtTiming) != HAL_OK)
  {
    Error_Handler( );
  }

  /** Disconnect NADV
  */

  __HAL_AFIO_FSMCNADV_DISCONNECTED();

  /* USER CODE BEGIN FSMC_Init 2 */

  /* USER CODE END FSMC_Init 2 */
}

 

 

LCD_BASE,须根据外部电路的连接来确定,如Bank1.sector4就是从地址0x6C000000开始,而0x000007FE,则是A10的偏移量。以A10为例,7FE换成二进制位为:111 1111 1110,而16位数据时,地址右移一位对齐,对应到地址引脚,就是:A10:A0 = 011 1111 1111,此时A10是0,但是如果16位地址再加1,那么A10:A0 = 100 0000 0000,此时A10就是1了,即实现了对RS的0和1的控制。

这里是A22作为RS口,有上面同理算得,

#define LCD_BASE        ((uint32_t)(0x6C000000 | 0x007FFFFE))
#define LCD             ((LCD_TypeDef *) LCD_BASE)

 

在ili9341.h中定义结构体

typedef struct
{
    __IO uint16_t LCD_REG;
    __IO uint16_t LCD_RAM;
} LCD_TypeDef;

写数据和寄存器的函数:

  //写寄存器函数
//regval:寄存器值
void LCD_WR_REG(vu16 regval)
{   
    regval=regval;        //使用-O2优化的时候,必须插入的延时
    LCD->LCD_REG=regval;//写入要写的寄存器序号     
}                                                
//写LCD数据
//data:要写入的值
void LCD_WR_DATA(vu16 data)
{      
    data=data;            //使用-O2优化的时候,必须插入的延时
    LCD->LCD_RAM=data;         
}

剩下参考上面代码即可。

posted @ 2020-05-12 10:37  无乐不作丶  阅读(4378)  评论(1编辑  收藏  举报