串行I/O有如下两个API函数:
printf()函数通常在特定函数中调用,这些特定函数来自所使用编译器套件提供的标准C库,读者可参考国际标准化组织ISO 标准C库对该函数的完整描述。要注意的是,一些嵌入式C库实现的printf()函数不支持浮点运算,格式化输出字符串后printf()仅调用函数putchar(),函数putchar()有一个依赖于硬件的实现,该实现一次向串口发送一个字节。
Contiki 操作系统有一个基于“行”的串行通信通用接口,该接口的定义在文件core\dev\serial-line.h 中,在使用该单元之前,需要调用函数serial_line_init(),以便初始化所需要的serial_line_process 和环形(ring)缓存。要注意的是,在调用函数serial_line_init()之前必须调用函数process_init()将serial_line_process添加到进程列表process_list中。
图5-1 读取字符中断
当准备从串口读取字符时会产生中断, 中断处理程序调用serial_line_input_byte()函数,该函数将接收的数据填充到缓存中直到接收到新行符(new-line)为止。如果接收到完整的行,系统将给所有进程广播一个事件serial_line_event_message。函数serial_line_input_byte()是一个回调函数,在几种Contiki 操作系统支持的平台中,该函数从串口驱动程序中接收输入字节填充本地缓存直到接收到行中断为止,之后再轮询serial_line_process 进程。通过参数SERIAL_LINE_CONF_BUFSIZE 可以为串行接口设置本地缓存大小,默认值为80 字节。如果接收行太长,只有SERIAL_LINE_CONF_BUFSIZE- 1个字节和nil 字节将被传递到serial_line_process 进程。进程serial_line_process将会给所有进程广播serial_line_event_message 消息以及接收到的字符串(事件数据指针指向的)。
串行驱动程序有两个控制输入的宏定义:IGNORE_CHAR(c)、END。宏IGNORE_CHAR(c)提供了一种简单的过滤器,如果字符c不应该放入本地串行缓存则返回真值,目前的定义仅过滤回车键(ASCⅡ码是0x0D)。宏END指定可能导致轮询serial_line_process 进程的符号,目前设置为行中断(ASCⅡ码0x0a)符号。
当处理器处于具有低功耗模式的平台时,为了进一步地处理,函数serial_line_input_byte() 可以指明CPU 是否需要保持唤醒状态。 由于serial_line_input_byte()函数通常是在串行驱动程序中由中断处理调用,所以它可以在低功耗模式下调用。因此,如果需要进一步处理,Contiki 操作系统的硬件相关部分必须确保CPU 进入活动模式,以便能够调度其他可能对串行通信感兴趣的进程执行。为此,Contiki操作系统中的所有单字节串行输入函数,包括serial_line_input_byte(),必须指明是否系统应该继续处于休眠模式。非零返回值指定CPU 进入活动模式,反之,零返回值告诉驱动程序系统可以继续保持低功耗模式下的休眠状态。
图5-2 串行通信
当底层设备驱动程序接收到行中断时, 广播串行事件serial_line_event_message 给所有进程,事件数据中包含具有数据行的字符串。下面的例子说明了串行通信的方法,运行结果如图5-2所示。(www.xing528.com)
我们也可以使用如下回调函数实现串行通信,运行结果见图5-3。
图5-3 回调函数实现串行通信
该例中uart_rx_callback()函数是串口回调函数,当新的字节到达时Contiki系统调用该函数,所以该例中不需要前例中所使用的事件监控代码if(ev ==serial_line_event_message)。 另外, 因为每次一个字节到达时调用uart_rx_callback()函数,例如,如果输入“welcome”,将会出现如图5-3 所示的结果,因此,我们可以使用数据缓存存储数据,通过修改前面程序,可看到如图5-4所示的运行结果:
图5-4 回调函数实现串行通信
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。