На основе данной лекции из файла добавь в код полу...
Created on: April 16, 2025
Created on: April 16, 2025
На основе данной лекции из файла добавь в код получение данных с помощью DMA организовать отправку строк ответов с помощью DMA. Не удаляй исходные функции, только добавляй. /* USER CODE BEGIN Header /
/*
/
/ USER CODE END Header /
/ Includes ------------------------------------------------------------------*/
#include "main.h"
#include <string.h>
#include <stdlib.h>
/* Private includes ----------------------------------------------------------/
/ USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------/
/ USER CODE BEGIN PTD /
typedef enum {
LED_STATE_OFF,
LED_STATE_ON,
LED_STATE_BLINKING
} LedState;
/ USER CODE END PTD */
/* Private define ------------------------------------------------------------/
/ USER CODE BEGIN PD /
#define UART_BUFFER_SIZE 64
#define MAX_PERIOD 5000
#define MIN_PERIOD 10
#define DEFAULT_PERIOD 500
#define DEVICE_ID "STM52"
/ USER CODE END PD */
/* Private macro -------------------------------------------------------------/
/ USER CODE BEGIN PM /
#define ACK "ACK\r\n"
#define NACK "NACK\r\n"
/ USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
UART_HandleTypeDef huart6;
/* USER CODE BEGIN PV /
volatile uint32_t ledPeriod = DEFAULT_PERIOD;
volatile LedState ledState = LED_STATE_OFF;
volatile uint32_t lastToggleTime = 0;
char uartBuffer[UART_BUFFER_SIZE];
uint8_t uartBufferIndex = 0;
/ USER CODE END PV */
/* Private function prototypes -----------------------------------------------/
void SystemClock_Config(void);
static void MPU_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART6_UART_Init(void);
/ USER CODE BEGIN PFP /
void processCommand(char command);
void handleLED(void);
void sendResponse(const char* response);
void UART_ReceiveHandler(void);
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------/
/ USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
/* USER CODE END 1 */
/* MPU Configuration--------------------------------------------------------*/
MPU_Config();
/* 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_USART6_UART_Init();
/ USER CODE BEGIN 2 /
HAL_UART_Transmit(&huart6, (uint8_t)"Hello everyone! Enter command:\r\n", 32, HAL_MAX_DELAY);
HAL_UART_Receive_IT(&huart6, (uint8_t*)&uartBuffer[uartBufferIndex], 1);
/* USER CODE END 2 */
/* Infinite loop /
/ USER CODE BEGIN WHILE */
while (1)
{
texthandleLED(); /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);
/** Initializes the RCC Oscillators according to the specified parameters
/** Initializes the CPU, AHB and APB buses 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();
}
}
/**
/**
/* USER CODE END MX_GPIO_Init_1 */
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOI_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOI, GPIO_PIN_1, GPIO_PIN_RESET);
/*Configure GPIO pin : PI1 */
GPIO_InitStruct.Pin = GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);
/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}
/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef huart)
{
HAL_UART_Transmit(&huart6, (uint8_t)&uartBuffer[uartBufferIndex], 1, HAL_MAX_DELAY);
if (huart->Instance == USART6)
{
if (uartBuffer[uartBufferIndex] == '\r' || uartBuffer[uartBufferIndex] == '\n')
{
if (uartBufferIndex > 0)
{
uartBuffer[uartBufferIndex] = '\0';
processCommand(uartBuffer);
uartBufferIndex = 0;
}
HAL_UART_Transmit(&huart6, (uint8_t*)"\r\n", 2, HAL_MAX_DELAY);
}
else if (uartBufferIndex < UART_BUFFER_SIZE - 1)
{
uartBufferIndex++;
}
else
{
uartBufferIndex = 0;
sendResponse(NACK);
}
HAL_UART_Receive_IT(&huart6, (uint8_t*)&uartBuffer[uartBufferIndex], 1);
}
}
void processCommand(char* command)
{
char* cmd = command;
while (*cmd == ' ') cmd++;
char* end = cmd + strlen(cmd) - 1;
while (end > cmd && *end == ' ') end--;
*(end + 1) = '\0';
if (strcmp(cmd, "ID?") == 0)
{
sendResponse(ACK);
HAL_UART_Transmit(&huart6, (uint8_t*)DEVICE_ID, strlen(DEVICE_ID), HAL_MAX_DELAY);
HAL_UART_Transmit(&huart6, (uint8_t*)"\r\n", 2, HAL_MAX_DELAY);
}
else if (strcmp(cmd, "START") == 0)
{
ledState = LED_STATE_BLINKING;
lastToggleTime = HAL_GetTick();
sendResponse(ACK);
}
else if (strcmp(cmd, "STOP") == 0)
{
ledState = LED_STATE_OFF;
HAL_GPIO_WritePin(GPIOI, GPIO_PIN_1, GPIO_PIN_RESET);
sendResponse(ACK);
}
else if (strncmp(cmd, "PERIOD ", 7) == 0)
{
char* periodStr = cmd + 7;
int period = atoi(periodStr);
textif (period >= MIN_PERIOD && period <= MAX_PERIOD) { ledPeriod = period; sendResponse(ACK); } else { sendResponse(NACK); }
}
else if (strcmp(cmd, "PERIOD?") == 0)
{
char response[20];
sendResponse(ACK);
snprintf(response, sizeof(response), "%lu", ledPeriod);
HAL_UART_Transmit(&huart6, (uint8_t*)response, strlen(response), HAL_MAX_DELAY);
HAL_UART_Transmit(&huart6, (uint8_t*)"\r\n", 2, HAL_MAX_DELAY);
}
else
{
sendResponse(NACK);
}
}
void handleLED(void)
{
if (ledState == LED_STATE_BLINKING)
{
uint32_t currentTime = HAL_GetTick();
if (currentTime - lastToggleTime >= ledPeriod)
{
HAL_GPIO_TogglePin(GPIOI, GPIO_PIN_1);
lastToggleTime = currentTime;
}
}
}
void sendResponse(const char* response)
{
HAL_UART_Transmit(&huart6, (uint8_t*)"\r\n", 2, HAL_MAX_DELAY);
HAL_UART_Transmit(&huart6, (uint8_t*)response, strlen(response), HAL_MAX_DELAY);
}
/* USER CODE END 4 */
/* MPU Configuration */
void MPU_Config(void)
{
MPU_Region_InitTypeDef MPU_InitStruct = {0};
/* Disables the MPU */
HAL_MPU_Disable();
/** Initializes and configures the Region and the memory to be protected
*/
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
MPU_InitStruct.BaseAddress = 0x0;
MPU_InitStruct.Size = MPU_REGION_SIZE_4GB;
MPU_InitStruct.SubRegionDisable = 0x87;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.AccessPermission = MPU_REGION_NO_ACCESS;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/* Enables the MPU */
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}
/**
#ifdef USE_FULL_ASSERT
/**
where the assert_param error has occurred.
Чтобы организовать получение и отправку данных с использованием DMA, необходимо внести изменения в ваш код, чтобы использовать DMA для получения данных через UART и отправки строк через UART. Я предложу изменения, основываясь на информации о DMA, приведённой в лекции.
Вот как можно это сделать:
Добавим переменные и настроим DMA для получения и отправки данных.
c/* DMA handler declaration */ DMA_HandleTypeDef hdma_usart6_rx; DMA_HandleTypeDef hdma_usart6_tx; /* DMA buffer declarations */ #define DMA_RX_BUFFER_SIZE 64 #define DMA_TX_BUFFER_SIZE 64 uint8_t dmaRxBuffer[DMA_RX_BUFFER_SIZE]; uint8_t dmaTxBuffer[DMA_TX_BUFFER_SIZE];
Теперь необходимо инициализировать DMA для передачи данных.
cstatic void MX_DMA_Init(void) { /* DMA controller clock enable */ __HAL_RCC_DMA1_CLK_ENABLE(); /* Configure DMA for USART6_RX */ hdma_usart6_rx.Instance = DMA1_Stream1; hdma_usart6_rx.Init.Channel = DMA_CHANNEL_5; hdma_usart6_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_usart6_rx.Init.PeriphInc = DMA_PINC_DISABLE; hdma_usart6_rx.Init.MemInc = DMA_MINC_ENABLE; hdma_usart6_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; hdma_usart6_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_usart6_rx.Init.Mode = DMA_CIRCULAR; // Циклический режим для приёма hdma_usart6_rx.Init.Priority = DMA_PRIORITY_HIGH; HAL_DMA_Init(&hdma_usart6_rx); /* Link DMA with USART RX */ __HAL_LINKDMA(&huart6, hdmarx, hdma_usart6_rx); /* Configure DMA for USART6_TX */ hdma_usart6_tx.Instance = DMA1_Stream6; hdma_usart6_tx.Init.Channel = DMA_CHANNEL_5; hdma_usart6_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; hdma_usart6_tx.Init.PeriphInc = DMA_PINC_DISABLE; hdma_usart6_tx.Init.MemInc = DMA_MINC_ENABLE; hdma_usart6_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; hdma_usart6_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_usart6_tx.Init.Mode = DMA_NORMAL; hdma_usart6_tx.Init.Priority = DMA_PRIORITY_HIGH; HAL_DMA_Init(&hdma_usart6_tx); /* Link DMA with USART TX */ __HAL_LINKDMA(&huart6, hdmatx, hdma_usart6_tx); }
Теперь настроим UART на использование DMA.
cstatic void MX_USART6_UART_Init(void) { huart6.Instance = USART6; huart6.Init.BaudRate = 115200; huart6.Init.WordLength = UART_WORDLENGTH_8B; huart6.Init.StopBits = UART_STOPBITS_1; huart6.Init.Parity = UART_PARITY_NONE; huart6.Init.Mode = UART_MODE_TX_RX; huart6.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart6.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart6) != HAL_OK) { Error_Handler(); } /* Enable DMA for RX */ HAL_UART_Receive_DMA(&huart6, dmaRxBuffer, DMA_RX_BUFFER_SIZE); }
Необходимо добавить обработчики прерываний для получения и отправки данных через DMA.
c/* DMA RX callback */ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { // После получения данных через DMA можно обработать команду processCommand((char*)dmaRxBuffer); /* Перезапуск получения данных через DMA */ HAL_UART_Receive_DMA(&huart6, dmaRxBuffer, DMA_RX_BUFFER_SIZE); } /* DMA TX callback */ void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) { // Обработчик завершения передачи через DMA } /* DMA error callback */ void HAL_DMA_ErrorCallback(DMA_HandleTypeDef *hdma) { // Обработчик ошибок DMA }
Для отправки данных через DMA, используйте функцию HAL_UART_Transmit_DMA
:
cvoid sendResponse(const char* response) { size_t length = strlen(response); memcpy(dmaTxBuffer, response, length); /* Start DMA transmission */ HAL_UART_Transmit_DMA(&huart6, dmaTxBuffer, length); }
main
:В функции main
добавьте вызов инициализации DMA:
cint main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_USART6_UART_Init(); MX_DMA_Init(); // Инициализация DMA HAL_UART_Transmit(&huart6, (uint8_t*)"Hello everyone! Enter command:\r\n", 32, HAL_MAX_DELAY); HAL_UART_Receive_DMA(&huart6, dmaRxBuffer, DMA_RX_BUFFER_SIZE); // Запуск приема данных через DMA while (1) { handleLED(); } }
Теперь, когда данные будут поступать через UART, они будут автоматически передаваться в буфер с помощью DMA. Аналогично, данные для отправки будут передаваться через UART с использованием DMA.
Эти изменения позволяют улучшить производительность, разгрузив основной процессор от обработки каждого байта данных и передачи.
Укажи конкретно на какие строчки это добавлять, или выведи полную программу с дополнительными строками