基于HAL库STM32的FSMC驱动8位TFTLCD屏
先上代码。
main.c:
/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** * @attention * * <h2><center>© 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****/
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 }
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
在使用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; }
剩下参考上面代码即可。