打印
[ARM入门]

众拳【STM8入门】第25讲 STM8 Printf重定向

[复制链接]
2441|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
第25讲.STM8 Printf重定向.zip (311.09 KB)
众拳【剑齿虎STM8】开发板学习笔记分享
25讲   STM8 Printf重定向
25.1 STM8 Printf重定向概述   
在编程和调试的过程中,有些内部参数我们想及时知道它们当前的数值是多少,比如我们自己定义了一个变量i”,那么这个变量“i”的数值是多少?像这样的问题我们可以有几种方法可以实现我们的观察。
(1). 我们可以通过开发板LCD输液晶屏显示出来;
(2). 我们可以通过数码管显示参数
(3). 有一些简单的的参数可以通过发光二极管显示;
(4). 通过串口输出到计算机屏幕上显示出来;
在以上4中方法中,第4种使用起来最为方便,并且STM8提供了一个专用的打印输出函数Printf,它直接就可以把一些我们需要观察的参数打印到串口输出,不需要我们额外的编写程序。通过以上说明我们可以看看Printf函数是怎样实现的。
25.1.1  Printf重定向
(1). printf打印输出格式:printf("%d",d1);
        %d     按照十进制整型数打
        %x     按照十六进制打印
        %c     打印字符
        %s     打印字符串
        %6.2d  按照十进制整型数打印,至少6个字符宽,至少2个数据位
        %6.2x  按照十六进制小写打印,至少6个字符宽,至少2个数据位
        %6.2X  按照十六进制大写打印,至少6个字符宽,至少2个数据位
(2). STM8单片机中长整型(u32)数据类型打印方法:
        %6.2ld  按照十进制整型数打印,至少6个字符宽,至少2个数据位
        %6.2lx  按照十六进制小写打印,至少6个字符宽,至少2个数据位
        %6.2lX  按照十六进制大写打印,至少6个字符宽,至少2个数据位
(3). STM8单片机不支持浮点类型数据打印输出,但可以自己编写写程序实现。
25.1.2  Printf重定向函数
对于这个函数,如果在程序中引用它,我们需要做哪些工作才可以正确使用它呢?
u 首先需要引用这个头文件才能实现#include <stdio.h>”;
u 接着书写这个定义函数段:
     #ifdef __GNUC__
        #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
     #else
        #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
     #endif /* __GNUC__ */
u 重要的还有发送通道选择,Printf我们习惯使用串口1作为输出通道。
PUTCHAR_PROTOTYPE //发送一个字符协议
{
/* Printf内容发往串口 */
  UART1_SendData8((unsigned char) ch);
  while (!(UART1->SR & UART1_FLAG_TXE));//如果发送未完成, //标志位未置位,则循环等待
  return (ch);
}
25.2实验目的   
通过Printf重定向函数打印输出我们需要观测的参数状态。通过“蓝精灵多功能监控软件”串口调试窗口观测这些数据。
25.3程序文件设计25.3.1  Printf重定向IAR软件配置过程
IAR软件中我们要做一些设置,下面说一下设置过程。
25.1 “IAR”软件中选项功能进入方法
IAR软件中打开工程文件,选中主文件名称,在其上点击右键弹出对话框,选中“Options”,弹出配置对话框,如“图25.2 “IAR”软件中printf配置”。把第3块选项卡置前,然后把“library”选择框选为“Full”,确定。这样printf才能正常使用。
25.2 “IAR”软件中printf配置
25.3.2  main.c文件中的程序
主程序就实现初始化和调用驱动程序,这样主程序控制思路清晰,流程简单。要想了解全面详实的程序,请大家参考光盘(网盘)中程序及程序注释。
/***********************************************************************
*   说    明: printf重定向实验
*   开发平台: 剑齿虎STM8开发板        
*   关注微信公众平台微信号:"zxkj-ly",免费获取STM8资料。
*   STM8技术交流QQ群【335123291】
*   哈尔滨卓恩科技开发有限公司
*
*   作    者: 刘洋 张殿东
*   版    本: V1.0
*   日    期: 2016-05-03   
*
*   IAR开发环境    版本 V2.20.1
*   ST库函数       版本 V2.2.0
***********************************************************************/
#include "pbdata.h"//引入自定义公共头文件
void BSP_Configuration(void);//硬件初始化函数声明
/***********************************************************************
*   函 数 名: main
*   功能说明: c程序入口
*   形    参:无
*   返 回 值: 错误代码(无需处理)
***********************************************************************/
int main(void)
{
  BSP_Configuration();//硬件驱动初始化函数
  while(1)//主程序循环,反复执行循环体里的语句
  {
    UART1_Printf_Demo();
  }
}
/***********************************************************************
*   函 数 名: BSP_Configuration
*   功能说明: 初始化硬件设备。只需要调用一次。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。
*   形    参:无
*   返 回 值: 无
***********************************************************************/
void BSP_Configuration(void)
{  
  CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);//时钟速度为内部16M,1分频,
  UART1_Congfiguration();//调用RS232串口1初始化函数
  LED_Init();//调用LED初始化函数
  rim();//打开总中断
}
/*断言函数:它的作用是在编程的过程中为程序提供参数检查*/
#ifdef USE_FULL_ASSERT
void assert_failed(u8* file,u32 line)
{
  while(1)
  {
  }
}
#endif
25.3.3  pbdata.c文件中的程序
#include "pbdata.h"   //引入自定义公共头文件
/***************************************************************************
*   函 数 名: delay_us
*   功能说明: 微秒延时程序,注意此函数的运行环境为(16M时钟速度)
*   形    参:nCount要延时的微秒数,输入nCount=1微妙
*   返 回 值: 无
***************************************************************************/
void delay_us(u16 nCount)   //16M 晶振时  延时 1个微妙
{
    nCount*=3;//等同于 nCount=nCount*3  相当于把nCount变量扩大3倍
    while(--nCount);//nCount变量数值先减一,再判断nCount的数值是否大于0,大于0循环减一,等于0退出循环。
}
/***************************************************************************
*   函 数 名: delay_ms
*   功能说明: 毫秒延时程序,注意此函数的运行环境为(16M时钟速度)
*   形    参:nCount要延时的毫秒数,输入nCount=1毫秒
*   返 回 值: 无
***************************************************************************/
void delay_ms(u16 nCount)  //16M 晶振时  延时 1个毫秒
{
    while(nCount--)//先判断while()循环体里的nCount数值是否大于0,大于0循环,减一执行循环体,等于0退出循环。
    {
        delay_us(1000);//调用微妙延时函数,输入1000等译演示1毫秒。
    }
}
/***************************************************************************
*   函 数 名: Get_decimal
*   功能说明: 获得数值小数部分
*   形    参:dt输入数据 deci小数位数,最多保留4位小数
*   返 回 值: 放大后的小数部分
***************************************************************************/
u16 Get_decimal(double dt,u8 deci)   //获得数值小数部分
{
    long x1=0;
    u16 x2=0,x3=0;
    if(deci>4) deci=4;
    if(deci<1) deci=1;
    x3=(u16)pow(10, deci);
    x1=(long)(dt*x3);
    x2=(u16)(x1%x3);
    return x2;
}
25.3.4  pbdata.h文件中的程序
#ifndef _PBDATA_H//宏定义,定义文件名称
#define _PBDATA_H
#include "stm8s.h"//引入STM8的头文件
#include <stdio.h>//需要引用这个头文件才能实现
#include "math.h"//需要引用这个头文件才能实现
#include "led.h"  //引用LED头文件
#include "uart1.h"//引用RS232头文件
void delay_us(u16 nCount); //微秒延时程序
void delay_ms(u16 nCount); //毫秒延时程序
u16 Get_decimal(double dt,u8 deci);   //获得数值小数部分
#endif //定义文件名称结束
25.3.5  uart1.c文件中的程序
#include "pbdata.h"
/***************************************************************************
*   函 数 名: UART1_Congfiguration
*   功能说明: UART1 配置函数
*   形    参:无
*   返 回 值: 无
***************************************************************************/
void UART1_Congfiguration(void)
{
    //配置串口参数为:波特率115200,8位数据位,1位停止位,无校验,禁止同步传输,允许接收发送    UART1_Init((u32)115200,UART1_WORDLENGTH_8D,UART1_STOPBITS_1,UART1_PARITY_NO,UART1_SYNCMODE_CLOCK_DISABLE,UART1_MODE_TXRX_ENABLE);
    UART1_ITConfig(UART1_IT_RXNE_OR, ENABLE);//使能接收中断
    UART1_Cmd(ENABLE);//使能UART1
}
/***************************************************************************
*   函 数 名: UART1_Send_Byte
*   功能说明: UART1发送数据函数
*   形    参:u8 byte  一次发送一个字节
*   返 回 值: 无
***************************************************************************/
void UART1_Send_Byte(u8 byte)
{
    UART1_SendData8(byte);//UART1发送8位数据
    while(UART1_GetFlagStatus(UART1_FLAG_TXE)==RESET);//等待发送完成
}
void UART1_Printf_Demo(void)
{
    //u16 d2=123;
    //u32 d1=12345678;
    //u8 d3='a';
    //u8 d5[5];
  double d4=(double)145.23412;
  printf("%d.%d\r\n",(u16)d4,Get_decimal(d4,4));
  printf("%d.%d\r\n",(u16)d4,Get_decimal(d4,2));
    //printf("%ld\r\n",d1);
    //printf("%6.4d\r\n",d2);
    //printf("%8x\r\n",d2);
    //printf("%X\r\n",d2);
    //printf("%c\r\n",d3);
    /*d5[0]='a';
    d5[1]='b';
    d5[2]='c';
    d5[3]='d';
    d5[4]='\0';
    printf("%s\r\n",d5);*/
    while(1);
}
//printf函数
#ifdef __GNUC__
    #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
    #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
PUTCHAR_PROTOTYPE //发送一个字符协议
{
/* 将Printf内容发往串口 */
  UART1_SendData8((unsigned char) ch);
  while (!(UART1->SR & UART1_FLAG_TXE));//如果发送未完成, //标志位未置位,则循环等待
  return (ch);
}


相关帖子

沙发
刘洋讲单片机|  楼主 | 2017-1-11 14:20 | 只看该作者
25.3.6  uart1.h文件中的程序
/***********************************************************************
*    剑齿虎STM8开发板硬件连接
*    PA4/UART1_RXD         
*    PA5/UART1_TXD         
************************************************************************/
#ifndef _UART1_H //宏定义,定义文件名称
#define _UART1_H
/*---------------------------头文件引用-----------------------------------*/
#include "stm8s.h"
/*---------------------------函数声明------------------------------------*/
void UART1_Congfiguration(void);//UART1 配置函数
void UART1_Send_Byte(u8 byte);//UART1发送数据函数
void UART1_Printf_Demo(void);
#endif//定义文件名称结束
25.3.7  补充说明
在C语言中,有一类库函数称为标准输入输出函数,可以用来从键盘读取键入的字符,以及将字符在屏幕上输出。这类函数的声明都包含在头文件stdio.h中。下面就先来谈谈主要的标准输出函数(printf函数)的用法:
一、printf()函数是格式化输出函数,一般用于向标准输出设备按规定格式输出信息。在编写程序时经常会用到此函数。printf()函数的调用格式为:
    printf("<格式化字符串>",<参量表>);
其中格式化字符串包括两部分内容:一部分是正常字符,这些字符将按原样输出;另一部分是格式化规定字符,以"%"开始,后跟一个或几个规定字符, 用来确定输出内容格式。
  参量表是需要输出的一系列参数, 其个数必须与格式化字符串所说明的输出参数个数一样多,各参数之间用“,”分开,且顺序一一对应,否则将会出现意想不到的错误。
    格式化字符串的格式是:
    %[标志][输出最小宽度][.精度][长度]格式字符
      标志          意义
           -        结果左对齐,右边填空格
           +        输出符号(正号或负号)
          空格       输出值为正时输出空格,为负时输出负号
           #        在八进制和十六进制线显示前导航O,Ox

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

148

主题

499

帖子

63

粉丝