加入收藏 | 设为首页 | 会员中心 | 我要投稿 PHP编程网 - 黄冈站长网 (http://www.0713zz.com/)- 数据应用、建站、人体识别、智能机器人、语音技术!
当前位置: 首页 > 教程 > 正文

ARM 平台printf函数定位到uart输出详解

发布时间:2021-11-23 14:57:45 所属栏目:教程 来源:互联网
导读:1.1 ARM 串口输出函数uart_printf ARM如果能使用C函数库自带的printf函数格式输出,那多方便,但是默认的printf都是定位到stdout终端,而不是串口,本文章讲述的是如何定位到ARM的串口。 1.1.1 函数主要代码 有在Mini2440开发板上验证过 //*****************

1.1 ARM 串口输出函数uart_printf
ARM如果能使用C函数库自带的printf函数格式输出,那多方便,但是默认的printf都是定位到stdout终端,而不是串口,本文章讲述的是如何定位到ARM的串口。
 
1.1.1 函数主要代码
有在Mini2440开发板上验证过
 
//*****************main.c*******************************
 
#include"serial.h"
 
int Main()
 
{
 
unsignedint plck_val = 50000000;
 
unsignedint buad_val = 115200;
 
unsignedint ch_val = 0;
 
char*string="Hello,http://blog.csdn.net/wfq0624";
 
 uart_init();
 
 uart_printf("nr%sn",string);             
 
 uart_printf("rUse uart0nrParameter:PCLK is %d,buad is %d,uart_port is %d n",plck_val,buad_val,ch_val);
 
 uart_printf("r该函数不能打印浮点数!");            
 
 return 0;
 
}
 
//***********************serial.c**************************
 
#include"s3c2440.h"
 
#include"serial.h"
 
#include <stdarg.h>                                             //需要包含此stdarg.h头文件
 
#include <stdio.h>                                                              //需要包涵此stdio.h头文件
#define TXD0READY   (1<<2)
 
#defineRXD0READY   (1)
 
 
 
#definePCLK            50000000    // init.c中的clock_init函数设置PCLK为50MHz
 
#defineUART_CLK        PCLK        // UART0的时钟源设为PCLK
 
#defineUART_BAUD_RATE  115200      // 波特率
 
#defineUART_BRD        ((UART_CLK / (UART_BAUD_RATE * 16)) - 1)
 
voiduart_init()
 
{ //UART初始化:端口使能、功能设定、波特率、设置数据格式
 
 GPHCON = (GPHCON & ~(0xfff<<4)) |(0xaaa<<4);//端口配置成uart0、uart1,uart3
 
 GPHUP = 0x38; //端口GPH禁止上拉
 
 UFCON0 = 0x0; //禁止FIFO
 
 UMCON0 = 0x0; //禁止AutoFlow Control
 
 //Normal:No parity:One stop:8-bits 中断响应 UART clock: PCLK
 
 ULCON0 = 0x03;     // 8N1(8个数据位,无较验,1个停止位)
 
 UCON0  = 0x05;     // 查询方式,UART时钟源为PCLK
 
 UBRDIV0 = UART_BRD; // 波特率为115200
 
}
 
 
 
voiduart_send_byte(char data)
 
{
 
 while (!(UTRSTAT0 & TXD0READY));
 
 UTXH0 = data;
 
}
 
voiduart_send_string(char *string)
 
{
 
 while(*string)
 
 {
 
  uart_send_byte(*string++);
 
 }
 
}
 
void uart_printf(char *fmt,...)                                //这个才是本文重点
 
{
 
 va_listap;
 
 charstring[256];
 
 va_start(ap,fmt);
 
 vsprintf(string,fmt,ap);
 
 uart_send_string(string);
 
 va_end(ap);
 
}
 
//***************************************************
 
1.1.2    uart_printf分析
这里涉及到一个重要概念,变参函数,比如C库函数int printf(char *fmt, ...),就是一个典型的变参函数。
 
我们即将编写的uart_printf毫无疑问,也是一个变参函数。
 
 
 
可变参数入栈顺序
 
在进程中,堆栈地址是从高到低分配的.当执行一个函数的时候,将参数列表入栈,压入堆栈的高地址部分,然后入栈函数的返回地址,接着入栈函数的执行代码,这个入栈过程,堆栈地址不断递减,一些黑客就是在堆栈中修改函数返回地址,执行自己的代码来达到执行自己插入的代码段的目的.
 
总之,函数在堆栈中的分布情况是:地址从高到低,依次是:函数参数列表,函数返回地址,函数执行代码段.
 
堆栈中,各个函数的分布情况是倒序的.即最后一个参数在列表中地址最高部分,第一个参数在列表地址的最低部分.参数在堆栈中的分布情况如下:
 
  最后一个参数
 
  倒数第二个参数
 
  ...
 
  第一个参数
 
  函数返回地址
 
  函数代码段

(编辑:PHP编程网 - 黄冈站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读