庫函數(shù)的話就看下他們提供的例程,再看下每一個外設(shè)的.C里面的接口函數(shù)源碼,一般一看命名就知道這個函數(shù)做什么用的了。命名規(guī)則很一致的
站在用戶的角度思考問題,與客戶深入溝通,找到土默特左旗網(wǎng)站設(shè)計與土默特左旗網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗,讓設(shè)計與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個性化、用戶體驗好的作品,建站類型包括:成都網(wǎng)站設(shè)計、做網(wǎng)站、成都外貿(mào)網(wǎng)站建設(shè)公司、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣、域名注冊、網(wǎng)絡(luò)空間、企業(yè)郵箱。業(yè)務(wù)覆蓋土默特左旗地區(qū)。
io口用哪個是根據(jù)GPIO_Pin這個結(jié)構(gòu)變量來判定,準確說是按它的二進制的各個位來表示使用哪些io口。
GPIO_Pin_11是個宏定義,假設(shè)等于00000001(二進制),而GPIO_Pin_12假設(shè)等于00000010(二進制),它兩個或就等于00000011,判定使用哪些io口時,就是根據(jù)這個數(shù)的各個位來分析,當最低位為1要用GPIO_Pin_11,第二位為1表示也要用GPIO_Pin_12口。
所有是或運算符。
簡單地說:想在mdk 中用printf,需要同時重定義fputc函數(shù)和避免使用semihosting(半主機模式),
標準庫函數(shù)的默認輸出設(shè)備是顯示器,要實現(xiàn)在串口或LCD輸出,必須重定義標準庫函數(shù)里調(diào)用的與輸出設(shè)備相關(guān)的函數(shù).
例如: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()之類的函數(shù),使用了半主機模式。使用標準庫會導致程序無法運行,以下是解決方法:
方法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.另一種方法:(其實大同小異)
需要添加以下代碼
(論壇里應(yīng)該有完整介紹這個的帖子,但是我沒搜到,也許是沉了。)
#pragma import(__use_no_semihosting)
/******************************************************************************
*標準庫需要的支持函數(shù)
******************************************************************************/
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.
按我的理解,這個模式是用來調(diào)試的,通過仿真器,使用主機的輸入輸出代替單片機自己的,也就是說即便單片機沒有輸出口也能printf到電腦上。反過來,由于這個模式更改了printf()等的實現(xiàn)方式,輸入輸出就不走單片機的外設(shè)了,所以只重定義fputc不起作用。
用代碼關(guān)閉此模式后,需要同時更新一下__stdout 和__stdin 的定義,所以有后面的語句。
以上僅為個人理解,如有錯誤請指正。
另外,勾選microlib之后,也許編譯的時候就不把開啟semihosting的文件包進去了,所以沒事。
C庫函數(shù)重定向:
用戶能定義自己的C語言庫函數(shù),連接器在連接時自動使用這些新的功能函數(shù)。這個過程叫做重定向C語言庫函數(shù),如下圖所示。
舉例來說,用戶有一個I/O設(shè)備(如UART)。本來庫函數(shù)fputc()是把字符輸出到調(diào)試器控制窗口中去的,但用戶把輸出設(shè)備改成了UART端口,這樣一來,所有基于fputc()函數(shù)的printf()系列函數(shù)輸出都被重定向到UART端口上去了。
下面是實現(xiàn)fputc()重定向的一個例子:
externvoidsendchar(char*ch);
intfputc(intch,FILE*f)
{/*e.g.writeacharactertoanUART*/
chartempch=ch;
sendchar(tempch);
returnch;
}
這個例子簡單地將輸入字符重新定向到另一個函數(shù)sendchar(),sendchar()假定是個另外定義的串口輸出函數(shù)。在這里,fputc()就似乎目標硬件和標準C庫函數(shù)之間的一個抽象層。
首先,兩個都是C語言。
從51過渡過來的話,就先說寄存器操作。每個MCU都有自己的寄存器,51是功能比較簡單的一種,相應(yīng)的寄存器也比較少,我們常用的就那么幾個,像P0 P1 SMOD TMOD之類的,這些存在于標準頭文件reg.h里面,因為少,所以大家就直接這么去操作了,每一位對應(yīng)的意義隨便翻一下手冊就看得到,甚至做幾個小項目就記的很清楚了。所以做51開發(fā)的時候大多數(shù)都是直接操作寄存器。
到了STM32,原理一樣,也是有自己的寄存器,但是作為一款ARM內(nèi)核的芯片,功能多了非常多,寄存器自然也就多了很多,STM32的手冊有一千多頁,這時候想去像51那樣記住每個寄存器已經(jīng)不現(xiàn)實了,所以ST的工程師就給大家提供了庫函數(shù)這么一個東西。
這是個神器。
庫函數(shù)里面把STM32的所有寄存器用結(jié)構(gòu)體一一對應(yīng)并且封裝起來,而且提供了基本的配置函數(shù)。我們要去操作配置某個外設(shè)的時候不需要再去翻眼花繚亂的數(shù)據(jù)手冊,直接找到庫函數(shù)描述拿來就可以用,這樣就能把精力放在邏輯代碼的開發(fā)上,而不是去費力的研究一個芯片的外設(shè)要怎么配置寄存器才能驅(qū)動起來。
簡單講就是這些了,庫函數(shù)是為了讓開發(fā)者從大量繁瑣的寄存器操作中脫離出來的一個文件包,在使用一個外設(shè)的時候讓開發(fā)者直接去調(diào)用相應(yīng)的驅(qū)動函數(shù)而不是自己去翻手冊一個一個配置寄存器。
有人說用庫函數(shù)掌握不到芯片的精髓,見仁見智了。熟悉一款芯片是在不斷的開發(fā)使用中逐漸了解并掌握的,調(diào)試的過程中會遇到很多問題,會要求我們?nèi)ジ櫹嚓P(guān)寄存器的狀態(tài),在整個框架都已經(jīng)建立起來的基礎(chǔ)上再去對照手冊做具體到寄存器每一位的分析,代碼對照現(xiàn)象,很快就能積累起來經(jīng)驗,祝成功。