android串口通訊

來源:互聯網
上載者:User
轉載時請註明出處和作者文章出處:http://www.cnblogs.com/xl19862005作者:Xandy

 

最近段時間一直在做android下串口通訊的東東,大概功能是android系統端的ARM和系統外的一個MCU通訊,通過android介面控制MCU上掛的裝置,如radio、TV、BT等等,下面對這個過程作一個淺顯的闡述,有錯之處還望大家斧正……

先來看一張圖,如下:

我是直接在HAL層中通過兩個線程對串口的裝置節點/dev/ttymxc1進行讀和寫的,相應的代碼如下:

1、init代碼

/***************************************************************
** fun: init uart(/dev/ttymxc1);
** in:
** out: fd sucess, -1 false;
** init_mcuuart
***************************************************************/
static int init_mcuuart(void)
{
int fd,var;
portinfo pPort_info;
int err;

dbg(DBG_DEBUG," init_mcuuart in");

//clear message buf
memset(&pPort_info,0,sizeof(portinfo));

//alloc sent and receive buf
pSentMessagePackage = malloc(sizeof(msgpkg));
pReceiveMessagePackage = malloc(sizeof(msgpkg));

fd=open_mcuport();

pSentMessagePackage->fd= fd;
pReceiveMessagePackage->fd= fd;

if(fd == -1)
{
LOGE("init_mcuuart open port error!");
return -1;
}

pPort_info.baud_rate=COM1MCU_BAUD;
pPort_info.data_bits=COM1MCU_DATABIT;
pPort_info.flow_ctrl=COM1MCU_CTRL;
pPort_info.stop_bit=COM1MCU_STOPBIT;
pPort_info.parity=COM1MCU_PARITY;
pPort_info.port_fd=fd;

//pthread_mutex_lock(&pPort_info.portlock);
var = set_portLocked(&pPort_info);
//pthread_mutex_unlock(&pPort_info.portlock);

if(var < 0)
{
LOGE("set_portLocked error!");
return -1;
}

//handshake message
//messagePackage(&PowerOnHandShakeCmd,NULL);

//messagePackage(&TestCmd,"************com1mcu.c mode for test*********");

//uart send message thread
sem_init(&pSentMessagePackage->uart_begin, 0, 0);
sem_init(&pSentMessagePackage->uart_end, 0, 0);
pSentMessagePackage->uart_inited = true;
err = pthread_create(&pSentMessagePackage->thread_id, NULL, &uartUploadData, (void *)pSentMessagePackage);

if(err != 0)
LOGE("init_mcuuart pthread_create pSentMessagePackage error %s!",strerror(err));

//uart receive message thread and analyze it
//sem_init(&pReceiveMessagePackage->uart_begin, 0, 0);
sem_init(&pReceiveMessagePackage->uart_end, 0, 0);
pReceiveMessagePackage->uart_inited = true;
err = pthread_create(&pReceiveMessagePackage->thread_id, NULL, &uartDownloadData, (void *)pReceiveMessagePackage);

if(err != 0)
LOGE("init_mcuuart pthread_create pReceiveMessagePackage error %s!",strerror(err));

return 0;
}

2、發送資料回呼函數

/***************************************************************
** fun: uart send handle
** in: arg pSentMessagePackage
**out:
** uartUploadData
****************************************************************/
static void * uartUploadData(void * arg)
{
pMsgPkg upData = (pMsgPkg)arg;

while(1)
{
sem_wait(&upData->uart_begin);
if(!upData->uart_inited)
{
sem_post(&upData->uart_end);
break;
}
//No message to upload
if(upData->messageCnt <= 0)
sem_wait(&upData->uart_begin);

upData->SYNCCode = SYNCDATA1;

#if 1
if(!CRCCheck((uuint8*)upData,Send)) //CRC
{
LOGE("uartUploadData CRC Error!");
sem_wait(&upData->uart_begin);
}
#endif

//sent message len = SYNCCodeLen(2)+CmdCnt(1)+CmdLen(1)+messageLen(N)+CRCLen(1)
send_mcuuart(upData->fd,upData,upData->messageLen+5);

sem_post(&upData->uart_end);

upData->messageCnt = 0;
upData->messageLen = 0;
}

return true;
}

3、接收資料回呼函數

/***************************************************************
** fun: uart receive handle
** in: arg pReceiveMessagePackage
** out:
** uartDownloadData
****************************************************************/
static void * uartDownloadData(void * arg)
{
uuint8 buffer[RECMSGONCELEN];
pMsgPkg pmsg = (pMsgPkg)arg;
int len,i;

while(1)
{
if(!pmsg->uart_inited)
{
sem_post(&pmsg->uart_end);
break;
}

recv_mcuuart(pmsg->fd,buffer,&len,RECMSGONCELEN,RECMSGTIMEOUT);

if(len > 0)
{
//copy the receive data to the big buf
for(i=0;i<len;i++)
{
if(pmsg->pRecPoint >= RECMSGBUFLEN)
pmsg->pRecPoint = 0;

receiveBuf[pmsg->pRecPoint] = buffer[i];
pmsg->pRecPoint++;
}

memset(buffer,0,RECMSGONCELEN);
}

LOGI("pAnalyzePoint=%d,pRecPoint=%d",pmsg->pAnalyzePoint,pmsg->pRecPoint);

//have new message and prev message have handout to app, analyze from the analyze Point
if((pmsg->pAnalyzePoint != pmsg->pRecPoint)&&(!pmsg->handOutFlag))
analyzeMsgPackage(pmsg, &(receiveBuf[pmsg->pAnalyzePoint]));
}

return true;
}

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" 

文章出處:http://www.cnblogs.com/xl19862005作者:Xandy
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.