android串口通信实例

本文介绍了一种在Android系统中实现ARM与外部MCU串口通信的方法。通过创建读写两个线程,对串口设备节点进行操作,并利用JNI与Java层交互。详细解释了初始化、发送与接收数据的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

作者:Xandy

最近段时间一直在做android下串口通信的东东,大概功能是android系统端的ARM和系统外的一个MCU通信,通过android界面控制MCU上挂的设备,如radio、TV、BT等等,下面对这个过程作一个浅显的阐述,有错之处还望大家斧正……
我是直接在HAL层中通过两个线程对串口的设备节点/dev/ttymxc1进行读和写的,相应的代码如下:
[html]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. 1、init代码  
  2. /***************************************************************  
  3. ** fun:   init uart(/dev/ttymxc1);  
  4. ** in:      
  5. ** out:   fd sucess, -1 false;  
  6. ** init_mcuuart  
  7. ***************************************************************/  
  8. static int  init_mcuuart(void)  
  9. {  
  10.     int fd,var;  
  11.     portinfo pPort_info;  
  12.     int err;  
  13.   
  14.     dbg(DBG_DEBUG," init_mcuuart in");  
  15.       
  16.     //clear message buf  
  17.     memset(&pPort_info,0,sizeof(portinfo));  
  18.   
  19.     //alloc sent and receive buf  
  20.     pSentMessagePackage = malloc(sizeof(msgpkg));  
  21.     pReceiveMessagePackage = malloc(sizeof(msgpkg));  
  22.   
  23.     fd=open_mcuport();  
  24.       
  25.     pSentMessagePackage->fdfd;  
  26.     pReceiveMessagePackage->fdfd;  
  27.       
  28.     if(fd == -1)  
  29.     {  
  30.         LOGE("init_mcuuart open port error!");  
  31.       return -1;  
  32.     }  
  33.       
  34.     pPort_info.baud_rate=COM1MCU_BAUD;  
  35.     pPort_info.data_bits=COM1MCU_DATABIT;  
  36.     pPort_info.flow_ctrl=COM1MCU_CTRL;  
  37.     pPort_info.stop_bit=COM1MCU_STOPBIT;  
  38.     pPort_info.parity=COM1MCU_PARITY;  
  39.     pPort_info.port_fd=fd;  
  40.   
  41.     //pthread_mutex_lock(&pPort_info.portlock);  
  42.     var = set_portLocked(&pPort_info);  
  43.     //pthread_mutex_unlock(&pPort_info.portlock);  
  44.       
  45.     if(var < 0)  
  46.     {  
  47.         LOGE("set_portLocked error!");  
  48.         return -1;  
  49.     }  
  50.   
  51.     //handshake message  
  52.     //messagePackage(&PowerOnHandShakeCmd,NULL);  
  53.       
  54.     //messagePackage(&TestCmd,"************com1mcu.c mode for test*********");  
  55.   
  56.     //uart send message thread  
  57.     sem_init(&pSentMessagePackage->uart_begin, 0, 0);  
  58.     sem_init(&pSentMessagePackage->uart_end, 0, 0);  
  59.     pSentMessagePackage->uart_inited = true;  
  60.     err = pthread_create(&pSentMessagePackage->thread_id, NULL, &uartUploadData, (void *)pSentMessagePackage);  
  61.   
  62.     if(err != 0)  
  63.         LOGE("init_mcuuart pthread_create pSentMessagePackage error %s!",strerror(err));  
  64.   
  65.     //uart receive message thread and analyze it  
  66.     //sem_init(&pReceiveMessagePackage->uart_begin, 0, 0);  
  67.     sem_init(&pReceiveMessagePackage->uart_end, 0, 0);  
  68.     pReceiveMessagePackage->uart_inited = true;  
  69.     err = pthread_create(&pReceiveMessagePackage->thread_id, NULL, &uartDownloadData, (void *)pReceiveMessagePackage);  
  70.   
  71.     if(err != 0)  
  72.         LOGE("init_mcuuart pthread_create pReceiveMessagePackage error %s!",strerror(err));  
  73.   
  74.     return 0;                 
  75. }  
  76. 2、发送数据回调函数  
  77. /***************************************************************  
  78. ** fun:   uart send handle  
  79. ** in:    arg pSentMessagePackage  
  80. **out:     
  81. ** uartUploadData  
  82. ****************************************************************/  
  83. static void * uartUploadData(void * arg)  
  84. {  
  85.     pMsgPkg upData = (pMsgPkg)arg;  
  86.   
  87.     while(1)  
  88.     {  
  89.         sem_wait(&upData->uart_begin);  
  90.         if(!upData->uart_inited)  
  91.         {  
  92.             sem_post(&upData->uart_end);  
  93.             break;  
  94.         }  
  95.         //No message to upload  
  96.         if(upData->messageCnt <= 0)  
  97.             sem_wait(&upData->uart_begin);  
  98.   
  99.         upData->SYNCCode = SYNCDATA1;      
  100.   
  101. #if 1          
  102.         if(!CRCCheck((uuint8*)upData,Send))    //CRC  
  103.         {  
  104.             LOGE("uartUploadData CRC Error!");  
  105.             sem_wait(&upData->uart_begin);  
  106.         }  
  107. #endif          
  108.   
  109.         //sent message len = SYNCCodeLen(2)+CmdCnt(1)+CmdLen(1)+messageLen(N)+CRCLen(1)  
  110.         send_mcuuart(upData->fd,upData,upData->messageLen+5);  
  111.   
  112.         sem_post(&upData->uart_end);  
  113.   
  114.         upData->messageCnt = 0;  
  115.         upData->messageLen = 0;  
  116.     }  
  117.   
  118.     return true;  
  119. }  
  120. 3、接收数据回调函数  
  121. /***************************************************************  
  122. ** fun:   uart receive handle  
  123. ** in:    arg pReceiveMessagePackage  
  124. ** out:     
  125. ** uartDownloadData  
  126. ****************************************************************/  
  127. static void * uartDownloadData(void * arg)  
  128. {  
  129.     uuint8 buffer[RECMSGONCELEN];  
  130.     pMsgPkg pmsg = (pMsgPkg)arg;  
  131.     int len,i;  
  132.   
  133.     while(1)  
  134.     {      
  135.         if(!pmsg->uart_inited)  
  136.         {  
  137.             sem_post(&pmsg->uart_end);  
  138.             break;  
  139.         }  
  140.           
  141.         recv_mcuuart(pmsg->fd,buffer,&len,RECMSGONCELEN,RECMSGTIMEOUT);  
  142.   
  143.         if(len > 0)  
  144.         {              
  145.             //copy the receive data to the big buf  
  146.             for(i=0;i<len;i++)  
  147.             {  
  148.                 if(pmsg->pRecPoint >= RECMSGBUFLEN)  
  149.                     pmsg->pRecPoint = 0;  
  150.                   
  151.                 receiveBuf[pmsg->pRecPoint] = buffer[i];  
  152.                 pmsg->pRecPoint++;  
  153.             }  
  154.               
  155.             memset(buffer,0,RECMSGONCELEN);  
  156.         }  
  157.   
  158.         LOGI("pAnalyzePoint=%d,pRecPoint=%d",pmsg->pAnalyzePoint,pmsg->pRecPoint);  
  159.   
  160.         //have new message and prev message have handout to app, analyze from the analyze Point  
  161.         if((pmsg->pAnalyzePoint != pmsg->pRecPoint)&&(!pmsg->handOutFlag))  
  162.             analyzeMsgPackage(pmsg, &(receiveBuf[pmsg->pAnalyzePoint]));  
  163.     }  
  164.   
  165.     return true;      
  166. }  



JNI中的代码很简单,通过init、upload、download这三个HAL层中的函数接口对串进行初始化、写数据和读数据。

写数据的时候,直接把java传过来的数据通过upload在HAL中加上数据头及CRC位,然后在写线程中写入串口设备节点……

读数据的时候,在HAL中通过读数据的线程从串口设备节点中将数据读出后进行解析和CRC校验,如果CRC校验正常则把解析之后的数据通过JNI层传给java中进行使用。

值得一提的是接收数据和解析数据的时候相应buffer的控制,我这里在接收数据的时候用的是一个环形buffer,容量为1KByte,这样做的目的的防止接收数据丢失。

 

JAVA中的代码主要是两部分,一部分是实现写数据的方法,这个比较简单,封闭好JNI中的本地函数uart_upload就行了。别一部分是实现读数据的方法,这个有点麻烦,因为在我的系统里读数据的时候可能有主动上报的数据,也就是ARM这边没有请求,MCU那边如果有数据时会主动上报给ARM,比如MCU那边的按键信息等。我在读的方法里用了一个线程来处理这些,不停的扫描解析数据的buffer,当有正确的数据已经解析并存在于解析buffer中时,就在这个线程里通过广播的方式将消息广播出去,然后在APP中监听这个广播就行了,相应的代码比较多,这里就不发上来了!

最后要强调一点的是,由于操作设备节点的时候,需要有system用户的权限,我是在相应的app的配置文件中增加了android:sharedUserId="android.uid.system" 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值