Arduino代码机制-Serial上

来源:互联网 发布:网络电玩游戏 编辑:程序博客网 时间:2024/05/16 06:44

串口调试是个非常有用的调试技巧,可以在程序中是有Serial.print()输出关键信息,Serial还能与别的设备进行串口通信。Serial是类HardwareSerial的一个对象,用这个对象可以操作串口0。对于有些单片机不止一个串口的,可以用Serial1操作串口1,Serial2操作串口2,Serial3操作串口3。

从源文件中可以看到几个类的继承关系,HardwareSerial继承类Stream,Stream继承类Print。

按照继承顺序,先讲Print类。
Print类是个非常有用的类。
由名字能看出来,这个类的作用是打印数据。通过不同的东西打印的过程都是一样的,只是最底层实现不一样。

最底层的实现就是打印一个字符

如果用不同硬件,那么打印一个字符的方式将会不一样。如果用串口的话,那么这一个字符的数据将会按位发送出去,如果要在LCD液晶屏上打印一个字符的话,那又会不一样。除此之外,其他部分都一样了。比如要打印一个字符串的话,可以逐个打印每一个字符,如果要打印数字123的话,那么就需要打印三个字符。这些内容不管是在串口上还是在LCD上还是在其他硬件上都是一样的。

因此,可以写一个类,给出共同部分的实现,而最底层实现写成虚函数。同时还包含了一些反应运行时状态(是否传送错误)的变量与方法。这个类就是Print类。

Print类

write

Print类给出了两个虚函数,分别用来发送一个字符和一个字符串

virtual size_t write(uint8_t) = 0;virtual size_t write(const uint8_t *buffer, size_t size);

write(uint8_t c)这个函数是要在子类中实现的,当调用这个函数时,打印c对应的那个字符。比如

unsigned char ch = 'B';write('A');write(ch);

将会打印字符A和B。
第二个为打印长度为size的字符串。也需要在子类中实现。
还有另外两个write函数,需要用这两个虚函数实现

size_t write(const char *str) {  if (str == NULL) return 0;  return write((const uint8_t *)str, strlen(str));}size_t write(const char *buffer, size_t size) {  return write((const uint8_t *)buffer, size);}

print

Print类中为了能打印多种类型的数据,重载了很多个print和println。特别好的是,能打印String类型的对象和Flash中的字符串。
1.打印Flash中字符串

size_t print(const __FlashStringHelper *);

调用这个函数能打印位于Flash中的字符串,关于__FlashStringHelper在上一篇中讲到,有两种方法能使用这个函数,一个是用宏F,或者是强制类型转换:

print(F("it's a string in flash"));const char* str = PSTR("it's a string in flash");print((const __FlashStringHelper*)str);

如果要打印String类型对象
2.打印String类型对象

size_t print(const String &);

print支持打印String类型对象实在是太方便了,String有着强大的字符串处理功能,Print类支持这种对象的打印使得编程大大简单了很多。

3.打印字符

size_t print(char c);

4.打印字符串

size_t print(const char[]);

5.打印整形,这时候需要指定数字的进制,默认为十进制。

size_t print(unsigned char, int = DEC);size_t print(int, int = DEC);size_t print(unsigned int, int = DEC);size_t print(long, int = DEC);size_t print(unsigned long, int = DEC);

6.打印浮点类型

size_t print(double, int = 2);

println

println与print功能相同,只是每次打印结束时额外打印两个控制符,分别是\r回车和\n回车换行。

print和write的区别

说清楚这个问题还是不太容易的。用例子来说,先看write。

int a = 0x4141;char b = 'a';write(a);write(b);write((unsigned char)b);

由于write只能接受unsigned char类型的变量,第一句write会将int 强制转换为unsigned char类型,高字节部分将丢弃,最终显示0x41对应的字符A。第二句write也会强制类型转换,显示字符a。第三句传入的就是unsigned char类型,会显示字符a。

int a = 0x4141;char b = 'a';print(a);print(b);print(unsigned char)b);

第一句print会调用函数print(int, int = DEC),默认为十进制。因此会将a转化为十进制显示,最终显示为16705(0x4141的十进制)。
第二句会调用print(char),需要看一下函数的实现:

size_t Print::print(char c){  return write(c);}

这里直接调用了write函数,因此将显示字符a。
第三句会调用print(unsigned char, int = DEC),这时候会显示数字了,将字符a对应的数字以十进制显示出来,所以显示的结果是97。

说完了write和print的区别了,能自己总结咩。

在使用print时,参数类型为char和unsigned char结果是不一样的,前者将会显示字符,后者将会显示数字。

1 0
原创粉丝点击