韦东山ARM裸机和uboot大全(第1期加强版)学习笔记11-第011课_串口的使用

一串口知识基础

  1. TTL电平
    TTL是Transistor-Transistor Logic,即晶体管-晶体管逻辑的简称,它是计算机处理器控制的设备内部各部分之间通信的标准技术。TTL电平信号应用广泛,是因为其数据表示采用二进制规定,+5V等价于逻辑”1”,0V等价于逻辑”0”。

数字电路中,由TTL电子元器件组成电路的电平是个电压范围,规定:
输出高电平>=2.4V,输出低电平<=0.4V;
输入高电平>=2.0V,输入低电平<=0.8V。
韦东山ARM裸机和uboot大全(第1期加强版)学习笔记11-第011课_串口的使用_第1张图片
2. RS232电平
RS232电平是串口的一个标准。
在TXD和RXD数据线上:
  (1)逻辑1为-3~-15V的电压
  (2)逻辑0为3~15V的电压
在RTS、CTS、DSR、DTR和DCD等控制线上:
  (1)信号有效(ON状态)为3~15V的电压
  (2)信号无效(OFF状态)为-3~-15V的电压
这是由通信协议RS-232规定的。

RS-232:标准串口,最常用的一种串行通讯接口。有三种类型(A,B和C),它们分别采用不同的电压来表示on和off。最被广泛使用的是RS-232C,它将mark(on)比特的电压定义为-3V到-12V之间,而将space(off)的电压定义到+3V到+12V之间。传送距离最大为约15米,最高速率为20kb/s。RS-232是为点对点(即只用一对收、发设备)通讯而设计的,其驱动器负载为3~7kΩ。所以RS-232适合本地设备之间的通信。
韦东山ARM裸机和uboot大全(第1期加强版)学习笔记11-第011课_串口的使用_第2张图片

二 从零实现用于裸机调试的printf函数

  1. printf在是一个标准库函数,功能是:打印(变量、字符串)等等。
    问题:能不能依据printf的原理,写一个简易的用于裸机程序调试的my_printf函数呢?
  2. 函数原型
//====================================================
//printf的声明
int printf(const char *format, ...);
//format:固定参数
//...   :可变参数(变参)
  1. 函数使用示例
    韦东山ARM裸机和uboot大全(第1期加强版)学习笔记11-第011课_串口的使用_第3张图片
    printf中的格式字符
    韦东山ARM裸机和uboot大全(第1期加强版)学习笔记11-第011课_串口的使用_第4张图片
  2. 可变参数

1)c语言指针的复习

2)代码:手工确定可变参数

①函数调用push_test("abcd",123);

int push_test(const char *format, ...)
{
	char *p = (char *)&format;
	//参数1
	printf("arg1 : %s\n",format);	 
	//参数2
	p = p + sizeof(char *);
	i = *((int *)p);
	printf("arg2 : %d\n",i);   
	...
}

②函数调用

struct  person{
	char *name;
	int  age;
	char score;
	int  id;
};
struct  person per={"www.100ask.org",10,'A',123};
push_test("abcd",123,per);

如何实现push_test函数呢?

int push_test(const char *format, ...)
{
	char *p = (char *)&format;
	int i;
	struct  person per;  
	
	printf("arg1 : %s\n",format);	 

    //==============
	/*指针对连续空间操作时: 1) 取值  2)移动指针*/  
	p = p + sizeof(char *);
	i = *((int *)p);
	printf("arg2 : %d\n",i);   

    //==============             
	/*指针对连续空间操作时: 1) 取值  2)移动指针*/    
	p = p + sizeof(int);  
	per = *((struct  person *)p);  
	printf("arg3: .name = %s, .age = %d, .socre=%c  .id=%d\n",\
		          per.name,   per.age,   per.score, per.id);   
}

③由于在x86(32位机器)平台下,GCC编译器默认按4字节对齐,
如:结构体4字节对齐,即结构体成员变量所在的内存地址是4的整数倍。
可以通过使用gcc中的__attribute__选项来设置指定的对齐大小。

 struct  person{
	char *name;
	int  age;
	char score;
	int  id;
};
/*1):__attribute__ ((packed)),让所作用的结构体取消在编译过程中的优化对齐,
	   按照实际占用字节数进行对齐。
*/
struct  person1{
	char *name;
	int  age;
	char score;
	int  id;
}__attribute__ ((packed));
/*2):__attribute((aligned (n))),让所作用的结构体成员对齐在n字节边界上。
	  如果结构体中有成员变量的字节长度大于n,则按照最大成员变量的字节长度来对齐。
*/
struct  person2{
	char *name;
	int  age;
	char score;
	int  id;
}__attribute((aligned (4)));

④变参数传递过程中:浮点数默认按照double型变量传递。

3)代码:自动确定可变参数

你可能感兴趣的:(韦东山ARM裸机和uboot大全(第1期加强版)学习笔记11-第011课_串口的使用)