SAM4E單片機(jī)之旅——17、通過UART進(jìn)行標(biāo)準(zhǔn)IO
交互還是很有必要的,而且使用鍵盤和顯示器的交互效率還是很高的。當(dāng)然,可以直接使用UART進(jìn)行字符的輸入和輸出。但是又何必浪費(fèi)了C的標(biāo)準(zhǔn)輸入輸出的格式控制之類的功能呢?
本文引用地址:http://www.ex-cimer.com/article/201704/346616.htm這次內(nèi)容就是使用scanf() 和printf() 函數(shù)進(jìn)行PC和開發(fā)板的交互。
一、 C標(biāo)準(zhǔn)函數(shù)庫
與硬件相關(guān)的功能,最終都需要直接訪問硬件。這一點(diǎn),C的標(biāo)準(zhǔn)函數(shù)庫的實(shí)現(xiàn)面對(duì)眾多的硬件設(shè)備,已經(jīng)無能為力了。
Atmel Studio使用的C標(biāo)準(zhǔn)庫的實(shí)現(xiàn)疑似為Newlib。
在工程的 ASFsamutilssyscallsgccsyscalls.c 文件中,ASF已經(jīng)實(shí)現(xiàn)了若干需要自己實(shí)現(xiàn)的函數(shù)了(這個(gè)文件雖然叫syscall,但是可能只是因遵守unix的習(xí)慣起的。因?yàn)檫@里沒有操作系統(tǒng),也就沒有“系統(tǒng)調(diào)用”一說了)。但是類似輸入輸出這些定制性較高的實(shí)現(xiàn)就沒有默認(rèn)的實(shí)現(xiàn)。
Newlib的大部分文件讀寫功能是通過_read() 和_write() 函數(shù)實(shí)現(xiàn)了。所以實(shí)現(xiàn)了這兩個(gè)函數(shù)就可以實(shí)現(xiàn)標(biāo)準(zhǔn)輸入輸出了。函數(shù)的簽名及參數(shù)含義可以google。
二、 實(shí)現(xiàn)
注意需要先完成UART的配置工作。
在具體的實(shí)現(xiàn)就很簡單了。在實(shí)現(xiàn)時(shí),可以不對(duì)目標(biāo)文件進(jìn)行判斷,而對(duì)所有的輸入輸出均通過UART完成。若需要判斷目標(biāo)文件是否為標(biāo)準(zhǔn)輸入輸出,以及在檢測到錯(cuò)誤時(shí)對(duì)這個(gè)錯(cuò)誤進(jìn)行報(bào)告,就需要包含以下頭文件:
#include
#include
_write:
int _write(int file,const char *ptr,int len)
{
// 只處理標(biāo)準(zhǔn)輸出
if (file == STDOUT_FILENO){
for (int i = 0; i<LEN ; ++i){< p>
// 通過UART寫出數(shù)據(jù)
while (!(UART0->UART_SR & UART_SR_TXRDY));
UART0->UART_THR = ptr[i];
}
return len;
}else {
errno = EBADF;
return -1;
}
}
_read:
int _read (int file, char *ptr, int len)
{
// 只處理標(biāo)準(zhǔn)輸入
if (file == STDIN_FILENO){
int i;
for (i = 0; i < len; i++){
// 通過UART讀入數(shù)據(jù)
while(!(UART0->UART_SR & UART_SR_RXRDY));
ptr[i] = UART0->UART_RHR;
/* 當(dāng)讀到換行符時(shí)返回
if ('n' == ptr[i])
return i;
}
return i; /* 緩o沖?區(qū)?已°?慢y */
}else{
errno = EBADF;
return -1;
}
}
測試,以下代碼獲取UART的輸入,并通過UART重新輸出:
#include
printf("-I- Test for stdio through UART0rn");
char readbuf[64];
while (1)
{
printf("-I- Input something...rn");
scanf("%s", readbuf);
printf("Output: %srn",readbuf);
}
注意,PC端在發(fā)送數(shù)據(jù)時(shí)需要加上換行符。
三、 在ASF中使用
因?yàn)檫@是一個(gè)很常用的功能,所以在ASF中也有實(shí)現(xiàn)。在ASF中不但可以進(jìn)行一些配置,而且在使用的時(shí)候真正需要編寫的代碼只有幾行,甚至這幾行代碼也可以完全參考(抄)ASF示例中的代碼。
添加模塊Standard serial I/O。
在conf_board.h里面已經(jīng)默認(rèn)聲明了相應(yīng)的宏了:
1
2/* Configure UART pins */
#define CONF_BOARD_UART_CONSOLE
在conf_uart_serial.h 里,已經(jīng)有了使用UART相關(guān)的參考設(shè)置代碼了。刪去參考代碼前面的注釋符號(hào)即可:
/* A reference setting for UART */
/** UART Interface */
#define CONF_UART CONSOLE_UART
/** Baudrate setting */
#define CONF_UART_BAUDRATE 115200
/** Parity setting */
#define CONF_UART_PARITY UART_MR_PAR_NO
調(diào)用stdio_serial_init初始化串行標(biāo)準(zhǔn)I/O:
const usart_serial_options_t uart_serial_options = {
.baudrate = CONF_UART_BAUDRATE,
.paritytype = CONF_UART_PARITY
};
/* Configure console UART. */
sysclk_enable_peripheral_clock(CONSOLE_UART_ID);
stdio_serial_init(CONF_UART, &uart_serial_options);
評(píng)論