📄 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 + -