1.printf系列的函数实现

懂得了单片机通过串口传输数据给电脑端窗口查看,那么,有时我们需要发送字符串,有时需要发送一个变量的数值是多少,以及还要发送回车换行这三种情况。所以我们把这三个功能函数封装起来,方便后续的串口使用。

首先笔者写的“void printf_str(u8 *str)”函数就是专门用来发送字符串给电脑端的。

其次“void printf_num(u32 num)”发送的变量的数值只支持显示十进制数0~4294967295,也就是参数是u32类型。

最后“void printf_rn()”就是发送回车换行符了。

关于这三部分的代码大家可以尝试去阅读一下是怎么实现的,如果有很多地方看不懂那么可以不用深究,往下学,笔者会在后面的知识点中讲解其中的运用。

我们希望串口这部分功能模块也能像定时器那样封装一个单独文件来使用。

所以创建好“uart.c”和“uart.h”文件,复制以下代码

2.uart.c的代码

#include <reg52.h>
#include <function.h>//详见第六章第8讲
  
void ConfigUART(u16 baud)
{
    SCON  = 0x50;  //配置串口为模式1
    TMOD &= 0x0F;  //清零T1的控制位
    TMOD |= 0x20;  //配置T1为模式2
    TH1 = 256 - (11059200/12/32)/baud;//计算T1重载值
    TL1 = TH1;     //初值等于重载值
    ET1 = 0;       //禁止T1中断
    ES  = 1;       //使能串口中断
    TR1 = 1;       //启动T1
} 
   
void printf_str(u8 *str)
{ 
    while(*str != '\0')//连续发送字符串数据,直到检测到结束符
    {
        SBUF=*str++;
        while(!TI);    //等待字节发送完成TI被置1就退出这个while循环
        TI = 0;        //清0标志位
    }  
}
  
void printf_num(u32 num)
{
    u8 buf[10];
    char i;//取值范围为-128~127
   
    for (i=0; i<10; i++)       //把长整型数转换为10位十进制的数组
    {
        buf[i] = num % 10;
        num = num / 10;        //舍掉个位数,重新装载
    }
   
    for (i=9; i>=1; i--)  
    {
        if (buf[i] != 0)break; //从最高位起,遇到0不理会,遇到非0则退出循环
    }
   
    while(i>=0)          //剩余低位都如实发送出去
    {   
        SBUF='0'+buf[i]; //如果此时的buf[i]的值是1,那么电脑端窗口在“字符格式”模式下要想显示字符“1”,只需'0'+1,因为‘0’就是ASCII码值48
        while(!TI);      //等待字节发送完成TI被置1就退出这个while循环
        TI = 0;          //清0标志位
        i--;   
    }
}
  
void printf_rn() //发送回车换行符
{
    SBUF='\r';
    while(!TI);  //等待字节发送完成TI被置1就退出这个while循环
    TI = 0;      //清0标志位
   
    SBUF='\n';
    while(!TI);  //等待字节发送完成TI被置1就退出这个while循环
    TI = 0;      //清0标志位
}

3.uart.h的代码

#ifndef __UART_H__
#define __UART_H__
  
void ConfigUART(u16 baud);
void printf_str(u8 *str);//发送字符串
void printf_num(u32 num);//发送参数的数值
void printf_rn();        //发送回车换行符
  
#endif

4.main.c的代码

#include <reg52.h> 
#include <function.h>//详见第六章第8讲
#include <uart.h>

void main()
{  
    u8 key;
    u32 value=65535;
    LED_Init();//初始化LED硬件模块
    KEY_Init();//初始化按键模块
    EA = 1;    //闭合总中断开关
    ConfigUART(9600);
  
    while(1)
    {  
        key=KEY_Scan(0,1000);
        if(key==4)
        {
            printf_str("value=");//发送字符串
            printf_num(value);   //发送变量的数值
            printf_rn();         //发送回车换行符
            value++;
        }
    } 
}
 
void InterruptUART() interrupt 4
{
    if (RI)    //接收到字节
    {
        RI = 0;//手动清零接收中断标志位                     
    }
}

在串口中断函数中我们没有再写“if(TI){ TI = 0; }”,那是因为我们在所有的发送函数中都做了TI的清0处理,所以可以在串口中断函数中不用再书写TI。

大家别忘了创建好“uart.c”和“uart.h”之后要添加到工程文件中

printf1


打开串口,选择“字符格式显示”模式,不断按K4,不停打印出如下内容

printf2

点赞(0)

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

Dotcpp在线编译      (登录可减少运行等待时间)