起由:
在一个已有工程里合入移植来的应用文件,里面的函数调用就导致main初始化不通过,原已有工程是可以正常运行。
调试步骤:
在新移植的文件,增加一个空函数void test_app(){},放在main硬件初始化之后
int main(void){
Init_All_Periph();
test_app();
Relay11Close();
Relay12Open();;
while(1)
{
}
}
重新上电仍不能打开后面继电器,但在调试模式下多点击几次F5能跑到Relay11Close()
把void test_app(){}放在原有工程已有的一个.c文件里,程序是可以正常运行
重点检查新增的那个文件代码,发现代码里有printf,因此检查fputc重定向是否有,发现原有工程没定义,补上重定义
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE
{
int handle;
};
FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
_sys_exit(int x)
{
x = x;
}
//重定义fputc函数
int fputc(int ch, FILE *f)
{
USART_ClearFlag(USART2,USART_FLAG_TC);
USART2->DR = (u8) ch;
while(USART_GetFlagStatus(USART2, USART_FLAG_TC)==RESET);
return ch;
}
void _ttywrch(int ch){}
再次把void test_app(){}放在含有printf新增的.c,main里可正常调用test_app()
原理分析:
mdk中用printf,需要同时定义fputc函数和避免使用semihosting(半主机模式),标准库函数的默认输出设备是显示器,要实现在串口或lcd输出,必须重定义标准库函数里调用的与输出设备相关的函数。
因printf之类的函数,使用了半主机模式,使用标准库会导致程序无法运行,解决办法
使用微库,因为使用微库的话,不会使用半主机模式
仍然使用标准库,在主程序添加上面那段的代码