最近公司拓展要在树莓派上研发一些新项目,以前一直只是听说树莓派,但是没接触过。

而树莓派关于串口通信有以下三种方案,根据我的项目选择了wiringPi,

    【python GPIO】
    【开发语言】——python
    【简单介绍】——该库更确切的名称为raspberry-gpio-python,树莓派官方资料中推荐且容易上手。python GPIO是一个小型的python库,可以帮助用户完成raspberry相关IO口操作。但是python GPIO库还没有支持SPI、I2C或者1-wire等总线接口。除了python GPIO之外,还有众多的python扩展库(例如webiopi),毫无疑问的说python非常适合树莓派,树莓派也非常适合python。

    【wiringPi】
    【开发语言】——C语言
    【简单介绍】——wiringPi适合那些具有C语言基础,在接触树莓派之前已经接触过单片机或者嵌入式开发的人群。wiringPi的API函数和arduino非常相似,这也使得它广受欢迎。作者给出了大量的说明和示例代码,这些示例代码也包括UART设备,I2C设备和SPI设备等,毫无疑问地说wiringPi功能非常强大。

    【BCM2835 C Library】
    【开发语言】——C语言
    【简单介绍】BCM2835 C Library可以理解为使用C语言实现的相关底层驱动,它给我的感觉更像STM32的库函数,BCM2835 C Library的驱动库包括GPIO、SPI和UART等,可以通过学习BCM2835 C Library熟悉BCM2835相关的寄存器操作。如果有机会开发树莓派上的linux驱动,或自主开发python或PHP扩展驱动,可以从BCM2835 C Library找到不少的“灵感”。

接下来就了解一下wiringPi库,下面的说明都是我从官方手册翻译过来的​​http://wiringpi.com/​

设置

有四种方法来初始化wiringPi

int wiringPiSetup (void) ;
int wiringPiSetupGpio (void) ;
int wiringPiSetupPhys (void) ;
int wiringPiSetupSys (void) ;

必须在程序开始时调用其中一个设置功能,否则您的程序将无法正常运行。您可能会从中遇到一些症状,而这些症状根本无法解决段错误和计时问题。

注意:如果这些功能由于任何原因失败,则connectionPi版本1返回错误代码。版本2返回总是返回零。在讨论和检查了connectionPi用户编写的许多程序并观察到很多人都没有去检查返回码后,我采取了这样的态度:如果connectionPi设置功能之一失败,则将其视为致命的程序错误,并且此时程序执行将终止,并在终端上显示一条错误消息。

  • 如果要还原v1行为,则需要设置环境变量:WIRINGPI_CODES(为任何值,只需要存在即可)


设置功能之间的差异如下:

wiringPiSetup (void) ;

这初始化wiringPi并假定调用程序将要使用wiringPi引脚编号方案。这是一种简化的编号方案,提供了从0到16的虚拟引脚号到实际的基础Broadcom GPIO引脚号的映射。请参阅​​引脚页面​​以获取将接线Pi引脚号与Broadcom GPIO引脚号映射到边缘连接器上物理位置的表。

需要使用root特权来调用此函数。

routingPiSetupGpio (void) ;

这与上面相同,但是它允许调用程序直接使用Broadcom GPIO引脚号,而无需重新映射。

如上所述,此功能需要使用root特权来调用,并且请注意,某些引脚与版本1到版本2板不同。

connectionPiSetupPhys (void) ;

与上述相同,但是它允许调用程序仅使用P1连接器上的物理引脚号。

如上所述,需要使用root特权来调用此函数。

wiringPiSetupSys (void) ;

这将初始化connectionPi,但是使用/ sys / class / gpio接口,而不是直接访问硬件。如果事先使用gpio程序导出了GPIO引脚,则可以称为非root用户。在此模式下,引脚编号是本机Broadcom GPIO编号-与上面的connectionPiSetupGpio()相同,因此请注意Rev 1和Rev 2板之间的差异。

注意:在这种模式下,您只能在运行程序之前使用通过/ sys / class / gpio接口导出的引脚。您可以在单独的shell脚本中执行此操作,也可以在程序内部使用system()函数来调用gpio程序。

另外请注意,某些功能使用此模式时,有没有影响,因为他们目前还不能操作,除非称为具有root权限。(尽管您可以根据需要使用system()调用gpio来设置/更改模式)

核心函数

这些功能可以直接在Raspberry Pi上使用,也可以与外部GPIO模块(例如GPIO扩展器等)一起使用,尽管并非所有模块都支持所有功能-例如PiFace已预先配置为其固定的输入和输出,而Raspberry Pi没有板载模拟硬件。

void pinMode (int pin, int mode) ;

会将引脚的模式设置为INPUTOUTPUTPWM_OUTPUTGPIO_CLOCK。请注意,只有wireingPi引脚1(BCM_GPIO 18)支持PWM输出,只有wireingPi引脚7(BCM_GPIO 4)支持CLOCK输出模式。

Sys模式下,此功能无效。如果您需要更改引脚模式,则可以在启动程序之前使用脚本中的gpio程序进行操作。

void pullUpDnControl (int pin, int pud) ;

这将在给定的引脚上设置上拉或下拉电阻器模式,应将其设置为输入。与Arduino不同,BCM2835都具有下拉内部电阻器。参数pud应该是;PUD_OFF,(不上拉/下拉),PUD_DOWN(上拉至接地)或PUD_UP(上拉至3.3v)在Raspberry Pi上,内部上拉/下拉电阻的阻值约为50KΩ。

处于Sys模式时,此功能对Raspberry Pi的GPIO引脚无效。如果您需要激活上拉/下拉,则可以在启动程序之前使用脚本中的gpio程序进行激活。

void digitalWrite (int pin, int value) ;

将值HIGHLOW(1或0)写入必须预先设置为输出的给定引脚。

WiringPi将任何非零数字视为 HIGH,但是0是 LOW的唯一表示。

void pwmWrite (int pin, int value) ;

将值写入给定引脚的PWM寄存器。Raspberry Pi有一个板载PWM引脚,即引脚1(BMC_GPIO 18,物理层12),范围为0-1024。其他PWM器件可能具有其他PWM范围。

Sys模式下,此功能无法控制Pi的板载PWM 。

int digitalRead (int pin) ;

该函数返回在给定引脚上读取的值。根据引脚上的逻辑电平,它将为高电平低电平(1或0)。

analogRead (int pin) ;

这将返回在提供的模拟输入引脚上读取的值。您将需要注册其他模拟模块才能为Gertboard,quick2Wire模拟板等设备启用此功能。

analogWrite (int pin, int value) ;

这会将给定值写入提供的模拟引脚。您将需要注册其他模拟模块才能为诸如Gertboard之类的设备启用此功能。

树莓派特性

这些功能不是核心connectionPi集中的一部分,而是专门作用于Raspberry Pi硬件本身。但是,某些外部硬件驱动程序模块可能会提供某些此功能。

void digitalWriteByte (int value) ;

这将写入提供给前8个GPIO引脚的8位字节。尽管仍然需要对Pi的GPIO硬件进行两次写操作,但这是一次将所有8位都设置为特定值的最快方法。

pwmSetMode (int mode) ;

PWM发生器可以两种模式运行-“平衡”和“ mark:space”。mark:space模式是传统模式,但是Pi的默认模式是“平衡”模式。您可以通过提供参数PWM_MODE_BALPWM_MODE_MS来切换模式。

pwmSetRange (unsigned int range) ;

这将在PWM发生器中设置范围寄存器。默认值为1024。

pwmSetClock (int divisor) ;

这将设置PWM时钟的除数。

注意:在Sys模式下不能使用PWM控制功能。要了解有关PWM系统的更多信息,您需要阅读Broadcom ARM外设手册。

piBoardRev (void) ;

这将返回Raspberry Pi的主板修订版。从1版到2版时,某些BCM_GPIO引脚会更改编号和功能,因此,如果您使用的是BCM_GPIO引脚编号,则需要了解它们之间的区别。

wpiPinToGpio (int wPiPin) ;

此返回供给的BCM_GPIO管脚号wiringPi销。它考虑了董事会修订。

physPinToGpio (int physPin) ;

这将返回P1连接器上提供的物理引脚的BCM_GPIO引脚号。

setPadDrive (int group, int value) ;

这为特定的一组引脚设置了焊盘驱动器的“强度”。有3组引脚,驱动强度为0到7。除非您知道自己在做什么,否则请不要使用它。

定时



虽然Linux提供了许多系统调用和功能来提供各种定时和睡眠功能,但有时可能会造成很大的混乱,尤其是如果您是Linux的新手,因此此处介绍的功能模仿了Arduino平台上可用的功能,从而移植了代码并编写新代码要容易一些。

注意:即使您没有使用任何输入/输出功能,您仍需要调用其中的一项connectionPi设置功能– 如果您不需要在程序中进行超级用户访问,请仅使用connectioningPiSetupSys(),并记住#include <wiringPi .h>

unsigned int millis (void)

这将返回一个数字,该数字表示自您的程序调用wireingPiSetup函数之一以来的毫秒数。它返回一个无符号的32位数字,该数字在49天后自动换行。

unsigned int micros (void)

这将返回一个数字,该数字表示自您的程序调用wireingPiSetup函数之一以来的微秒数。它返回一个无符号的32位数字,该数字会在大约71分钟后自动换行。

void delay (unsigned int howLong)

这将导致程序执行至少暂停 毫秒由于Linux的多任务性质,它可能会更长。请注意,最大延迟是无符号的32位整数或大约49天。

void delayMicroseconds (unsigned int howLong)

这将导致程序执行暂停至少howLong 微秒由于Linux的多任务性质,它可能会更长。请注意,最大延迟是无符号的32位整数微秒或大约71分钟。

小于100微秒的延迟是通过持续轮询系统时间的硬编码循环来计时的,大于100微秒的延迟是使用系统nanosleep()函数完成的–您可能需要考虑非常短的延迟对系统整体性能的影响,尤其是在使用线程的情况下。



 

串口库



WiringPi包括一个简化的串行端口处理库。它可以使用板载串行端口,也可以使用任何没有特殊区别的USB串行设备。您只需在初始打开功能中指定设备名称。

若要使用,请确保您的程序包含以下文件:

#include <wiringSerial.h>

然后可以使用以下功能:

int serialOpen (char *device, int baud) ;

这将打开并初始化串行设备并设置波特率。它将端口设置为“原始”模式(一次为字符且不进行翻译),并将读取超时设置为10秒。返回值是文件描述符或任何错误的-1,在这种情况下,将适当地设置errno

void serialClose (int fd) ;

关闭由给定文件描述符标识的设备。

void  serialPutchar (int fd, unsigned char c) ;

将单个字节发送到给定文件描述符标识的串行设备。

void  serialPuts (int fd, char *s) ;

将以nul结尾的字符串发送到由给定文件描述符标识的串行设备。

void  serialPrintf (int fd, char *message, ) ;

将系统printf功能仿真到串行设备。

int   serialDataAvail (int fd) ;

返回可读取的字符数,或者对于任何错误情况返回-1,在这种情况下,将正确设置errno

int serialGetchar (int fd) ;

返回串行设备上可用的下一个字符。如果没有可用数据,此调用将最多阻塞10秒钟(返回-1时)

这里我想说一句他这里的阻塞时间太长,最好不要直接调用这个函数,而采用下面的方式

int recbytenum = serialDataAvail(filedevid);
if(recbytenum > 0)
{
i=0;
while(recbytenum--)
{
buf[i++] = serialGetchar(filedevid);
}
}
void serialFlush (int fd) ;

这会丢弃接收到的所有数据,或等待向下发送给定设备的所有数据。

注意:返回的文件描述符(fd)是标准的Linux文件描述符。您可以根据需要在此文件描述符上使用标准的read(),write()等系统调用。例如,您可能希望编写更大的二进制数据块,其中serialPutchar()或serialPuts()函数可能不是最适合使用的函数,在这种情况下,可以使用write()发送数据。

先进的串口控制

wiringSerial库旨在提供简化的控制-适用于大多数应用,但是如果你需要先进的控制- (!通过USB适配器,有没有对皮的板载UART),例如奇偶性控制,调制解调器控制线等,那么您需要以“老式”方式进行一些此类操作。

例如–要将串行线设置为7位模式加上偶数奇偶校验,您需要执行此操作…

在您的程序中:



#include <termios.h>

并在一个函数中:

struct termios options ;

tcgetattr (fd, &options) ; // Read current options
options.c_cflag &= ~CSIZE ; // Mask out size
options.c_cflag |= CS7 ; // Or in 7-bits
options.c_cflag |= PARENB ; // Enable Parity - even by default
tcsetattr (fd, &options) ; // Set new options

 上面的'fd'变量是serialOpen()返回的文件描述符。

有关可以设置的所有选项,请参见tcgetattr的手册页。

man tcgetattr