本文共 6099 字,大约阅读时间需要 20 分钟。
使用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 32int 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;
}
转载地址:http://nelvi.baihongyu.com/