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

/*******************************************************************************************
 *       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"

 

时间: 2024-10-24 10:08:12

I.MX6 Android Linux UART send receive with multi-thread and multi-mode demo的相关文章

I.MX6 Android Linux shell MMPF0100 i2c 设置数据

#!/system/bin/busybox ash # # I.MX6 Android Linux shell MMPF0100 i2c 设置数据 # 说明: # 本文主要记录通过shell脚本来设置MMPF0100的数据. # # 2016-4-6 深圳 南山平山村 曾剑锋 # # 检查参数个数 if [ $# -lt 3 ]; then echo "USAGE:" echo " i2cSetData.sh <curPage> <address(hex)&

I.MX6 Android Linux shell MMPF0100 i2c 获取数据

#!/system/bin/busybox ash # # I.MX6 Android Linux shell MMPF0100 i2c 获取数据 # 说明: # 本文主要记录通过shell脚本来获取MMPF0100的数据,更多的是为了更为 # 方便的获取到数据,在进行一些调试的时候能够更有效. # # 2016-4-1 深圳 南山平山村 曾剑锋 # # 检查参数个数 if [ $# -lt 3 ]; then echo "USAGE:" echo " i2cData.sh

I.MX6 Android 5.1 纯Linux、U-Boot编译

/***************************************************************************** * I.MX6 Android 5.1 纯Linux.U-Boot编译 * 说明: * 单纯编译一下Linux内核和U-Boot这部分代码,用于测试用. * * 2017-5-12 台湾 中和区 曾剑锋 *********************************************************************

I.MX6 Android iperf3 porting failed

/***************************************************************************** * I.MX6 Android iperf3 porting failed * 说明: * 本来想移植一下iperf3到Android系统上测试一下网卡,可能是版本高了点,最后 * 运行客户端的时候会报错,也找了一些解决办法,但还是未能解决. * * 2016-4-5 深圳 南山平山村 曾剑锋 ***********************

I.MX6 Android can-utils 移植

/******************************************************************* * I.MX6 Android can-utils 移植 * 说明: * 由于最近要用到CAN,于是先移植一下can-tuils来看一下情况. * * 2016-8-1 深圳 南山平山村 曾剑锋 ******************************************************************/ 一.获取源码: https:/

I.MX6 android 获取framebuffer信息

/******************************************************************************** * I.MX6 android 获取framebuffer信息 * 声明: * 调试显示屏的时候,我们可能会需要去知道我们设置的信息是否正确,或者有时候 * 需要去确认别人的设置的是否正确. * * 2016-1-20 深圳 南山平山村 曾剑锋 *********************************************

I.MX6 Android i2c-tools porting

/************************************************************************** * I.MX6 Android i2c-tools porting * 说明: * 判断I2C总线设备是否存在,每次都去查dmesg,实在是烦了,于是还是移植 * 一个i2c-tools比较好,不用翻那长长内核信息. * * 2016-3-31 深圳 南山平山村 曾剑锋 **************************************

I.MX6 Android netperf

/***************************************************************************** * I.MX6 Android netperf * 说明: * 之前移植iperf3网络测试工具不成功,本来想再移植一个iperf2来试一下,但是 * 在检查Android源码系统的时候不小心看到netperf文件夹,查了点资料,貌似可以实 * 现iperf的功能,于是又省了点事. * * 2016-4-18 深圳 南山平山村 曾剑锋 **

I.MX6 android BatteryService jni hacking

/**************************************************************************** * I.MX6 android BatteryService jni hacking * 声明: * 本文主要是为了知道Android的获取的电源管理的数据的jni是从Linux系统的 * 什么位置获取的,获取的机制是什么. * * 2016-2-22 深圳 南山平山村 曾剑锋 ********************************