mini210的串口驱动的应用程序

使用mini210开发板通过串口与PC通信

即要发给串口的数据由android的NDK程序先放入管道,由应用程序读取发到串口给PC

pc发到串口的数据,mini210读到后放入管道,然后由android的NDK程序取走

用管道完成程序设计

 

 

代码如下

使用arm-linux-gcc -o xxx  xxx.c   -static编译 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/ioctl.h>


#define COM_PORT  "/dev/s3c2410_serial0"

#define SERIAL_FIFO0_NAME "/tmp/fifo0"  //管道0
#define SERIAL_FIFO1_NAME "/tmp/fifo1"  //管道1

#define BUFF_MAX_SIZE  600
//#define FIFO_BUF_SIZE PIPE_BUF
//#define FIFO_MSG_SIZE 1000
//#define FIFO_NAME_SIZE 40
#define MAX_FD_NUM 32

int serial_fd;
int fifor_fd;
int fifow_fd;
char send_buf[BUFF_MAX_SIZE];
char recv_buf[BUFF_MAX_SIZE];
 
typedef int (* fd_cb_t)(int, void *);
typedef int (* timeout_cb_t)(void *);

typedef struct
{
  int fd;
  fd_cb_t cb;
} fd_t;

typedef struct
{
  fd_t fds[MAX_FD_NUM];
  int fd_num;
  int fd_max;
  struct timeval tv;
  timeout_cb_t timeout_cb;
  fd_set readset;
} fd_list_t;

static fd_list_t serial_fd_list;
static int serial_rx_cb(int fd, void *ptr);
static int serial_tx_cb(int fd, void *ptr);
int fifo_create(const char *fifo_name);
int fifo_rd_open(const char *fifo_name);
int fifo_wr_open(const char *fifo_name);
int select_init(fd_list_t *fd_list);
int select_wait(fd_list_t *fd_list);
int select_add_fd(fd_list_t *fd_list, int fd, fd_cb_t cb);

int open_port()
{
  int fd_port;
  fd_port = open(COM_PORT, O_RDWR|O_NOCTTY|O_NDELAY); //打开串口
  if(fd_port < 0)
  {
    perror("open serial port");
    return -1;
  }
 
  if(fcntl(fd_port, F_SETFL, 0)<0)
  {
    perror("fcntl F_SETFL\n");
  }
 
//  if(isatty(STDIN_FILENO) == 0)
//  {
//    perror("standard input is not a terminal device");
//  }
  return fd_port;
 
}
       
int set_com_config(int fd, int baud_rate, int data_bits, char parity,
                    int stop_bits)
{
  struct termios new_cfg, old_cfg;
  int speed;
 
  if(tcgetattr(fd, &old_cfg) != 0)
  {
    perror("tcgetattr");
    return -1;
  }
 
  new_cfg = old_cfg;
  cfmakeraw(&new_cfg);
  new_cfg.c_cflag &= ~CSIZE;
 
 
  switch(baud_rate)
  {
    case 115200:
        speed = B115200;
    break;
   
    default:
        speed = B115200;
    break;
  }
  cfsetispeed(&new_cfg, speed);
  cfsetospeed(&new_cfg, speed);
 
  switch(data_bits)
  {
    case 8:
      new_cfg.c_cflag |= CS8;
    break;
   
    default: 
      new_cfg.c_cflag |= CS8;
    break;
  }
 
  switch(parity)
  {
    default:
    case 'n':
    case 'N':
    {
      new_cfg.c_cflag &= ~PARENB;
      new_cfg.c_iflag &= ~INPCK;
    }
    break;
  }
 
  switch(stop_bits)
  {
    default:
    case 1:
      new_cfg.c_cflag &= ~CSTOPB;
    break;
  }     
   
  new_cfg.c_cc[VTIME] = 0; //read 不用等待即返回
  new_cfg.c_cc[VMIN] = 1;  //至少读一个byte返回
 
  tcflush(fd, TCIFLUSH);
 
  if((tcsetattr(fd, TCSANOW, &new_cfg)) != 0)
  {
    perror("tcsetattr");
    return -1;
  }
 
  return 0;
}
      
                                     
int main(void)
{
 

  select_init(&serial_fd_list);
 
  if(mkdir("/tmp", 0777) == -1)
  {
    if(errno == EEXIST)
    {
      printf("/tmp  has been exist!\n");
    }
    else
    {
      perror("can't create tmp");
      return 1;
    }   
  } 
   
  if((serial_fd = open_port()) < 0)
  {
    perror("open_port");
    return 1;
  }

  if (fifo_create(SERIAL_FIFO0_NAME) < 0) exit(1);
  if ((fifor_fd = fifo_rd_open(SERIAL_FIFO0_NAME)) < 0) exit(1);
  if (fifo_create(SERIAL_FIFO1_NAME) < 0) exit(1);
  if ((fifow_fd = fifo_wr_open(SERIAL_FIFO1_NAME)) < 0) exit(1); 
     
 select_add_fd(&serial_fd_list, serial_fd, serial_rx_cb);      //PC串口-->管道-->A8
 select_add_fd(&serial_fd_list, fifor_fd, serial_tx_cb);       //A8-->管道-->PC串口

 
  if((set_com_config(serial_fd, 115200, 8, 'n', 1) < 0))
  {
    perror("set_com_config");
    return 1;
  }

 while(1)
  {
    select_wait(&serial_fd_list);
  }
 
  close(fifor_fd);
  close(fifow_fd);  
  close(serial_fd);
  return 0;
}


static int serial_rx_cb(int fd, void *ptr)
{
  memset(recv_buf, 0, BUFF_MAX_SIZE);
  if(read(fd, recv_buf, BUFF_MAX_SIZE) > 0) //从串口读数据存入recv_buf
  {
    printf("the received word are: %s\r\n", recv_buf);
  }
  printf("the received word length: %d\r\n", strlen(recv_buf));
  write(fifow_fd, recv_buf, strlen(recv_buf));  //写入管道
  return 0;
}

static int serial_tx_cb(int fd, void *ptr)
{
  int len,j = 0;
  read(fd, send_buf, BUFF_MAX_SIZE);  //从管道读出数据存入send_buf
  //len = strlen(send_buf);
  while(send_buf[j] != 0xfd)
  {
    printf("words will send are: 0x%x\r\n", send_buf[j]);
    j++;
  }
  printf("%d words will be send,last word 0x%x!\r\n", j+1, send_buf[j]);
  write(serial_fd, send_buf, j+1);  //发到串口,以0xfd为结尾字符
  return 0;
}


int fifo_create(const char *fifo_name) //创建管道
{
  char sys_str[50];

  sprintf(sys_str, "rm -rf %s", fifo_name);

  /* Remove old fifos */
  system(sys_str);

  if((mkfifo(fifo_name, 0777) < 0) && (errno != EEXIST))
  {
    fprintf(stderr, "cannot create fifo\n");
    return -1;
  }

  return 0;

}

int fifo_rd_open(const char *fifo_name)
{
  int fd;

  fd = open(fifo_name, O_RDWR | O_NONBLOCK);

  if (fd == -1)
  {
    fprintf(stderr, "fifo rd open failed. errno:%d\n", errno);
  }
 
  return fd;
}

int fifo_wr_open(const char *fifo_name)
{
  int fd;

  fd = open(fifo_name, O_RDWR);

  if (fd == -1)
  {
    fprintf(stderr, "fifo wr open failed. errno:%d\n", errno);
  }
  return fd;
}


/*

下面几个函数是内核驱动函数的poll函数对应的select函数
uart驱动对应一个select
管道对应一个select,当管道有数据时,会调用对应select的回调函数

*/

int select_init(fd_list_t *fd_list)
{
  fd_list->fd_num = 0;
  fd_list->fd_max = 0;
  FD_ZERO(&fd_list->readset);
}

int select_add_fd(fd_list_t *fd_list, int fd, fd_cb_t cb)
{
  if (fd > 0)
  {
    fd_list->fds[fd_list->fd_num].fd = fd;
    fd_list->fds[fd_list->fd_num].cb = cb;
    fd_list->fd_num++;

    if (fd > fd_list->fd_max) fd_list->fd_max = fd;

    FD_SET(fd, &(fd_list->readset));
  }

  return  fd_list->fd_num - 1;

}


int select_wait(fd_list_t *fd_list)
{
  int rc, i;

  FD_ZERO(&fd_list->readset);
  for (i=0; i<fd_list->fd_num; i++)
  {
    if (fd_list->fds[i].fd > 0)
    {
      FD_SET(fd_list->fds[i].fd, &(fd_list->readset));
    }
  }

  if (fd_list->tv.tv_sec == 0)
    rc = select(fd_list->fd_max+1, &(fd_list->readset), (void *)0, (void *)0, (void *)0);
  else
    rc = select(fd_list->fd_max+1, &(fd_list->readset), (void *)0, (void *)0, &fd_list->tv);

  //printf("select get rc:%d\n", rc);

  if (rc > 0)
  {
    for (i=0; i<fd_list->fd_num; i++)
    {
      if (FD_ISSET(fd_list->fds[i].fd, &(fd_list->readset)))
      {
//        printf("select get fd:%d\n", fd_list->fds[i].fd);
        if (fd_list->fds[i].cb)
        {
          fd_list->fds[i].cb(fd_list->fds[i].fd, (void *)0);
        }
        break;
      }
    }
  }
  else if (rc == 0)
  {
    if (fd_list->timeout_cb != NULL)
    {
      fd_list->timeout_cb(NULL);
    }
  }
  else
  {
    printf("select return error:%d\n", errno);
  }

  return rc;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值