Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 
 
 

422 строки
11 KiB

  1. /* USER CODE BEGIN Header */
  2. /**
  3. ******************************************************************************
  4. * @file : main.c
  5. * @brief : Main program body
  6. ******************************************************************************
  7. * @attention
  8. *
  9. * Copyright (c) 2026 STMicroelectronics.
  10. * All rights reserved.
  11. *
  12. * This software is licensed under terms that can be found in the LICENSE file
  13. * in the root directory of this software component.
  14. * If no LICENSE file comes with this software, it is provided AS-IS.
  15. *
  16. ******************************************************************************
  17. */
  18. /* USER CODE END Header */
  19. /* Includes ------------------------------------------------------------------*/
  20. #include "main.h"
  21. #include "usb_device.h"
  22. /* Private includes ----------------------------------------------------------*/
  23. /* USER CODE BEGIN Includes */
  24. #include "ucos_ii.h"
  25. #include "modbus_rtu_slave.h"
  26. #include "stdio.h"
  27. /* USER CODE END Includes */
  28. /* Private typedef -----------------------------------------------------------*/
  29. /* USER CODE BEGIN PTD */
  30. /* USER CODE END PTD */
  31. /* Private define ------------------------------------------------------------*/
  32. /* USER CODE BEGIN PD */
  33. /* USER CODE END PD */
  34. /* Private macro -------------------------------------------------------------*/
  35. /* USER CODE BEGIN PM */
  36. /* USER CODE END PM */
  37. /* Private variables ---------------------------------------------------------*/
  38. UART_HandleTypeDef huart1;
  39. DMA_HandleTypeDef hdma_usart1_rx;
  40. DMA_HandleTypeDef hdma_usart1_tx;
  41. /* USER CODE BEGIN PV */
  42. static OS_STK AppTaskStartStk[APP_TASK_START_STK_SIZE];
  43. /* USER CODE END PV */
  44. /* Private function prototypes -----------------------------------------------*/
  45. void SystemClock_Config(void);
  46. static HAL_StatusTypeDef BackupSramInit(void);
  47. static void MX_GPIO_Init(void);
  48. static void MX_DMA_Init(void);
  49. static void MX_USART1_UART_Init(void);
  50. /* USER CODE BEGIN PFP */
  51. static void AppTaskStart(void *p_arg);
  52. /* USER CODE END PFP */
  53. /* Private user code ---------------------------------------------------------*/
  54. /* USER CODE BEGIN 0 */
  55. static void AppTaskStart(void *p_arg)
  56. {
  57. (void)p_arg;
  58. /*
  59. * F4作为Modbus RTU从站,触摸屏作为主站。
  60. * 初始化函数会立即启动USART1的DMA空闲接收。
  61. */
  62. ModbusSlaveInit(&huart1, MODBUS_SLAVE_DEFAULT_ADDRESS);
  63. ModbusRetainedRegistersLoad();
  64. while (1)
  65. {
  66. /*
  67. * 维护几个供触摸屏首次联调读取的保持寄存器:
  68. * 4x地址0:器件标识0xF407;
  69. * 4x地址1:系统运行秒数;
  70. * 4x地址2:收到的有效Modbus帧数;
  71. * 4x地址10:触摸屏读写测试值,由协议层保存。
  72. */
  73. (void)ModbusSlaveSetHoldingRegister(//OS时钟
  74. HMI_REG_UPTIME_SECONDS,
  75. (uint16_t)(OSTimeGet() / OS_TICKS_PER_SEC));
  76. (void)ModbusSlaveSetHoldingRegister(//有效帧计数
  77. HMI_REG_RX_FRAME_COUNT,
  78. (uint16_t)ModbusSlaveStatistics.validFrameCount);
  79. (void)ModbusSlaveSetHoldingRegister(//从站地址不匹配计数
  80. 3,
  81. (uint16_t)ModbusSlaveStatistics.ignoredAddressCount);
  82. (void)ModbusSlaveSetHoldingRegister(//非法功能码计数
  83. 4,
  84. (uint16_t)ModbusSlaveStatistics.illegalFunctionCount);
  85. (void)ModbusSlaveSetHoldingRegister(//非法地址计数
  86. 5,
  87. (uint16_t)ModbusSlaveStatistics.illegalAddressCount);
  88. (void)ModbusSlaveSetHoldingRegister(//非法数据值计数
  89. 6,
  90. (uint16_t)ModbusSlaveStatistics.illegalValueCount);
  91. HistorySaveToRegisters();
  92. /*
  93. * 协议解析和应答在任务上下文完成,中断只接收一帧并设置标志。
  94. * 每1ms轮询一次,不在串口中断中执行耗时的CRC和寄存器操作。
  95. */
  96. ModbusSlavePoll();
  97. ModbusRetainedRegistersPoll();
  98. // printf("123");
  99. OSTimeDly(1U);
  100. }
  101. }
  102. /* USER CODE END 0 */
  103. /**
  104. * @brief The application entry point.
  105. * @retval int
  106. */
  107. int main(void)
  108. {
  109. /* USER CODE BEGIN 1 */
  110. /* USER CODE END 1 */
  111. /* MCU Configuration--------------------------------------------------------*/
  112. /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  113. HAL_Init();
  114. /* USER CODE BEGIN Init */
  115. /* USER CODE END Init */
  116. /* Configure the system clock */
  117. SystemClock_Config();
  118. /* USER CODE BEGIN SysInit */
  119. /* USER CODE END SysInit */
  120. /* Initialize all configured peripherals */
  121. MX_GPIO_Init();
  122. MX_DMA_Init();
  123. MX_USB_DEVICE_Init();
  124. MX_USART1_UART_Init();
  125. BackupSramInit();
  126. /* USER CODE BEGIN 2 */
  127. /* uC/OS-II接口通常用返回错误码的方式报告执行结果。 */
  128. INT8U os_err;
  129. /*
  130. * 初始化内核的任务表、就绪表、事件控制块等内部数据。
  131. * OSInit()只完成初始化,此时任务调度尚未开始。
  132. */
  133. OSInit();
  134. /*
  135. * 创建应用启动任务,各参数依次为:
  136. * 1. 任务入口函数;
  137. * 2. 传给任务的参数(当前不需要,所以为0);
  138. * 3. 初始栈顶地址;
  139. * 4. 任务优先级,数值越小优先级越高;
  140. * 5. 任务ID,本工程暂时与优先级取相同值;
  141. * 6. 栈底地址;
  142. * 7. 栈容量,单位是OS_STK元素而不是字节;
  143. * 8. 用户扩展指针(当前不用);
  144. * 9. 创建选项:允许栈检查并在创建时清零任务栈。
  145. */
  146. os_err = OSTaskCreateExt(AppTaskStart,
  147. 0,
  148. &AppTaskStartStk[APP_TASK_START_STK_SIZE - 1u],
  149. APP_TASK_START_PRIO,
  150. APP_TASK_START_PRIO,
  151. &AppTaskStartStk[0],
  152. APP_TASK_START_STK_SIZE,
  153. 0,
  154. (OS_TASK_OPT_STK_CHK |
  155. OS_TASK_OPT_STK_CLR));
  156. if (os_err != OS_ERR_NONE)
  157. {
  158. Error_Handler();
  159. }
  160. /*
  161. * 启动抢占式调度,内核会运行当前最高优先级的就绪任务。
  162. * OSStart()成功后不会返回,后面的裸机while循环不会再被执行。
  163. */
  164. OSStart();
  165. /* USER CODE END 2 */
  166. /* Infinite loop */
  167. /* USER CODE BEGIN WHILE */
  168. while (1)
  169. {
  170. /* USER CODE END WHILE */
  171. /* USER CODE BEGIN 3 */
  172. }
  173. /* USER CODE END 3 */
  174. }
  175. static HAL_StatusTypeDef BackupSramInit(void)
  176. {
  177. HAL_PWR_EnableBkUpAccess();
  178. __HAL_RCC_BKPSRAM_CLK_ENABLE();
  179. return HAL_PWREx_EnableBkUpReg();
  180. }
  181. /**
  182. * @brief System Clock Configuration
  183. * @retval None
  184. */
  185. void SystemClock_Config(void)
  186. {
  187. RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  188. RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  189. /** Configure the main internal regulator output voltage
  190. */
  191. __HAL_RCC_PWR_CLK_ENABLE();
  192. __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  193. /** Initializes the RCC Oscillators according to the specified parameters
  194. * in the RCC_OscInitTypeDef structure.
  195. */
  196. RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  197. RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  198. RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  199. RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  200. RCC_OscInitStruct.PLL.PLLM = 12;
  201. RCC_OscInitStruct.PLL.PLLN = 336;
  202. RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  203. RCC_OscInitStruct.PLL.PLLQ = 7;
  204. if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  205. {
  206. Error_Handler();
  207. }
  208. /** Initializes the CPU, AHB and APB buses clocks
  209. */
  210. RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
  211. |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  212. RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  213. RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  214. RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  215. RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
  216. if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
  217. {
  218. Error_Handler();
  219. }
  220. /** Enables the Clock Security System
  221. */
  222. HAL_RCC_EnableCSS();
  223. }
  224. /**
  225. * @brief USART1 Initialization Function
  226. * @param None
  227. * @retval None
  228. */
  229. static void MX_USART1_UART_Init(void)
  230. {
  231. /* USER CODE BEGIN USART1_Init 0 */
  232. /* USER CODE END USART1_Init 0 */
  233. /* USER CODE BEGIN USART1_Init 1 */
  234. /* USER CODE END USART1_Init 1 */
  235. huart1.Instance = USART1;
  236. huart1.Init.BaudRate = 115200;
  237. huart1.Init.WordLength = UART_WORDLENGTH_9B;
  238. huart1.Init.StopBits = UART_STOPBITS_1;
  239. huart1.Init.Parity = UART_PARITY_EVEN;
  240. huart1.Init.Mode = UART_MODE_TX_RX;
  241. huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  242. huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  243. if (HAL_UART_Init(&huart1) != HAL_OK)
  244. {
  245. Error_Handler();
  246. }
  247. /* USER CODE BEGIN USART1_Init 2 */
  248. /* USER CODE END USART1_Init 2 */
  249. }
  250. /**
  251. * Enable DMA controller clock
  252. */
  253. static void MX_DMA_Init(void)
  254. {
  255. /* DMA controller clock enable */
  256. __HAL_RCC_DMA2_CLK_ENABLE();
  257. /* DMA interrupt init */
  258. /* DMA2_Stream2_IRQn interrupt configuration */
  259. HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 5, 0);
  260. HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn);
  261. /* DMA2_Stream7_IRQn interrupt configuration */
  262. HAL_NVIC_SetPriority(DMA2_Stream7_IRQn, 5, 0);
  263. HAL_NVIC_EnableIRQ(DMA2_Stream7_IRQn);
  264. }
  265. /**
  266. * @brief GPIO Initialization Function
  267. * @param None
  268. * @retval None
  269. */
  270. static void MX_GPIO_Init(void)
  271. {
  272. /* USER CODE BEGIN MX_GPIO_Init_1 */
  273. /* USER CODE END MX_GPIO_Init_1 */
  274. /* GPIO Ports Clock Enable */
  275. __HAL_RCC_GPIOH_CLK_ENABLE();
  276. __HAL_RCC_GPIOA_CLK_ENABLE();
  277. /* USER CODE BEGIN MX_GPIO_Init_2 */
  278. /* USER CODE END MX_GPIO_Init_2 */
  279. }
  280. /* USER CODE BEGIN 4 */
  281. void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
  282. {
  283. if (huart->Instance == USART1)
  284. {
  285. /* 应答发送完成后,协议模块重新启动DMA接收。 */
  286. ModbusSlaveOnTxComplete(huart);
  287. }
  288. }
  289. void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
  290. {
  291. if (huart->Instance == USART1)
  292. {
  293. /*
  294. * DMA遇到串口空闲事件后进入这里。
  295. * 仅复制帧并重启DMA
  296. */
  297. ModbusSlaveOnRxEvent(huart, Size);
  298. }
  299. }
  300. void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
  301. {
  302. if (huart->Instance == USART1)
  303. {
  304. /* 溢出、噪声、帧错误等异常后恢复USART1 DMA接收。 */
  305. ModbusSlaveOnUartError(huart);
  306. }
  307. }
  308. /* USER CODE END 4 */
  309. /**
  310. * @brief This function is executed in case of error occurrence.
  311. * @retval None
  312. */
  313. void Error_Handler(void)
  314. {
  315. /* USER CODE BEGIN Error_Handler_Debug */
  316. /* User can add his own implementation to report the HAL error return state */
  317. __disable_irq();
  318. while (1)
  319. {
  320. }
  321. /* USER CODE END Error_Handler_Debug */
  322. }
  323. #ifdef USE_FULL_ASSERT
  324. /**
  325. * @brief Reports the name of the source file and the source line number
  326. * where the assert_param error has occurred.
  327. * @param file: pointer to the source file name
  328. * @param line: assert_param error line source number
  329. * @retval None
  330. */
  331. void assert_failed(uint8_t *file, uint32_t line)
  332. {
  333. /* USER CODE BEGIN 6 */
  334. /* User can add his own implementation to report the file name and line number,
  335. ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  336. /* USER CODE END 6 */
  337. }
  338. #endif /* USE_FULL_ASSERT */