📄 uart.c
字号:
/*********************************************************************************************************//*/* 程序名称: uart_cmd.c /*/* 程序用途:Pmon平台下串口格式输入,格式输出命令函数/* 编写日期:2005.11.05/* 编写人员:凯达电子南京研发部 董亮 /* 联系方式:support@kd-soc.com/* 程序原理:输出命令通过物理地址调出串口线路状态寄存器(line status register)中第五位状态并进行比较操作/* 输入命令通过物理地址调出串口线路状态寄存器(line status register)中第二位状态并进行比较操作 ***********************************************************************************************************//*调用常规函数库,使用va_arg,va_start,va_end等函数*/#include<stdarg.h>#include<string.h>#include<ctype.h>#include<stdlib.h>#include<rtc.h>/*调用uart口初始化文件*/#include<uart.h>/****************************************************************************************************//* uart初始化/****************************************************************************************************/void uart_Init(void){ r16550LCTRL=0x00; r16550INTEN=0x00; r16550IIFIFO=0x07; //00000111 r16550LCTRL=0x80; //10000000 r16550DLL = 0x18; //00011000 300 baud [5 MHz crystal:(5M/2)/(6*16*BAUD_DATA)=300 baud] r16550DLM = 0x00; // set divisor 12 r16550LCTRL = 0x03; //00000011 (8-bit data;1 stop bit;no parity) r16550MCTRL = 0x01|0x02|8; //00111011 /* Clear interrupt bits */ r16550INTEN = 0x00;} /****************************************************************************************************//* test_sendc函数:单个字符输出*****************************************************************************************************/void test_sendchar(char tdata){ //该判断语句也可写为:while((r16550LSTAT & 0x20)); while(!(r16550LSTAT & (0x01<<5))); //等待THR寄存器为空 r16550RXTX = tdata; }/***************************************************************************************************/ /* 函数名称: test_sendch/* /* 函数目的:如字符串结束,则回车换行,符合书写规范****************************************************************************************************/void test_SendCh(char tdata){ if(tdata == '\n') { test_sendchar('\r'); } test_sendchar(tdata);}/***************************************************************************************************/ /* 函数名称: test_printf/* /* 函数目的:利用指针实现简单的字符串输出/* ****************************************************************************************************/void test_printf(char *pbstring){ while(*pbstring) test_SendCh(*pbstring++);}/***************************************************************************************************/ /* 结构体名称: printnum/* /* 结构体目的:作为数字输出专用,在printf函数中调用,用于输出各种格式数字/* ****************************************************************************************************/static unsigned charprintnum(long unsigned int num,int base,int sign,int maxwidth,int lead) //结构体定义{ long unsigned int n; int count; char toprint[1024]; if((sign==1)&&((long)num<0)){ test_SendCh('-'); num=-num; if (maxwidth)maxwidth--; } count=0; while((n=num/base)>0){ toprint[count++]=(num -(n*base)); num=n; } toprint[count++]=num; if (maxwidth && count<maxwidth){ for(n=maxwidth-count;n;n--) test_SendCh(lead); } for(n=0;n<count;n++){ test_SendCh("0123456789ABCDEF"[(int)(toprint[count-(n+1)])]); }}/*******************************************************************************************************/ /* 函数名称: printf/* /* 函数目的:实现字符串内格式打印功能/* 说明:test_sendchar函数已经实现单个字符输出的操作,此函数只需要调用常规函数库中va_start与va_end/* 函数来测量字符串长度并做相应的头尾标记,利用循环依次判断每一个字符并输出,参考consol中/* _doprntx函数原理编写,但将数字格式输出另做结构体调用,避免冗长的代码造成后期修改麻烦。/*/*********************************************************************************************************/void printf(char *fmt,...){ va_list ap; char c,*str; int lflag,base,sign,width,lead; va_start(ap,fmt); for(;*fmt!='\0';fmt++) //循环开始 { if(*fmt=='%') //判断是否为格式输出规则 { lflag=0;base=0;sign=0;width=0;lead=' '; //初始化相关参数 fmt++; if(*fmt=='0') { lead='0'; fmt++; } while(*fmt>='0'&&*fmt<='9') { width*=10; width+=(*fmt-'0'); fmt++; } if ((c=*fmt)=='1') { lflag=1; c=*++fmt; } switch(c) //不同格式输出定义 { case'b':case'B':base=2;sign=0;break; //二进制格式输出 case'o':case'O':base=8;sign=0;break; //八进制格式输出 case'd':case'D':base=10;sign=1;break; //十进制格式输出 case'u':case'U':base=10;sign=0;break; //无符号十进制格式输出 case'x':case'X':base=16;sign=0;break; //十六进制格式输出 case's': case'S':for(str=va_arg(ap,char*);*str;str++) //字符串输出 test_SendCh(*str); break; case'c': case'C':test_SendCh(va_arg(ap,char)); //单个字符格式 break; default:test_SendCh(c); break; } if(base) //各种格式数字输出 printnum(lflag ? va_arg(ap,long int):(long int)va_arg(ap,int), base,sign,width,lead); } else test_SendCh(*fmt); } va_end(ap);} /***************************************************************************************************//* test_getch函数:单个字符输入函数 *****************************************************************************************************/char test_getchar(void){ while(!(r16550LSTAT & (0x01<<0))); return r16550RXTX;}/***************************************************************************************************/ /* 函数名称: test_getstring/* /* 函数目的:使用指针实现简单的字符串输入****************************************************************************************************/void test_getstring(char *pbstring){ char *pbstring2=pbstring; char bC; while((bC=test_getchar())!='\r') { if(bC=='\b') //退格处理 { if((int)pbstring2<(int)pbstring){test_printf("\b \b");pbstring--;} } else { *pbstring++=bC;test_sendchar(bC); } } *pbstring='\0'; test_sendchar('\n');}/***************************************************************************************************/ /* 结构体名称: GetIntNum/* /* 结构体目的:作为数字读入专用,在scanf函数中调用,用于读入不同格式数字/* ****************************************************************************************************//*for getintnum--atoi*/int atoi(char *s){ return (int) strtol (s, (char **) 0, 10);}/*strtol函数中使用到的toupper函数*/int toupper(int c){ if (islower(c)) return c - ('a' - 'A'); else return c;} /*strtol函数中使用到的定义 */#define max_allowable(A) (MAXINT(sizeof(int))/A - 1)#define MAXINT(w) (\ ((w) == sizeof(signed char)) ? 0x7F :\ ((w) == sizeof(short int)) ? 0x7FFF :\ ((w) == sizeof(int)) ? 0x7FFFFFFF : 0\ )#define ERANGE 34 int errno; /*atoi函数下使用到的strtol函数*/ //自定义判断函数,用来判断输入字符,只允许数字输入int pan(unsigned char c){ if (c > '9' || c< '0') return(0); }long strtol( const char *str, char **endptr, int base){ long i = 0; int s = 1; int c; // 空格 while((!isspace(*str))) { str++; } // sign flag check if (*str == '+') str++; else if (*str == '-') { s = -1; str++; } if (*str == '0') { if (toupper(*++str) == 'X') base = 16,str++; else if (base == 0) base = 8; } if (base == 0) base = 10; if (base <= 10) // str to number for (; pan(*str); str++) { if (i < max_allowable(base)) i = i * base + (*str - '0'); else { i = MAXINT(sizeof(int)); errno = ERANGE; } } else if (base > 10) { for (; (c = *str); str++) { if (pan(c)) c = c - '0'; else { c = toupper(c); if (c >= 'A' && c < ('A' - 10 + base)) c = c - 'A' + 10; else break; } if (i < max_allowable(base)) i = i * base + c; else { i = MAXINT(sizeof(int)); errno = ERANGE; } } } else return 0; // negative base is not allowed if (endptr) *endptr = (char *) str; if (s == -1) i = -i; return i;}/*getintnum函数中使用到的strlen函数*/int strlen(const char *s){ int l = 0; while (*s++) l++; return l;}/**************************************************************************************************/#define __isalpha(c) (c >'9')#define __isupper(c) !(c & 0x20)int getintnum(void){ char abStr[30]; char *pbstring=abStr; int wbase=10; int wminus=0; int wlastindex; int wresult=0; int wi; test_getstring(pbstring); if(pbstring[0]=='-'){wminus=1;pbstring++;} //负数 if(pbstring[0]=='0' && (pbstring[1]=='x' || pbstring[1]=='X')) //输入格式为0x十六进制 { wbase=16; pbstring+=2; } wlastindex=strlen(pbstring)-1; if( pbstring[wlastindex]=='h' || pbstring[wlastindex]=='H' ) //输入格式为h 处理方式 { wbase=16; pbstring[wlastindex]=0; wlastindex--; } if(wbase==10) //十进制 { wresult=atoi(pbstring); //atoi函数转换成整型量,相关函数上 wresult=wminus ? (-1*wresult):wresult; } else { for(wi=0; wi<=wlastindex; wi++) { if(__isalpha(pbstring[wi])) { if(__isupper(pbstring[wi])) wresult=(wresult<<4)+pbstring[wi]-'A'+10; else wresult=(wresult<<4)+pbstring[wi]-'a'+10; } else { wresult=(wresult<<4)+pbstring[wi]-'0'; } } wresult=wminus ? (-1*wresult):wresult; } return wresult;}/********************************************************************************************************//* 函数名称: test_Scanf/* /* 函数目的:实现字符串内格式读入功能/* 说明:test_getchar函数已经实现单个字符输出的操作,此函数只需要调用常规函数库中va_start与va_end/* 函数来测量字符串长度并做相应的头尾标记,利用循环依次判断每一个字符并读入/********************************************************************************************************/void test_scanf(char *fmt,...){ va_list ap; char cchar; int *pwint; char *pbchar; va_start(ap, fmt); while((cchar=*fmt++) != '\0') { if(cchar != '%')continue; //格式输入 switch(*fmt) { case 's': //字符串输入 case 'S': pbchar = va_arg(ap, char *); test_getstring(pbchar); break; case 'i': //数值输入 case 'I': pwint = va_arg(ap, int *); *pwint =getintnum(); break; case 'c': //单个字符输入 case 'C': pbchar = va_arg(ap, char *); *pbchar =test_getchar(); break; } } va_end(ap);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -