|
|
|
|
| [Linux Serial Programming]Non-Canonicalmode如何SIGIO |
 [Linux Serial Programming]Non-Canonicalmode如何SIGIO - geshu [ 2005-07-26 22:49 | 5,857 byte(s)]
 Re: [Linux Serial Programming]Non-Canonicalmode如何S - z_york [ 2005-07-27 09:40 | 199 byte(s)]
|
|
|
|
[Original]
[Print]
[Top]
|
主 题: [Linux Serial Programming 问题] Non-Canonical mode 如何 加上 SIGIO 信号处理
小弟第一次 在这里提问。
麻烦经历如下.
现在要给公司开发短信程序,基于 linux 平台。最终的问题 归结于 linux 串口编程。
在 google 上 search 发现这篇 资料, linux serial how-to.
http://www.ibiblio.org/pub/Linux/docs/HOWTO/Serial-Programming-HOWTO
我想要的东西是, 用一个 semaphore 来控制 程序是否去读 serial port, 而不是用一个 while loop 来循环读 serial port。要不然 cpu 时间 都耗在这个上面了。
于是 经过思考, 得出以下思路。
[1] 直接修改 Asynchronous Input 的 programme (因为它已经有了 signal handling)
[2] 修改 Non-Canonical Input Processing 的 programme, 然后加上 signal handling
第一个方案 好像必须在输入的字符上,做手脚 才可以,因必须得读满一行(cononical mode, 至少得有一个 line feed)。只好放弃
第二个方案 现在可以做到 死循环 读取 serial port, 但是 想 加进 SIGIO 就是不行。
[问题 1] 望各位NB的 大大 帮帮小弟, 第二个方案 如何 加进 SIGIO handling? 现在的问题是, 既石有IO, signal_handler_IO 也不会被调用。(郁闷中)
[问题 2] 现在 第二个方案,发现所有 输入的 input 都会在下次输入的时候,重新读回来 (好像是 所说的 echo), 如何控制参数 关闭这个 echo?
代码(修改 后 Non-Canonical Input Processing 的 programme)如下:
// global variables
static bool bWaitFlag = true; // TRUE while no signal received
static char SerialBuffer[512];
static int nByteRead;
static int nStrLength;
static char * BufferPtr;
static int DevPtr;
static termios OldTermios, NewTermios;
// external variables
extern sem_t ReadBufferCounter;
void * ReadThread(void *) {
struct sigaction SigAction; // definition of signal action
/* open the device to be non-blocking (read will return immediatly) */
DevPtr = open(MODEMDEVICE, O_RDWR | O_NOCTTY);
if (DevPtr < 0) {
std::cout << "Failed to open Modem!" << std::endl;
exit(-1);
}
/* install the signal handler before making the device asynchronous */
SigAction.sa_handler = signal_handler_IO;
sigemptyset(&SigAction.sa_mask);
SigAction.sa_flags = 0;
SigAction.sa_restorer = NULL;
sigaction(SIGIO, &SigAction, NULL);
/* allow the process to receive SIGIO */
fcntl(DevPtr, F_SETOWN, getpid());
/* Make the file descriptor asynchronous (the manual page says only O_APPEND and O_NONBLOCK, will work with F_SETFL...) */
//fcntl(DevPtr, F_SETFL, FASYNC);
tcgetattr(DevPtr,&OldTermios); // save current port settings
/* set new port settings for non-canonical input processing */
bzero(&NewTermios, sizeof(NewTermios));
NewTermios.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
NewTermios.c_iflag = IGNPAR;// | ICRNL;
NewTermios.c_oflag = 0;
NewTermios.c_lflag = 0; //ICANON;
NewTermios.c_cc[VMIN] = 0;
NewTermios.c_cc[VTIME] = 1; // maximum time of 100 ms
tcflush(DevPtr, TCIFLUSH);
tcsetattr(DevPtr, TCSANOW, &NewTermios);
// initialize the Modem
strcpy(SerialBuffer, "AT+CMGF=1x0D");
nStrLength = strlen(SerialBuffer);
write(DevPtr, SerialBuffer, nStrLength);
/* loop while waiting for input. normally we would do something useful here */
while (true) {
//sleep(2);
BufferPtr = SerialBuffer;
sleep(1);
//sem_wait(& ReadBufferCounter); // wating for SIGIO
while (true) {
//std::cout << "Reading +" << std::endl;
nByteRead = read(DevPtr, BufferPtr, 255);
//std::cout << "Reading -" << std::endl;
if (nByteRead == -1 || nByteRead == 0) {
break;
}
BufferPtr[nByteRead] = 0;
//std::cout << nByteRead << " Bytes:" << BufferPtr << std::endl;
BufferPtr += nByteRead;
}
if (BufferPtr != SerialBuffer) {
std::cout << "Reading over:" << SerialBuffer << std::endl;
MessageHandler(); // handle buffer message
SerialBuffer[0] = 0;
}
}
/* restore old port settings */
tcsetattr(DevPtr, TCSANOW, & OldTermios);
}
/***************************************************************************
* signal handler. sets bWaitFlag to FALSE, to indicate above loop that *
* characters have been received. *
***************************************************************************/
void signal_handler_IO (int status) {
std::cout << "received SIGIO signal." << std::endl;
//sem_post(& ReadBufferCounter); // unlocking
}
|
|
|
[Original]
[Print]
[Top]
|
|
[Original]
[Print]
[Top]
|
如果用一个独立的线程或进程去读串口,即使是在一个while loop里面读,也是不会耗尽CPU的,而且实现起来很简单──使用pipe去缓冲就行了。
附件里的miniterm.c,一个不错的串口例子。
|
|
|
----
I love David Beckham and Man.Utd. for ever.
|
|
--
|
|
[Original]
[Print]
[Top]
|
|
|