From 80b577588504999467142e1ff6234f5c1a7f3af7 Mon Sep 17 00:00:00 2001 From: RB Date: Thu, 10 Apr 2025 19:35:47 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=AF=E5=8A=A8dma=E4=BC=A0=E8=BE=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Core/Inc/dma.h | 52 + Core/Inc/stm32f1xx_hal_conf.h | 2 +- Core/Inc/stm32f1xx_it.h | 1 + Core/Src/dma.c | 55 + Core/Src/main.c | 2 + Core/Src/spi.c | 20 + Core/Src/stm32f1xx_it.c | 16 +- MDK-ARM/mini_croe.uvoptx | 120 +- MDK-ARM/mini_croe.uvprojx | 58 +- MDK-ARM/mini_croe/mini_croe.axf | Bin 1003208 -> 1022540 bytes MDK-ARM/mini_croe/mini_croe.hex | 2410 +++++++++++++++++-------------- User/device/lcd.c | 192 +-- User/task/mointor.c | 11 +- mini_croe.ioc | 32 +- 14 files changed, 1698 insertions(+), 1273 deletions(-) create mode 100644 Core/Inc/dma.h create mode 100644 Core/Src/dma.c diff --git a/Core/Inc/dma.h b/Core/Inc/dma.h new file mode 100644 index 0000000..493d98e --- /dev/null +++ b/Core/Inc/dma.h @@ -0,0 +1,52 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file dma.h + * @brief This file contains all the function prototypes for + * the dma.c file + ****************************************************************************** + * @attention + * + * Copyright (c) 2025 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __DMA_H__ +#define __DMA_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "main.h" + +/* DMA memory to memory transfer handles -------------------------------------*/ + +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* USER CODE BEGIN Private defines */ + +/* USER CODE END Private defines */ + +void MX_DMA_Init(void); + +/* USER CODE BEGIN Prototypes */ + +/* USER CODE END Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif /* __DMA_H__ */ + diff --git a/Core/Inc/stm32f1xx_hal_conf.h b/Core/Inc/stm32f1xx_hal_conf.h index 5cad91f..9060417 100644 --- a/Core/Inc/stm32f1xx_hal_conf.h +++ b/Core/Inc/stm32f1xx_hal_conf.h @@ -42,7 +42,7 @@ /*#define HAL_CORTEX_MODULE_ENABLED */ /*#define HAL_CRC_MODULE_ENABLED */ /*#define HAL_DAC_MODULE_ENABLED */ -/*#define HAL_DMA_MODULE_ENABLED */ +#define HAL_DMA_MODULE_ENABLED /*#define HAL_ETH_MODULE_ENABLED */ /*#define HAL_FLASH_MODULE_ENABLED */ #define HAL_GPIO_MODULE_ENABLED diff --git a/Core/Inc/stm32f1xx_it.h b/Core/Inc/stm32f1xx_it.h index 055d8d1..6bba357 100644 --- a/Core/Inc/stm32f1xx_it.h +++ b/Core/Inc/stm32f1xx_it.h @@ -53,6 +53,7 @@ void BusFault_Handler(void); void UsageFault_Handler(void); void DebugMon_Handler(void); void SysTick_Handler(void); +void DMA1_Channel3_IRQHandler(void); /* USER CODE BEGIN EFP */ /* USER CODE END EFP */ diff --git a/Core/Src/dma.c b/Core/Src/dma.c new file mode 100644 index 0000000..aa57ab7 --- /dev/null +++ b/Core/Src/dma.c @@ -0,0 +1,55 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file dma.c + * @brief This file provides code for the configuration + * of all the requested memory to memory DMA transfers. + ****************************************************************************** + * @attention + * + * Copyright (c) 2025 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Includes ------------------------------------------------------------------*/ +#include "dma.h" + +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/*----------------------------------------------------------------------------*/ +/* Configure DMA */ +/*----------------------------------------------------------------------------*/ + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ + +/** + * Enable DMA controller clock + */ +void MX_DMA_Init(void) +{ + + /* DMA controller clock enable */ + __HAL_RCC_DMA1_CLK_ENABLE(); + + /* DMA interrupt init */ + /* DMA1_Channel3_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(DMA1_Channel3_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn); + +} + +/* USER CODE BEGIN 2 */ + +/* USER CODE END 2 */ + diff --git a/Core/Src/main.c b/Core/Src/main.c index 2372a36..b7d8827 100644 --- a/Core/Src/main.c +++ b/Core/Src/main.c @@ -20,6 +20,7 @@ #include "main.h" #include "cmsis_os.h" #include "can.h" +#include "dma.h" #include "spi.h" #include "tim.h" #include "usart.h" @@ -92,6 +93,7 @@ int main(void) /* Initialize all configured peripherals */ MX_GPIO_Init(); + MX_DMA_Init(); MX_SPI1_Init(); MX_TIM3_Init(); MX_CAN1_Init(); diff --git a/Core/Src/spi.c b/Core/Src/spi.c index e535607..86fde68 100644 --- a/Core/Src/spi.c +++ b/Core/Src/spi.c @@ -25,6 +25,7 @@ /* USER CODE END 0 */ SPI_HandleTypeDef hspi1; +DMA_HandleTypeDef hdma_spi1_tx; /* SPI1 init function */ void MX_SPI1_Init(void) @@ -81,6 +82,23 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle) GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + /* SPI1 DMA Init */ + /* SPI1_TX Init */ + hdma_spi1_tx.Instance = DMA1_Channel3; + hdma_spi1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; + hdma_spi1_tx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_spi1_tx.Init.MemInc = DMA_MINC_ENABLE; + hdma_spi1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + hdma_spi1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_spi1_tx.Init.Mode = DMA_NORMAL; + hdma_spi1_tx.Init.Priority = DMA_PRIORITY_LOW; + if (HAL_DMA_Init(&hdma_spi1_tx) != HAL_OK) + { + Error_Handler(); + } + + __HAL_LINKDMA(spiHandle,hdmatx,hdma_spi1_tx); + /* USER CODE BEGIN SPI1_MspInit 1 */ /* USER CODE END SPI1_MspInit 1 */ @@ -104,6 +122,8 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* spiHandle) */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5|GPIO_PIN_7); + /* SPI1 DMA DeInit */ + HAL_DMA_DeInit(spiHandle->hdmatx); /* USER CODE BEGIN SPI1_MspDeInit 1 */ /* USER CODE END SPI1_MspDeInit 1 */ diff --git a/Core/Src/stm32f1xx_it.c b/Core/Src/stm32f1xx_it.c index e0fd96d..6de7f7e 100644 --- a/Core/Src/stm32f1xx_it.c +++ b/Core/Src/stm32f1xx_it.c @@ -57,7 +57,7 @@ /* USER CODE END 0 */ /* External variables --------------------------------------------------------*/ - +extern DMA_HandleTypeDef hdma_spi1_tx; /* USER CODE BEGIN EV */ /* USER CODE END EV */ @@ -182,6 +182,20 @@ void SysTick_Handler(void) /* please refer to the startup file (startup_stm32f1xx.s). */ /******************************************************************************/ +/** + * @brief This function handles DMA1 channel3 global interrupt. + */ +void DMA1_Channel3_IRQHandler(void) +{ + /* USER CODE BEGIN DMA1_Channel3_IRQn 0 */ + + /* USER CODE END DMA1_Channel3_IRQn 0 */ + HAL_DMA_IRQHandler(&hdma_spi1_tx); + /* USER CODE BEGIN DMA1_Channel3_IRQn 1 */ + + /* USER CODE END DMA1_Channel3_IRQn 1 */ +} + /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ diff --git a/MDK-ARM/mini_croe.uvoptx b/MDK-ARM/mini_croe.uvoptx index 24af30b..0a868da 100644 --- a/MDK-ARM/mini_croe.uvoptx +++ b/MDK-ARM/mini_croe.uvoptx @@ -309,6 +309,18 @@ 0 0 0 + ../Core/Src/dma.c + dma.c + 0 + 0 + + + 2 + 7 + 1 + 0 + 0 + 0 ../Core/Src/spi.c spi.c 0 @@ -316,7 +328,7 @@ 2 - 7 + 8 1 0 0 @@ -328,7 +340,7 @@ 2 - 8 + 9 1 0 0 @@ -340,7 +352,7 @@ 2 - 9 + 10 1 0 0 @@ -352,7 +364,7 @@ 2 - 10 + 11 1 0 0 @@ -372,7 +384,7 @@ 0 3 - 11 + 12 1 0 0 @@ -384,7 +396,7 @@ 3 - 12 + 13 1 0 0 @@ -396,7 +408,7 @@ 3 - 13 + 14 1 0 0 @@ -408,7 +420,7 @@ 3 - 14 + 15 1 0 0 @@ -420,7 +432,7 @@ 3 - 15 + 16 1 0 0 @@ -432,7 +444,7 @@ 3 - 16 + 17 1 0 0 @@ -444,7 +456,7 @@ 3 - 17 + 18 1 0 0 @@ -456,7 +468,7 @@ 3 - 18 + 19 1 0 0 @@ -468,7 +480,7 @@ 3 - 19 + 20 1 0 0 @@ -480,7 +492,7 @@ 3 - 20 + 21 1 0 0 @@ -492,7 +504,7 @@ 3 - 21 + 22 1 0 0 @@ -504,7 +516,7 @@ 3 - 22 + 23 1 0 0 @@ -516,7 +528,7 @@ 3 - 23 + 24 1 0 0 @@ -528,7 +540,7 @@ 3 - 24 + 25 1 0 0 @@ -540,7 +552,7 @@ 3 - 25 + 26 1 0 0 @@ -552,7 +564,7 @@ 3 - 26 + 27 1 0 0 @@ -572,7 +584,7 @@ 0 4 - 27 + 28 1 0 0 @@ -592,7 +604,7 @@ 0 5 - 28 + 29 1 0 0 @@ -604,7 +616,7 @@ 5 - 29 + 30 1 0 0 @@ -616,7 +628,7 @@ 5 - 30 + 31 1 0 0 @@ -628,7 +640,7 @@ 5 - 31 + 32 1 0 0 @@ -640,7 +652,7 @@ 5 - 32 + 33 1 0 0 @@ -652,7 +664,7 @@ 5 - 33 + 34 1 0 0 @@ -664,7 +676,7 @@ 5 - 34 + 35 1 0 0 @@ -676,7 +688,7 @@ 5 - 35 + 36 1 0 0 @@ -688,7 +700,7 @@ 5 - 36 + 37 1 0 0 @@ -700,7 +712,7 @@ 5 - 37 + 38 1 0 0 @@ -720,7 +732,7 @@ 0 6 - 38 + 39 5 0 0 @@ -732,7 +744,7 @@ 6 - 39 + 40 1 0 0 @@ -744,7 +756,7 @@ 6 - 40 + 41 5 0 0 @@ -756,7 +768,7 @@ 6 - 41 + 42 1 0 0 @@ -768,7 +780,7 @@ 6 - 42 + 43 5 0 0 @@ -780,7 +792,7 @@ 6 - 43 + 44 1 0 0 @@ -792,7 +804,7 @@ 6 - 44 + 45 5 0 0 @@ -820,7 +832,7 @@ 0 8 - 45 + 46 1 0 0 @@ -832,7 +844,7 @@ 8 - 46 + 47 1 0 0 @@ -844,7 +856,7 @@ 8 - 47 + 48 1 0 0 @@ -856,7 +868,7 @@ 8 - 48 + 49 1 0 0 @@ -868,7 +880,7 @@ 8 - 49 + 50 1 0 0 @@ -880,7 +892,7 @@ 8 - 50 + 51 1 0 0 @@ -892,7 +904,7 @@ 8 - 51 + 52 5 0 0 @@ -912,7 +924,7 @@ 0 9 - 52 + 53 1 0 0 @@ -924,7 +936,7 @@ 9 - 53 + 54 5 0 0 @@ -944,7 +956,7 @@ 0 10 - 54 + 55 1 0 0 @@ -956,7 +968,7 @@ 10 - 55 + 56 5 0 0 @@ -968,7 +980,7 @@ 10 - 56 + 57 1 0 0 @@ -980,7 +992,7 @@ 10 - 57 + 58 5 0 0 @@ -992,7 +1004,7 @@ 10 - 58 + 59 5 0 0 @@ -1004,7 +1016,7 @@ 10 - 59 + 60 1 0 0 @@ -1016,7 +1028,7 @@ 10 - 60 + 61 5 0 0 diff --git a/MDK-ARM/mini_croe.uvprojx b/MDK-ARM/mini_croe.uvprojx index a9b6482..8842ba1 100644 --- a/MDK-ARM/mini_croe.uvprojx +++ b/MDK-ARM/mini_croe.uvprojx @@ -339,7 +339,7 @@ USE_HAL_DRIVER,STM32F105xC - ../Core/Inc;../Drivers/STM32F1xx_HAL_Driver/Inc;../Drivers/STM32F1xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32F1xx/Include;../Drivers/CMSIS/Include;../Middlewares/Third_Party/FreeRTOS/Source/include;../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2;../Middlewares/Third_Party/FreeRTOS/Source/portable/RVDS/ARM_CM3;..\User + ../Core/Inc;../Drivers/STM32F1xx_HAL_Driver/Inc;../Drivers/STM32F1xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32F1xx/Include;../Drivers/CMSIS/Include;../Middlewares/Third_Party/FreeRTOS/Source/include;../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2;../Middlewares/Third_Party/FreeRTOS/Source/portable/RVDS/ARM_CM3;../User @@ -515,6 +515,62 @@ + + dma.c + 1 + ../Core/Src/dma.c + + + 2 + 0 + 0 + 0 + 0 + 1 + 2 + 2 + 2 + 2 + 11 + + + 1 + + + + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 0 + 0 + 2 + 2 + 2 + 2 + 2 + + + + + + + + + + spi.c 1 diff --git a/MDK-ARM/mini_croe/mini_croe.axf b/MDK-ARM/mini_croe/mini_croe.axf index f4ad731be1ce6e2c986f06294fac4e479ed47363..ad613f5c530d24f701b7d2985b741aca85cfeb2e 100644 GIT binary patch delta 57330 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≀#2}C6Rn;S-fKywj9`+buOPmwos~_N; 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 bl`r+2VZVumkkwBWAvvYFY@YE?K>hfCkz#Vl delta 44740 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 // 添加标准库以使用 malloc 和 free - -// 写命令 +// 写命令到LCD static void LCD_WriteCommand(uint8_t cmd) { LCD_DC_LOW(); LCD_CS_LOW(); @@ -10,7 +10,7 @@ static void LCD_WriteCommand(uint8_t cmd) { LCD_CS_HIGH(); } -// 写数据 +// 写数据到LCD static void LCD_WriteData(uint8_t data) { LCD_DC_HIGH(); LCD_CS_LOW(); @@ -18,36 +18,51 @@ static void LCD_WriteData(uint8_t data) { LCD_CS_HIGH(); } -// 写16位数据 -static void LCD_WriteData16(uint16_t data) { - uint8_t buf[2] = {data >> 8, data & 0xFF}; +// // 写多个数据到LCD +// static void LCD_WriteDataBuffer(uint8_t *data, uint16_t size) { +// LCD_DC_HIGH(); +// LCD_CS_LOW(); +// HAL_SPI_Transmit(&hspi1, data, size, HAL_MAX_DELAY); +// LCD_CS_HIGH(); +// } + +// 使用 DMA 写多个数据到 LCD +static void LCD_WriteDataBuffer_DMA(uint8_t *data, uint16_t size) { LCD_DC_HIGH(); LCD_CS_LOW(); - HAL_SPI_Transmit(&hspi1, buf, 2, HAL_MAX_DELAY); + HAL_SPI_Transmit_DMA(&hspi1, data, size); // 使用 DMA 传输 + while (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY); // 等待传输完成 LCD_CS_HIGH(); } +// 修改原来的 LCD_WriteDataBuffer,增加 DMA 支持 +static void LCD_WriteDataBuffer(uint8_t *data, uint16_t size) { + if (size > 64) { // 如果数据量较大,使用 DMA + LCD_WriteDataBuffer_DMA(data, size); + } else { // 否则使用普通传输 + LCD_DC_HIGH(); + LCD_CS_LOW(); + HAL_SPI_Transmit(&hspi1, data, size, HAL_MAX_DELAY); + LCD_CS_HIGH(); + } +} + // 初始化LCD void LCD_Init(void) { - // 复位屏幕 LCD_RST_LOW(); - HAL_Delay(10); + HAL_Delay(50); LCD_RST_HIGH(); - HAL_Delay(10); + HAL_Delay(50); - // 初始化命令序列(以ST7789为例) LCD_WriteCommand(0x36); // Memory Data Access Control - LCD_WriteData(0xC0); // RGB Color Order + LCD_WriteData(0x60); // 横屏模式,向右旋转90度 LCD_WriteCommand(0x3A); // Interface Pixel Format - LCD_WriteData(0x05); // 16-bit/pixel + LCD_WriteData(0x05); // 16位色 LCD_WriteCommand(0xB2); // Porch Setting - LCD_WriteData(0x0C); - LCD_WriteData(0x0C); - LCD_WriteData(0x00); - LCD_WriteData(0x33); - LCD_WriteData(0x33); + uint8_t porch[] = {0x0C, 0x0C, 0x00, 0x33, 0x33}; + LCD_WriteDataBuffer(porch, sizeof(porch)); LCD_WriteCommand(0xB7); // Gate Control LCD_WriteData(0x35); @@ -60,8 +75,10 @@ void LCD_Init(void) { LCD_WriteCommand(0xC2); // VDV and VRH Command Enable LCD_WriteData(0x01); + LCD_WriteCommand(0xC3); // VRH Set LCD_WriteData(0x12); + LCD_WriteCommand(0xC4); // VDV Set LCD_WriteData(0x20); @@ -73,97 +90,110 @@ void LCD_Init(void) { LCD_WriteData(0xA1); LCD_WriteCommand(0xE0); // Positive Voltage Gamma Control - LCD_WriteData(0xD0); - LCD_WriteData(0x04); - LCD_WriteData(0x0D); - LCD_WriteData(0x11); - LCD_WriteData(0x13); - LCD_WriteData(0x2B); - LCD_WriteData(0x3F); - LCD_WriteData(0x54); - LCD_WriteData(0x4C); - LCD_WriteData(0x18); - LCD_WriteData(0x0D); - LCD_WriteData(0x0B); - LCD_WriteData(0x1F); - LCD_WriteData(0x23); + uint8_t gamma_pos[] = {0xD0, 0x04, 0x0D, 0x11, 0x13, 0x2B, 0x3F, 0x54, 0x4C, 0x18, 0x0D, 0x0B, 0x1F, 0x23}; + LCD_WriteDataBuffer(gamma_pos, sizeof(gamma_pos)); LCD_WriteCommand(0xE1); // Negative Voltage Gamma Control - LCD_WriteData(0xD0); - LCD_WriteData(0x04); - LCD_WriteData(0x0C); - LCD_WriteData(0x11); - LCD_WriteData(0x13); - LCD_WriteData(0x2C); - LCD_WriteData(0x3F); - LCD_WriteData(0x44); - LCD_WriteData(0x51); - LCD_WriteData(0x2F); - LCD_WriteData(0x1F); - LCD_WriteData(0x1F); - LCD_WriteData(0x20); - LCD_WriteData(0x23); + uint8_t gamma_neg[] = {0xD0, 0x04, 0x0C, 0x11, 0x13, 0x2C, 0x3F, 0x44, 0x51, 0x2F, 0x1F, 0x1F, 0x20, 0x23}; + LCD_WriteDataBuffer(gamma_neg, sizeof(gamma_neg)); - LCD_WriteCommand(0x21); // Inversion On + LCD_WriteCommand(0x21); // Display Inversion On LCD_WriteCommand(0x11); // Sleep Out HAL_Delay(120); LCD_WriteCommand(0x29); // Display On } -// 清屏 -void LCD_Clear(uint16_t color) { +// 设置显示窗口 +static void LCD_SetAddressWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h) { + uint16_t x_start = x + X_OFFSET; + uint16_t x_end = x_start + w - 1; + uint16_t y_start = y + Y_OFFSET; + uint16_t y_end = y_start + h - 1; + LCD_WriteCommand(0x2A); // Column Address Set - LCD_WriteData16(X_OFFSET); // 起始列地址 - LCD_WriteData16(X_OFFSET + LCD_WIDTH - 1); // 结束列地址 + uint8_t data_x[] = {x_start >> 8, x_start & 0xFF, x_end >> 8, x_end & 0xFF}; + LCD_WriteDataBuffer(data_x, sizeof(data_x)); LCD_WriteCommand(0x2B); // Row Address Set - LCD_WriteData16(Y_OFFSET); // 起始行地址 - LCD_WriteData16(Y_OFFSET + LCD_HEIGHT - 1); // 结束行地址 + uint8_t data_y[] = {y_start >> 8, y_start & 0xFF, y_end >> 8, y_end & 0xFF}; + LCD_WriteDataBuffer(data_y, sizeof(data_y)); LCD_WriteCommand(0x2C); // Memory Write - for (uint32_t i = 0; i < LCD_WIDTH * LCD_HEIGHT; i++) { - LCD_WriteData16(color); +} + +// 清屏 +// void LCD_Clear(uint16_t color) { +// uint8_t color_data[] = {color >> 8, color & 0xFF}; +// LCD_SetAddressWindow(0, 0, LCD_WIDTH, LCD_HEIGHT); + +// for (uint32_t i = 0; i < LCD_WIDTH * LCD_HEIGHT; i++) { +// LCD_WriteDataBuffer(color_data, 2); +// } +// } + +void LCD_Clear(uint16_t color) { + uint8_t color_data[] = {color >> 8, color & 0xFF}; + LCD_SetAddressWindow(0, 0, LCD_WIDTH, LCD_HEIGHT); + + // 创建一个缓冲区,用于存储整屏颜色数据 + uint32_t buffer_size = LCD_WIDTH * LCD_HEIGHT * 2; // 每个像素 2 字节 + uint8_t *buffer = malloc(buffer_size); + if (buffer == NULL) return; // 分配失败,直接返回 + + for (uint32_t i = 0; i < buffer_size; i += 2) { + buffer[i] = color_data[0]; + buffer[i + 1] = color_data[1]; } + + // 使用 DMA 传输整个缓冲区 + LCD_WriteDataBuffer_DMA(buffer, buffer_size); + + free(buffer); // 释放缓冲区 } -// 绘制单个像素 +// 绘制像素 void LCD_DrawPixel(uint16_t x, uint16_t y, uint16_t color) { - if (x >= LCD_WIDTH || y >= LCD_HEIGHT) return; // 超出屏幕范围则返回 - - LCD_WriteCommand(0x2A); // 设置列地址 - LCD_WriteData16(X_OFFSET + x); - LCD_WriteData16(X_OFFSET + x); - - LCD_WriteCommand(0x2B); // 设置行地址 - LCD_WriteData16(Y_OFFSET + y); - LCD_WriteData16(Y_OFFSET + y); - - LCD_WriteCommand(0x2C); // 写入内存 - LCD_WriteData16(color); + LCD_SetAddressWindow(x, y, 1, 1); + uint8_t color_data[] = {color >> 8, color & 0xFF}; + LCD_WriteDataBuffer(color_data, 2); } -// 在指定位置显示一个字符 -void LCD_DrawChar(uint16_t x, uint16_t y, char ch, uint16_t color, uint16_t bgColor) { - if (ch < 32 || ch > 126) return; // 字符范围检查 (ASCII 32-126) +// // 绘制字符(旋转90度) +// void LCD_DrawChar(uint16_t x, uint16_t y, char ch, uint16_t color, uint16_t bgColor) { +// const unsigned char *font = ascii_1206[ch - ' ']; +// for (uint8_t i = 0; i < FONT_WIDTH; i++) { // 遍历字体宽度 +// for (uint8_t j = 0; j < FONT_HEIGHT; j++) { // 遍历字体高度 +// if (font[j] & (1 << i)) { // 行列交换,旋转90度 +// LCD_DrawPixel(x + i, y + j, color); +// } else { +// LCD_DrawPixel(x + i, y + j, bgColor); +// } +// } +// } +// } - const uint8_t *charData = ascii_1206[ch - 32]; // 获取字符点阵数据 - for (uint8_t i = 0; i < FONT_HEIGHT; i++) { // 遍历字符的高度 - uint8_t line = charData[i]; // 获取字符的每一行数据 - for (uint8_t j = 0; j < FONT_WIDTH; j++) { // 遍历字符的宽度 - if (line & (1 << j)) { // 判断当前像素是否为1 - LCD_DrawPixel(x + j, y + i, color); // 绘制前景色 +// 绘制字符(逆时针旋转90度) +void LCD_DrawChar(uint16_t x, uint16_t y, char ch, uint16_t color, uint16_t bgColor) { + const unsigned char *font = ascii_1206[ch - ' ']; + for (uint8_t i = 0; i < FONT_WIDTH; i++) { // 遍历字体宽度 + for (uint8_t j = 0; j < FONT_HEIGHT; j++) { // 遍历字体高度 + if (font[j] & (1 << i)) { // 行列交换,逆时针旋转90度 + LCD_DrawPixel(x + j, y - i, color); // 注意坐标变换 } else { - LCD_DrawPixel(x + j, y + i, bgColor); // 绘制背景色 + LCD_DrawPixel(x + j, y - i, bgColor); } } } } -// 在指定位置显示字符串 + + +// 绘制字符串(沿y轴绘制) void LCD_DrawString(uint16_t x, uint16_t y, const char *str, uint16_t color, uint16_t bgColor) { + y = LCD_HEIGHT-1 -y; while (*str) { - LCD_DrawChar(x, y, *str, color, bgColor); // 显示单个字符 - x += FONT_WIDTH; // 移动到下一个字符位置 + LCD_DrawChar(x, y, *str, color, bgColor); + y -= FONT_WIDTH; // 每个字符向下移动一个字符宽度 str++; } } \ No newline at end of file diff --git a/User/task/mointor.c b/User/task/mointor.c index 9d43680..0c6423f 100644 --- a/User/task/mointor.c +++ b/User/task/mointor.c @@ -14,16 +14,21 @@ void Task_Monitor(void *argument) { (void)argument; // 消除未使用参数的警告 const uint32_t delay_tick = osKernelGetTickFreq() / TASK_FREQ_MONITOR; // 100Hz uint32_t tick = osKernelGetTickCount(); /* 控制任务运行频率的计时 */ + char tick_str[16]; LCD_Init(); LCD_Clear(BLACK); + // HAL_Delay(5000); // 延时 1 秒 LCD_Clear(RED); - LCD_DrawChar(0, 0, '0', WHITE, BLACK); // 在屏幕上显示字符 - LCD_DrawString(0, 20, "Hello", WHITE, BLACK); // 在屏幕上显示字符串 + // LCD_DrawChar(0, 0, '0', WHITE, BLACK); // 在屏幕上显示字符 + LCD_DrawString(0, 0, "Hello", WHITE, BLACK); // 在屏幕上显示字符串 + LCD_DrawString(50, 0,"this is sick (DT35-driver)",BLACK,WHITE); BSP_LED_Set(BSP_LED_RED, BSP_LED_ON, 0); BSP_LED_Set(BSP_LED_BLUE, BSP_LED_ON, 0); while (1) { tick += delay_tick; /* 计算下一个唤醒时刻 */ - + sprintf(tick_str, "Tick: %lu", tick); + //展示tick + LCD_DrawString(0, 20, tick_str, WHITE, BLACK); // 在屏幕上显示 tick 值 // 切换 LED 状态 BSP_LED_Set(BSP_LED_GREEN, BSP_LED_TAGGLE, 0); // 50% 占空比 osDelayUntil(tick); /* 运行结束,等待下一次唤醒 */ diff --git a/mini_croe.ioc b/mini_croe.ioc index cb241e2..783c574 100644 --- a/mini_croe.ioc +++ b/mini_croe.ioc @@ -10,6 +10,17 @@ CAN2.CalculateBaudRate=749999 CAN2.CalculateTimeBit=1333 CAN2.CalculateTimeQuantum=444.44444444444446 CAN2.IPParameters=CalculateTimeQuantum,CalculateTimeBit,CalculateBaudRate +Dma.Request0=SPI1_TX +Dma.RequestsNb=1 +Dma.SPI1_TX.0.Direction=DMA_MEMORY_TO_PERIPH +Dma.SPI1_TX.0.Instance=DMA1_Channel3 +Dma.SPI1_TX.0.MemDataAlignment=DMA_MDATAALIGN_BYTE +Dma.SPI1_TX.0.MemInc=DMA_MINC_ENABLE +Dma.SPI1_TX.0.Mode=DMA_NORMAL +Dma.SPI1_TX.0.PeriphDataAlignment=DMA_PDATAALIGN_BYTE +Dma.SPI1_TX.0.PeriphInc=DMA_PINC_DISABLE +Dma.SPI1_TX.0.Priority=DMA_PRIORITY_LOW +Dma.SPI1_TX.0.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority FREERTOS.IPParameters=Tasks01,configTOTAL_HEAP_SIZE FREERTOS.Tasks01=defaultTask,24,128,StartDefaultTask,Default,NULL,Dynamic,NULL,NULL FREERTOS.configTOTAL_HEAP_SIZE=0x1000 @@ -20,14 +31,15 @@ Mcu.CPN=STM32F105RBT6 Mcu.Family=STM32F1 Mcu.IP0=CAN1 Mcu.IP1=CAN2 -Mcu.IP2=FREERTOS -Mcu.IP3=NVIC -Mcu.IP4=RCC -Mcu.IP5=SPI1 -Mcu.IP6=SYS -Mcu.IP7=TIM3 -Mcu.IP8=USART3 -Mcu.IPNb=9 +Mcu.IP2=DMA +Mcu.IP3=FREERTOS +Mcu.IP4=NVIC +Mcu.IP5=RCC +Mcu.IP6=SPI1 +Mcu.IP7=SYS +Mcu.IP8=TIM3 +Mcu.IP9=USART3 +Mcu.IPNb=10 Mcu.Name=STM32F105R(8-B-C)Tx Mcu.Package=LQFP64 Mcu.Pin0=PD0-OSC_IN @@ -61,6 +73,7 @@ Mcu.UserName=STM32F105RBTx MxCube.Version=6.14.0 MxDb.Version=DB.6.0.140 NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false +NVIC.DMA1_Channel3_IRQn=true\:5\:0\:false\:false\:true\:true\:false\:true\:true NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false NVIC.ForceEnableDMAVector=true NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false @@ -165,7 +178,7 @@ ProjectManager.ToolChainLocation= ProjectManager.UAScriptAfterPath= ProjectManager.UAScriptBeforePath= ProjectManager.UnderRoot=false -ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_SPI1_Init-SPI1-false-HAL-true,4-MX_TIM3_Init-TIM3-false-HAL-true,5-MX_CAN1_Init-CAN1-false-HAL-true,6-MX_CAN2_Init-CAN2-false-HAL-true,7-MX_USART3_UART_Init-USART3-false-HAL-true +ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_DMA_Init-DMA-false-HAL-true,4-MX_SPI1_Init-SPI1-false-HAL-true,5-MX_TIM3_Init-TIM3-false-HAL-true,6-MX_CAN1_Init-CAN1-false-HAL-true,7-MX_CAN2_Init-CAN2-false-HAL-true,8-MX_USART3_UART_Init-USART3-false-HAL-true RCC.ADCFreqValue=36000000 RCC.AHBFreq_Value=72000000 RCC.APB1CLKDivider=RCC_HCLK_DIV2 @@ -214,3 +227,4 @@ VP_FREERTOS_VS_CMSIS_V2.Signal=FREERTOS_VS_CMSIS_V2 VP_SYS_VS_Systick.Mode=SysTick VP_SYS_VS_Systick.Signal=SYS_VS_Systick board=custom +rtos.0.ip=FREERTOS