在使用STM32过程中,可能会因为没有定义好调试工具的连接管脚,例如JTAG和SW需要的管脚被程序重新初始化复用了,然后就没法调试变砖了,此时可以通过ISP的方式擦写flash,或者跳线重启,进入BootLoader模式用JLink下载新的程序或直接擦除MCU的flash,再把跳线改回来重启。
通过串口printf打印输出,添加C语言标准库文件:
#include "stdio.h"
根据编译器定义改写相关函数
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
根据自己的串口收发改写相应的函数:
int fputc(int ch, FILE *f)
{
USART1->DR=(uint8_t)ch;
while((USART1->SR&0X40)==0);
return ch;
}
int fputc(int ch, FILE *f)
{
Write_Usart1_C((uint8_t) ch);
return(ch);
}
int fgetc(FILE *f)
{
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
return (USART_ReceiveData(USART1));
}
}
如果使用HAL库:
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1 ,(uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
然后就可以使用C语言的标准输出:printf(" test good! \n");
在C99中printf原型:
int __cdecl printf(const char * __restrict__ _Format,...)
在使用标准库和C99环境下,单纯改写fputc还不行,还需要:
struct __FILE { int handle; /* Add whatever you need here */ };
FILE __stdout;
FILE __stdin;
缺少这个定义,编译会通过,但在程序跑起来调用printf()会直接死机,可能的原因是程序中有操作或定义过FILE指向,printf无法接受一个指向FILE的正确指针对象。修改后,应用中没有加#pragma import(__use_no_semihosting)也可以跑起来。
在STM32中,初始化TX输出模式:
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;