happyavr 发表于 2010-9-28 21:35:22

转帖:linux串口编程中非标准波特率的实现

linux下实现标准波特率的编程非常方便,这方面的资料也举不胜举。通常,在linux下面,设置串口使用终端IO的相关函数设置,如tcsetattr等函数,linux内部有一个对常用波特率列表的索引,根据设置的波特率用底层驱动来设置异步通信芯片的寄存器
但是在一些特定应用中需要用到非标准的波特率,比如125000、28800等,这种情况下,如何实现串口通信呢?linux同样提供了对非标准波特率的支持:
对于非标准的任意波特率需要用ioctl(fd, TIOCGSERIAL, p)和ioctl(fd, TIOCSSERIAL, p)的配合,ioctl的最后一个参数是struct serial_struct *类型,在linux/serial.h中定义。其中baud_base是基准晶振频率/16(对于SEP4020来说,baud_base=sysclk/16),你需要设的是custom_divisor这个值,最终的波特率计算公式为baud=baud_base/custom_divisor,所以要设置custom_divisor=baud_base/baud,。
具体过程为,先设置波特率设为38400(tcsetattr),然后用TIOCGSERIAL得到当前的设置,将flags设置ASYNC_SPD_CUST位,设置custom_divisor,最后用TIOCSSERIAL设置。
相关代码如下:
void set_baud(int fd, int baud)
{
      int   status;
      struct termios   Opt;
      struct serial_struct Serial;

      tcgetattr(fd, &Opt);      /*Get current options*/
      tcflush(fd, TCIOFLUSH);/*Flush the buffer*/   
      cfsetispeed(&Opt, B38400);/*Set input speed,38400 is necessary? who can tell me why?*/
      cfsetospeed(&Opt, 38400); /*Set output speed*/
      tcflush(fd,TCIOFLUSH);      /*Flush the buffer*/
      status = tcsetattr(fd, TCSANOW, &Opt);/*Set the 38400 Options*/
      if(status != 0)
      {      
                perror("tcsetattr fd1");
                return;   
      }   
                        
      if((ioctl(fd,TIOCGSERIAL,&Serial))<0)/*Get configurations vim IOCTL*/
      {
                printf("Fail to get Serial!\n");
                return;
      }
      Serial.flags = ASYNC_SPD_CUST;/*We will use custom buad,May be standard,may be not */
      Serial.custom_divisor=Serial.baud_base/baud;/*In Sep4020,baud_base=sysclk/16*/
      printf("divisor is %x\n",Serial.custom_divisor);
      if((ioctl(fd,TIOCSSERIAL,&Serial))<0)/*Set it*/
      {
                printf("Fail to set Serial\n");
                return;
      }
      ioctl(fd,TIOCGSERIAL,&Serial);/*Get it again,not necessary.*/
   printf("\nBAUD: success set baud to %d,custom_divisor=%d,baud_base=%d\n",baud,Serial.custom_divisor,Serial.baud_base);
}

附件是一个在SEP4020开发板上实现的波特率为125000的串口通信例子,用跳线将两块4020开发板(俺用的一块Mini4020,一块Micro4020)的T/R交叉连接(两块开发板都使用的uart1,注意共地):
在Micro上用ADS初始化波特率后暂停程序运行,用内存察看窗口打开0x10006000地址,并打开定时刷新功能观察这个地址的内容变化,这个地址就是RX_FIFO,有数据收到的话会有变化,看变化的数据与发送方是否一致即可简单验证波特率设置是否正确。
在Mini上启动Linux系统,将附件中的uart.c编译成可执行程序并执行,即可观察到Micro的FiFO在0x31-0x36变化,与Linux应用程序发送的数据一致

转自:http://www.armfans.net
参考:http://blog.chinaunix.net/u3/103428/showart_2091817.html

DoDo915 发表于 2010-9-29 04:16:25

Mark

tornadoyun 发表于 2014-3-24 15:08:57

学习了      
页: [1]
查看完整版本: 转帖:linux串口编程中非标准波特率的实现