六.串口测试代码
我们已经配置了mini2440的串口配置,然后根据mini2440开发板的硬件电路知道S3C2440本身总共有3个串口:UART0、1、2,其中UART0,1可组合为一个全功能的串口,在大部分的应用中,我们只用到3个简单的串口功能(本开发板提供的Linux和WinCE驱动也是这样设置的),即通常所说的发送(TXD)和接收(RXD),它们分别对应板上的CON1、CON2、CON3,这3个接口都是从CPU直接引出的,是TTL电平。为了方便用户使用,其中UART0做了RS232电平转换,它们对应于COM0,可以通过附带的直连线与PC机互相通讯。我们这个实验选用CON1作为测试串口的端口。用导线将CON1的1号(TXD1)和2号(RXD1)引脚相连,实现自发自收。
实验环境:内核linux2.6.32.2,arm-linux-gcc交叉编译器,mini2440开发板
内核配置:选中s3c2440.o samsung.o serial_core.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o tty_buffer.o tty_port.o。
测试代码如下:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define FALSE 1
#define TRUE 0
char *recchr='We received:\'';
int speed_arr[] = {
B921600, B460800, B230400, B115200, B57600, B38400, B19200,
B9600, B4800, B2400, B1200, B300, B38400, B19200, B9600,
B4800, B2400, B1200, B300,
};
int name_arr[] = {
921600, 460800, 230400, 115200, 57600, 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(fd, TCSANOW, &Opt); //设置线路设置
if (status != 0)
perror('tcsetattr fd1');
return;
}
tcflush(fd,TCIOFLUSH); //刷新输入输出队列
}
}
int set_Parity(int fd,int databits,int stopbits,int parity, int flowctrl)
{
struct termios options;
if ( tcgetattr( fd,&options) != 0) { //获取线路设置
perror('SetupSerial 1');
return(FALSE);
}
options.c_cflag &= ~CSIZE ; //利用CSIZE掩码把正确位从cflag中分离并清零,其他位不变
switch (databits) {
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;
options.c_iflag &= ~INPCK;
break;
case 'o':
case 'O':
options.c_cflag |= (PARODD | PARENB);
options.c_iflag |= INPCK;
break;
case 'e':
case 'E':
options.c_cflag |= PARENB;
options.c_cflag &= ~PARODD;
options.c_iflag |= INPCK;
break;
case 'S':
case 's':
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
break;
default:
fprintf(stderr,'Unsupported parity\n');
return (FALSE);
}
switch (stopbits) {
case 1:
options.c_cflag &= ~CSTOPB; //相应位置0
break;
case 2:
options.c_cflag |= CSTOPB;
break;
default:
fprintf(stderr,'Unsupported stop bits\n');
return (FALSE);
}
if (flowctrl)
options.c_cflag |= CRTSCTS;
else
options.c_cflag &= ~CRTSCTS;
if (parity != 'n')
options.c_iflag |= INPCK;
// VTIME设定字节输入时间计时器
options.c_cc[VTIME] = 150; // 15 seconds
//VMIN设定满足读取功能的最低字节个数
options.c_cc[VMIN] = 0;
options.c_lflag &= ~(ECHO | ICANON);
tcflush(fd,TCIFLUSH); //刷新输入队列
if (tcsetattr(fd,TCSANOW,&options) != 0) { //设置线路设置
perror('SetupSerial 3');
return (FALSE);
}
return (TRUE);
}
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, next_option, havearg = 0;
char *device = '/dev/ttySAC1';
int speed = 115200;
int flowctrl = 0;
int nread;
char buff[512];
pid_t pid;
char *xmit = 'com test by ptr 2012';
sleep(1);
fd = OpenDev(device);
if (fd > 0) {
set_speed(fd,speed);
} else {
fprintf(stderr, 'Error opening %s: %s\n', device, strerror(errno));
exit(1);
}
if (set_Parity(fd,8,1,'N',flowctrl)== FALSE) {
fprintf(stderr, 'Set Parity Error\n');
close(fd);
exit(1);
}
pid = fork();
if (pid < 0) {
fprintf(stderr, 'Error in fork!\n');
} else if (pid == 0){
while(1) {
printf('SEND: %s\n',xmit);
write(fd, xmit, strlen(xmit));
sleep(1);
}
exit(0);
} else {
while(1) {
if (nread > 0) {
buff[nread] = '\0';
printf('RECV: %s\n', buff);
}
}
}
close(fd);
exit(0);
}
测试结果:
虚拟机下编译arm-linux-gcc serial.c –o serial
在超级终端下运行./serial
可以看到:
SEND:com test by ptr 2012
RECV:com test by ptr 2012