Chinaunix首页 | 论坛 | 博客
  • 博客访问: 173870
  • 博文数量: 35
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 305
  • 用 户 组: 普通用户
  • 注册时间: 2016-02-01 12:35
个人简介

不断超越自己,将更强大!

文章分类

全部博文(35)

文章存档

2022年(1)

2017年(5)

2016年(29)

我的朋友

分类: 嵌入式

2016-03-02 22:06:38

      普通单片机的串口操作比较容易,但是基于Linux系统的串口操作难不难呢?其实,基于Linux操作系统的串口操作分过两部分:串口驱动(注册设备)与串口的应用程序,一般厂家或是Linux内核已经提供了基于开发板的串口驱动,只需要注册一下,就可以使用了。我手头上有一块AT91SAM9261EK的开发板,只是为了学习Linux,因此,学习一下串口的操作。

     首先看一下内核是否注册了所有的串口。开发板可用的串口,硬件板子上的,我这里有 三个串口,其中一个为:DEBUG,也就是还有两个串口可以用来测试。启动开发板,控制台打印出的串口注册的信息,只有DEBUG注册了,因此,需要修改内核里的开发板相关的文件:我这里为:

linux-2.6.32.2/arch/arm/mach-at91/board-sam9261ek.c

找到相应的串口初始化注册的函数:

static void __init ek_map_io(void)
{
    /* Initialize processor: 18.432 MHz crystal */
    at91sam9261_initialize(18432000);

    /* Setup the LEDs */
    at91_init_leds(AT91_PIN_PA13, AT91_PIN_PA14);

    /* DBGU on ttyS0. (Rx & Tx only) */
    at91_register_uart(0, 0, 0);

    /* Add USART0 USART1 USART2 */
    at91_register_uart(AT91SAM9261_ID_US0, 1, 0);
    at91_register_uart(AT91SAM9261_ID_US1, 2, 0);
    at91_register_uart(AT91SAM9261_ID_US2, 3, 0);

    /* set serial console to ttyS0 (ie, DBGU) */
    at91_set_serial_console(0);
}


    然后重新编译内核,发现另外三个串口的设备注册成功。分别为:

atmel_usart.0: ttyS0 at MMIO 0xfefff200 (irq = 1) is a ATMEL_SERIAL
atmel_usart.1: ttyS1 at MMIO 0xfffb0000 (irq = 6) is a ATMEL_SERIAL
atmel_usart.2: ttyS2 at MMIO 0xfffb4000 (irq = 7) is a ATMEL_SERIAL
atmel_usart.3: ttyS3 at MMIO 0xfffb8000 (irq = 8) is a ATMEL_SERIAL

串口注册成功,操作的方式就像打开文件一样了。分别为 /dev/ttyS0 /dev/ttyS1 /dev/ttyS2

下面为操作串口的应用程序,为网上找到,自己修改了一下,实验好用。连接好串口线,DEBUG也连接,我这里使用USB转串口的,设置好波特率:程序里设置为:9600 8 N 1,串口助手发送,开发板收到后,通过DEBUG口打印接收到的,并且再通过相应的串口发送回来。

这里涉及到串口的配置,文件的open 与write。
程序如下:

点击(此处)折叠或打开

  1. //rs232_test.c

  2. #include <sys/types.h>
  3. #include <sys/stat.h>
  4. #include <unistd.h>
  5. #include <fcntl.h>
  6. #include <termios.h>
  7. #include <stdio.h>
  8. #include <errno.h>
  9. #include <string.h>
  10. #include <sys/time.h>

  11. #define BAUDRATE B9600


  12. static int open_com(char *dev_name, long com_baud, int com_data,
  13.         int com_pry, int com_stop)
  14. {
  15.     uint    baud = 0, data = 0, parity = 0, stop = 0;
  16.     struct    termios    strNewTio;
  17.     int    fd;

  18.     //set baudrate:
  19.     switch(com_baud) {
  20.     case 50: baud = B50; break;
  21.     case 75: baud = B75; break;
  22.     case 110: baud = B110; break;
  23.     case 134: baud = B134; break;
  24.     case 150: baud = B150; break;
  25.     case 200: baud = B200; break;
  26.     case 300: baud = B300; break;
  27.     case 600: baud = B600; break;
  28.     case 1200: baud = B1200; break;
  29.     case 1800: baud = B1800; break;
  30.     case 4800: baud = B4800; break;
  31.     case 9600: baud = B9600; break;
  32.     case 19200: baud = B19200; break;
  33.     case 38400: baud = B38400; break;
  34.     case 57600: baud = B57600; break;
  35.     case 115200: baud = B115200; break;
  36.     case 230400: baud = B230400; break;
  37.     default:
  38.         baud = B9600;
  39.     }

  40.     //set databits:
  41.     switch(com_data) {
  42.     case 5:    data = CS5; break;
  43.     case 6:    data = CS6; break;
  44.     case 7:    data = CS7; break;
  45.     case 8:    data = CS8; break;
  46.     default:
  47.         data = CS8;
  48.     }

  49.     //set parity:
  50.     switch(com_pry) {
  51.     case 0: parity = 0; break;
  52.     case 1: parity = PARENB | PARODD; break;
  53.     case 2: parity = PARENB; break;
  54.     default:
  55.         parity = 0;
  56.     }

  57.     //set stopbits:
  58.     switch(com_stop) {
  59.     case 1: stop = 0; break;
  60.     case 2: stop = CSTOPB; break;
  61.     default:
  62.         stop = 0;
  63.     }

  64.     fd = open(dev_name, O_RDWR | O_NOCTTY );
  65.     if (fd < 0) {
  66.         perror("com open() error");
  67.         return -1;
  68.     }

  69.     //set parameters:
  70.     tcgetattr(fd, &strNewTio);

  71.     strNewTio.c_cflag = baud | data | parity | stop | CREAD | CLOCAL;
  72.     strNewTio.c_iflag = 0;
  73.     strNewTio.c_lflag = 0;
  74.     strNewTio.c_oflag = 0;

  75.     if (tcsetattr(fd, TCSANOW, &strNewTio) < 0) {
  76.         close(fd);
  77.         perror("com tcsetattr() error");
  78.         return -1;
  79.     }

  80.     return fd;
  81. }


  82. int main(int argc, char *argv[])
  83. {
  84.     struct timeval tp;
  85.     long time1=0;
  86.     long time2=0;
  87.     int fd1,fd2;
  88.     struct termios tio1,tio2;

  89.     int res,cnt,i;
  90.     int mode = 1; //rs232 mode
  91.     unsigned char c;
  92.     
  93.     unsigned char dev1[10];
  94.     unsigned char dev2[10];
  95.     int tmp1,tmp2;

  96.     if (argc == 0x0) {
  97.         printf("Usage : rs232 com_no\n");
  98.         return 0;
  99.     }
  100.     else {
  101.         tmp1 = atoi(argv[1]);
  102.         
  103.         if (tmp1 > 16 ) {
  104.             printf("Usage : rs232_loopback com_no com_no\n");
  105.             return 0;
  106.         }
  107.         else {
  108.             sprintf(dev1, "/dev/ttyS%d", tmp1);
  109.         }
  110.     }
  111.     fd1 = open_com(dev1, 9600, 8, 0, 1);

  112.        
  113.     if (fd1 < 0) {
  114.         printf("can not open %s\n", dev1);
  115.         close(fd1);
  116.         return 0;
  117.     }
  118.     else
  119.     {
  120.      printf("Open COM %s Success!!\n", dev1);
  121.     }

  122. // clear the noise, made by change UART mode
  123. usleep(10000);

  124.     char    wr = 'k';
  125.     char    rd [1000];
  126.     int    ret;

  127.     rd[0] = 0;
  128.     while(1)
  129.     {
  130.         printf("=======%d\n ", i++);


  131.         //write(fd1, &wr, 1);
  132.         printf("=send:%c ", wr);

  133.         usleep(100);

  134.         ret = read(fd1, rd, 512);
  135.         if (ret)
  136.         {
  137.             printf("\n=========receive:%s\n", rd);
  138.             write(fd1, rd, strlen(rd));
  139.             memset(rd, 0, 512);
  140.         }
  141.     }

  142.     return 0;
  143. }

Makefile文件如下:

all:
arm-none-linux-gnueabi-gcc rs232_test.c -o rs232_test
clean:
rm -rf *.o rs232_test

执行make,就可以生成在开发板上运行的执行文件,记得设置一下执行权限,chmod 777 rs232_test

可以通过ftp等放到开发板的根文件系统里,在执行目录下执行:
#  ./rs232_test 1              //这里打开/dev/ttyS1

      然后连接好此串口的串口线,通过串口助手发送数据,串口助手就可以收到回复,回复的内容是发送的内容。同时DEBUG控制台会打印出收到的信息。
     至此,基本的串口操作实现了。
阅读(2119) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~