这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » MCU » 串口读取任务不执行?

共9条 1/1 1 跳转至

串口读取任务不执行?

菜鸟
2004-06-24 19:23:30     打赏

各位大侠好:

偶遇到一个特奇怪的问题:

在父任务中创建子任务用于读串口1的数据,子任务的优先级高于父任务。在大部分的情况下,两个任务均工作正常。偶尔在目标机启动后,程序也正常运行,但是子任务一直处于pend状态,但串口中是有数据的(此时把接到目标机串口1的串口接头拔下接到主机上,用超级终端观察,是有数据的)。此后,子任务就一直处于pend状态了。可以确定接收串口数据的程序没有错误,真是奇怪!

问题:

既然串口中有数据,且子任务的优先级也高于父任务,为什么子任务会永远不被执行? 题目最好明确问题 [align=right][color=#000066][此贴子已经被amine于2004-7-1 17:35:24编辑过][/color][/align]




关键词: 串口     读取     任务     执行    

菜鸟
2004-07-01 21:38:00     打赏
2楼
read() 函数会阻塞。 发现在read()函数处pend之后, 此任务一直处于pend状态了,此后也不会参加任何的调度。想请问高手如何解pend,使其能继续正常工作? 用了ioctl(fd, FIOCANCEL, 0)来flush串口的读写缓冲区以达解阻塞的目的,但是不好使。

菜鸟
2004-07-01 22:05:00     打赏
3楼
后来用select来读四个串口,但是也遇到了同样的问题。 请看下面的源码: //串口类的打开串口函数:m_hSerial相当于fd.
//此类的其它函数略。
BOOL CSerial::Open(int nPort, int nBaud)
{
char szPort[32];
if(m_hSerial != ERROR)
{
printf("serial %d already opened.\n", nPort);
return FALSE;
}
sprintf(szPort, "/tyCo/%d", nPort - 1);
if((m_hSerial = open(szPort, O_RDWR, 0)) == ERROR)
{
printf("open serial %d error.\n", nPort);
return FALSE;
} ioctl(m_hSerial, FIOSETOPTIONS, OPT_RAW); if((ioctl(m_hSerial, FIOBAUDRATE, nBaud)) == ERROR)
{
printf("set serial %d baud error.\n", nPort);
close(m_hSerial);
return FALSE;
}
if((ioctl(m_hSerial, FIORBUFSET, SERIAL_MAX_BUFFER)) == ERROR)
{
printf("set serial %d read buffer size error.\n", nPort);
close(m_hSerial);
return FALSE;
}
if((ioctl(m_hSerial, FIOWBUFSET, SERIAL_MAX_BUFFER)) == ERROR)
{
printf("set serial %d read buffer size error.\n", nPort);
close(m_hSerial);
return FALSE;
}
printf( "Serial %d open success!\n", nPort );
return TRUE;
} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//主程序;
简单描述:用select来读四个串口中的数据,然后打印出来。
#include <vxWorks.h>
#include <taskLib.h>
#include <selectLib.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.>
#include "Serial.h"

#define MAX_FDS 4
typedef unsigned char byte;
CSerial g_Serial1;
CSerial g_Serial2;
CSerial g_Serial3;
CSerial g_Serial4; /************************************************************************
* selServer - reads data as it becomes available from four different serials
*
* Opens four serials fds, reading from whichever becomes available.
*/

STATUS selSerials (void)
{
struct fd_set readFds; /* bit mask of fds to read from */
int fds[MAX_FDS]; /* array of fds on which to pend */
int width; /* number of fds on which to pend */
int i; /* index for fd array */
int len = 0;
byte buffer[SERIAL_MAX_BUFFER]; /* buffer for data that is read */
int nBytesUnread = 0;

/* open file descriptors */
if (g_Serial1.Open (1, 19200) == FALSE)
{
return (ERROR);
}
else
{
fds[0] = g_Serial1.m_hSerial;
}

if (g_Serial2.Open (2, 4800) == FALSE)
{
return (ERROR);
}
else
{
fds[1] = g_Serial2.m_hSerial;
}

if (g_Serial3.Open (3, 4800) == FALSE)
{
return (ERROR);
}
else
{
fds[2] = g_Serial3.m_hSerial;
} if (g_Serial4.Open (4, 19200) == FALSE)
{
return (ERROR);
}
else
{
fds[3] = g_Serial4.m_hSerial;
} /* Discards all the bytes currently in both the input and the output buffers */
for(i = 0; i < 4; i++)
{
ioctl(fds[i], FIOFLUSH, 0);
}

/* loop forever reading data and servicing clients */
while(true)
{
/* clear bits in read bit mask */
FD_ZERO (&readFds);

/* initialize read bit mask */
for(i = 0; i < 4; i++)
{
FD_SET (fds[i], &readFds);
}
/* initialize write bit mask */
FD_SET (fds[0], &writeFds); width = fds[0];
for(int j = 1; j < MAX_FDS; j++)
{
if(fds[j] > width)
{
width = fds[j];
}
}
width++;

/* pend, waiting for one or more fds to become ready */
if (select (width, &readFds, NULL, NULL, NULL) == ERROR)
{
perror("The select of serials is ERROR\n");
return (ERROR);
}

/* step through array and read from fds that are ready */
for (i = 0; i < MAX_FDS; i++)
{
/* check if this fd has data to read */
if (FD_ISSET (fds[i], &readFds))
{
/* typically read from fd now that it is ready */
memset(buffer, 0, sizeof(buffer));
ioctl (fds[i], FIONREAD, int (&nBytesUnread));
if(nBytesUnread == 0)
{
continue;
}

len = read (fds[i], buffer, SERIAL_MAX_BUFFER);
if(ioctl(fds[i], FIORFLUSH, 0) == ERROR)
{
return ERROR;
}

if(len <= 0)
{
continue;
} switch(i)
{
case 0:
printf("\n COM1 %d, %s\n", len, buffer);
break;
case 1:
printf("\n COM2 %d, %s\n", len, buffer);
break;
case 2:
printf("\n COM3 %d, %s\n", len, buffer);
break;
case 3:
printf("\n COM4 %d, %s\n", len, buffer);
break;
default:
break;
}
}
}
}
} //程序入口:
extern "C"
{
int zmap()
{

if (taskSpawn("SERIAL_SEL", 90, VX_FP_TASK, 20000,
(FUNCPTR)selSerials, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) != ERROR)
{
return (0);
}
else
{
return (-1);
} }
}

菜鸟
2004-07-01 22:17:00     打赏
4楼
everywhere 大侠: 我已经试过了(void)ioctl(fd,FIONREAD,(int)&nBytes); 但是其中的一个串口在任务刚执行时就在read()处pend了。 值得一提的是:这个串口接收的数据是 (ASCII 码 + 以字节表示的字符),其它三个串口接收的都是ASCII字符。 接收ASCII字符的三个串口出现错误的几率要小于剩下的那个串口。

菜鸟
2004-07-02 01:39:00     打赏
5楼
关键是明白阻塞消除的条件, 比如有回车符, 字符数大于某数, 超时机制

菜鸟
2004-07-02 19:12:00     打赏
6楼
525lcb:因为CSerial类只是对串口操作做简单的封装, long m_hSerial; 在此类的构造函数中赋 m_hSerial = ERROR; 当然,上面的问题的前提是四个串口都正常打开和初始化。

菜鸟
2004-07-02 19:24:00     打赏
7楼
525lcb:请查收邮件。

菜鸟
2004-07-03 04:09:00     打赏
8楼
studyarm:
偶做的是在vxworks下的,函数:(void)ioctl(fd,FIONREAD,(int)&nBytes); 你可参考 tyLib.h 或 tyLib.html

菜鸟
2004-07-05 17:55:00     打赏
9楼
lkh_cwdm 兄: 你好像误解了,我说的是一个任务读一个串口,或者是在一个任务中用select()来管理(读写)多个串口。

共9条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]