历史上的今天
今天是:2025年02月18日(星期二)
2019年02月18日 | 【单片机笔记】51串口printf的使用和变量循环问题
2019-02-18 来源:eefocus
串口printf的使用
每次在使用到51内核的MCU是总会很头疼,原因有很多,主要的就是仿真,串口打印调试等比较麻烦。但是没办法,这还必须要用到。所以没办法,把之前用过的串口打印程序重新温习了下,用过51和32的朋友一定会发现51简直弱爆了,在串口打印程序上还非常的不方便。以最好用的printf为例子。我今天就把这个函数给写出来了,当然依托了网上的大神们,函数原型如下:
void USART0_Printf(char *fmt,...)//这个是我们的printf函数
{
char* ap;//typedef char *va_list; va_list是char型的指针
charxdata string[128];//访问外部RAM 两字节对齐
va_start(ap,fmt);//这个函数的功能是,找到第一个可变形参的地址,并把地址赋给ap
vsprintf(string,fmt,ap);//其实这个函数才是核心函数,没研究。。。
USART0_SendString(string);//这个函数就是发送字符串函数,通过上一个函数,就把该提取的东西都提取了
va_end(ap);//结束函数
}
这个函数在51调试的时候还是非常好用的,特别是又用串口ISP下载的用户。接下来简述下函数的用法:
1、在编写函数之前,首先需要添加stdarg.h头文件,其中va_start和va_end函数就是这个里面的库。
2、其次就是需要分配一个空间,例如上面的char xdata string[128]; 因为空间有限,我这里给的是外部128字节。打印的长度超出了可能就会出问题了,根据情况,在空间充足的情况下可以分配大一点。
3、编写底层的串口打印字符串函数,在51的程序里我一般写成如下:
//串口0发送一个字节
void USART0_SendByte(u8 value)
{
SBUF= value; //发送一个字节
while(!TI); //等待TI置1
TI=0;
}
//串口0发送字符串
void USART0_SendString(u8 *dat)
{
while(*dat!='\0')
USART0_SendByte(*dat++);
}
这是串口0的打印函数,如果换成串口1也是一样的。
在使用的过程中需要注意有数据的情况下,数据需要强转成int型不能直接用unsigned char,这个不是我今天所遇到的问题,在上学期间实践过,所以使用的时候我都加了强转,例如:
USART0_Printf("PWR_LEVEL=%d MOD_LEVEL=%d FAN_LEVEL=%d TIME_LEVEL=%d FUN_LEVEL=%d\n",
(int)PWR_LEVEL,(int)MOD_LEVEL,(int)FAN_LEVEL,(int)TIM_LEVEL,(int)FUN_LEVEL);
变量循环问题
在程序编程中往往会遇到一些奇怪的问题,今天调试的MCU就出现了个问题,问题是这样的,一个8位的变量(FAN_LEVEL),当我需要这个变量在1、2、3、4之前循环的时候,一开始没有别的想法直接写上简单的计算公式,如下:
FAN_LEVEL++;
FAN_LEVEL= FAN_LEVEL%4+1;
这是第一时间想到的方法,但是在调试的时候发现不对,一开始也没有发现,这还能出错吗?调到后面把变量值打出来才发先这个变量确实存在问题,以下是调试的串口打印结果:

很奇怪变量并不是按照设计的循环的,调试了很久,始终找不到问题,但是有一种情况是可以的,如下公式
FAN_LEVEL++;
FAN_LEVEL= FAN_LEVEL%4;
这样的结果确实是正确的,如下图:

那我就感觉很奇怪了,但是这个0-3循环不是1-4循环,不是想要的结果,到这里看到的朋友都会说再在后面递增一下不久可以了,加上之后的方法:
FAN_LEVEL++;
FAN_LEVEL= FAN_LEVEL%4;
FAN_LEVEL++;
经过实验,很幸运,结果还是错的,跟没有加递增是一样的结果。当然我到现在还是没有找到原因,但是总的结果不能不要啊,最后只能用个很笨的办法了,如下:

下一篇: 51单片机串口通讯UART
史海拾趣
|
整理下裁员/倒闭行业类别~有个快消招聘,找工作的来~ 奢侈品行业的情况有谁知道? 最近裁员倒闭的一片片,实在看的太多了,整理下下,有补充的可以跟贴,一并列举上。 也给要找的在找的将要找工作的人一点点参考。 申明: 本来的确打算一直做,因为都是大家提供的消息,但是似乎现在有些不同的“凡响”,我无意争什么,所以, ...… 查看全部问答> |
|
一个学长的感言:转载 从C语言到FPGA高手,我是怎么炼成的 这些日子我一直在写一个实时操作系统内核,已有小成了,等写完我会全部公开,希望能够为 国内IT的发展尽自己一份微薄的力量。最近看到很多学生朋友和我当年一样没有方向 ,所以把我的经历写出来与大家共勉,希望能给刚入行的朋友们一点点帮助。一转 ...… 查看全部问答> |
|
2440的板1gnandflash 32m sdram xip变大后,从13,531,423 字节到14,145,815 字节 原来的bootloader下载后断电不能自启动 Launch 0x30201000 后就不工作了。 是还需要改bootloader吗?… 查看全部问答> |
|
我在把linux的zImage文件和miniroot.cramfs烧进板子后,linux解压出错.错误信息如下: VIVI version 0.1.4 (root@localhost.localdomain) (gcc version 2.95.2 20000516 (re lease) [Rebel.com]) #0.1.4 五 5月 6 16:07:30 CST 2005 MMU table bas ...… 查看全部问答> |
|
目标板是基本最小系统+JTAG部分,所以很多部分都要自己动手来完成了! 数控电源人机界面 1、数码管+键盘; 2、LCD+键盘; 3、PC小工具; 预留PWM,ADC,COMP功能的外围脚 [ ...… 查看全部问答> |
|
今天把OK6410超频到了800M,但速度并没有显著提高,请教大神们。 琢磨了半天,把OK6410超频到了800M,主要是修改文件s3c6410.inc和soc_cfg.h OK6410运行正常,跑的还很欢实。 改动如下: Windows CE Kernel for ARM (Thumb Enabled) Built on Sep 25 2009& ...… 查看全部问答> |
|
[已售]20几天前刚买的stm32f103vc火牛开发板 转让 本帖最后由 ddllxxrr 于 2014-12-17 09:00 编辑 9月30日刚在淘宝网上买的,本来是买来做毕业设计的,可是毕业设计换了另一个题目,所以不需要再使用了。原价320 ,现在打9折,真的是全新的,刚买,没用过,光盘,配件,保修单什么的都是全的,可以 ...… 查看全部问答> |
|
有谁能把STM32库函数这三句TIM1_TimeBaseStructInit最基本的通俗解释一下 TIM1_TimeBaseInitTypeDef TIM1_TimeBaseStructure;TIM1_OCInitTypeDef TIM1_OCInitStructure;TIM1_BDTRInitTypeDef TIM1_BDTRInitStructure; 我知道是初始化操作 … 查看全部问答> |




