I.MX6 Android Linux UART send receive with multi-thread and multi-mode demo

简介: /******************************************************************************************* * I.
/*******************************************************************************************
 *       I.MX6 Android Linux UART send receive with multi-thread and multi-mode demo 
 * 声明:
 *  1. 本软件是为了测试Android底层的Linux驱动以及硬件是否存在缺陷而编写的测试软件;
 *  2. 本软件可以设置为发送、接收、发送并接收模式,并且提供q+enter键退出程序;
 *  3. 本人是采用NDK的方式进行编译的,并采用autorun.sh脚本进行调用,主要是不想敲太多键盘;
 *  4. 本程序并不打算给出太多的注释,没有理由;
 *  5. 如果想知道波特率更多细节,可以参考本人的《I.MX6 Linux Serial Baud Rate hacking》。
 *
 *                                                 2015-8-22 晴 深圳 南山平山村 曾剑锋
 ******************************************************************************************/

                            \\\\\\\\\-*- 目录 -*-////////
                            |     一、cat uartRS.c      |
                            |     二、cat Android.mk    |
                            |     三、cat autorun.sh    |
                            \\\\\\\\\\\\\\\//////////////

一、cat uartRS.c
    #include <stdio.h>  
    #include <stdlib.h>  
    #include <unistd.h>  
    #include <sys/types.h>  
    #include <sys/stat.h>  
    #include <fcntl.h>      
    #include <termios.h>    
    #include <errno.h>  
    #include <pthread.h>
    
    #define SENDWORKMODE        1
    #define RECVWORKMODE        2
    #define SENDANDRECVWORKMODE 3
    
    int  serial_fd          = 0;  
    int  serialNumber       = 0;
    int  baudRate           = 0;
    int  workMode           = 0;        // 1 send; 2 recv; 3 send and recv
    char serialString[20]   = {0};
    
    char sendString[512]    = {0};
    char recvString[512]    = {0};
    
    int  help ( int argc );
    int  initSerial ( void );
    
    int  getBaudRate ( char *baudRateString );
    void getSerial ( char* commandLineserialString );
    int  getWorkMode ( char *workMode );
    
    int  uart_send ( int fd, char *data, int datalen );
    int  uart_recv ( int fd, char *data, int datalen );
    
    pthread_t recv_thread;
    void *recvDataThread ( void *arg );
    
    pthread_t quitOut_thread;
    void *quitOutThead ( void *arg );
    
    int main(int argc, char **argv)  
    {  
        
        if ( help( argc ) != 0)
            return -1;
        
        getSerial ( argv[1] );
        baudRate = getBaudRate ( argv[2] );
        workMode = getWorkMode ( argv[3] );
    
        initSerial ();
    
        if ( workMode == RECVWORKMODE || workMode == SENDANDRECVWORKMODE ) {
            pthread_create ( &recv_thread, NULL, recvDataThread, NULL );
        }
    
        pthread_create ( &quitOut_thread, NULL, quitOutThead, NULL );
    
        int i = 0;
        while ( 1 ) {
    
            if ( workMode == SENDWORKMODE || workMode == SENDANDRECVWORKMODE ) {
                sprintf ( sendString, "%03d: %s\r\n", i++, argv[4] );
                uart_send ( serial_fd, sendString, strlen ( sendString ) );  
            }
            usleep ( 100000 );
        } 
          
        close ( serial_fd );  
        return 0;  
    }
    
    int getWorkMode ( char *workModeString ) {
    
        int ret = atoi( workModeString );
    
        switch ( ret ) {
            case 1 :
                printf ( "workMode: send.\n" );
                break;
            case 2 :
                printf ( "workMode: recv.\n" );
                break;
            case 3 :
                printf ( "workMode: send and recv.\n" );
                break;
            default:
                printf ( "none of this workMode.\n" );
                exit ( 0 );
        }
    
        return ret;
    }
    
    void *quitOutThead(void *arg) {
    
        //system("stty raw -echo");     can't work well in Android linux
        char ch = '\0';
    
        while ( 1 ) {
            scanf ( "%c", &ch );
            if ( ch == 'q' || ch == 'Q' ) {
                exit ( 0 );
            }
        }
    }
    
    void *recvDataThread(void *arg) {
    
        int ret = 0;
        int i = 0;
    
        while ( 1 ) {
            ret = uart_recv ( serial_fd, recvString, sizeof(recvString) );
            printf ( "%03d %s\n", i++, recvString );
            bzero ( recvString, sizeof(recvString) );
            usleep ( 100000 );
        }
    }
    
    int help( int argc ) {
    
        if ( argc != 5 ) {
            printf ( "USAGE:\n" );
            printf ( "    command <serial absolute path> <baudRate> <workMode> <send String>\n" );
            printf ( "    example:\n" );
            printf ( "        ./uartRS /dev/ttymxc1 115200 3 \"1234567890ABCDEFG\"\n" );
            return -1;
        }
    
        return 0;
    }
    
    int uart_recv(int fd, char *data, int datalen) {  
    
        int ret = 0;
    
        ret = read ( fd, data, datalen );
          
        return ret;  
    }
    
    int uart_send(int fd, char *data, int datalen) {  
    
        int len = 0;  
    
        len = write ( fd, data, datalen );      //实际写入的长度  
        if(len == datalen) {  
            return len;  
        } else {  
            tcflush(fd, TCOFLUSH);              //TCOFLUSH刷新写入的数据但不传送  
            return -1;  
        }  
          
        return 0;  
    }  
    
    int initSerial( void ) {  
    
        //serial_fd = open( serialString, O_RDWR | O_NOCTTY | O_NDELAY );  
        serial_fd = open ( serialString, O_RDWR );  
        if ( serial_fd < 0 ) {  
            perror ( "open" );  
            return -1;  
        }  
          
        // 串口主要设置结构体termios <termios.h>  
        struct termios options;  
          
        /**
         * tcgetattr函数用于获取与终端相关的参数,参数fd为终端的文件描述符,
         * 返回的结果保存在termios结构体中 
         */  
        tcgetattr ( serial_fd, &options );  
        /**2. 修改所获得的参数*/  
        options.c_cflag |= (CLOCAL | CREAD);    //设置控制模式状态,本地连接,接收使能  
        options.c_cflag &= ~CSIZE;              //字符长度,设置数据位之前一定要屏掉这个位  
        options.c_cflag &= ~CRTSCTS;            //无硬件流控  
        options.c_cflag |= CS8;                 //8位数据长度  
        options.c_cflag &= ~CSTOPB;             //1位停止位  
        options.c_iflag |= IGNPAR;              //无奇偶检验位  
        options.c_oflag = 0;                    //输出模式  
        options.c_lflag = 0;                    //不激活终端模式  
        cfsetospeed ( &options, baudRate );     //设置波特率  
        //cfsetospeed(&options, B2000000);      //设置波特率  
          
        /* 设置新属性,TCSANOW:所有改变立即生效*/  
        tcflush ( serial_fd, TCIFLUSH );        //溢出数据可以接收,但不读  
        tcsetattr ( serial_fd, TCSANOW, &options );  
          
        return 0;  
    }  
    
    void getSerial ( char* commandLineserialString ) {
    
        sprintf ( serialString, "%s", commandLineserialString );
        printf ( "serialString : %s.\n", serialString );
    }
    
    /**
     * 该函数之所以采用这种方式,主要是为了波特率出错时方便调试
     */
    int getBaudRate ( char* baudRateString ) {
        int ret = atoi ( baudRateString );
        switch ( ret ) {
            case 0:
                printf ( "baudRate %s.\n", "0" );
                ret = B0;
                break;
            case 50:
                printf ( "baudRate %s.\n", "50" );
                ret = B50;
                break;
            case 75:
                printf ( "baudRate %s.\n", "75" );
                ret = B75;
                break;
            case 110:
                printf ( "baudRate %s.\n", "110" );
                ret = B110;
                break;
            case 134:
                printf ( "baudRate %s.\n", "134" );
                ret = B134;
                break;
            case 150:
                printf ( "baudRate %s.\n", "150" );
                ret = B150;
                break;
            case 200:
                printf ( "baudRate %s.\n", "200" );
                ret = B200;
                break;
            case 300:
                printf ( "baudRate %s.\n", "300" );
                ret = B300;
                break;
            case 600:
                printf ( "baudRate %s.\n", "600" );
                ret = B600;
                break;
            case 1200:
                printf ( "baudRate %s.\n", "1200" );
                ret = B1200;
                break;
            case 1800:
                printf ( "baudRate %s.\n", "1800" );
                ret = B1800;
                break;
            case 2400:
                printf ( "baudRate %s.\n", "2400" );
                ret = B2400;
                break;
            case 4800:
                printf ( "baudRate %s.\n", "4800" );
                ret = B4800;
                break;
            case 9600:
                printf ( "baudRate %s.\n", "9600" );
                ret = B9600;
                break;
            case 19200:
                printf ( "baudRate %s.\n", "19200" );
                ret = B19200;
                break;
            case 38400:
                printf ( "baudRate %s.\n", "38400" );
                ret = B38400;
                break;
            case 57600:
                printf ( "baudRate %s.\n", "57600" );
                ret = B57600;
                break;
            case 115200:
                printf ( "baudRate %s.\n", "115200" );
                ret = B115200;
                break;
            case 230400:
                printf ( "baudRate %s.\n", "230400" );
                ret = B230400;
                break;
            case 460800:
                printf ( "baudRate %s.\n", "460800" );
                ret = B460800;
                break;
            case 500000:
                printf ( "baudRate %s.\n", "500000" );
                ret = B500000;
                break;
            case 576000:
                printf ( "baudRate %s.\n", "576000" );
                ret = B576000;
                break;
            case 921600:
                printf ( "baudRate %s.\n", "921600" );
                ret = B921600;
                break;
            case 1000000:
                printf ( "baudRate %s.\n", "1000000" );
                ret = B1000000;
                break;
            case 1152000:
                printf ( "baudRate %s.\n", "1152000" );
                ret = B1152000;
                break;
            case 1500000:
                printf ( "baudRate %s.\n", "1500000" );
                ret = B1500000;
                break;
            case 2000000:
                printf ( "baudRate %s.\n", "2000000" );
                ret = B2000000;
                break;
            case 2500000:
                printf ( "baudRate %s.\n", "2500000" );
                ret = B2500000;
                break;
            case 3000000:
                printf ( "baudRate %s.\n", "3000000" );
                ret = B3000000;
                break;
            case 3500000:
                printf ( "baudRate %s.\n", "3500000" );
                ret = B3500000;
                break;
            case 4000000:
                printf ( "baudRate %s.\n", "4000000" );
                ret = B4000000;
                break;
            default:
                printf ( "baudRate is not exist %s.\n", "0" );
                ret = B0;
        }
        //printf ("baudRate %s.\n", baudRateString);
        return ret;
    }
    
二、cat Android.mk
    LOCAL_PATH := $(call my-dir)
    
    include $(CLEAR_VARS)
    LOCAL_MODULE    := uartRs 
    #LOCAL_STATIC_LIBRARIES :=libpthread
    #LOCAL_SHARED_LIBRARIES :=libpthread
    LOCAL_STATIC_LIBRARIES :=libpthread
    LOCAL_SRC_FILES := uartRS.c
    #LOCAL_LDLIBS    += -lpthread 
    
    include $(BUILD_EXECUTABLE)

三、cat autorun.sh
    # ./uartRS <serial absolute path> <baudRate> <work mode> <send String>
    #   1.serial absolute path
    #     the absolute path for serial port, example:
    #         /dev/ttymxc1
    #   2. referrence baudrate:
    #      0
    #      50
    #      75
    #      110
    #      134
    #      150
    #      200
    #      300
    #      600
    #      1200
    #      1800
    #      2400
    #      4800
    #      9600
    #      19200
    #      38400
    #      57600
    #      115200
    #      230400
    #      460800
    #      500000
    #      576000
    #      921600
    #      1000000
    #      1152000
    #      1500000
    #      2000000
    #      2500000
    #      3000000
    #      3500000
    #      4000000
    #   3. work mode
    #     1. send;
    #     2. recv;
    #     3. send and recv
    #   4. send string
    #     the string what you want to send
    
    chmod 777 ./uartRS              # give excute-permission
    # ./uartRS <serial absolute path> <baudRate> <work mode> <send String>
    ./uartRS      /dev/ttymxc1          115200        3       "1234567890ABCDEF"

 

目录
相关文章
|
8月前
|
Linux 编译器 Android开发
FFmpeg开发笔记(九)Linux交叉编译Android的x265库
在Linux环境下,本文指导如何交叉编译x265的so库以适应Android。首先,需安装cmake和下载android-ndk-r21e。接着,下载x265源码,修改crosscompile.cmake的编译器设置。配置x265源码,使用指定的NDK路径,并在配置界面修改相关选项。随后,修改编译规则,编译并安装x265,调整pc描述文件并更新PKG_CONFIG_PATH。最后,修改FFmpeg配置脚本启用x265支持,编译安装FFmpeg,将生成的so文件导入Android工程,调整gradle配置以确保顺利运行。
302 1
FFmpeg开发笔记(九)Linux交叉编译Android的x265库
|
8月前
|
Android开发
Android MediaTek 平台增加UART接口的红外模块支持,支持NEC红外遥控
Android MediaTek 平台增加UART接口的红外模块支持,支持NEC红外遥控
162 0
|
8月前
|
Unix Linux Shell
FFmpeg开发笔记(八)Linux交叉编译Android的FFmpeg库
在Linux环境下交叉编译Android所需的FFmpeg so库,首先下载`android-ndk-r21e`,然后解压。接着,上传FFmpeg及相关库(如x264、freetype、lame)源码,修改相关sh文件,将`SYSTEM=windows-x86_64`改为`SYSTEM=linux-x86_64`并删除回车符。对x264的configure文件进行修改,然后编译x264。同样编译其他第三方库。设置环境变量`PKG_CONFIG_PATH`,最后在FFmpeg源码目录执行配置、编译和安装命令,生成的so文件复制到App工程指定目录。
372 9
FFmpeg开发笔记(八)Linux交叉编译Android的FFmpeg库
|
8月前
|
Linux Android开发
测试程序之提供ioctl函数应用操作GPIO适用于Linux/Android
测试程序之提供ioctl函数应用操作GPIO适用于Linux/Android
150 0
|
5月前
|
XML API Android开发
码农之重学安卓:利用androidx.preference 快速创建一、二级设置菜单(demo)
本文介绍了如何使用androidx.preference库快速创建具有一级和二级菜单的Android设置界面的步骤和示例代码。
157 1
码农之重学安卓:利用androidx.preference 快速创建一、二级设置菜单(demo)
|
2月前
|
Java Linux Android开发
深入探索Android系统架构:从Linux内核到应用层
本文将带领读者深入了解Android操作系统的复杂架构,从其基于Linux的内核到丰富多彩的应用层。我们将探讨Android的各个关键组件,包括硬件抽象层(HAL)、运行时环境、以及核心库等,揭示它们如何协同工作以支持广泛的设备和应用。通过本文,您将对Android系统的工作原理有一个全面的认识,理解其如何平衡开放性与安全性,以及如何在多样化的设备上提供一致的用户体验。
|
3月前
|
Ubuntu Linux Android开发
termux+anlinux+Rvnc viewer来使安卓手机(平板)变成linux服务器
本文介绍了如何在Android设备上安装Termux和AnLinux,并通过这些工具运行Ubuntu系统和桌面环境。
210 2
termux+anlinux+Rvnc viewer来使安卓手机(平板)变成linux服务器
|
4月前
|
Java Maven 开发工具
第一个安卓项目 | 中国象棋demo学习
本文是作者关于其第一个安卓项目——中国象棋demo的学习记录,展示了demo的运行结果、爬坑记录以及参考资料,包括解决Android Studio和maven相关问题的方法。
第一个安卓项目 | 中国象棋demo学习
|
3月前
|
Linux API 开发工具
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
ijkplayer是由B站研发的移动端播放器,基于FFmpeg 3.4,支持Android和iOS。其源码托管于GitHub,截至2024年9月15日,获得了3.24万星标和0.81万分支,尽管已停止更新6年。本文档介绍了如何在Linux环境下编译ijkplayer的so库,以便在较新的开发环境中使用。首先需安装编译工具并调整/tmp分区大小,接着下载并安装Android SDK和NDK,最后下载ijkplayer源码并编译。详细步骤包括环境准备、工具安装及库编译等。更多FFmpeg开发知识可参考相关书籍。
120 0
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
|
7月前
|
存储 Linux 开发工具
Linux手动升级替换Android Studio
【6月更文挑战第22天】
146 8