200分送了!!!急,小弟急求各位大侠
具体的是这样,主程序是一个死循环(在计算数据),这个时候,需要响应串口传过来的数据进行计算
1。需中断响应,这个程序怎么写?
2。我用了termios这个结构,很奇怪的是,可以接收(用信号,听说这个类似DOS的INT),但是不能够发送,不知道哪里出错了,向串口发送数据是(write(fd,buff,100))这个函数吗?有其他的函数吗?我在DOS下面用的outportb这个,直接对地址发送(outportb(0x3f8,buff,1))Linux下面的outb这个函数是否一样?
3,因为在中断里面需要判断当前串口是发送还是接收,需要直接读取UART寄存器的值,我在DOS下面用如下代码『
adr1 = 0x3f8
cb=inportb(adr1+2);
if(cb==6)
{
inportb(adr1+5);
continue;
}
if(cb==4)//这个时候中断接收数据
{
readserial()
continue;
}
if(cb==2)//这个时候中断发送数据
{
writeserial();
continue;
}
} while((cb & 1)==0); //2
outportb(0x20,0x20);
』
上面这段程序在linux下面如何实现?用outb这个函数可以直接读取吗?关键问题就是如何判断串口寄存器的状态
下面这个是我写的Linux下面的第一个程序,请大家看看,错在哪里呀?只能够接收,不能够发送!!!
程序:
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <asm/io.h>
#include <errno.h>
#include <sys/mman.h>
#include <signal.h>
#include <fcntl.h>
#include <termios.h>
#define BAUDRATE B38400
#define MODEMDEVICE "/dev/ttyS1"
void readserial();
void writeserial();
void signal_handler_IO (int status);
main() {
int fd,c, res;
struct termios oldtio,newtio;
struct sigaction saio;
char buf[255];
fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
if (fd <0) {perror(MODEMDEVICE); exit(-1); }
saio.sa_handler = signal_handler_IO;
saio.sa_mask = 0;
saio.sa_flags = 0;
saio.sa_restorer = NULL;
sigaction(SIGIO,&saio,NULL);
fcntl(fd, F_SETOWN, getpid());
fcntl(fd, F_SETFL, FASYNC);
tcgetattr(fd,&oldtio);
newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
newtio.c_iflag = IGNPAR | ICRNL;
newtio.c_oflag = 0; //这个发送我不知道怎么设置,老是发送不对
newtio.c_lflag = ICANON;
newtio.c_cc[VMIN]=1;
newtio.c_cc[VTIME]=0;
tcflush(fd, TCIFLUSH);
tcsetattr(fd,TCSANOW,&newtio);
while (1) {
// 计算
需要串口实时传送过来的数据,必须中断发送和接收
}
tcsetattr(fd,TCSANOW,&oldtio);
}
void readserial();
{
read(fd,readbuf,1) //
/* 这个readbuf的值需要返回mian的while中进行计算
}//read 程序已经调通
void writeserial()
{
write(fd,writebuf,1)
//这个writebuf是while计算以后的值,发送出去
}//不知道这错在哪里?????老实发送不了??
void signal_handler_IO (int status)
{
/*
这里就需要刚才上面那个程序说的如何判断 UART寄存器的状态值了
if(串口有数据传入)
readserial();
if(有数据输出)
writeserial();
}//这个问题现在是一点都没有搞明白
小弟,在次谢过完整看了问题的各位大哥,如果你能帮忙,请回帖,如果不能,大家一起交流!
问题点数:100、回复次数:14Top
1 楼h_bin16888(木之杉)回复于 2004-12-01 21:02:02 得分 0
各位看完以后,都麻烦顶一下,谢谢Top
2 楼FreeSeagull(蓝天,白云,松花江)回复于 2004-12-02 20:49:36 得分 100
看端口应该是COM1,关于Linux下的Serial port编程,你可以看看这个资料:
《Serial Programming Guide for POSIX Operating Systems》
5th Edition
Michael R. Sweet
http://digilander.libero.it/robang/rubrica/serial.htm
我们公司就生产串口卡,而我本人负责Linux驱动程序开发。我们的例程就是参考那篇文章写的。Top
3 楼FreeSeagull(蓝天,白云,松花江)回复于 2004-12-02 20:53:22 得分 0
以下是我们的一块板卡的manual中的摘录,该文档目前尚未提交,如有错误欢迎指正:
4.2. Necessary Header Files
Now, start a new project and include necessary header files
#include <stdio.h> /*standard IO definition*/
#include <stdlib.h> /*standard functions definition*/
#include <unistd.h> /*Unix standard function definition*/
#include <sys/types.h> /*types definition*/
#include <sys/stat.h> /*status definition*/
#include <fcntl.h> /*file control definition*/
#include <termios.h> /*PPSIX terminal control definition*/
#include <errno.h> /*error number definition*/
4.3. Open
Next, let’s open a port for read and write.
int fd;
/* open COM1 for read/write */
fd = open( "/dev/ttyS1", O_RDWR | O_NOCTTY | O_NDELAY);
if (-1 == fd){
/* fail to open the port*/
perror(" Fail to open COM1!");
You'll notice that when we opened the device file we used two other flags along with the read + write mode:
fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
The O_NOCTTY flag tells UNIX that this program doesn't want to be the "controlling terminal" for that port.
If you don't specify this then any input (such as keyboard abort signals and so forth) will affect your process.
Programs like getty (1M/8) use this feature when starting the login process, but normally a user program does not want this behavior.
The O_NDELAY flag tells UNIX that this program doesn't care what state the DCD signal line is in − whether the other end of the port is up and running. If you do not specify this flag, your process will be put to sleep until the DCD signal line is the space voltage.
4.4. Configure
To configure a serial port, you should use an important structure:
struct termio
{ unsigned short c_iflag; /* Input mode flag*/
unsigned short c_oflag; /* Output mode flag*/
unsigned short c_cflag; /* Control flag*/
unsigned short c_lflag; /* local mode flag*/
unsigned char c_line; /* line discipline */
unsigned char c_cc[NCC]; /* control characters */
};
Some commonly used members’ configuration:
struct termios Opt;
tcgetattr(fd, &Opt);
cfsetispeed(&Opt,B19200); /*Baud rate = 19200Bps*/
cfsetospeed(&Opt,B19200);
tcsetattr(fd,TCANOW,&Opt);
The following example demonstrates setting baud rate of COM1:
/**
* brief Setup baud rate of specified port
* param fd Handle of an opened port
* param speed Desired baud rate
* return void
*/
int speed_arr[] = { B38400, B19200, B9600, B4800, B2400, B1200, B300, B38400,B19200, B9600, B4800, B2400, B1200, B300, };
int name_arr[] = {38400, 19200, 9600, 4800, 2400, 1200, 300, 38400,
19200, 9600, 4800, 2400, 1200, 300, };
void set_speed(int fd, int speed){
int i;
int status;
struct termios Opt;
tcgetattr(fd, &Opt);
for ( i= 0; i < sizeof(speed_arr) / sizeof(int); i++) {
if (speed == name_arr[i]) {
tcflush(fd, TCIOFLUSH);
cfsetispeed(&Opt, speed_arr[i]);
cfsetospeed(&Opt, speed_arr[i]);
status = tcsetattr(fd1, TCSANOW, &Opt);
if (status != 0) {
perror("tcsetattr fd1");
return;
}
tcflush(fd, TCIOFLUSH);
}
}
}
Currently, Advantech PCM-3614 card support following parity check types:
No parity 8位 Option.c_cflag &= ~PARENB;
Option.c_cflag &= ~CSTOPB;
Option.c_cflag &= ~CSIZE;
Option.c_cflag |= ~CS8;
Odd Parity 7位 Option.c_cflag |= ~PARENB;
Option.c_cflag &= ~PARODD;
Option.c_cflag &= ~CSTOPB;
Option.c_cflag &= ~CSIZE;
Option.c_cflag |= ~CS7;
Even parity 7位 Option.c_cflag &= ~PARENB;
Option.c_cflag |= ~PARODD;
Option.c_cflag &= ~CSTOPB;
Option.c_cflag &= ~CSIZE;
Option.c_cflag |= ~CS7;
Space Parity 7位 Option.c_cflag &= ~PARENB;
Option.c_cflag &= ~CSTOPB;
Option.c_cflag &= &~CSIZE;
Option.c_cflag |= CS8;
Now, setup data bits, stop bits and parity check type:
/**
* brief Setup data bits, stop bits and parity type
* param fd Handle of an opened port
* param databits Data bits
* param stopbits Stop bits
* param parity Parity check N,E,O,,S
*/
int set_Parity(int fd, int databits, int stopbits, int parity)
{
struct termios options;
if ( tcgetattr(fd, &options) != 0) {
perror("Setup Serial 1");
return(FALSE);
}
Top
4 楼FreeSeagull(蓝天,白云,松花江)回复于 2004-12-02 20:53:28 得分 0
options.c_cflag &= ~CSIZE;
switch (databits) /*set data bits*/
{
case 7:
options.c_cflag |= CS7;
break;
case 8:
options.c_cflag |= CS8;
break;
default:
fprintf(stderr,"Unsupported data size\n"); return (FALSE);
}
switch (parity)
{
case 'n':
case 'N':
options.c_cflag &= ~PARENB; /* Clear parity enable */
options.c_iflag &= ~INPCK; /* Enable parity checking */
break;
case 'o':
case 'O':
options.c_cflag |= (PARODD | PARENB); /* Odd parity check*/
options.c_iflag |= INPCK; /* Disable parity checking */
break;
case 'e':
case 'E':
options.c_cflag |= PARENB; /* Enable parity */
options.c_cflag &= ~PARODD; /* Change to Even parity check*/
options.c_iflag |= INPCK; /* Disable parity checking */
break;
case 'S':
case 's': /*as no parity*/
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;break;
default:
fprintf(stderr,"Unsupported parity\n");
return (FALSE);
}
/* set stop bits */
switch (stopbits)
{
case 1:
options.c_cflag &= ~CSTOPB;
break;
case 2:
options.c_cflag |= CSTOPB;
break;
default:
fprintf(stderr,"Unsupported stop bits\n");
return (FALSE);
}
/* Set input parity option */
if (parity != 'n')
options.c_iflag |= INPCK;
tcflush(fd,TCIFLUSH);
options.c_cc[VTIME] = 150; /* time out: 15 seconds*/
options.c_cc[VMIN] = 0; /* Update the options and do it NOW */
if (tcsetattr(fd,TCSANOW,&options) != 0)
{
perror("Setup Serial 3");
return (FALSE);
}
return (TRUE);
}
Note: If you want to develop application used for transferring data rather than acting as data terminals, you should choose Raw Mode for input and output as shown below:
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /*Input*/
options.c_oflag &= ~OPOST; /*Output*/
4.5. Read and Write
Reading and writing a port is as simple as reading and writing an ordinary file.
Write data:
char buffer[1024];
int Length;
int nBytes = write(fd, buffer, Length)
The write function returns the number of bytes sent or −1 if an error occurred. Usually the only error you'll run into is EIO when a MODEM or data link drops the Data Carrier Detect (DCD) line. This condition will persist until you close the port.
Read data:
char buff[1024];
int Length;
int nBytes = read(fd, buff, Length);
Reading data from a port is a little trickier. When you operate the port in raw data mode, each read system call will return the number of characters that are actually available in the serial input buffers. If no characters are available, the call will block (wait) until characters come in, an interval timer expires, or an error occurs.
The read function can be made to return immediately by doing the following:
fcntl(fd, F_SETFL, FNDELAY);
The FNDELAY option causes the read function to return 0 if no characters are available on the port. To restore
normal (blocking) behavior, call fcntl() without the FNDELAY option:
fcntl(fd, F_SETFL, 0);
This is also used after opening a serial port with the O_NDELAY option.
4.6. Close
After finished using a port, you should close it to allow other application to access this port like this.
close(fd);
Where fd is the handle of the opened port.
4.7. Example
This example demonstrates how to open, configure, read and close a port.
/*********************************************************************
* Demo project
* Show how to open/configure/read/write/close a serial port
**********************************************************************/
#define FALSE -1
#define TRUE 0
/*********************************************************************/
int OpenDev(char *Dev)
{
int fd = open( Dev, O_RDWR | O_NOCTTY | O_NDELAY)
if (-1 == fd)
{
perror("Can't Open Serial Port");
return -1;
}
else
return fd;
}
int main(int argc, char **argv){
int fd;
int nread;
char buff[512];
char *dev = "/dev/ttyS1"; //Serial port 2
fd = OpenDev(dev);
set_speed(fd,19200);
if (set_Parity(fd,8,1,'N') == FALSE) {
printf("Set Parity Error\n");
exit (0);
}
while (1) //loop to read data
{
while((nread = read(fd, buff, 512))>0)
{
printf("\nLen %d\n",nread);
buff[nread+1] = '\0';
printf( "\n%s", buff);
}
}
close(fd);
exit (0);
}
Top
5 楼h_bin16888(木之杉)回复于 2004-12-03 19:57:03 得分 0
谢谢,楼上这位兄弟,你说的那篇文章我看过,里面没有讲到我所需要的响应中断,比如如何直接判断当前是发送,还是接收,还有一个问题就是,我的read为什么一会好,一会不行,而write根本就不行,最开始的时候,也可以的,我很郁闷呀,求助,你是搞这个网卡驱动的吗?留下qq好不?我的qq:63305340,想请教你Top
6 楼yanwenyuan0102(小郎)回复于 2004-12-09 14:04:54 得分 0
顶啦Top
7 楼h_bin16888(木之杉)回复于 2004-12-19 02:25:37 得分 0
没有人知道吗?顶一下Top
8 楼h_bin16888(木之杉)回复于 2005-02-17 13:32:46 得分 0
高手解答一下。顶一下
Top
9 楼h_bin16888(木之杉)回复于 2005-02-19 19:32:02 得分 0
定Top
10 楼tengulre(debian core developer)回复于 2005-02-20 14:06:36 得分 0
dingTop
11 楼tengulre(debian core developer)回复于 2005-02-20 15:31:37 得分 0
zai dingTop
12 楼h_bin16888(木之杉)回复于 2005-02-20 19:52:40 得分 0
定Top
13 楼h_bin16888(木之杉)回复于 2005-02-23 18:55:53 得分 0
顶呀Top
14 楼h_bin16888(木之杉)回复于 2005-02-26 11:07:25 得分 0
顶Top




