📄 嵌入式串口驱动程序.txt
字号:
#include<stdarg.h>
#include<string.h>
#include<ctype.h>
#include<stdlib.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 char
printnum(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 + -