如何讓printf語句從指定的端口打印信息,本章節爲你解鎖……
一、直接上代碼說明
我使用的AliOS Things Developer Kit,硬件上使用LPUART1(PB10/PB11)作爲串口輸出。
也可以根據具體情況配置其它UART。
UART_HandleTypeDef hlpuart1;
//初始化串口LPUART1
void MX_LPUART1_UART_Init(void)
{
hlpuart1.Instance = LPUART1;
hlpuart1.Init.BaudRate = 115200;
hlpuart1.Init.WordLength = UART_WORDLENGTH_8B;
hlpuart1.Init.StopBits = UART_STOPBITS_1;
hlpuart1.Init.Parity = UART_PARITY_NONE;
hlpuart1.Init.Mode = UART_MODE_TX_RX;
hlpuart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
//hlpuart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
//hlpuart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&hlpuart1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
//重寫HAL_UART_MspInit
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(uartHandle->Instance==LPUART1)
{
/* USER CODE BEGIN LPUART1_MspInit 0 */
__HAL_RCC_GPIOB_CLK_ENABLE(); //特別注意,我參考的alios thing中代碼,沒有這句,導致串口沒有輸出,這裏添加這句後就OK了
/* USER CODE END LPUART1_MspInit 0 */
/* LPUART1 clock enable */
__HAL_RCC_LPUART1_CLK_ENABLE();
/**LPUART1 GPIO Configuration
PB10 ------> LPUART1_RX
PB11 ------> LPUART1_TX
*/
GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF8_LPUART1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* LPUART1 interrupt Init */
HAL_NVIC_SetPriority(LPUART1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(LPUART1_IRQn);
/* USER CODE BEGIN LPUART1_MspInit 1 */
/* USER CODE END LPUART1_MspInit 1 */
}
}
// 重寫write函數, printf時最終會調用這個函數。這裏類似keil ARMCC中的fputc函數
int _write(int file, char *ptr, int len)
{
int i=0;
for (i = 0; i < len; i++)
{
while (!(LPUART1->ISR & USART_ISR_TXE))
{
}
LPUART1->TDR = ptr[i];
}
return len;
}
// main函數實現
int main(void)
{
HAL_Init();
/* Configure the System clock to have a frequency of 80 MHz */
SystemClock_Config();
/* Add your application code here
*/
MX_LPUART1_UART_Init();
/* Infinite loop */
while (1)
{
printf("Hello world!\n");
fflush(stdout); //如果printf函數最後不添加"\n",信息不會打印出來,所以這裏需要添加這一句
/* Insert delay 500 ms */
HAL_Delay(500);
}
}
// 以下爲系統初始化代碼,保證系統能運行即可,與printf重定向無關,僅供參考
/**
* @brief System Clock Configuration
* The system Clock is configured as follow :
* System Clock source = PLL (MSI)
* SYSCLK(Hz) = 80000000
* HCLK(Hz) = 80000000
* AHB Prescaler = 1
* APB1 Prescaler = 1
* APB2 Prescaler = 1
* MSI Frequency(Hz) = 4000000
* PLL_M = 1
* PLL_N = 40
* PLL_R = 2
* PLL_P = 7
* PLL_Q = 4
* Flash Latency(WS) = 4
* @param None
* @retval None
*/
static void SystemClock_Config(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;
/* MSI is enabled after System reset, activate PLL with MSI as source */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;
RCC_OscInitStruct.PLL.PLLM = 1;
RCC_OscInitStruct.PLL.PLLN = 40;
RCC_OscInitStruct.PLL.PLLR = 2;
RCC_OscInitStruct.PLL.PLLP = 7;
RCC_OscInitStruct.PLL.PLLQ = 4;
if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
/* Initialization Error */
while(1);
}
/* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
clocks dividers */
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
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_4) != HAL_OK)
{
/* Initialization Error */
while(1);
}
}
二、Makefile注意事項
需要用到一些lib。libc.a\libgcc.a等
在使用 arm gcc 編譯鏈接的過程可能會出現錯誤undefined reference to `_sbrk' `_close' `_fstat' `_read' `_write' 。
添加以下鏈接參數:
-std=gun99
--specs=nano.specs //使用靜態庫 libc_nano.a
--specs=nosys.specs //使用靜態庫 libnosys.a
我使用的編譯參數參考如下:
# 使用了編譯優化和硬件浮點數
CFLAGS += -mcpu=$(CPU) -mthumb -Wall
CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
CFLAGS += -Os
CFLAGS += -ffunction-sections -fdata-sections -std=c99
LFLAGS += -mcpu=$(CPU) -mthumb
LFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
LFLAGS += -Wl,--gc-sections
# link libgcc.a libc.a libm.a
LFLAGS += -lgcc -lc -lm --specs=nosys.specs --specs=nano.specs -std=c99
# generate map file
LFLAGS += -Wl,-Map,$(TARGET).map
三、參考文檔
stm32 基於ARM GCC Compliler(EmBitz IDE) print重定向到串口打印輸出 com serial https://blog.csdn.net/daxiebao/article/details/52651891
STM32高級開發(12)-在GCC中使用printf打印串口數據 https://blog.csdn.net/zhengyangliu123/article/details/54966402