mini210的串口驱动的应用程序

2024-02-03 19:32

本文主要是介绍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;

}

这篇关于mini210的串口驱动的应用程序的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/675151

相关文章

Java通过驱动包(jar包)连接MySQL数据库的步骤总结及验证方式

《Java通过驱动包(jar包)连接MySQL数据库的步骤总结及验证方式》本文详细介绍如何使用Java通过JDBC连接MySQL数据库,包括下载驱动、配置Eclipse环境、检测数据库连接等关键步骤,... 目录一、下载驱动包二、放jar包三、检测数据库连接JavaJava 如何使用 JDBC 连接 mys

Python模拟串口通信的示例详解

《Python模拟串口通信的示例详解》pySerial是Python中用于操作串口的第三方模块,它支持Windows、Linux、OSX、BSD等多个平台,下面我们就来看看Python如何使用pySe... 目录1.win 下载虚www.chinasem.cn拟串口2、确定串口号3、配置串口4、串口通信示例5

如何在Ubuntu上安装NVIDIA显卡驱动? Ubuntu安装英伟达显卡驱动教程

《如何在Ubuntu上安装NVIDIA显卡驱动?Ubuntu安装英伟达显卡驱动教程》Windows系统不同,Linux系统通常不会自动安装专有显卡驱动,今天我们就来看看Ubuntu系统安装英伟达显卡... 对于使用NVIDIA显卡的Ubuntu用户来说,正确安装显卡驱动是获得最佳图形性能的关键。与Windo

嵌入式Linux之使用设备树驱动GPIO的实现方式

《嵌入式Linux之使用设备树驱动GPIO的实现方式》:本文主要介绍嵌入式Linux之使用设备树驱动GPIO的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录一、设备树配置1.1 添加 pinctrl 节点1.2 添加 LED 设备节点二、编写驱动程序2.1

嵌入式Linux驱动中的异步通知机制详解

《嵌入式Linux驱动中的异步通知机制详解》:本文主要介绍嵌入式Linux驱动中的异步通知机制,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录前言一、异步通知的核心概念1. 什么是异步通知2. 异步通知的关键组件二、异步通知的实现原理三、代码示例分析1. 设备结构

利用Python调试串口的示例代码

《利用Python调试串口的示例代码》在嵌入式开发、物联网设备调试过程中,串口通信是最基础的调试手段本文将带你用Python+ttkbootstrap打造一款高颜值、多功能的串口调试助手,需要的可以了... 目录概述:为什么需要专业的串口调试工具项目架构设计1.1 技术栈选型1.2 关键类说明1.3 线程模

usb接口驱动异常问题常用解决方案

《usb接口驱动异常问题常用解决方案》当遇到USB接口驱动异常时,可以通过多种方法来解决,其中主要就包括重装USB控制器、禁用USB选择性暂停设置、更新或安装新的主板驱动等... usb接口驱动异常怎么办,USB接口驱动异常是常见问题,通常由驱动损坏、系统更新冲突、硬件故障或电源管理设置导致。以下是常用解决

如何使用C#串口通讯实现数据的发送和接收

《如何使用C#串口通讯实现数据的发送和接收》本文详细介绍了如何使用C#实现基于串口通讯的数据发送和接收,通过SerialPort类,我们可以轻松实现串口通讯,并结合事件机制实现数据的传递和处理,感兴趣... 目录1. 概述2. 关键技术点2.1 SerialPort类2.2 异步接收数据2.3 数据解析2.

JAVA系统中Spring Boot应用程序的配置文件application.yml使用详解

《JAVA系统中SpringBoot应用程序的配置文件application.yml使用详解》:本文主要介绍JAVA系统中SpringBoot应用程序的配置文件application.yml的... 目录文件路径文件内容解释1. Server 配置2. Spring 配置3. Logging 配置4. Ma

Linux_kernel驱动开发11

一、改回nfs方式挂载根文件系统         在产品将要上线之前,需要制作不同类型格式的根文件系统         在产品研发阶段,我们还是需要使用nfs的方式挂载根文件系统         优点:可以直接在上位机中修改文件系统内容,延长EMMC的寿命         【1】重启上位机nfs服务         sudo service nfs-kernel-server resta