printf配置
在usart.c相应位置添加以下程序
/* USER CODE BEGIN 0 */
#include <stdio.h>
#include <string.h>
/* USER CODE END 0 */
/* USER CODE BEGIN 1 */
#ifdef __GNUC__
//#if 0
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
/*******************************************************************************
* Function Name : PUTCHAR_PROTOTYPE
* Description : Retargets the C library printf function to the USART.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
// fflush(stdout);
return ch;
}
/* USER CODE END 1 */
在使用时后面必须添加\r\n
否则有可能打印不出来。
printf("printf test\r\n");
1 PlatformIO + Vscode
创建一个文件夹
用CubeMX新建工程,makefile输出
拖入platform.ini文件
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[platformio]
src_dir = Core/Src
[env:genericSTM32F103ZE]
platform = ststm32
board = genericSTM32F103ZE
; framework = stm32cube
monitor_speed = 115200
upload_protocol = cmsis-dap ; 使用cmsis-dap烧写代码
debug_tool = cmsis-dap ; 使用cmsis-dap进行在线调试
; 表示使用项目目录下的链接文件
board_build.ldscript = STM32F103ZETx_FLASH.ld
; 表示使用项目目录下的HAL库
build_flags =
; -DUSE_HAL_DRIVER
; -DSTM32F103xE
-Wl,-u_printf_float
-Wl,-u_scanf_float
-ICore/Inc
-IDrivers/CMSIS/Include
-IDrivers/CMSIS/Device/ST/STM32F1xx/Include
-IDrivers/STM32F1xx_HAL_Driver/Inc
-IDrivers/STM32F1xx_HAL_Driver/Inc/Legacy
-IMiddlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS
-IMiddlewares/Third_Party/FreeRTOS/Source/include
-IMiddlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM3
; 表示使用src_dir目录下的HAL库
src_filter =
+<./>
+<../../Middlewares/>
+<../../startup_stm32f103xe.s>
+<../../Drivers/>
在core/src中添加syscalls.c
/* Support files for GNU libc. Files in the system namespace go here.
Files in the C namespace (ie those that do not start with an
underscore) go in .c. */
//#include <_ansi.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include <sys/times.h>
#include <errno.h>
//#include <reent.h>
#include <unistd.h>
#include <sys/wait.h>
#undef errno
extern int errno;
#define MAX_STACK_SIZE 0x2000
extern int __io_putchar(int ch) __attribute__((weak));
extern int __io_getchar(void) __attribute__((weak));
#ifndef FreeRTOS
register char *stack_ptr asm("sp");
#endif
caddr_t _sbrk(int incr) {
extern char end asm("end");
static char *heap_end;
char *prev_heap_end;
// char *min_stack_ptr;
if (heap_end == 0) {
heap_end = &end;
}
prev_heap_end = heap_end;
#ifdef FreeRTOS
/* Use the NVIC offset register to locate the main stack pointer. */
min_stack_ptr = (char *)(*(unsigned int *)*(unsigned int *)0xE000ED08);
/* Locate the STACK bottom address */
min_stack_ptr -= MAX_STACK_SIZE;
if (heap_end + incr > min_stack_ptr)
#else
if (heap_end + incr > stack_ptr)
#endif
{
// write(1, "Heap and stack collision\n", 25);
// abort();
errno = ENOMEM;
return (caddr_t)-1;
}
heap_end += incr;
return (caddr_t)prev_heap_end;
}
/*
* _gettimeofday primitive (Stub function)
* */
int _gettimeofday(struct timeval *tp, struct timezone *tzp) {
/* Return fixed data for the timezone. */
if (tzp) {
tzp->tz_minuteswest = 0;
tzp->tz_dsttime = 0;
}
return 0;
}
void initialise_monitor_handles();
int _getpid(void) {
return 1;
}
int _kill(int pid, int sig) {
errno = EINVAL;
return -1;
}
void _exit(int status) {
_kill(status, -1);
while (1);
}
int _write(int file, char *ptr, int len) {
int DataIdx;
for (DataIdx = 0; DataIdx < len; DataIdx++) {
__io_putchar(*ptr++);
}
return len;
}
int _close(int file) {
return -1;
}
int _fstat(int file, struct stat *st) {
st->st_mode = S_IFCHR;
return 0;
}
int _isatty(int file) {
return 1;
}
int _lseek(int file, int ptr, int dir) {
return 0;
}
int _read(int file, char *ptr, int len) {
int DataIdx;
for (DataIdx = 0; DataIdx < len; DataIdx++) {
*ptr++ = __io_getchar();
}
return len;
}
int _open(char *path, int flags, ...) {
/* Pretend like we always fail */
return -1;
}
int _wait(int *status) {
errno = ECHILD;
return -1;
}
int _unlink(char *name) {
errno = ENOENT;
return -1;
}
int _times(struct tms *buf) {
return -1;
}
int _stat(char *file, struct stat *st) {
st->st_mode = S_IFCHR;
return 0;
}
int _link(char *old, char *new) {
errno = EMLINK;
return -1;
}
int _fork(void) {
errno = EAGAIN;
return -1;
}
int _execve(char *name, char **argv, char **env) {
errno = ENOMEM;
return -1;
}
2 Keil + Vscode + Keil Assistant
用vscode打开工程MDK-ARM文件
在生成的c_cpp_properties.json文件中添加keil的安装路径
"{自己keil的安装路径}\\Keil_v5\\ARM\\ARMCC\\include",
"{自己keil的安装路径}\\Keil_v5\\ARM\\ARMCC\\include\\rw",
按键库推荐
在stm32可以使用multibutton
使用方法
在arduino可以使用onebutton
日志调试
esp可以用esp-hal-log.h
stm32可以用easylog