1、能不能解释一下下面程序是什么意思啊拜托了,小弟很急的
是关于I/O的重定义
2、如何使用STM32F107的串口4
你的重定向有点问题啊,用下面这个吧,我发一个串口的文件给你,你打开看看,上面的四个串口都是同时在运行的
有什么不明的看一下上传的文件,如果还有问题再交流
重定向程序
#if 1
//可以在这里写
//#define USARTx 为哪个串口,我用的方法是,当用到哪个串口时,就把哪个串口赋给USARTx
//例如要用到串口4,那就写成
//USARTx =UART4 ;
//不过你得先定义一下USARTx 这个变量,定义为32位的,因为UART4是指向一个32位的地址的,上面的赋值只是把
//UART4指向的地址赋给USARTx 而已,其它串口的使用也是一样的
#pragma import(__use_no_semihosting)
/******************************************************************************
*标准库需要的支持函数
******************************************************************************/
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 is typedef’ d in stdio.h. */
FILE __stdout;
/// <summary>
/// 定义_sys_exit()以避免使用半主机模式
/// </summary>
/// <param name="x"></param>
/// <returns></returns>
_sys_exit(int x)
{
x = x;
}
int fputc(int ch, FILE *f)
{
USARTx->DR = (u8) ch;
/* Loop until the end of transmission */
while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET)
{
}
return ch;
}
/*******************************************************************************
* 函数名 :fgetc
* 输 入 :
* 输 出 :
* 功能说明 :
* 重定义getc函数,这样可以使用scanff函数从串口1输入数据
*******************************************************************************/
int fgetc(FILE *f)
{
/* 等待串口1输入数据 */
while (USART_GetFlagStatus(USARTx, USART_FLAG_RXNE) == RESET);
return (int)USART_ReceiveData(USARTx);
}
#endif
3、怎么解决STM32中不能使用printf函数的问题
简单地说:想在mdk 中用printf,需要同时重定义fputc函数和避免使用semihosting(半主机模式),
标准库函数的默认输出设备是显示器,要实现在串口或LCD输出,必须重定义标准库函数里调用的与输出设备相关的函数.
例如:printf输出到串口,需要将fputc里面的输出指向串口(重定向),方法如下:
#ifdef __GNUC__
/* 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__ */
PUTCHAR_PROTOTYPE
{
/* Place your implementation of fputc here */
/* e.g. write a character to the USART */
USART_SendData(USART1, (uint8_t) ch);
/* Loop until the end of transmission */
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
return ch;
}
因printf()之类的函数,使用了半主机模式。使用标准库会导致程序无法运行,以下是解决方法:
方法1.使用微库,因为使用微库的话,不会使用半主机模式.
方法2.仍然使用标准库,在主程序添加下面代码:
#pragma import(__use_no_semihosting)
_sys_exit(int x)
{
x = x;
}
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 is typedef’ d in stdio.h. */
FILE __stdout;
如果使用的是MDK,请在工程属性的“Target“-》”Code Generation“中勾选”Use MicroLIB;今天参考了一下论坛,使用微库可以很好的解决这个问题。
2.另一种方法:(其实大同小异)
需要添加以下代码
(论坛里应该有完整介绍这个的帖子,但是我没搜到,也许是沉了。)
#pragma import(__use_no_semihosting)
/******************************************************************************
*标准库需要的支持函数
******************************************************************************/
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 is typedef’ d in stdio.h. */
FILE __stdout;
/// <summary>
/// 定义_sys_exit()以避免使用半主机模式
/// </summary>
/// <param name="x"></param>
/// <returns></returns>
_sys_exit(int x)
{
x = x;
}
int fputc(int ch, FILE *f)
{
//USART_SendData(USART1, (u8) ch);
USART1->DR = (u8) ch;
/* Loop until the end of transmission */
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)
{
}
return ch;
}
semihosting的作用,介绍如下
Semihosting is a mechanism for ARM targets to communicate input/output requests
from application code to a host computer running a debugger. This mechanism could be
used, for example, to allow functions in the C library, such as printf() and scanf(), to use the screen and keyboard of the host rather than having a screen and keyboard on the target system.
This is useful because development hardware often does not have all the input and
output facilities of the final system. Semihosting allows the host computer to provide these facilities.
Semihosting is implemented by a set of defined software interrupt (SWI) operations.
The application invokes the appropriate SWI and the debug agent then handles the SWI
exception. The debug agent provides the required communication with the host.
In many cases, the semihosting SWI will be invoked by code within library functions. The application can also invoke the semihosting SWI directly. Refer to the C library descriptions in the ADS Compilers and Libraries Guide for more information on support for semihosting in the ARM C library.
按我的理解,这个模式是用来调试的,通过仿真器,使用主机的输入输出代替单片机自己的,也就是说即便单片机没有输出口也能printf到电脑上。反过来,由于这个模式更改了printf()等的实现方式,输入输出就不走单片机的外设了,所以只重定义fputc不起作用。
用代码关闭此模式后,需要同时更新一下__stdout 和__stdin 的定义,所以有后面的语句。
以上仅为个人理解,如有错误请指正。
另外,勾选microlib之后,也许编译的时候就不把开启semihosting的文件包进去了,所以没事。
C库函数重定向:
用户能定义自己的C语言库函数,连接器在连接时自动使用这些新的功能函数。这个过程叫做重定向C语言库函数,如下图所示。
举例来说,用户有一个I/O设备(如UART)。本来库函数fputc()是把字符输出到调试器控制窗口中去的,但用户把输出设备改成了UART端口,这样一来,所有基于fputc()函数的printf()系列函数输出都被重定向到UART端口上去了。
下面是实现fputc()重定向的一个例子:
externvoidsendchar(char*ch);
intfputc(intch,FILE*f)
{/*e.g.writeacharactertoanUART*/
chartempch=ch;
sendchar(&tempch);
returnch;
}
这个例子简单地将输入字符重新定向到另一个函数sendchar(),sendchar()假定是个另外定义的串口输出函数。在这里,fputc()就似乎目标硬件和标准C库函数之间的一个抽象层。
4、STM32调试求助,无法进入main函数
昨天调试STM32程序,以前使用的是MDK3.40的版本,把版本升了下级,升到了MDK4.10,装好后,一运行,哈哈,新版本给人的感觉就是不一样啊,很爽,较之前有很多改进,把自己以前的程序打开,编译运行发现程序调试时无法进入Main函数,弄了很久,很是郁闷啊,最后还是在ourdev的坛子里,找到了同样问题的解决方法, 以下是坛子里面的帖子,我把他贴出来了.
sdc666 :
请问高手,我在调试我的STM32F101c8t6时,遇到一个问题,因为我要调试串口,我在main.c中添加了#include <stdio.h> ,编译可以通过,但是当我用jlink硬件调试时,一开始就停在了 " 0x08001460 BEAB BKPT 0xAB";并且无法向下运行. 请问高手,这个问题的原因是什么?怎么解决? 谢谢!
_sys_open:
0x08001450 B50E PUSH {r1-r3,lr}
0x08001452 E9CD0100 STRD r0,r1,[sp,#0]
0x08001456 F000FAF9 BL.W strlen (0x08001A4C)
0x0800145A 9002 STR r0,[sp,#0x08]
0x0800145C 4669 MOV r1,sp
0x0800145E 2001 MOVS r0,#0x01
0x08001460 BEAB BKPT 0xAB
0x08001462 BD0E POP {r1-r3,pc}
pldjn :
应该是项目设置的问题,检查一下你的设置.
sdc666:
pldjn 你好,能详细指点以下么?应该怎样设置? 这个程序是我该的,本来是没有#include <stdio.h>,我添加串口后因为需要标准库函数,所以才加上的. 是不是还要设置编译环境? 谢谢.
pldjn :
你用J-Flash打开你的HEX文件看看编译的是否是对的.不用自动下载使用J-flash烧进去调一下试试.
dragonwww:
我也遇到同样问题,我是调用printf时出现的这个错误,我已经把putchar重定位了,不知道为何还是出错,求解,THX!
yugen:
那是因为你使用了printf之类的库函数,需要编写_sys_exit()之类底层函数。照你的提示看,也许是_sys_open()没写。_sys_xxx之类的的只要写个空函数就行了。
dragonwww:
to yugen:
能否说的再仔细些,如果自己编写个空函数应该放在哪里?函数定义格式是什么样的呢?
纳闷的是以前也用过printf,没出现这个提示啊。
PZLPDY:
5楼的应该不是这样吧?
应该是你没有选中微库造成的。这个问题昨天我遇到过。在工程的设置选项里把微库勾上就OK了
dragonwww:
to PZLPDY:
苍天啊,果然如你所说,把微库勾上就OK了,奇怪了为什么以前用的的时候没报错呢?以前也没选微库啊!
yugen:
因printf()之类的函数,使用了半主机模式。使用微库的话,不会使用半主机模式,所以就没有问题。
添加下面代码,就可以使用标准库了:
#pragma import(__use_no_semihosting)
_sys_exit(int x)
{
x = x;
}
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 is typedef’ d in stdio.h. */
FILE __stdout;
dragonwww:
yugen是高手啊,再请教一下:
1.何为“半主机模式”?与 非半主机模式有何区别?
2.你的这段代码需要放在那个文件里?自己的main函数所在的文件吗?
3.看到代码实现了_sys_exit,那我提示错误的_sys_open()不用实现吗?
请指教,多谢!
yugen:
你说的问题都可以在"RealView® 编译工具库和浮点支持指南"书中找到,网上有下,我就不复制了。书有中文的。realview编译器有好几本书,都有中文。
5、C++程序无法进入到main函数,代码、运行结果如下
func函数内的p未指向任何有效的内存空间就进行解引用,会导致程序崩溃。
#include <iostream>6、stm32 f407 串口scanf如何接收数据的例程
1,使用半主机模式, #pragma import(__use_no_semihosting) ,
2. 声明 struct __FILE {int handler;}
3. 重定义 FILE __stdin;
4. 实现 int fgetc(FILE*); 从串口中读取一个字符,
5.以上步骤 + 调试。
7、STM32 DMA 内存地址不会设。
stm32手册里有一块是关于外设地址,还有一般全局变量地址以及局部变量地址的介绍,如果使用dma的话,可以把地址尽量往后设,比如 0x40012440,这就已经是离你会用的那些变量的地址很远很远了,不会有冲突。
8、stm32F030F4P6的芯片 串口通信不成功代码在图里
建议串口连接到PC进行调试。可以先进行单元测试,测试成功后再去进行业务实现。
直接printf,看看PC端是否能收到。
直接getchar看看stm32端是否能收到。
最后,附上我用的重定义的代码,仅实现了fputc,实测可用。
#define PRINT_UART USART19、调试的时候为什么要禁用半主机模式
调试的时候为什么要禁用半主机模式
在部署生产应用程序或进行任何性能测量之前,始终记住禁用调试模式。如果启用了调试模式,应用程序的性能可能受到非常大的影响。
10、scnprintf这个函数怎么在网上都搜不到
#ifdef __GNUC__
/* 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__ */
PUTCHAR_PROTOTYPE
{
/* Place your implementation of fputc here */
/* e.g. write a character to the USART */
USART_SendData(USART1, (uint8_t) ch);
/* Loop until the end of transmission */
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
return ch;
}
因printf()之类的函数,使用了半主机模式。使用标准库会导致程序无法运行,以下是解决方法:
方法1.使用微库,因为使用微库的话,不会使用半主机模式.
方法2.仍然使用标准库,在主程序添加下面代码:
#pragma import(__use_no_semihosting)
_sys_exit(int x)
{
x = x;
}
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 is typedef’ d in stdio.h. */
FILE __stdout;