简介:
我们在前一篇已经了解了STM32H7S78-DK XIP 工程的运行方式,我们基于此基础上添加串口打印功能,从原理图可以看到,STM32H7S78-DK 的PD0/PD1 UART4引脚连接到STLINK 上并虚拟出一个虚拟串口用于串口打印。
UART 配置
我们使用Cubemux 工具配置uart4 ,在application mode 下配置PTD0/PTD1为串口功能
Cubemux 使能uart 中断,然后生成初始化代码。
在cubemux 上配置好串口会自动初始化好,在此基础上添加如下代码重定向printf函数至uart4,实现底层IO __write 函数通过uart4打印,本地使用的IAR 9.50.2 环境。
/* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #if defined(__ICCARM__) #include <LowLevelIOInterface.h> #endif /* __ICCARM__ */ /* USER CODE END Includes */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ #if defined(__ICCARM__) /* New definition from EWARM V9, compatible with EWARM8 */ int iar_fputc(int ch); #define PUTCHAR_PROTOTYPE int iar_fputc(int ch) #elif defined ( __CC_ARM ) || defined(__ARMCC_VERSION) /* ARM Compiler 5/6*/ #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f) #elif defined(__GNUC__) #define PUTCHAR_PROTOTYPE int __io_putchar(int ch) #endif /* __ICCARM__ */ /* USER CODE END PM */ #if defined(__ICCARM__) size_t __write(int file, unsigned char const *ptr, size_t len) { size_t idx; unsigned char const *pdata = ptr; for (idx = 0; idx < len; idx++) { iar_fputc((int)*pdata); pdata++; } return len; } #endif /* __ICCARM__ */ /** * @brief Retargets the C library printf function to the USART. * @param None * @retval None */ PUTCHAR_PROTOTYPE { /* Place your implementation of fputc here */ /* e.g. write a character to the USART2 and Loop until the end of transmission */ HAL_UART_Transmit(&huart4, (uint8_t *)&ch, 1, 0xFFFF); return ch; } /* USER CODE END 4 */
以上修改后在main函数内添加printf 周期打印 hello world,下载运行后连接STLINK的虚拟串口已经按照预取的能够打印输出。
上述我们已经适配好了串口输出功能,我们在此基础上继续适配串口接收功能,串口我们使用中断接收的方式处理数据,接收到的数据通过ringbuff 来缓存避免应用程序未及时读取数据造成的数据丢失,添加如下代码对接收的数据进行回显。
/* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ void pUART_RxdataCallback(UART_HandleTypeDef *huart) { (void)huart; RingBuffer_Write(&uart_rx,&uartrx,1); HAL_UART_Receive_IT(&huart4, &uartrx, 1); } uint8_t uartgetchar(uint8_t * pdata) { return RingBuffer_Read(&uart_rx,pdata,1); } void ThreadOne_Entry(void) { /* Enable uart2 rx interrupt */ static uint8_t uart_rx_buff[128] = {0}; RingBuffer_Init(&uart_rx,uart_rx_buff,128); HAL_UART_RegisterCallback(&huart4,HAL_UART_RX_COMPLETE_CB_ID,pUART_RxdataCallback); HAL_UART_Receive_IT(&huart4, &uartrx, 1); //littleshell_main_entry(NULL); } /* USER CODE END 0 */ int main(void) { /* USER CODE BEGIN 1 */ MPU_Config(); /* USER CODE END 1 */ /* Enable the CPU Cache */ /* Enable I-Cache---------------------------------------------------------*/ SCB_EnableICache(); /* Enable D-Cache---------------------------------------------------------*/ SCB_EnableDCache(); /* MCU Configuration--------------------------------------------------------*/ /* Update SystemCoreClock variable according to RCC registers values. */ SystemCoreClockUpdate(); /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_UART4_Init(); ThreadOne_Entry(); /* USER CODE BEGIN 2 */ /* Initialize LD1 */ BSP_LED_Init(LD1); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ /* Toggle LD1 every 250ms */ BSP_LED_Toggle(LD1); HAL_Delay(250); uint8_t ch; if(uartgetchar(&ch)) { printf("%c\r\n",ch); } //printf("hello world.\r\n"); } /* USER CODE END 3 */ }
下载到板卡里验证已经按照预期的将接收到的数据进行回显,说明串口的收发功能都已经是ok的了,串口的收发都是适配完毕了,我们可以在此基础上添加shell 功能和板子交互。