单片机
返回首页

Linux下的串口总线驱动(四)

2016-03-08 来源:eefocus

六.串口测试代码

我们已经配置了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

进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • 如何利用ESP8266制作一个简单的四轴飞行器

  • 离子检测器电路分析

  • 非常简单的150W功放电路图

  • 一个简单的警笛电路图

  • 优化电路板布局的简单方法

  • 使用NE555和磁簧开关的橱柜照明电路

    相关电子头条文章