【方法】STM32F103C8单片机在Keil 5环境下使用C++编写程序,并将printf和cout重定向到串口
发布日期:2021-06-29 10:16:54 浏览次数:4 分类:技术文章

本文共 6142 字,大约阅读时间需要 20 分钟。

程序下载地址:(提取码:s7d6)

首先,用pragma指令禁用半主机模式,防止调用printf就出现HardFault。然后在std命名空间中重写fgetc、fputc、fclose、fseek和fflush函数,还要重写__stdin、__stdout和__stderr这三个全局变量。

_sys_exit和_ttywrch也要重写,前者是main函数返回后调用的函数,_ttywrch是出现错误时往串口打印字符的函数。

_sys_exit函数不允许返回,必须以无限循环结尾。

另外,工程属性里面不要勾选Use MicroLIB,这个选项和C++是不兼容的!!即使使用C语言,。

【cout.cpp】

#include 
#include
#include "common.hpp"#pragma import(__use_no_semihosting) // 禁用半主机模式// 请不要勾选Use MicroLib#ifdef __MICROLIB#error "Please do not use MicroLib!"#endifextern "C"{ void _sys_exit(int returncode) { printf("Exited! returncode=%d\n", returncode); while (1); } void _ttywrch(int ch) { if (ch == '\n') HAL_UART_Transmit(&huart1, (uint8_t *)"\r\n", 2, HAL_MAX_DELAY); else HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY); }}namespace std{ struct __FILE { int handle; /* Whatever you require here. If the only file you are using is */ /* standard output using printf() for debugging, no file handling */ /* is required. */ }; FILE __stdin = {0}; FILE __stdout = {1}; FILE __stderr = {2}; int fgetc(FILE *stream) { int c = 0; if (stream->handle == 0) { while (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE) == RESET); HAL_UART_Receive(&huart1, (uint8_t *)&c, 1, HAL_MAX_DELAY); _ttywrch((c == '\r') ? '\n' : c); // 回显 return c; } return EOF; } int fputc(int c, FILE *stream) { if (stream->handle == 1 || stream->handle == 2) { _ttywrch(c); return c; } return EOF; } int fclose(FILE * stream) { return 0; } int fseek(FILE *stream, long int offset, int whence) { return -1; } int fflush(FILE *stream) { if (stream->handle == 1 || stream->handle == 2) while (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_TC) == RESET); return 0; }}

另外,启动文件startup_stm32f103xb.s中默认分配的堆空间太小,必须要改大,否则将无法进入main函数。如果程序运行过程中出现HardFault,说明堆空间仍然不够,还需要继续改大。

Heap_Size       EQU     0x0001000

 

以下是测试代码:

【main.cpp】

#include 
#include
#include
#include
#include
#include "common.hpp"using namespace std;// 类class Test{ private: int num; public: Test(int num) : num(num) {} void display(void) { cout << "num=" << num << endl; }};// 函数模板template
static void further_test(T a){ cout << "[" << typeid(a).name() << "] a=" << a << endl;}// 字符串替换static void str_replace(string search, string replace, string &subject){ string::size_type pos = 0; for (pos = 0; (pos = subject.find(search, pos)) != string::npos; pos += replace.length()) subject.replace(pos, search.length(), replace);}static void further_test(void){ // string字符串 string str = "this is"; str.append(" a string"); str_replace("is", "[IS]", str); cout << str << " len=" << str.length() << endl; // vector容器 vector
items; vector
::iterator iter; items.push_back("fooo"); items.push_back("bar"); items.push_back("welcome"); cout << "size=" << items.size() << endl; for (iter = items.begin(); iter != items.end(); ++iter) cout << *iter << " "; cout << endl; // new和delete运算符 int i; int n = items.size(); int *arr = new int[n]; for (i = 0; i < n; i++) arr[i] = items.at(i).length(); for (i = 0; i < n; i++) cout << arr[i] << " "; cout << endl; delete[] arr; // 类 Test t = 50; t.display(); // 引用 Test &u = t; u.display(); // scanf输入 printf("Please input: "); scanf("%d", &n); printf("2n=%d\n", 2 * n); // cin输入 cout << "Please input: "; cin >> n; cout << "3n=" << 3 * n << endl;}// s文件中的Heap_Size必须改大,不能采用默认值,否则进不了main函数// 如果出现Hard Error, 则说明还需要继续改大int main(void){ HAL_Init(); clock_init(); usart_init(115200); printf("STM32F103C8 printf\n"); printf("SystemCoreClock=%u\n", SystemCoreClock); cout << "STM32F103C8 cout" << endl; cout << "SystemCoreClock=" << SystemCoreClock << endl; // 函数重载 further_test(15); further_test("this"); further_test(); return 0;}

【common.cpp】

#include 
#include
#include "common.hpp"UART_HandleTypeDef huart1;extern "C"{#ifdef USE_FULL_ASSERT // HAL库参数错误警告 void assert_failed(uint8_t *file, uint32_t line) { printf("%s: file %s on line %d\n", __FUNCTION__, file, line); while (1); }#endif void HardFault_Handler(void) { printf("Hard Error!\n"); while (1); } void SysTick_Handler(void) { HAL_IncTick(); }}// 配置系统和总线时钟void clock_init(void){ HAL_StatusTypeDef status; RCC_ClkInitTypeDef clk = {0}; RCC_OscInitTypeDef osc = {0}; // 外部晶振为8MHz, 配置PLL倍频器倍频9倍后是72MHz osc.OscillatorType = RCC_OSCILLATORTYPE_HSE; osc.HSEState = RCC_HSE_ON; osc.PLL.PLLMUL = RCC_PLL_MUL9; osc.PLL.PLLSource = RCC_PLLSOURCE_HSE; osc.PLL.PLLState = RCC_PLL_ON; status = HAL_RCC_OscConfig(&osc); // 如果外部晶振启动失败, 则改用内部的8MHz晶振, 经过2分频后倍频16倍, 变成64MHz if (status != HAL_OK) { osc.HSEState = RCC_HSE_OFF; osc.PLL.PLLMUL = RCC_PLL_MUL16; osc.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2; HAL_RCC_OscConfig(&osc); } // ADC时钟不能超过14MHz, 所以需要6分频, 72MHz经过分频后是12MHz __HAL_RCC_ADC_CONFIG(RCC_ADCPCLK2_DIV6); // 配置AHB和APB2总线时钟为72MHz, APB1总线时钟为36MHz clk.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; clk.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; clk.AHBCLKDivider = RCC_SYSCLK_DIV1; clk.APB1CLKDivider = RCC_HCLK_DIV2; clk.APB2CLKDivider = RCC_HCLK_DIV1; HAL_RCC_ClockConfig(&clk, FLASH_LATENCY_2);}void usart_init(int baud_rate){ GPIO_InitTypeDef gpio = {0}; __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_USART1_CLK_ENABLE(); gpio.Mode = GPIO_MODE_AF_PP; gpio.Pin = GPIO_PIN_9; gpio.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA, &gpio); huart1.Instance = USART1; huart1.Init.BaudRate = baud_rate; huart1.Init.Mode = UART_MODE_TX_RX; HAL_UART_Init(&huart1);}

【common.hpp】

#ifndef __COMMON_H#define __COMMON_H#ifdef HAL_UART_MODULE_ENABLEDextern UART_HandleTypeDef huart1;#endifvoid clock_init(void);void usart_init(int baud_rate);#endif

程序运行结果:

STM32F103C8 printfSystemCoreClock=72000000STM32F103C8 coutSystemCoreClock=72000000[i] a=15[PKc] a=thisth[IS] [IS] a string len=20size=3fooo bar welcome4 3 7num=50num=50Please input: 1232n=246Please input: -4563n=-1368Exited! returncode=0

 

转载地址:https://blog.csdn.net/ZLK1214/article/details/104763870 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:【STemWin】STM32F429IG单片机用LTDC驱动正点原子7寸RGB彩色触摸屏,并裸机移植STemWin图形库
下一篇:【解决方案】STM32L152单片机驱动段码LCD屏,执行HAL_LCD_Init函数失败返回HAL_TIMEOUT,长时间卡在LCD_FLAG_RDY的while循环里面的解决办法

发表评论

最新留言

逛到本站,mark一下
[***.202.152.39]2024年05月01日 08时12分22秒