Louie NRT Story

[임베디드] 안드로이드 보드 Serial Port 통신 본문

전기차충전기

[임베디드] 안드로이드 보드 Serial Port 통신

hyeok0724.kim@gmail.com 2021. 10. 26. 10:23
반응형

작성일: 21년 10월 26일

PS. Smatek에서 제공하는 안드로이드 OS가 올라가는 ST-RK3288-01 보드를 이용하여 개발을 하고자 함

android-serialport-api-master.zip
0.10MB

 

Index

1. Developer's Kit

2. android-serialport-api 오픈소스

3. SDK Tool 다운로드

4. 프로젝트 생성

5. Seriap Port 통신 환경 만들기

6. 코드 개발하기

 

 

1. Developer's Kit

 1) SDK(Software Developer's Kit)
  - Java기반으로 Application Level에서 개발을 쉽게 해주는 도구임

2) NDK(Native Developer's Kit)
 - Application을 개발하는데 있어서 하드웨어에 직접 접근해야 하는 일이 발생하게 됨
 - 효과적으로 개발을 위해서는 Java가 아닌 C/C++로 개발된 코드를 이용하게 됨
 - Android Studio에서는 Java에서 호출을 하기 위한 동적 링크 라이브러리를 제공하는 NDK를 이용하여 컴파일을 하게 됨.
 - C/C++을 개발하기 위해 NDK를 사용할때는 JNI 필수로 있어야함

3) PDK(Platform Developer's Kit)
 - SDK와 NDK를 포괄하는 개념으로 Unix 계열의 OS에서 개발이 이루어지며 Android 전체 코드를 이용하여 개발함
 - Linux Kernal Level과 그 위에 위치한 Native Library의 HAL 부분 등에 대해 개발을 함


2. android-serialport-api 오픈소스

 - 아래의 코드를 다운로드함

 - 9년전의 코드인데 지금도 쓰고 있다는게 참 대단함

https://github.com/cepr/android-serialport-api

 

 

3. SDK Tool 다운로드

 - NDK와 컴파일에 필요한 CMake를 다운로드함

 - Tools -> SDK Manager 클릭

 - NDK와 CMake를 체크후 하단의 OK 버튼을 눌러 다운로드함

 

 

4. 프로젝트 생성

 - File -> New -> New Project 클릭함

 - Empty Activity를 선택함

 - 프로젝트의 이름을 입력함

 

 

5. Seriap Port 통신 환경 만들기

 1) 코드 복사하기

 - 위에서 다운로드한 "android-serialport-api\project\src" 하위의 폴더 "android_serialport_api"를 java 폴더 하위에 복사함 

 

 

2) 코드 복사하기

-  android-serialport-api\project 하위에 jni 폴더와 libs 폴더를 프로젝트의 "main" 폴더 하위에 복사함

 

3) 컴파일할 파일 선택하기

 - 프로젝트 우클릭하여 "Add C++ to Module" 클릭

- 복사한 jni 폴더 하위의 "Android.mk" 파일을 선택함

 

 

6. 코드 개발하기

 - MainActivity 코드 입력

- SerialPort에게 연결할 포트와 보드레이트 정보를 입력함

- OutputStream을 이용하여 Byte 데이터를 전송함

- InputStream으로 데이터가 들어오면 OnDataReceived() 함수를 통하여 데이터를 읽게 됨

public class MainActivity extends AppCompatActivity {

    private static final String LOG_TAG = "MainActivity";

    protected SerialPort mSerialPort;
    protected OutputStream mOutputStream;
    private InputStream mInputStream;
    private ReadThread mReadThread;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        try {
            mSerialPort = getSerialPort("/dev/ttyS1",115200);
            mOutputStream = mSerialPort.getOutputStream();
            mInputStream = mSerialPort.getInputStream();

            /* Create a receiving thread */
            mReadThread = new ReadThread();
            mReadThread.start();

            SendReadCardCommand();
        }
        catch (SecurityException e) {
            Log.e(LOG_TAG,e.getMessage());
        }
        catch (InvalidParameterException e) {
            Log.e(LOG_TAG,e.getMessage());
        }
    }

    @Override
    protected void onDestroy() {
        if(mReadThread != null){
            mReadThread.interrupt();
            closeSeiralPort();
            mSerialPort = null;
        }
        super.onDestroy();
    }

    byte bRcvBuf[] = new byte[1024];
    int nOffset = 0;

    protected void onDataReceived(final byte[] buffer, final int size) {
        try {
     	   System.arraycopy(buffer, 0, bRcvBuf, nOffset, size);
       	   nOffset += size;
       	   Log.d(LOG_TAG, "Offset: " + nOffset);
           Log.d(LOG_TAG, "ReadResponse: " + byteArrayToString(bRcvBuf, nOffset));
           
           bRcvBuf = null;
           bRcvBuf = new byte[1024];
           nOffset = 0;

        } catch (Exception ex) {
           Log.e(LOG_TAG, ex.getMessage());
        }
    }

    private String byteArrayToString(byte[] a,int nSize) {
        StringBuilder sb = new StringBuilder();
        int nBreak = 0;
        for(final byte b: a) {
            sb.append(String.format("0x%02x ", b & 0xff));
            nBreak++;
            if(nBreak >= nSize){
                break;
            }
        }
        return sb.toString();
    }

    public void SendReadCardCommand(){
        byte bSendVal[] = new byte[12];
        bSendVal[0] = (byte)0x02;
        bSendVal[1] = (byte)0x01;
        bSendVal[2] = (byte)0xB0;
        bSendVal[3] = (byte)0x01;
        bSendVal[4] = (byte)0x0E;
        bSendVal[5] = (byte)0x01;
        bSendVal[6] = (byte)0xEA;
        bSendVal[7] = (byte)0x00;
        bSendVal[8] = (byte)0x00;
        bSendVal[9] = (byte)0x48;
        bSendVal[10] = (byte)0xDD;
        bSendVal[11] = (byte)0x03;

        try{
            mOutputStream.write(bSendVal);
        } catch (IOException ex){
            Log.e(LOG_TAG, ex.getMessage());
        }
    }

    private class ReadThread extends Thread {
        @Override
        public void run() {
            super.run();
            while (!isInterrupted()) {
                int size;
                try {
                    byte[] buffer = new byte[64];
                    if (mInputStream == null) return;
                    size = mInputStream.read(buffer);
                    if (size > 0) {
                        onDataReceived(buffer, size);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    return;
                }
            }
        }
    }

    private SerialPort m_SerialRFID = null;
    private SerialPort m_SerialCARD = null;
    private SerialPort m_Serial = null;

	public SerialPort getSerialPort(String strPortNum , int nBaudrate){
        try {
            if (m_Serial == null) {
                m_Serial = new SerialPort(new File(strPortNum), nBaudrate, 0);
            }
        }
        catch (Exception ex){
            Log.e(LOG_TAG, ex.getMessage());
        }
        return m_Serial;
    }

    public void closeSeiralPort(){
        if(m_Serial != null){
            m_Serial.close();
            m_Serial = null;
        }
    }
}

- Byte 단위로 읽은 데이터를 String으로 변환하여 로그에 찍도록 함.

 

 

Referece:

https://github.com/cepr/android-serialport-api

 

GitHub - cepr/android-serialport-api: Accessing serial ports for Android

Accessing serial ports for Android. Contribute to cepr/android-serialport-api development by creating an account on GitHub.

github.com

https://blog.naver.com/PostView.nhn?blogId=yuyyulee&logNo=221691984923&parentCategoryNo=&categoryNo=20&viewDate=&isShowPopularPosts=false&from=postView 

 

[Android Tip] SerialPort(시리얼 통신) 사용하기 (JNI)

안드로이드 OS는 모바일 뿐만 아니라 다양한 기기에 적용될 수 있는데, 셋탑 박스나 디지털 광고 매체 등...

blog.naver.com

https://blog.csdn.net/cdemtronix/article/details/78364565?locationNum=9&fps=1&utm_term=android%E4%B8%BB%E6%9D%BF%E5%BA%94%E7%94%A8%E5%BC%80%E5%8F%91&utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2~all~sobaiduweb~default-0-78364565 

 

Android Studio应用开发简介_cdemtronix的博客-CSDN博客

2017年6月,英创公司在ESM6802+10.1”LCD的硬件平台上成功运行Android 7.1.1原生操作系统。2017年8月,ESM6802 Android 版可以支持GPIO、串口、以太网、U盘。后续将进一步完善对CAN、SPI、I2C、WIFI、4G等接口

blog.csdn.net

 

반응형
Comments