VxWorks操作系统下的串口读写程序

关于传统的串口编程,在各大操作系统下的流程基本是一致的,只是针对不同的操作系统,函数接口可能有所差异而已,下面讲述VxWorks操作系统下对于串口读写的编程步骤和代码

相关的VxWorks串口,请参阅 VxWorks下的串口测试程序设计和源码

串口配置过程

打开串口

fd = open("/tyCo/0", O_RDWR, 0);
  • “/tyCo/0”: 串口1的设备名
  • O_RDWR: 按照读写方式打开串口

设置串口raw模式,清空输入输出的缓冲区

在VxWorks中配置串口可以直接通过ioctl的控制命令来实现

ioctl(fd,FIOSETOPTIONS,OPT_RAW);
ioctl(fd,FIOFLUSH,0);
ioctl(int fd,int function,int arg);

function的参数如下:

参数 说明
FIOBAUDRATE 设置波特率,arg为一整数,表示要设定的波特率
FIOGETOPTIONS 取得设备控制字,arg表示读出的内容存放的位置
FIOSETOPTIONS 设置设备控制字,arg表示要设置的选项
FIOGETNAME 取得文件描述符对应的文件名,arg存放文件名的缓冲区
FIOREAD 取得输入缓冲区内未读取的字符数,arg用于接收结果的整型指针
FIOWRITE 取得输出缓冲区内的字符个数,arg用于接收结果的整型指针
FIOFLUSH 清空输入输出缓冲区的字符
FIOCANCEL 取消读和写

设置波特率,数据位,停止位,校验方式

在 VxWorks 中设置串口也是用 ‘ioctl’ 系统调用加控制命令实现,其控制命令为’SIO_HW_OPTS_SET’,第三个参数跟配置参数,如:数据位为8,停止位为1,无奇偶校验位,无流控可以这样配置

ioctl(fd,SIO_HW_OPTS_SET,CS8|PARENB|CLOCAL|CREAD);

具体各项参数意义如下:

参数 说明
CLOCAL 忽略modem控制信号
CREAD 启动接收器
CSIZE 指定数据位:CS5~CS8
HUPCL 最后关闭时挂断modem连接
STOP8 被设置时指定2位停止位,否则默认为1位停止位
PARENB 被设置时启用奇偶校验,否则默认为无奇偶校验
PARODD 被设置时启用奇校验,否则默认为偶校验(PARENB设置时才有效)

串口读写操作

在VxWorks系统中串口的读写操作非常简单,直接使用系统调用函数 read() 和 write() 就能实现串口的读写操作。

int read(int fd, char *buffer, size_t maxbytes)

参数说明:

  • fd: 用open函数打开串口设备返回的文件描述符
  • buffer: 读取的内容将要存放的地址,为指针变量
  • maxbytes: 读取的最大字节数
int write(int fd, char *buffer, size_t nbytes)

参数说明:

  • fd: 用open函数打开串口设备返回的文件描述符
  • buffer: 将要写的内容的地址,为指针变量,通常为字符串首地址
  • nbytes: 将要写入的字节数,通常为要写入的字符串的长度

实例代码

VxWorks系统下串口读写的实例代码,仅供参考。

#include "vxWorks.h"
#include "stdio.h"
#include "ioLib.h"
#include "taskLib.h"
#include "sioLib.h"
#include "sdLib.h"
#include "semLib.h"
#include "msgQLib.h"

char wbuf[] = "hello";

#define DEV_NAME "/tyCo/2"
#define MAX_BUF_SIZE    20
#define SD_COMMDATA_NAME    "share_data"
#define SD_COMMDATA_MUTEX   "share_sem"
#define SHARE_DATA_LENGTH 20

typedef struct unix_clock_struct 
{
    UINT32      sec;        /* ms */    
    UINT32      msec;       /* s */
    UINT8       quality;    /* 时标质量 */
} UNIX_CLOCK_STRUCT;

char *comdata;
int set_serial(int fd);
SEM_ID mutexComdata;

void taskUart(void);
int main(void)
{
    int ret;
    int sdCommId;
    char r_buff[MAX_BUF_SIZE];

    mutexComdata = semOpen(SD_COMMDATA_MUTEX, SEM_TYPE_MUTEX, SEM_FULL, SEM_Q_PRIORITY | SEM_DELETE_SAFE | \
                SEM_INVERSION_SAFE, OM_CREATE | OM_DELETE_ON_LAST_CLOSE, NULL);
    if(mutexComdata == NULL)
    {
        /*致命错误,无法创建互斥锁*/
        printf("ERROR TO OPEN SD_COMMDATA_MUTEX\n");
        taskExit(0);
    }   

    /* 申请公共数据共享内存  */
    sdCommId = sdOpen(SD_COMMDATA_NAME, SD_LINGER, OM_CREATE, SHARE_DATA_LENGTH, 0, SD_ATTR_RW|SD_CACHE_OFF, &comdata);
    if(sdCommId == NULL)    
    {
        /*致命错误,无法分配公共数据内存,报错退出*/
        printf("ERROR TO OPEN SD_COMMDATA\n");
        taskExit(0);
    }   

    if((ret = taskSpawn("taskUart",90,0x100, 20000, (FUNCPTR)taskUart,\
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) < 0)
    {
        printf("taskSpawn failed:ret = %s\n");
    }

    return 0;
}

void taskUart(void)
{
    int ret;
    int fd = -1;
    UNIX_CLOCK_STRUCT w_buff;

    if((fd = open(DEV_NAME, O_RDWR,0)) < 0)
    {
        printf("open %s failed.\n",DEV_NAME);
    }

    /*配置串口参数*/
    if((ret = set_serial(fd)) < 0)
    {
        printf("ret = %d\nset_serial failed.\n");
    }

    while(1)
    {
        semRTake(mutexComdata,WAIT_FOREVER);
#if 0
        /*清空输入输出缓冲*/
        if((ret = ioctl(fd, FIOFLUSH, 0))<0)
        {
            printf(" ret = %d\nset FIOFLUSH failed.\n",ret);
        }

        memset(r_buff,0,sizeof(r_buff));
        /*读取串口中的值*/
        if((ret = read(fd,r_buff,sizeof(r_buff)))<0)
        {
            printf("ret = %d:read %s failed.\n",ret,DEV_NAME);
        }
        else
            printf("Received:%s\n",r_buff);
#endif  

#if 1
        /*清空输入输出缓冲*/
        if((ret = ioctl(fd, FIOFLUSH, 0))<0)
        {
            printf(" ret = %d\nset FIOFLUSH failed.\n",ret);
        }

        if(NULL == bzero(&w_buff,sizeof(w_buff)))
        {
            printf("memset failed.\n");
        }

        if(NULL == memcpy(&w_buff,comdata,sizeof(w_buff)))
        {
            printf("memset failed.\n");
        }

        if(&w_buff != NULL)
        {
            /*往串口中写值*/
            if((ret = write(fd, &w_buff.sec, sizeof(ret)))<0)
           // if((ret = write(fd, wbuf, sizeof(wbuf)))<0)
            {
                printf("ret = %d:write %s failed.\n",ret,DEV_NAME);
            }
            else
            {
                printf("write success:%d\n",w_buff.sec);
            }
        }

        semGive(mutexComdata);
#endif
        taskDelay(sysClkRateGet()*2);
   }
}

int set_serial(int fd)
{
    int error = -1;
    int ok = 0;
    int ret;

    if(fd<0)
    {
        printf("error:fd is %d\n",fd);
    }
    /*设定波特率为9600*/
    if((ret = ioctl(fd, FIOBAUDRATE, 9600))<0)
    {
        printf("ret = %d\n set baudrate failed\n",ret);
        return error;
    }

    /*设定:数据位为8,无奇偶校验,1位停止位*/
    /*CLOCAL:忽略modem控制信号
     * CREAD:启动接收器
     * CS8:设定数据位为8*/
    if((ret = ioctl(fd, SIO_HW_OPTS_SET,CREAD|CS8 |CLOCAL))<0)
    {
        printf("ret = %d\nset SIO_HW_OPTS_SET failed.\n");
        return error;
    }

    return ok;
}