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