?? uart.c
字號:
#include "Main.h"
void UART_init(unsigned int ch,unsigned int baud)
{
if(ch)
{
UARTLCON1=0x3; // 8-bit no pariy 1 stop-bit
UARTCONT1=0x9; // rx/tx interrupt
UARTBRD1 =((int)(MCLK_MHz/(baud<<5)))<<4;
}
else
{
UARTLCON0=0x3;
UARTCONT0=0x9;
UARTBRD0 =((int)(MCLK_MHz/(baud<<5)))<<4; //(int)(MCLK/(32*baud)-1);
Enable_Int(nUART0_RX_ERR_INT);
}
init_queue(&Uart_buffer);
}
//-***********************************************-//
// 串口發送出一個字符串
//-***********************************************-//
void Print_URAT(int port,char *s)
{
if(port==0)
for(;*s!='\0';s++)
{
for(;(!(UARTSTAT0&0x40)););
UARTTXH0=*s;
}
else if(port==1)
for(;*s!='\0';s++)
{
for(;(!(UARTSTAT1&0x40)););
UARTTXH1=*s;
}
}
/* printp() ------------ a simply version of printf() */
/*修改了部分printp()代碼,
打印時如果 %后面的x,d為大寫,打印的數不區分正負數
為小寫,區分正負數
加l為取長型變量。
例如打印如下語句:
printp("\n here i is 0xF123ABCD, j is 0xF123");
printp("\n 1 : %%X i is: %X",i);
printp("\n 2 : %%x i is: %x",i);
printp("\n 3 : %%D i is: %D",i);
printp("\n 4 : %%d i is: %d",i);
printp("\n 5 : %%X j is: %X",j);
printp("\n 6 : %%x j is: %x",j);
printp("\n 7 : %%D j is: %D",j);
printp("\n 8 : %%d j is: %d",j);
結果為:
here i is 0xF123ABCD, j is 0xF123
1 : %X i is: F123ABCD
2 : %x i is: -EDC5433
3 : %D i is: 4045646797
4 : %d i is: -249320499
5 : %X j is: F123
6 : %x j is: F123
7 : %D j is: 61731
8 : %d j is: 61731 */
/************************************************************************/
#define CR_as_CRLF TRUE // if true , you can use "\n" to act as CR/LF,
// if false , you have to use "\n\r",but can get a higher speed
void uart_putchar(unsigned char ch)
{
for(;(!(UARTSTAT0&0x40)););
UARTTXH0=ch;
}
static int do_padding;
static int left_flag;
static int len;
static int num1;
static int num2;
static char pad_character;
/*---------------------------------------------------*/
/* */
/* This routine puts pad characters into the output */
/* buffer. */
/* */
static void padding( const int l_flag)
{
int i;
if (do_padding && l_flag && (len < num1))
for (i=len; i<num1; i++)
uart_putchar( pad_character);
}
/*---------------------------------------------------*/
/* */
/* This routine moves a string to the output buffer */
/* as directed by the padding and positioning flags. */
/* */
static void outs( char* lp)
{
/* pad on left if needed */
len = strlen( lp);
padding( !left_flag);
/* Move string to the buffer */
while (*lp && num2--)
uart_putchar( *lp++);
/* Pad on right if needed */
len = strlen( lp);
padding( left_flag);
}
/*---------------------------------------------------*/
/* */
/* This routine moves a number to the output buffer */
/* as directed by the padding and positioning flags. */
/* */
static void reoutnum(unsigned long num, unsigned int negative, const long base )
{
char* cp;
char outbuf[32];
const char digits[] = "0123456789ABCDEF";
/* Build number (backwards) in outbuf */
cp = outbuf;
do {
*cp++ = digits[(int)(num % base)];
} while ((num /= base) > 0);
if (negative)
*cp++ = '-';
*cp-- = 0;
/* Move the converted number to the buffer and */
/* add in the padding where needed. */
len = strlen(outbuf);
padding( !left_flag);
while (cp >= outbuf)
uart_putchar( *cp--);
padding( left_flag);
}
static void outnum(long num, const long base ,unsigned char sign)//1, signed 0 unsigned
{ unsigned int negative;
if ( (num < 0L) && sign )
{ negative=1;
num = -num;
}
else negative=0;
reoutnum(num,negative,base);
}
/*---------------------------------------------------*/
/* */
/* This routine gets a number from the format */
/* string. */
/* */
static int getnum( char** linep)
{
int n;
char* cp;
n = 0;
cp = *linep;
while (isdigit(*cp))
n = n*10 + ((*cp++) - '0');
*linep = cp;
return(n);
}
/*---------------------------------------------------*/
/* */
/* This routine operates just like a printf/sprintf */
/* routine. It outputs a set of data under the */
/* control of a formatting string. Not all of the */
/* standard C format control are supported. The ones */
/* provided are primarily those needed for embedded */
/* systems work. Primarily the floaing point */
/* routines are omitted. Other formats could be */
/* added easily by following the examples shown for */
/* the supported formats. */
/* */
void printp( char* ctrl, ...)
{
int long_flag;
int dot_flag;
char ch;
va_list argp; //由于為可變參數函數,需要進行參數提取;argp依次批向各可變參數
va_start( argp, ctrl);//初始化argp,使它指向第一個參數
for ( ; *ctrl; ctrl++)
{
/* move format string chars to buffer until a */
/* format control is found. */
if (*ctrl != '%')
{
uart_putchar(*ctrl);
#if CR_as_CRLF==TRUE
if(*ctrl=='\n') uart_putchar('\r');
#endif
continue;
}
/* initialize all the flags for this format. */
dot_flag =
long_flag =
left_flag =
do_padding = 0;
pad_character = ' ';
num2=0x7fffffff;
try_next:
ch = *(++ctrl);
if (isdigit(ch))
{
if (dot_flag)
num2 = getnum(&ctrl);
else {
if (ch == '0')
pad_character = '0';
num1 = getnum(&ctrl);
do_padding = 1;
}
ctrl--;
goto try_next;
}
switch (ch)
{
case '%':
uart_putchar( '%');
continue;
case '-':
left_flag = 1;
break;
case '.':
dot_flag = 1;
break;
case 'd':
outnum( va_arg(argp, int), 10,1);
continue;
case 'D':
outnum( va_arg(argp, unsigned int),10,0);
continue;
case 'x': // X 無符號 , x 有符號
outnum( va_arg(argp, int), 16 ,1);
continue;
case 'X':
outnum( va_arg(argp, unsigned int), 16 ,0);
continue;
//如果按照16進制打印,將全部按照無符號數進行
continue;
case 's':
outs( va_arg( argp, char*));
continue;
case 'c':
uart_putchar((char)va_arg( argp, int));
continue;
default:
continue;
}
goto try_next;
}
va_end( argp);
}
/*
How to use variable argument function
C語言支持va函數,作為C語言的擴展--C++同樣支持va函數,但在C++中并不推薦使用,
C++引入的多態性同樣可以實現參數個數可變的函數。不過,C++的重載功能畢竟只能
是有限多個可以預見的參數個數。比較而言,C中的va函數則可以定義無窮多個相當于
C++的重載函數,這方面C++是無能為力的。va函數的優勢表現在使用的方便性和易用
性上,可以使代碼更簡潔。C編譯器為了統一在不同的硬件架構、硬件平臺上的實現,
和增加代碼的可移植性,提供了一系列宏來屏蔽硬件環境不同帶來的差異。
ANSI C標準下,va的宏定義在stdarg.h中,它們有:va_list,va_start(),va_arg(),va_end()。
va_list arg_ptr:定義一個指向個數可變的參數列表指針;
va_start(arg_ptr, argN):使參數列表指針arg_ptr指向函數參數列表中的第一個可選參數,
說明:argN是位于第一個可選參數之前的固定參數,(或者說,最后一個固定參數;…之前的一個參數)
,函數參數列表中參數在內存中的順序與函數聲明時的順序是一致的。如果有一va函數的聲明是
void va_test(char a, char b, char c, …),則它的固定參數依次是a,b,c,最后一個固定參數argN為c,
因此就是va_start(arg_ptr, c)。
va_arg(arg_ptr, type):返回參數列表中指針arg_ptr所指的參數,返回類型為type,并使指針arg_ptr
指向參數列表中下一個參數。
va_copy(dest, src):dest,src的類型都是va_list,va_copy()用于復制參數列表指針,將dest初始化為src。
va_end(arg_ptr):清空參數列表,并置參數指針arg_ptr無效。說明:指針arg_ptr被置無效后,可以
通過調用va_start()、va_copy()恢復arg_ptr。每次調用va_start() / va_copy()后,必須得有相應
的va_end()與之匹配。參數指針可以在參數列表中隨意地來回移動,但必須在va_start() … va_end()之內。
*/
char get_char(unsigned int channel)
{
char ch;
if(channel)
{
while(!(UARTSTAT1 & USTAT_RCV_READY))
ch = UARTRXB1;
}
else
{
while(!(UARTSTAT0 & USTAT_RCV_READY))
ch = UARTRXB0;
}
return ch;
}
void Uart0_R_interrupt(void)
{
char ch;
ch = UARTRXB0;
if(command_flag == TRUE)
{
if(Enqueue(&Uart_buffer,ch) == FALSE)
printp("\n Uart_buffer is full!");
}
else
{
*Puart_receiver_buffer++ = ch;
printp("%x ",ch);
uart_receiver_count++;
if(!(uart_receiver_count%5000)) printp("*");
Uart_receiving_file = TRUE;
Time0_count = 0;
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -