在 VxWorks 中,串口是一种特殊的字符型设备,它的驱动程序并不是直接挂在 I/O 系统中,而是通过在其上构建的 tty 驱动及其支持库 tyLib 接入。
Vxworks下I/O设备都是以文件存取的方式操作,这里以串口为例,”/tyCo/0”表示一个物理串口,”/tyCo/”是设备名(设备名称是 VxWorks系统规定的),表明此设备为串行设备,”0”是设备号。
打开一个串口设备:open(dev_addr, O_RDWR, 0) // 读写方式打开
传输设置波特率:ioctl(serialFd,FIOBAUDRATE,9600) // 设置波特率9600
串口模式设置:ioctl(serialFd,SIO_HW_OPTS_SET,CS8); // 串口工作模式8 N 1
如:
ioctl(serialFd,SIO_HW_OPTS_SET, CLOCAL| CREAD|CS8|STOPB|PARENB|PARODD);
设置为没有流控制CLOCAL,使能读CREAD,8位数据位,2位停止位,带校验位,奇校验
STOPB:两位停止位,默认是1位停止位。PARENB使能校验,PARODD奇校验,使能后默认是偶校验,未使能则是无校验,CS5,CS6,CS7,CS8:5,6,7,8位数据位。
如:CS8|PARENB :8位数据位,1位停止位,偶校验;
CS8|PARENB|PARODD:8位数据位,1位停止位,奇校验;
CS8:8位数据位,1位停止位,无校验;
CS8|STOPB:8位数据位,2位停止位,无校验;
串口读写可以使用write和read函数。
int write
(
int fd, /* file descriptor on which to write */
char * buffer, /* buffer containing bytes to be written */
size_t nbytes /* number of bytes to write */
)
read函数:
int read
(
int fd, /* file descriptor from which to read */
char * buffer, /* pointer to buffer to receive bytes */
size_t maxbytes /* max no. of bytes to read into buffer */
)
下面使用VxWorks创建两个任务,一个向串口不断写入数据,另一个任务不断接受串口信息,并将收到的信息打印出来。这里接收使用到了select函数,当串口上没有数据时,任务二进入阻塞等待状态,一旦有数据或者超时函数才会返回。通常在串口编程中都会用select等待超时。
#include <vxWorks.h>
#include <ioLib.h>
#include <sioLib.h>
#include <taskLib.h>
#include <selectLib.h>
int serial_fd;
int sysRsInit(char *dev_addr, unsigned int baundrate)
{
int serialFd;
serialFd = open(dev_addr, O_RDWR, 0);
if((serialFd < 0) || (serialFd == ERROR))
printf("open seria error!\n");
/*设置串口速率*/
if(ioctl(serialFd, FIOBAUDRATE, baundrate)== ERROR)
perror("ioctl 1");
/*设置8个数据位一个停止位无校验*/
ioctl(serialFd,SIO_HW_OPTS_SET,CS8);
/*设置串口模式为 RAW 模式*/
if(ioctl(serialFd, FIOSETOPTIONS, OPT_RAW)== ERROR)
perror("ioctl 2");
else
printf("\n\rioctl set mode RAW\n\r");
/*清空输入输出缓冲区*/
ioctl(serialFd, FIOFLUSH, 0);
return serialFd;
}
int sysRsDataRecv(int fd, unsigned char *pdata, unsigned int maxBytes,unsigned int timewait)
{
int byte=0,rc=0;
int ret;
fd_set readFds;
struct timeval timing;
/*初始化超时时间*/
timing.tv_sec = 0;
timing.tv_usec = timewait * 1000;
for(byte=0; byte<maxBytes; byte+=rc)
{
FD_ZERO(&readFds);
FD_SET(fd, &readFds); /*添加fd到select*/
ret = select(fd + 1, &readFds, 0, 0, &timing);
if(ret == 0)
{
/*超时返回实际读到的个数*/
return byte;
}
else if(ret > 0)
{
/*有数据可读*/
if(FD_ISSET(fd, &readFds))
{
rc = read(fd, pdata + byte, maxBytes - byte);
if(rc < 0 && errno != EINTR)
{
break; /*读取出错*/
}
}
}
}
return byte;
}
int UsrTask1( void )
{
int index = 0;
char snd_buf[30] = {0};
for(;;)
{
sprintf(snd_buf, "Hello,World %d", index++);
write(serial_fd, snd_buf, strlen(snd_buf));
taskDelay(180);
}
}
int UsrTask2( void )
{
int index;
int bytes;
char rev_buf[30] = {0};
for(;;)
{
memset(rev_buf, 0 , 30);
bytes = sysRsDataRecv(serial_fd, rev_buf, 30, 1000);
printf("recved %d bytes\n", bytes);
for(index=0;index<bytes;index++)
{
printf("%c", rev_buf[index]);
}
printf("\n");
taskDelay(60);
}
}
int UsrAppConfig( void )
{
serial_fd = sysRsInit("/tyCo/0",9600);
printf("serial_fd: %d\n", serial_fd);
taskSpawn( "task1",60, VX_FP_TASK, 0x1000, &UsrTask1, 0,0,0,0,0, 0,0,0,0,0 );
taskSpawn( "task2",61, VX_FP_TASK, 0x1000, &UsrTask2, 0,0,0,0,0, 0,0,0,0,0 );
return 0;
}
int usrEnter(void)
{
UsrAppConfig ();
return 0;
}
串口自发自收测试可以正常收发数据:
评论