新一期ARM作业(二)----UART串口

目录

描述

解答


描述

  • 1

putchar在没有读到数据时会一直死等,实现一个putchar_nowait函数, 有串口数据就读出来,没有串口数据就立刻返回错误

 

  • 2

printf函数是把输出信息直接从串口输出了,有时候我们要得到这些信息,比如后面的LCD程序中,想在LCD上显示这些信息时,就要先得到这些信息再一次性的输出到LCD。实现这个函数:int snprintf(char *str, size_t size, const char *format, …);它会把输出信息先保存在str里。(提示: printf函数中最终使用__out_putchar进行打印,你也许可以修改它,把字符保存在str中。)

 

解答

  • 1

putchar在没有读到数据时会一直死等,实现一个putchar_nowait()函数, 有串口数据就读出来,没有串口数据就立刻返回错误,(添加一个时间变量,在while中一直递减就大致模拟无阻塞等待)

//修改前
void putchar(int c)
{
	while (!(UTRSTAT0 & (1<<2)));
	UTXH0 = (unsigned char)c;
}


//修改后(阻塞一段时间)
int putchar_nowait(void)
{
	unsigned int time = 2000000;
	unsigned char val;
        while(!(UTRSTAT0&(1<<2)) && --time);
	if(time)
	{
		val = URXH0;
		while(!(UTRSTAT0&(1<<2)));
		UTXH0 = (unsigned char)val;
		return 1;
	}
	else
		return 0;
}

 

  • 2

思想是把原本输出到串口的内容都输出到str,在格式化输出的时候需要统计转换到的字符数,改变str指针位置,同时要检查是否超出长度指定的长度

//my_print.h

/*
 *模仿sprint函数,按照format格式,把数据输入到str中
 */
int snprintf(char *str, int size, const char *format, ...);


//my_printf.c
#include "my_printf.h"

void __out_putchar(char *str,unsigned char c)
{
	*str = c;
	return ;
}

unsigned char hex_tab[]= {'0','1','2','3','4','5','6','7',\
                          '8','9','a','b','c','d','e','f'
                         };

static int outc(char *str,int c)
{
	__out_putchar(str,c);
	return 0;
}

static int outs(char *str, const char *s)
{
	int ret = 0;
	while (*s != '\0')
	{
		__out_putchar(str++,*s++);
		ret++;
	}
	return ret;
}

static int out_num(char *str,long n, int base,char lead,int maxwidth)
{
	unsigned long m=0;
	char buf[MAX_NUMBER_BYTES];
	char *s = buf + sizeof(buf);
	int count=0,i=0;
	*--s = '\0';

	if (n < 0)
	{
		m = -n;
	}
	else
	{
		m = n;
	}

	do
	{
		*--s = hex_tab[m%base];
		count++;
	}
	while ((m /= base) != 0);

	if( maxwidth && count < maxwidth)
	{
		for (i=maxwidth - count; i; i--)
			*--s = lead;
	}
	if (n < 0)
		*--s = '-';

	return outs(str,s);
}

static int my_vprintf(char *str,int size,const char *fmt, va_list ap)
{
	char lead=' ';
	int  maxwidth=0;
	int s = 0;

	for(; *fmt != '\0'; fmt++)
	{
		if (*fmt != '%')
		{
			if(++s <= size)
			{
				outc(str++,*fmt);
				continue;
			}
			else
				break;
		}

		//format : %08d, %8d,%d,%u,%x,%f,%c,%s
		fmt++;
		if(*fmt == '0')
		{
			lead = '0';
			fmt++;
		}

		lead=' ';
		maxwidth=0;

		while(*fmt >= '0' && *fmt <= '9')
		{
			maxwidth *=10;
			maxwidth += (*fmt - '0');
			fmt++;
		}

		int len;
		switch (*fmt)
		{
		case 'd':
			len = out_num(str,va_arg(ap, int),          10,lead,maxwidth);
			break;
		case 'o':
			len = out_num(str,va_arg(ap, unsigned int),  8,lead,maxwidth);

			break;
		case 'u':
			len = out_num(str,va_arg(ap, unsigned int), 10,lead,maxwidth);
			break;
		case 'x':
			len = out_num(str,va_arg(ap, unsigned int), 16,lead,maxwidth);
			break;
		case 'c':
			if(++s <= size)
				outc(str++,va_arg(ap, int   ));
			break;
		case 's':
			len = outs(str,va_arg(ap, char *));
			break;
		default:
			if(++s <= size)
				outc(str++,*fmt);
			break;
		}

		//检查输入的字符串是否超出长度
		if(len<= (size-s))
		{
			str+=len;
			s+=len;
		}
		else
		{
			*(str+size) = '\0';
			s = size+1;
		}
	}
	return 0;
}

int snprintf(char *str, int size, const char *format, ...)
{
	va_list ap;
	//得到数据缓冲区首地址
	va_start(ap, format);
	//根据格式+数据进行输出到str
	my_vprintf(str, size, format, ap);
	//指针赋值,避免野指针
	va_end(ap);
	return 0;	
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值