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

相关文章

Linux_kernel驱动开发11

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

cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个?

跨平台系列 cross-plateform 跨平台应用程序-01-概览 cross-plateform 跨平台应用程序-02-有哪些主流技术栈? cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个? cross-plateform 跨平台应用程序-04-React Native 介绍 cross-plateform 跨平台应用程序-05-Flutte

驱动(RK3588S)第七课时:单节点设备树

目录 需求一、设备树的概念1、设备树的后缀名:2、设备树的语法格式3、设备树的属性(重要)4、设备树格式举例 二、设备树所用函数1、如何在内核层种获取设备树节点:2、从设备树上获取 gpio 口的属性3、获取节点上的属性只针对于字符串属性的4、函数读取 np 结点中的 propname 属性的值,并将读取到的 u32 类型的值保存在 out_value 指向的内存中,函数的返回值表示读取到的

驱动安装注册表指令

HKCR: HKEY_CLASSES_ROOT HKCU: HKEY_CURRENT_USER HKLM: HKEY_LOCAL_MACHINE HKU: HEKY_USER HER: 相对根键

UMDF驱动安装

VS2013 + WDF8.1,UMDF驱动选择User Mode Driver,不要选User Mode Driver 2.0,否则Win7安装有问题,如图 另外,在驱动安装时不要忘记WUDFUpdate_<主版本号><次版本号>.dll文件,具体文件名在INF中查找。此文件可在WDF的安装目录中找到。注意:在WDF的安装目录中会有3个WUDFUpdate_xxx.dll文件,x86,x6

Java Web应用程序的推荐目录结构

以前没有用过maven管理过项目的依赖,最后使用上了maven,发现通过不能方式建立出来的web应用程序目录结构基本都不一样,既然每次都要到网上搜索如何建立maven管理的Web应用程序,不如自己找百度谷歌一下。 找了半天 ,感觉比较好的maven管理的web应用程序目录结构是这个: ├── pom.xml└── src├── main│ ├── java│ │ └── myg

安卓开发板_联发科MTK开发评估套件串口调试

串口调试 如果正在进行lk(little kernel ) 或内核开发,USB 串口适配器( USB 转串口 TTL 适配器的简称)对于检查系统启动日志非常有用,特别是在没有图形桌面显示的情况下。 1.选购适配器 常用的许多 USB 转串口的适配器,按芯片来分,有以下几种: CH340PL2303CP2104FT232 一般来说,采用 CH340 芯片的适配器,性能比较稳定,价

VB和51单片机串口通信讲解(只针对VB部分)

标记:该篇文章全部搬自如下网址:http://www.crystalradio.cn/thread-321839-1-1.html,谢谢啦            里面关于中文接收的部分,大家可以好好学习下,题主也在研究中................... Commport;设置或返回串口号。 SettingS:以字符串的形式设置或返回串口通信参数。 Portopen:设置或返回串口

电脑驱动分类

电脑驱动程序(驱动程序)是操作系统与硬件设备之间的桥梁,用于使操作系统能够识别并与硬件设备进行通信。以下是常见的驱动分类: 1. 设备驱动程序 显示驱动程序:控制显卡和显示器的显示功能,负责图形渲染和屏幕显示。 示例:NVIDIA、AMD 显示驱动程序。打印机驱动程序:允许操作系统与打印机通信,控制打印任务。 示例:HP、Canon 打印机驱动程序。声卡驱动程序:管理音频输入和输出,与声卡硬件

麒麟系统安装GPU驱动

1.nvidia 1.1显卡驱动 本机显卡型号:nvidia rtx 3090 1.1.1下载驱动 打开 https://www.nvidia.cn/geforce/drivers/ 也可以直接使用下面这个地址下载 https://www.nvidia.com/download/driverResults.aspx/205464/en-us/ 1.1.3安装驱动 右击,