Search This Blog

Showing posts with label Communication. Show all posts
Showing posts with label Communication. Show all posts

Tuesday, April 12, 2016

Using 3rd party CC2530 modules

Aliexpress ကဝယ်လိုက်တဲ့ 3rd party CC2530 module သေးသေးလေးတွေ ( ပထမတခု ဒုတိယတခု ) ကို သုံးတဲ့ အကြောင်း ပြောချင်ပါတယ်။ အရင် ဆောင်းပါး မှာ TI ရဲ့ CC2530DK ကို သုံးတဲ့ အကြောင်း ပြောဖူးပါတယ်။ အခု ဆောင်းပါး ကတော့ 3rd party module တွေကို SmartRF05EB ကိုသုံးပြီး debug နဲ့ download လုပ်တဲ့ အကြောင်း ပါ။


Figure. CC2530 အသေးလေးပါ။ 13 mm x 18 mm အရွယ်ပဲ ရှိပါတယ်။

Thursday, January 21, 2016

Mesh Bee - JN5168

Mesh Bee က NXP ကထုတ်တဲ့ JN516x wireless chip ကိုသုံးပြီး seeed studio ထုတ်တဲ့ 2.4GHz wireless transceiver ပါ။ ကောင်းတာ တခုက သူက လုံးဝ open hardware, open source ပါ။ NXP ကပေးတဲ့ development environment နဲ့ tools တွေကလည်း free ရပါတယ်။

Wednesday, November 25, 2015

CC2531 Zigbee USB Dongle

CC2531 USB Evaluation Module Kit ကိုသုံးပြီး wireless communication လုပ်ကြည့်တဲ့ အကြောင်းလေးပါ။ သူ့ရဲ့ website ကိုသွားပြီး CC USB Firmware Library and Examples ဆိုတဲ့ zip ဖိုင်ကို download လုပ်လိုက်ပါတယ်။ ဖိုင်ကိုဖြည်ပြီးတဲ့ အခါ Doc folder ထဲက CC USB Software Examples User’s Guide ထဲမှာ နမူနာပြထားတဲ့ USB RF Modem Example ကို စမ်းကြည့်ခဲ့ပါတယ်။

CC2531 Zigbee Wireless USB Dongle

Tuesday, November 24, 2015

Wireless Communication using CC2530 Zigbee Wireless MCU

CC2530 က IEEE 802.15.4 နဲ့ Zigbee တွေအတွက် RF transceiver နဲ့ 8051 MCU ကို ပေါင်းစပ်ထားတဲ့ system-on-chip (SoC) solution တခုပါ။ သူ့ကို သုံးပြီး wireless module စမ်းလုပ်ဖို့ အတွက် CC2530EM Evaluation Modules နှစ်ခု၊ SmartRF05EB Evaluation Boards နှစ်ခု၊ နဲ့ CC2531 USB Dongle တခုပါတဲ့ CC2530DK devolopment kit ကို ဝယ်တာ USD 400 လောက်ပေးရပါတယ်။ သူတို့နဲ့ သုံးဖို့အတွက် TI ရဲ့ ဝက်ဘ်ဆိုက်မှာ အလကားပေးတဲ့ SmartRF Studio ကို စက်ထဲမှာ install လုပ်ပါတယ်။

CC2530DK

Friday, September 25, 2015

Adafruit CC3000 WiFi for Arduino

WiFi သုံးပြီး microcontroller နဲ့ ဆက်သွယ်တဲ့ ဟာကို Arduino Uno နဲ့ Adafruit CC3000 WiFi Shield ကိုသုံးပြီး စမ်းကြည့်ထားတာပါ။ သူက Arduino ရဲ့ standard WiFi shield မဟုတ်တဲ့ အတွက် WiFi.h library ကို သုံးလို့မရပါဘူး။ ဒါ့ကြောင့် Adafruit CC3000 library ကို ဒေါင်းလုပ်လုပ်၊ un-zip လုပ်ပြီး C:\Program Files (x86)\Arduino\libraries folder ထဲမှာ ထည့်ဖို့လိုပါတယ်။


Figure. Adafruit CC3000 WiFi shield stacked with Arduino Uno.


Tuesday, August 4, 2015

Bluetooth Module to be Used with Microcontroller

HC-05 Master/Slave Bluetooth Module လေးက စျေးသက်သာပြီး (~SGD 16) သံုးရလွယ်တဲ့ Bluetooth module တစ်ခုဖြစ်ပြီး UART interface သံုးပါတယ်။ အဲဒီ HC-05 နဲ့ Arduino Uno microcontroller ကိုသံုးပြီး LED မီးလံုးကို ဖုန်းနဲ့ Bluetooth communication သံုးပြီး အဖွင့်၊ အပိတ် ထိန်း တဲ့ နမူနာတစ်ခု ကို ဆွေးနွေးပါမယ်။ တကယ်တော့ UART interface ပါတဲ့ ဘယ် မိုက်ကရိုကွန်ထရိုလာ မဆို သံုးလို့ရပါတယ်။


Figure. HC-05 Bluetooth module with Arduino Uno.

Tuesday, July 9, 2013

CAN bus

CAN Bus (controller area network) ဆိုသည်မှာ ဆက်သွယ်ရေး စနစ် တစ်ခုဖြစ်ပြီး မိုက်ခရိုကွန်ထရိုလာများ နှင့် အခြား အီလက်ထရွန်းနစ် ကိရိယာများကို ကွန်ပျူတာ မလိုအပ်ဘဲ အချင်းချင်း ဆယ်သွယ် နိုင်ရန် ပြုလုပ်ထားသော စနစ်ဖြစ်ပါတယ်။ CAN Bus ဟာ မက်ဆေ့ (message) အပေါ်တွင် အခြေခံသော ပရိုတိုကောလ်ဖြစ်ပြီး မော်တော်ယာဉ်များတွင် အဓိက အသုံးပြုလေ့ ရှိပေမယ့် စက်ရုံများနှင့် ဆေးဘက်ဆိုင်ရာ ကိရိယာများတွင်လည်း အသုံးပြုလေ့ ရှိပါတယ်။

Tuesday, May 3, 2011

Byte Stuffing

ပစ္စည်း တစ်ခု ကနေ တစ်ခု data bytes တွေကို ပို့ဖို့ နဲ့၊ လက်ခံဖို့ အတွက် program တွေကို မကြာခဏ ရေးရပါတယ်။ ဒါနဲ့ပဲ ရိုးရှင်းတဲ့ byte stuffing မူကွဲ တစ်ခု ကို ရွေးပြီး data bytes တွေကို frame ဆောက် ပြီး ပို့ဖို့ နဲ့၊ လက်ခံဖို့ အတွက် လုပ်ရပါတယ်။ ပထမဆုံး အနေနဲ့ Frame ရဲ့ အစ နဲ့ အဆုံးကို သတ်မှတ်ဖို့ အတွက် control characters တွေ အနေနဲ့ 0x02 နဲ့ 0x03 ကို start of text (STX) ရယ်၊ end of text (ETX) ရယ် လို့ ထားလိုက် ပါမယ်။ လက်ခံရရှိတဲ့ ဒေတာ မှာ အမှား ပါမပါ စစ်ဖို့ အတွက် data bytes တွေရဲ့ exclusive-or တန်ဖိုးကို ETX နောက်မှာ အဆုံးသတ် checksum အနေနဲ့ ထည့်လိုက်ပါမယ်။ ပိုကောင်းတဲ့ error detection အတွက်တော့

CRC Calculation in VB and C

မှာဖော်ပြထားသလို CRC ကို သုံးလို့ ရပါတယ်။
ဥပမာ data byte နှစ်လုံး
0x30 0x31
ကို ပို့ဖို့ ဆိုရင်၊ ပို့ရမယ့် frame က
0x02 0x30 0x31 0x03 0x01
ဖြစ်ပါတယ်။ အစက 0x02 က STX အနေနဲ့ ထည့်ထားပြီး၊ data bytes တွေကို ပို့ပါမယ်။ ဘိတ်ရှေ့ က 0x03 က ETX အနေနဲ့ ထည့်ထားတာပါ။ data byte တွေရဲ့ exclusive-or (0x02^0x03) ဖြစ်တဲ့ 0x01 ကို checksum အနေနဲ့ နောက်ဆုံးက နေ ထည့်ထားတာပါ။ အကယ်၍ ပို့ရမယ့် ဒေတာမှာ control characters တွေ အနေနဲ့ သုံးထားတဲ့ 0x02 တို့၊ 0x03 တို့ ပါလာရင် ဘယ်လို လုပ်မလဲ လို့ မေးစရာရှိ ပါတယ်။ အဲဒီ အတွက် နောက်ထပ် control character 0x10 ကို Data Link Escape (DLE) အနေနဲ့ သတ်မှတ်ဖို့ လိုပါတယ်။ နောက်ထပ် ဥပမာ အနေနဲ့ data byte ငါးလုံး ဖြစ်တဲ့
0x30 0x02 0x65 0x10 0x03
အတွက် frame တစ်ခု ဆောက်ကြည့် ပါမယ်။ ဒေတာထဲမှာ STX တို့၊ ETX တို့၊ DLE တို့ ကိုတွေ့တိုင်း control character မဟုတ်ကြောင်း သိအောင် ရှေ့မှာ DLE တစ်လုံးကို အပို ထည့်ပေး မှာပါ။ ဒါဆို ပို့ရမယ့် frame က
0x02 0x30 0x10 0x02 0x65 0x10 0x10 0x10 0x03 0x03 0x44
ဖြစ်ပါတယ်။ C တို့၊ LabVIEW တို့ နဲ့ ပရိုဂရမ် တချို့ ရေးကြည့်ထားပါတယ်။ Example programs တွေကို အောက်က link မှာ တွေ့နိုင်ပါတယ်။

Byte Stuffing on GitHub


အောက်ကဟာက ပို့ဖို့ အတွက် frame ဆောက်တဲ့ C++ code ဖြစ်ပါတယ်။
// Byte stuffing- sending and receiving frames
// Author: Yan Naing Aye

#ifndef  FRAME_H
#define FRAME_H

#include 
#define STX 0x02
#define ETX 0x03
#define DLE 0x10

#define TX_BUF_SIZE 128
#define RX_BUF_SIZE 128
enum RX_STATE { IGNORE,RECEIVING,ESCAPE,RXCRC1,RXCRC2 };
//-----------------------------------------------------------------------------
class Frame {    
    RX_STATE rState;
protected:
    int TxN;//number of transmitting bytes
    int RxN;//number of receiving bytes
    char tb[TX_BUF_SIZE];//transmit buffer
    char rb[RX_BUF_SIZE];//receiving data
public:
    Frame();
    int setTxFrame(char* d,int n);
    unsigned int CRC16CCITT_Calculate(char* s,unsigned char len,unsigned int crc);
    int getTxN();
    int getRxN();
    int receiveRxFrame(char c);//get receiving frame from received char
    char* getTxBuf();
    char* getRxBuf();
};
//-----------------------------------------------------------------------------
Frame::Frame():TxN(0),RxN(0),rState(IGNORE){}
//-----------------------------------------------------------------------------
char* Frame::getTxBuf(){
    return tb;
}
//-----------------------------------------------------------------------------
char* Frame::getRxBuf(){
    return rb;
}
//-----------------------------------------------------------------------------
//Prepare transmitting frame
int Frame::setTxFrame(char* d,int n)
{
    unsigned int txcrc=0xFFFF;//initialize crc
    char c;
    int i=0,j=0;
    tb[i++]=STX;//start of frame
    for(j=0;j < n;j++) {
        c=d[j];
        if((c==STX)||(c==ETX)||(c==DLE)) tb[i++]=(DLE);
        tb[i++]=c;
    }
    tb[i++]=(ETX);//end of frame

    txcrc=CRC16CCITT_Calculate(d,n,txcrc);//calculate crc
    tb[i++]=txcrc & 0xFF;
    tb[i++]=(txcrc >> 8) & 0xFF;
    TxN=i;
    return TxN;
}
//-----------------------------------------------------------------------------
//Inputs
//s : pointer to input char string
//len: string len (maximum 255)
//crc: initial CRC value

//Output
//Returns calculated CRC
unsigned int Frame::CRC16CCITT_Calculate(char* s,unsigned char len,unsigned int crc)
{
    //CRC Order: 16
    //CCITT(recommendation) : F(x)= x16 + x12 + x5 + 1
    //CRC Poly: 0x1021
    //Operational initial value:  0xFFFF
    //Final xor value: 0
    unsigned char i,j;
    for(i=0;i < len;i++,s++) {
        crc^=((unsigned int)(*s) & 0xFF) << 8;
        for(j=0;j<8;j++) {
            if(crc & 0x8000) crc=(crc << 1)^0x1021;
            else crc <<=1;
        }
    }
    return (crc & 0xFFFF);//truncate last 16 bit
}
//-----------------------------------------------------------------------------
//get number of transmitting bytes
int Frame::getTxN()
{
    return TxN;
}
//-----------------------------------------------------------------------------
//get number of transmitting bytes
int Frame::getRxN()
{
    return RxN;
}
//-----------------------------------------------------------------------------
//process receiving char
int Frame::receiveRxFrame(char c)
{
    static char b;
    unsigned int crc;
    unsigned int rxcrc=0xFFFF;//initialize CRC
    switch(rState){
        case IGNORE:
            if(c==STX) { rState=RECEIVING;RxN=0;}
            break;
        case RECEIVING:
            if(c==STX) { rState=RECEIVING;RxN=0;}
            else if(c==ETX){rState=RXCRC1;}
            else if(c==DLE){ rState=ESCAPE; }
            else { rb[RxN++]=c; }
            break;
        case ESCAPE:
            rb[RxN++]=c; rState=RECEIVING;
            break;
        case RXCRC1:
            b=c; rState=RXCRC2;
            break;
        case RXCRC2:
            rState=IGNORE;
            crc=( (int)c << 8 | ((int)b & 0xFF) ) & 0xFFFF;//get received crc
            rxcrc=CRC16CCITT_Calculate(rb,RxN,rxcrc);//calculate crc
            //printf("crc: %x  rxcrc:%x \n",crc,rxcrc);
            if(rxcrc==crc){return RxN;}//if crc is correct            
            else {RxN=0;}//discard the frame

            break;
    }
    return 0;
}

//-----------------------------------------------------------------------------

//#############################################################################

class Frame2:public Frame {
    char Dt[20];//transmitting data
public:
    Frame2();
    void printTxFrame();
    void printRxFrame();
    void printRxData();
    void setTxData(float x,float y,float z,float b,float t);
};
//-----------------------------------------------------------------------------
Frame2::Frame2():Frame(),Dt(""){}
//-----------------------------------------------------------------------------
//Print out frame content
void Frame2::printTxFrame()
{
    printf("Tx frame buffer: ");
    for(int j=0;j < TxN;j++) printf("%02X ",(unsigned char)tb[j]);
    printf("\n");
}
//-----------------------------------------------------------------------------
//Print out frame content
void Frame2::printRxFrame()
{
    printf("Rx data buffer: ");
    for(int j=0;j < RxN;j++) printf("%02X ",(unsigned char)rb[j]);
    printf("\n");
}
//-----------------------------------------------------------------------------
//Set transmitting data
void Frame2::setTxData(float x,float y,float z,float b,float t)
{
    *(float*)(Dt)=x;
    *(float*)(Dt+4)=y;
    *(float*)(Dt+8)=z;
    *(float*)(Dt+12)=b;
    *(float*)(Dt+16)=t;
    Frame::setTxFrame(Dt,20);
}
//-----------------------------------------------------------------------------
//Print out received data
void Frame2::printRxData()
{
    float x,y,z,b,t;
    x=*(float*)(Dt);
    y=*(float*)(Dt+4);
    z=*(float*)(Dt+8);
    b=*(float*)(Dt+12);
    t=*(float*)(Dt+16);
    printf("Rx data: %f %f %f %f %f \n",x,y,z,b,t);
}
//-----------------------------------------------------------------------------

#endif // FRAME_H

Friday, June 11, 2010

Circular Buffered UART Com Module for 8051 Microcontroller

Embedded system အများစု မှာ UART communication ကို သုံးကြပါတယ်။ ဒါကြောင့် ကျွန်တော် ရေးထားတဲ့ circular buffered UART comm module လေးကို ဒီမှာ ဖော်ပြချင်ပါတယ်။ သူ့ကို 8051 microcontroller အတွက် ရေးထားတာ ဖြစ်ပေမယ့် တစ်ခြား microcontroller တွေ အတွက်ဆိုရင် လဲ အလွယ်တစ်ကူ ပြောင်းသုံးလို့ ရပါတယ်။

Using Circular Buffered UART Com Module

သူ့ကို သုံးချင်တဲ့ module မှာ ထုံးစံ အတိုင်း header file ကြေငြာဖို့ လိုပါတယ်။ ကျွန်တော့် နမူနာ မှာတော့ header အားလုံးကို 'headers.h' ဖိုင်ထဲမှာ စုထားတဲ့ အတွက် အဲဒီဖိုင်ကို ထည့်လိုက်ရုံ ပါပဲ။
ပို့ဖို့၊ လက်ခံဖို့ အတွက် buffer အရွယ်အစားတွေကို ComConfig.h မှာ သတ်မှတ် နိုင်ပါတယ်။ အဲဒီမှာပဲ ဒေတာ လက်ခံရရှိတဲ့ အခါ ခေါ်ချင်တဲ့ function ကို သတ်မှတ်နိုင်ပါတယ်။
main function ထဲမှာ buffer ထဲမှာ ဒေတာ တွေ ရောက်နေ မနေ စစ်ဖို့ ComChkRx() function ကို poll လုပ် နိုင်ပါတယ်။
နမူနာ source code ကို

UART-Timer-8051 on GitHub

မှာရယူ နိုင်ပါတယ်။

Wednesday, May 26, 2010

Using SPI on Low-End Microcontroller

SPI က IC အချင်းချင်း ဆက်သွယ်ဖို့ အတွက် ရိုးရှင်းပြီး ထိရောက်တဲ့ bus တစ်ခုပါ။ Real Time Clock၊ EEPROM အစရှိတဲ့ chip အများစုမှာ ဆက်သွယ်ဖို့ အတွက် SPI ဒါမှမဟုတ် I2C bus တွေ ပါလေ့ရှိပါတယ်။ ထူးခြားတဲ့ အချက် မရှိရင် တော့ SPI သုံးရတာကို I2C ထက်ပိုကြိုက်ပါတယ်။ သူက ပိုမြန်ပြီး ပိုရှင်းလို့ပါ။ သူ့ကို software နဲ့ ဖန်တီး emulate လုပ်ဖို့လဲ လွယ်ပါတယ်။
တစ်ခါက 10MHz ရှိတဲ့ SPI ပါတဲ့ LED driver chip တစ်ခုကို လုပ်ဆောင်မှု အရမ်းမမြင့်တဲ့ 4MHz microcontroller နဲ့ တွဲသုံးဖြစ်ပါတယ်။ Design လုပ်တုန်းက ဈေးသက်သာ ဖို့ အတွက် အဓိက ထားလို့ပါ။ Microcontroller ကလဲ တစ် ဒေါ်လာတောင် မပေးရပါဘူး။ ဒါပေမယ့် သူ့မှာ firmware နဲ့ font တွေသိမ်းဖို့ flash အလုံအလောက် ရှိပါတယ်။ အစကတော့ SPI ကို ဒေတာ ပို့ဖို့၊ လက်ခံဖို့ အတွက် ပုံမှန် အတိုင်းပဲ နှေးတဲ့ အဝေးပို့ RS232 တို့၊ CAN bus တို့မှာ သုံးနေကြ အတိုင်း circular buffer ကို hardware interrupt နဲ့ တွဲသုံးပါတယ်။ အဲဒါက ပုံမှန် အခြေအနေမှာ တော့ အိုကေ ပါတယ်။ ပြဿနာ က ကြီးမားတဲ့ 96x16 dot-matrix LED ဆိုင်းဘုတ် ကြီးကို တစ်စက္ကန့် ၁၂၅ ကြိမ် မောင်းချင်ပြီး CPU ကို အသုံးချ တဲ့ utilization က အရမ်းမြင့်နေတာပါ။ အကျိုးဆက် အနေနဲ့ စာသားတွေကို ဘေးတိုက် ပြေးတာ အစရှိတဲ့ ဂရပ်ဖစ် လုပ်ဆောင်မှုတွေကို ကိုင်တွယ်ရတဲ့ အခါ ကောင်းကောင်း မလုပ်နိုင်တော့ပဲ ဖုတ်လှိုက် ဖုတ်လှိုက် ဖြစ်ချင်လာ ပါတယ်။ ဒါနဲ့ပဲ အရင်းအမြစ်ကို စာရင်းစစ် ကြည့်လိုက်တော့ အဓိက အသုံးအများဆုံး ဖြစ်တဲ့၊ CPU က အမြဲတမ်းလိုလို လုပ်ဆောင်နေ ရတဲ့ SPI function က interrupt တွေ၊ circular buffer တွေနဲ့ ဖောင်းပွ နေပြီး သူ့ကို ထိရောက်အောင် ပြင်နိုင်ရင် CPU က တော်တော် သက်သာသွားမယ် ဆိုတာ တွေ့ရပါတယ်။ ပုံမှန်ကတော့ hardware interrupt ကိုသုံးတာက ပိုထိရောက်၊ ပိုမြန်တာ မှန်ပါတယ်။ ဒါပေမယ့် ဒီ ကိစ္စမှာတော့ ပုံမှန် မဟုတ်ပါဘူး နှေးတဲ့ CPU က အရမ်းမြန် အရမ်းအသုံးပြုဖို့ လိုတဲ့ SPI ကို မောင်းဖို့ လိုနေလို့ပါ။ SPI ကို ဒေတာ တစ်လုံး ပို့တိုင်း CPU cycle တွေ အရမ်းစားတဲ့ ပို့တဲ့ interrupt function၊ လက်ခံတဲ့ interrupt function တွေကို လုပ်နေရလို့ပါ။ နောက်တော့ polling ဒါမှမဟုတ် emulation ကို သုံးပြီး SPI ကို ဆက်သွယ်တာက interrupt ထက် ပိုမြန်တာကို တွေ့ရပါတယ်။ ဒါတောင် polling ကိုသုံးမယ်ဆိုရင် hardware က လက်ခံတဲ့ bus speed ကိုပဲ သုံးလို့ရမှာပါ။ ဒါနဲ့ SPI function ကို ပိုထိရောက်အောင် firmware ကို ပြင်လိုက်တော့ ကောင်းသွားပါတယ်။ ဒါကြောင့် SPI ကို emulating လုပ်ရင် ကောင်းတဲ့ အချက် တစ်ချို့ ကို ကျွန်တော် တို့ရဲ့ အတွေ့အကြုံ အရ ပြောချင်တာက
  1. SPI ကို software မှာ emulate လုပ်ရင် ပိုမြန်တဲ့ အခါတွေ လည်း ရှိပါတယ်။
  2. အရည်အသွေး လည်း ပိုကောင်းပါတယ်။ ဘာကြောင့်လဲ ဆိုတော့ ရိုးရှင်းတာရယ်၊ interrupt ကြောင့် ဖြစ်လာနိုင်တဲ့ ပြဿနာ အများစုကနေ ရှောင်ပြီးသား ဖြစ်သွားလို့ပါ။
  3. ရိုးရှင်းတဲ့ code လေးကို ရေးရတာ ပိုမြန်၊ ပိုလွယ်ကူ၊ ပိုပြီး အမှားနည်းနိုင်ပါတယ်။ မဟုတ်ရင် အသစ်သုံးမယ့် microcontroller တိုင်း အတွက် အမျိုးမျိုးသော register setting တွေနားလည်ဖို့ datasheet ကို အချိန်ပေး ဖတ်ဖို့ လိုမှာပါ။
  4. အကောင်းဆုံးကတော့ portable ဖြစ်ပြီး hardware ကို မမှီခိုတော့ တာပါပဲ။
SPI မှာ တိကျတဲ့ formal standard မရှိပါဘူး။ ပုံမှန် shift register တစ်ခုလို ရှင်းလွန်းလို့ပါ။ Timing diagram ကိုမြင်ရုံနဲ့ နားလည်နိုင်ပါတယ်။ အောက်က နမူနာက SPI မျိုးကွဲ တစ်ခုကို emulate လုပ်တဲ့ C function တစ်ခုပါ။
//-------------------------------------
unsigned char spi(unsigned char d)
{
    unsigned char i;
    SCLK=1;
    EN=1;
    for(i=0;i<8;i++)
    {
        MOSI=(d & 0x80)?1:0;        
        //Delay(period/2)-optional for slower SPI bus speed
        SCLK=0;
        d<<=1;        
        d|=MISO;
        //Delay(period/2)-optional for slower SPI bus speed
        SCLK=1;
    }
    EN=0;
    return d;
}
//-------------------------------------

Saturday, October 10, 2009

Multidrop network for RS232

တစ်ခါက project တစ်ခုမှာ master device တစ်ခုနဲ့ slave device ရှစ်ခု ဆက်သွယ်ပြီး communicate လုပ်ဖို့ လိုလာပါတယ်။ အစက RS485 half-duplex communication သုံးဖို့ ရည်ရွယ်ထား ပေမယ့် ဖြစ်ချင်တော့ ရောက်လာ ပြီးသား ပစ္စည်း အားလုံးက RS232 interface တွေပဲ ရှိကြတယ်။ RS232 communication က ပစ္စည်း တစ်ခု တစ်ခု ချင်းဆက်ဖို့ပါ။ တစ်ကယ်လို့ master device တစ်ခုက ပဲ ပို့ပြီး ကျန်တဲ့ slave တွေက နားပဲထောင် နေရင် ပြသနာ မရှိပေမယ့် slave တွေရဲ့ transmit line တွေက disable ဖြစ်အောင် ပိတ်ထားလို့ မရတဲ့ အတွက် master device ဆီကို ပြန်ပို့ဖို့ ဝါယာ လိုင်း တစ်ခုထဲကို တိုက်ရိုက် သွားဆက်လို့ မရပါဘူး။ သူ့တို့ရဲ့voltage အဝင်အထွက် တွေကို ကြည့်ပြီးတဲ့ အခါမှာတော့ အဲဒီ ပြသနာကို ဖြေရှင်းဖို့ နည်းလမ်းတစ်ခု ကို စဉ်းစားမိ ပါတယ်။ slave တစ်ခုချင်း စီရဲ့ transmit line တွေမှာ diode တစ်ခုစီ ထည့်ပေးလိုက်ရင် RS485 half-duplex communication လိုပဲ ဆက်သွယ်လို့ ရမယ့် hardware connection တစ်ခုကို ရရှိနိုင်ပြီး အဲဒါကိုအောက်က ပုံမှာ ကြည့်နိုင်ပါတယ်။
Updated: 2017 Sep 02
မှတ်ချက် ရေးကြ၊ မေးကြ တဲ့ ပေါ်မူ တည်ပြီး နောက်ထပ် ဆက်လို့ ရတဲ့ ပုံစံ တွေထပ် ဖြည့်လိုက် ပါတယ်။ စိတ်ဝင်စား ကြတဲ့ အတွက် ကျေးဇူး တင် ပါတယ်။

RS232 network with multiple masters and multiple slaves



UART/TTL-Serial network with single master and multiple slaves

RS232 transceivers တွေ မသုံးပဲ UART ကအထွက် TTL level signal တွေကိုပဲ သုံးမယ် ဆိုရင်တော့ အောက် ကအတိုင်း ဆက်နိုင် ပါတယ်။



UART/TTL-Serial network with multiple masters and multiple slaves



Sunday, May 4, 2008

RS232-RS485 Converter

တစ်ခါတလေ ကွန်ပျူတာ ရဲ့ serial port က RS232 ကနေ RS422 သို့မဟုတ် RS485 ပြောင်းသုံးဖို့ လိုတာပဲဖြစ်ဖြစ်၊ RS485 သုံးတဲ့ ပစ္စည်းတွေကို ကွန်ပျူတာနဲ့ လှမ်းပြီးဆက်သွယ်ဖို့ လိုလာရင်ဖြစ်ဖြစ် RS485 converter များကို အလွယ်တကူ ဝယ်ယူ အသုံးပြုနိုင်ပါတယ်။ အောက်မှာ နမူနာအဖြစ် IC-485SN ဆိုတဲ့ bidirectional converter တစ်ခုကိုဖော်ပြထားပါတယ်။




ပထမပုံမှာ ပြထားတဲ့အတိုင်း သူ့ရဲ့ အသုံးပြုပုံကို ခလုပ်လေးနှစ်ခု ကိုသုံးပြီး လိုသလို configure လုပ်သုံးလို့ရပါတယ်။
ပထမ ခလုပ်က device mode ကို ရွေးဖို့ပါ... RS232 ဖက် (DB25 Female connector ရှိတဲ့ဖက်) က ကွန်ပျူတာ (သို့မဟုတ် Data Terminal Equipment တစ်ခုခု) ဆိုရင် DTE မှာထားပါ။ ဒါမှမဟုတ် modem အစရှိတဲ့ device (data communication equipment) တစ်ခုခု ဆိုရင် DCE မှာ ထားဖို့လိုပါတယ်။
ဒုတိယ ခလုပ်ကတော့ transmitting and receiving mode ကို ရွေးဖို့ပါ။

1. TxON, RxON Mode


TxON, RxON ကို point to point operations တွေအတွက် သုံးလေ့ရှိပါတယ်။ အမြဲတမ်း transmit driver က enable ဖြစ်နေပြီး၊ အမြဲတမ်းလဲ receiving လုပ်နေမှာပါ။ RS232 ကနေ RS422 ပြောင်းပေးတယ်လို့ ပြောနိုင်ပါတယ်။ RS232 ဖက်မှာ RTS နဲ့ CTS၊ DTR နဲ့ DSR တို့က loopback ဆက်နေပါတယ်။
RS485 ဖက်မှာကတော့ အောက်ပါအတိုင်း ဖြစ်ပါတယ်။


Pin 1 = Tx+
Pin 2 = Tx-
Pin 3 = Rx-
Pin 4 = Rx+


2. TxRTS, RxON Mode


TxRTS, RxON ကို multidrop operations တွေအတွက်သုံးပါတယ်။ အမြဲတမ်း receiving လုပ်နေပေမယ့် RTS ကို high ပေးမှ transmit driver က enable ဖြစ်ပြီး ဒေတာ ပို့လို့ရပါတယ်။ DCE အတွက်ဆိုရင် RTS အစား CTS ကိုသုံးရမှာပါ။ ဝါယာလေးခုသုံးတဲ့ RS485 full duplex အဖြစ်သုံးနိုင်ပါတယ်။ RS232 ဖက်မှာ RTS နဲ့ CTS၊ DTR နဲ့ DSR တို့ကလည်း loopback ဆက်နေပါတယ်။
RS485 ဖက်မှာကတော့ အောက်ပါအတိုင်း ဖြစ်ပါတယ်။


Pin 1 = Tx+
Pin 2 = Tx-
Pin 3 = Rx-
Pin 4 = Rx+


3. TxDTR/RTS, RxDSR/ON Mode


TxDTR/RTS, RxDSR/ON ကို RS485 half duplex အဖြစ်သုံးနိုင်ပါတယ်။ DTE အတွက်ဆိုရင် RTS က true ဖြစ်မှ data lines တွေနဲ့ busy lines တွေရဲ့ transmit driver တွေက enable ဖြစ်မှာ ဖြစ်ပါတယ်။ DTR ကို true ပေးရင် busy ဖြစ်ကြောင်း transmit လုပ်မှာ ဖြစ်ပြီး၊ busy ဖြစ်ကြောင်း receive ရရှိမယ်ဆိုရင် DSR မှာ true ပြမှာပါ။ DCE အတွက်ဆိုရင် RTS အစား CTS ဖြစ်ပြီး၊ DTR နဲ့ DSR ပြောင်းပြန်ဖြစ်သွားမှာပါ။ RS232 ဖက်မှာ RTS နဲ့ CTS တို့က loopback ဆက်နေပါတယ်။
RS485 ဖက်မှာကတော့ အောက်ပါအတိုင်း ဖြစ်ပါတယ်။


Pin 1 = Data+
Pin 2 = Data-
Pin 3 = Busy-
Pin 4 = Busy+

DB 9 female နဲ့ DB25 male Cable ရဲ့ ဆက်သွယ်မှုကို အောက်ပါ အတိုင်း တွေ့ရှိရပါတယ်။


Female DB9 -------------- Male DB25
pin 1 ---------------------- pin 8 .......... Black
pin 2 ---------------------- pin 3 .......... Brown
pin 3 ---------------------- pin 2 .......... Red
pin 4 ---------------------- pin 20 ........ Orange
pin 5 ---------------------- pin 7 .......... Yellow
pin 6 ---------------------- pin 6 .......... Green
pin 7 ---------------------- pin 4 .......... Blue
pin 8 ---------------------- pin 5 .......... Magenta
pin 9 ---------------------- pin 22 ........ Gray

Wednesday, April 23, 2008

Using PC Serial Port

ကွန်ပျူတာရဲ့ serial port ကို Visual Basic programming သုံးပြီး ထိန်းချုပ် တဲ့အကြောင်းပြောမှာပါ။ ကွန်ပျူတာတွေမှာ serial port တစ်ခုတော့ ပါလေ့ရှိပါတယ်။ မပါခဲ့ရင်လဲ USB ကနေ RS232 converter လေးတွေ ကို အလွယ်တကူ ဝယ်လို့ရပါတယ်။

ဒီမှာ Serial port ကို သုံးတာနဲ့ ပတ်သက်ပြီး
1. Using VB6
2. Using VB2005 (VB.NET2)
3. Serial Port as IO
ဆိုပြီး သုံးပိုင်း ခွဲပြောထားပါတယ်။

Using VB6


VB6 မှာ ဆိုရင် serial port ကို အသုံးပြုဖို့အတွက် MSComm ဆိုတဲ့ ActiveX contorl ကိုသုံးမှာပါ။ စစချင်း VB6 မှာ Standard Exe ကိုရွေးပြီး New project တစ်ခုဖန်တီးပါ။ ပြီးရင် Project Menu က Components ဆိုတဲ့ command ကိုနှိပ်ပြီးရင် တက်လာတဲ့ Components dialog မှာ Microsoft Comm Control 6.0 ဆိုတာကိုရွေးပါ။

OK နှိပ်ပြီးရင် တယ်လီဖုန်း icon နဲ့ MSComm control ကို Toolbox ထဲမှာ တွေ့ရမှာ ဖြစ်ပါတယ်။ ပြီးရင် အဲဒီ control ပေါ်မှာ double click နှိပ်ပြီး Form ပေါ်ကိုထည့်ပါ။ အောက်ကပုံမှာ ပြထားတဲ့ အတိုင်း ထည့်ပြီးတဲ့အခါ ဒီ control ရဲ့ နာမည်က MSComm1 ဆိုပြီး ဖြစ်နေမှာဖြစ်ပြီး ဘေးအောက်နားက Properties box ထဲမှာ သူ့ရဲ့ setting တွေကို ကြိုက်သလိုပြင်လို့ရပါတယ်။

ဒီနမူနာ အနေနဲ့ ကတော့ ဒီအတိုင်းထားပြီး settings တွေကို Form ရဲ့ လွတ်တဲ့ တစ်နေရာရာမှာ double click နှိပ်ပြီး ပေါ်လာမယ့် Form_Load() ဆိုတဲ့ event မှာပဲ အောက်မှာ အတိုင်းသွားပြင်ပါမယ်။


Private Sub Form_Load()
MSComm1.Settings = "9600,N,8,1"
MSComm1.RThreshold = 1
MSComm1.CommPort = 1
MSComm1.PortOpen = True
Text1.Text = ""
End Sub


Settings ထဲကိုထည့်လိုက်တဲ့ "9600,N,8,1" ဆိုတာက Baud rate ကို 9600 သုံးပြီး၊ No parity, 8 data bit and 1 stop bit လို့ဆိုလိုတာပါ။ RThreshold ကတော့ receive buffer ထဲကို data byte ဘယ်နှစ်လုံးရောက်ရင် လက်ခံရရှိကြောင်း Event ကို trigger လုပ်ရမလဲဆိုတာ ကိုသတ်မှတ်ပါတယ်။ ဒီနမူနာ မှာတော့ တစ်လုံးရောက်လာရင်တောင် Receive Event ကို ခေါ်ခိုင်းထားပါတယ်။ ပြီးရင် PC ရဲ့ Comm port 1 ကို အသုံးပြုထားပါတယ်။ ကြိုက်တဲ့ Comm port ကို သုံးနိုင်ပါတယ်။ ပြီးရင် Comm port ကို ဖွင့်ပါတယ်။ နောက်တစ်ခုကတော့ လက်ခံရရှိတဲ့ ဒေတာ တွေကို ဖော်ပြဖို့ Textbox ကို clear လုပ်ထားတာပါ။ ပြီးရင် data အစမ်းပို့ကြည့်ဖို့ command button တစ်ခုနဲ့ textbox တစ်ခုကို form ပေါ်မှာထည့်ပါ။ Command button ရဲ့ Caption ကို 'Send' လို့ ပြင်ပေးလိုက်ပါမယ်။

ပြီးရင် အဲဒီ button ပေါ်မှာ double click နှိပ်ပြီး သူ့ရဲ့ click ဆိုတဲ့ event function မှာ အောက်ပါအတိုင်းရေးပါမယ်။


Private Sub Command1_Click()
MSComm1.Output = "ABCD"
End Sub


ဒါဆိုရင် button ကိုနှိပ်တိုင်း ABCD ဆိုတဲ့ data ကို serial port ကနေ ပို့ပေးမှာပါ။ ABCD အစား ကိုယ်ပို့ချင်တဲ့ data ကို MSComm1.Output ထဲကို ထည့်ပေးလို့ ရပါတယ်။ နောက် data ကို လက်ခံဖို့ အတွက်ကတော့ MSComm control ရဲ့ OnComm ဆိုတဲ့ Event ကို သုံးပါမယ်။ MSComm control ပေါ်မှာ double click နှိပ်ပြီး သူ့ရဲ့ event function ထဲမှာ အောက်ပါအတိုင်းရေးပါမယ်။ OnComm Event အမျိုးမျိုး ရှိတဲ့ အထဲက data ကို လက်ခံရရှိခဲ့ ရင် Textbox ထဲကို သွားပေါင်းထည့်ပြီး ဖော်ပြပေးမှာပါ။


Private Sub MSComm1_OnComm()
If MSComm1.CommEvent = comEvReceive Then
  Text1.Text = Text1.Text & MSComm1.Input
End If
End Sub


အဲဒါဆိုရင် program က အောက်မှာ ပြထားတဲ့အတိုင်းဖြစ်သွားပါပြီ။

ပြီးရင် program ကို run ကြည့်ပါ။ Send button ကို နှိပ်တိုင်း ပို့ပေးမှာ ဖြစ်ပြီး၊ လက်ခံရရှိတဲ့ data တွေကို textbox ထဲမှာ ဖော်ပြပေးမှာ ဖြစ်ပါတယ်။

Using VB2005


VB2005 မှာဆိုရင် တော့ Serial port ကို သုံးရတာ ပိုပြီးလွယ်ကူ သွားပါတယ်။ ဘာဖြစ်လို့လဲဆိုတော့ သူ့မှာ serial port ကိုသုံးဖို့ SerialPort ဆိုတဲ့ control ပါလာပြီးသားမို့ပါ။ စစချင်း File Menu ထဲက New Project command ကိုရွေးပြီး Windows Application အသစ်တစ်ခုကို ဖန်တီးပါ။ ပြီးရင် Toolbox ထဲက SerialPort ဆိုတဲ့ Control ကို double click နှိပ်ပြီး ထည့်ပါ။


ပြီးရင် control ကို select မှတ်ပြီး ညာဖက်အောက်နားက properties box မှာ သူ့ရဲ့ properties တွေကို ပြင်ပါမယ်။ နာမည်ကတော့ ဒီအတိုင်း SerialPort1 လို့ပဲထားပါမယ်။ ဒီနမူနာမှာ BaudRates ကို 9600, Databits=8, Parity=None, StopBits= One လို့ထားပါမယ်။ ကိုယ်သုံးမယ့် အပေါ်မူတည်ပြီး settings တွေကို ထားနိုင်ပါတယ်။ ပြီးရင် ReceivedBytesThreshold ကိုလဲ နဂို တန်ဖိုးအတိုင်း 1 လို့ထားပါမယ်။ PC ရဲ့ COM1 ကို သုံးမှာ ဖြစ်တဲ့ အတွက် PortName ကို COM1 လို့ထားပါမယ်။
ပြီးရင် Form ပေါ်မှာ double click နှိပ်ပြီး Form Load Event မှာ အောက်ပါအတိုင်းရေးပါမယ်။


CheckForIllegalCrossThreadCalls = False
SerialPort1.Open()

ဒါဆိုရင် ပရိုဂရမ် စစချင်းမှာ port ကို ဖွင့်ပြီးသားဖြစ်သွားပါမယ်။ ပုံမှန် serial port control ရဲ့ Encoding က ASCII ဖြစ်တာကြောင့် ကိုယ်သုံးချင်တဲ့ပေါ်မူတည်ပြီး Encoding ကို Form Load Event မှာ ပြင်နိုင်ပါတယ်။


SerialPort1.Encoding = System.Text.Encoding.Default


ပြီးရင် ပို့ဖို့ Button တစ်ခုနဲ့၊ လက်ခံရရှိတာတွေကို ဖော်ပြဖို့ TextBox တစ်ခုထည့်ပါမယ်။ Button ရဲ့ Text ကို Send လို့ပြင်ပါမယ်။ Button ပေါ်မှာ double click နှိပ်ပြီး သူ့ရဲ့ click event မှာ အောက်ပါအတိုင်းရေးပါမယ်။


SerialPort1.Write("ABCD")


ဒါဆိုရင် အဲဒီ Send ဆိုတဲ့ button ကို နှိပ်တိုင်း ABCD ဆိုတဲ့ ဒေတာကို ပို့ပေးမှာပါ။ အဲဒီ ABCD အစား ကိုယ် ပို့ချင်တဲ့ ဒေတာ ကို အစားထိုးနိုင်ပါတယ်။ နောက် data လက်ခံဖို့ အတွက်ကတော့ SerialPort1 ရဲ့ DataReceived event မှာ အောက်ပါအတိုင်းသွားရေးပါမယ်။


TextBox1.Text &= SerialPort1.ReadExisting()


လက်ခံရရှိတဲ့ ဒေတာတွေကို တစ်လုံးချင်း ဖတ်ချင်တယ် ဆိုရင်လဲ အဲဒီအစား အောက်က ပုံစံလဲ ရေးလို့ရပါတယ်။


Dim n As Int32
Dim i As Int32
Dim cmd As String
Dim c As String
n = SerialPort1.BytesToRead
For i = 1 To n
  c = Chr(SerialPort1.ReadChar())
  cmd &= c
Next
TextBox1.Text &= cmd


အဲလိုရေးပြီးတဲ့အခါ ပရိုဂရမ်က အောက်ပါအတိုင်းဖြစ်သွားပါမယ်။

ပြီးရင် ပရိုဂရမ်ကို run ပြီး ဒေတာ ပို့တာ၊ လက်ခံတာ စမ်းသပ်လို့ရပါပြီ။
Sending Binary Data
အထက်မှာ ပြောခဲ့တာက character တွေပို့ဖို့အတွက်ပါ။ ဥပမာ ASCII code number 127 ထက်ကြီးတဲ့ binary code (128-255) တွေ အတွက်ကတော့ အောက်မှာပြထားတဲ့ အတိုင်းပို့နိုင်ပါတယ်။


Dim a(3) As Byte
a(0) = &H41
a(1) = &H31
a(2) = &HFF
a(3) = &H80
SerialPort1.Write(a, 0, 4)


သူတို့ကိုလက်ခံဖို့အတွက်ကလဲ ReadChar နဲ့ဖတ်လို့မရပါဘူး။ အဲဒီအစား ReadByte ကိုသုံးနိုင်ပါတယ်။ နမူနာ အနေနဲ့ အောက်မှာကြည့်နိုင်ပါတယ်။


Dim n As Int32
Dim i As Int32
Dim cmd As String = ""
Dim c As String
n = SerialPort1.BytesToRead
For i = 1 To n
c = Chr(SerialPort1.ReadByte())
cmd &= c
Next
TextBox1.Text &= cmd


Getting Port List in Your PC
သင့် PC မှာရှိတဲ့ port တွေကို Combo box တစ်ခုထဲမှာပြချင်ရင်၊ ပြီးတော့ သင့် setting ထဲမှာသိမ်းထားတဲ့ နံပါတ်ကို ပြနေစေချင်ရင် အောက်ပါအတိုင်းရေးပါမယ်။


Dim ports As String() = SerialPort.GetPortNames()
Dim port As String
Array.Sort(ports)
cmbSerial.Items.Clear()
For Each port In ports
cmbSerial.Items.Add(port)
Next port
Dim index As Integer
index = cmbSerial.FindString(My.Settings.MCOM)
cmbSerial.SelectedIndex = index



Using Serial Port as IO


အမှန်တော့ serial port မှာ data ပို့တဲ့၊ လက်ခံတဲ့ Tx, Rx အပြင် တခြား control output နှစ်လိုင်းနဲ့ status input လေးလိုင်းကို သုံးလို့ရပါသေးတယ်။ RTS, DTR တွေက output အဖြစ်သုံးနိုင်ပြီး၊ CTS, DSR, CD, RI တို့ကို input အဖြစ်သုံးနိုင်ပါတယ်။ IO အများကြီး မလိုတဲ့ application တွေမှာ serial port ကို IO interface အဖြစ်သုံးရင် အရမ်းလွယ်ကူ အဆင်ပြေပါတယ်။

Related post:

Saturday, April 19, 2008

Asynchronous Serial Communication- RS232, RS422 and RS485

ဒီ serial communication မှာဆိုရင် data byte ကို bit တစ်ခုချင်းစီ အစီအစဉ်လိုက် တစ်ခုပြီးတစ်ခု ပို့တဲ့ အတွက် ဝါယာအများကြီးသုံးစရာမလိုတော့ပဲ ဝါယာတစ်ခုနဲ့တင် ပို့လို့ရတဲ့ အားသာချက်ရှိပါတယ်။ ပို့တဲ့အခါ byte ကနေ bit တစ်ခုချင်း serial ပြောင်းပြီးထွက်လာဖို့၊ လက်ခံတဲ့အခါ တစ်ခုပြီးတစ်ခု ဝင်လာတဲ့ serial bit တွေကို byte အဖြစ်ပြန်တည်ဆောက်ဖို့ အတွက် UART ကိုသုံးကြပါတယ်။

UART


UART တစ်ခုဟာ serial bit stream ပြောင်းပေးနိုင်ရုံတင် မကပဲ start bit, parity bit, stop bit များထည့်ပေးခြင်း အစရှိတဲ့ လုပ်ငန်းများကိုလည်း Asynchronous Serial Communication Protocol နဲ့ကိုက်ညီအောင် ဆောင်ရွက်လုပ်ဆောင် ပေးပါတယ်။

Start Bit



ဒီလိုပါ UART တစ်ခုဟာ ပို့စရာ data မရှိပဲ idle ဖြစ်နေရင် output ကို 1 မှာထားပါတယ်။ ဒီအခါ လက်ခံမယ့် UART ဟာ idle ဖြစ်လို့ ထုတ်ထားတဲ့ 1 လား၊ ပို့ပေးနေတဲ့ ဒေတာ က 1 လား ခွဲခြားသိဖို့လိုလာပါတယ်။ အဲဒါကို ဖြေရှင်းဖို့အတွက် start bit ကိုသုံးပါတယ်။ 0 bit တစ်ခုကို start bit အနေနဲ့ သုံးပါတယ်။ လက်ခံနေတဲ့ UART တစ်ခုဟာ 0 ရောက်မလာမချင်း ရှိနေတဲ့ 1 ကို idle လို့ယူဆပါတယ်။ ပထမဆုံး 0 ရောက်လာတာနဲ့ အဲဒါကို start bit လို့ယူဆပြီး နောက်ဝင်လာမယ့် bit တစ်ခုက စပြီး data အနေနဲ့ လက်ခံပါတယ်။

Baud Rate



data bit တစ်ခုနဲ့ တစ်ခုကြားက အချိန်အကွာအဝေး ကို Baud rate ကသတ်မှတ်ပါတယ်။ ဥပမာ baud rate က 1 kHz ဆိုရင်၊ bit တစ်ခု အတွက် time period က 1/(1kHz) = 1 ms ကြာမှာ ဖြစ်ပါတယ်။ အသုံးများတဲ့ baud rate ကတော့ 9600 ဖြစ်ပါတယ်။

Data Bits


Data ပို့တဲ့အခါ ပို့တဲ့ UART နဲ့ လက်ခံတဲ့ UART data bit အရေအတွက်ခြင်းတူဖို့လိုပါတယ်။ ပို့တဲ့ အခါ 5 bit data ကနေ 8 bit data ထိ ပို့တတ် ပါတယ်။ ဥပမာ ASCII data ဆိုရင် ပို့တာ 7 bit ပဲရှိတဲ့အတွက် လက်ခံရင်လဲ 7 bit လက်ခံဖို့လိုပါတယ်။ Data bits တွေကိုပို့တဲ့ အခါ LSB ကနေ အရင်စပို့ပါတယ်။ အသုံးများတာကတော့ 8 bit ပါ။

Parity Bit


လက်ခံလိုက်တဲ့ data က မှန်ကန်ကိုက်ညီမှု ရှိရဲ့လား ပြန်စစ်ဖို့အတွက် parity bit ကိုလဲ data bits တွေရဲ့ နောက်မှာ အပိုထည့်ပေး တတ်ပါတယ်။ 1 အရေအတွက် စုံဂဏန်းဖြစ်အောင် ထည့်ပေးရင် Even parity၊ မ ဂဏန်းဖြစ်အောင် ပေါင်းထည့်ပေးရင် Odd parity ပါ။ ပို့တဲ့ UART နဲ့ လက်ခံတဲ့ UART parity ချင်းလည်း ကိုက်ညီဖို့လိုပါတယ်။ များသောအားဖြင့် Parity သုံးလေ့ မရှိပါဘူး။

Stop Bit


8 bits ရှိတဲ့ data byte တစ်ခုနဲ့ တစ်ခုကြားမှာ ခြားပေးဖို့အတွက် stop bits တွေကိုသုံးပါတယ်။ 1 ကို stop bit အနေနဲ့ သုံးပါတယ်။ Stop bit ကို တစ်ခု၊ သို့မဟုတ် နှစ်ခု သုံးလို့ရပါတယ်။ data တွေ၊ parity bit တွေ ပို့ပြီးတဲ့ အခါ နောက်မှာ 1 တစ်ခုပေါင်း ပေး၊ ဒါမှမဟုတ် နှစ်ခု ပေါင်းထည့် ပေးတာပါ။ အသုံးများတာတော့ stop bit တစ်ခုထဲ ပါပဲ။
အောက်မှာ နမူနာ အနေနဲ့ data byte 0x41 ကို UART တစ်ခုကနေ 9600, 8N1 နဲ့ ပို့တာကို ပြထားပါတယ်။ ဆိုလိုတာက
Baud rate = 9600
Data bit = 8 bits
Parity = No parity (N= No parity, E= Even parity, O= Odd parity)
Stop bit= 1 stop bit
လို့ ဆိုလိုတာပါ။ No parity ဖြစ်တဲ့အတွက် data ကို ပို့ပြီးတဲ့ အခါ parity bit ကို မထည့်ပဲ stop bit တန်းလာပါတယ်။

Forms of UART


UART တစ်ခုဟာ ပုံစံ အမျိုးမျိုးဖြစ်နိုင်ပါတယ်။ ပထမ ပုံစံကတော့ သီးသန့် IC တစ်ခုအနေနဲ့ ပါ။ အသုံးများတဲ့ IC ကတော့ 16550 ပါ။ CMOS ဆိုရင်တော့ 16C550 ပေါ့ဗျာ။ သူ့မှာ buffer တွေ၊ interrupt တွေ၊ အစရှိသဖြင့် ပါပြီးသားမို့ သုံးရတာ လွယ်ကူ အဆင်ပြေပါတယ်။ သူ့ရဲ့ serial data က sout ကနေ ထွက်လာတာပါ။ Basic configuration ကို အောက်မှာ ပြထားပါတယ်။

နောက်တစ်မျိုးကတော့ microcontroller ထဲမှာ တစ်ခါတည်း built in ပါပြီးသားမျိုးပါ။ နောက်ဆုံးအနေနဲ့ ကတော့ ရိုးရိုး IO pin ကိုပဲ software နဲ့ရေးပြီး emulate လုပ်လို့ရ တဲ့ software UART မျိုးလဲ လုပ်လို့ရပါတယ်။

RS232


UART တစ်ခုက ပုံမှန်အားဖြင့် 1 ဆိုရင် 5V ထုတ်ပေးပြီး၊ 0 ဆိုရင် 0V ထုတ်ပေးပါတယ်။ UART တစ်ခုက ထွက်လာတဲ့ voltage signal ကို များသောအားဖြင့် external device တွေနဲ့ ဆက်ဖို့ သင့်တော်တဲ့ signaling levels တွေအဖြစ်ပြောင်းဖို့ transceiver တစ်ခုခုခံပြီး ထုတ်ပေး လေ့ရှိပါတယ်။ အသုံးများတဲ့ standard တစ်ခုကတော့ RS232 ပါ။ RS232 transceiver တစ်ခုရဲ့ အလုပ်က 1 ဆိုရင် -10V ပြောင်းပေးပြီး၊ 0 ဆိုရင် +10V အဖြစ် အပြန်အလှန် ပြောင်းပေးတာပါ။ တကယ်တော့ အပေါင်း၊အနုတ် 3V ကနေ 25V အထိက valid ဖြစ်ပါတယ်။ အသုံးများတဲ့ IC ကတော့ MAX232 ဖြစ်ပါတယ်။ သူ့ရဲ့ configuration ကို အောက်က ပုံမှာ ပြထားပါတယ်။

Capacitor အသေး (0.1uF) နဲ့ IC အရွယ်အစား အသေးအတွက်တော့ MAX202 ကို အသုံးများပါတယ်။ အခုနက 16C550 နဲ့ စပ်ဆက်ပြီး ပြောရမယ်ဆိုရင်တော့ အဲဒီ UART ရဲ့ sout ကထွက်လာတဲ့ 0V,5V ကို သူ့ရဲ့ pin number 11 နဲ့ဆက်ရင် pin number 14 ကနေပြီး +10V,-10V ဆိုပြီး transmit (Tx) လိုင်းအနေနဲ့ထွက်လာမှာပါ။ အဲဒီလိုပဲ receive (Rx) လိုင်းကနေ ဝင်လာတဲ့ +10V, -10V တွေဟာလဲ MAX232 ရဲ့ pin number 13 နဲ့ဆက်ပေးမယ်ဆိုရင် သူ့ရဲ့ pin number 12 ကနေ 0V,5V အနေနဲ့ ပြန်ထွက်လာပြီး UART ရဲ့ sin နဲ့ ဆက်လို့ရသွားပါတယ်။
အောက်မှာ RS232 ရဲ့ ဆက်သွယ်ပုံကိုပြထားပါတယ်။ ပုံမှန်အားဖြင့် transmit and receive data lines တွေကိုပဲ သုံးလေ့ရှိတဲ့ အတွက် Tx တစ်လိုင်း၊ Rx တစ်လိုင်း နဲ့ Ground ဝါယာ တစ်လိုင်း စုစုပေါင်း သုံးလိုင်း သုံးဖို့လိုပါတယ်။ ပုံပေါ်မှာ ကလစ်နှိပ်ပြီး ပုံကြီးကြည့်နိုင်ပါတယ်။

RS232 ရဲ့ Tx နဲ့ Rx ကို တစ်ခါတလေ ခွဲခြားဖို့ လိုလာပြီဆို ကြိုးတွေကို open လုပ်ပြီး မီတာ ကိုသုံးပြီး အလွယ်အကူတိုင်းကြည့်နိုင်ပါတယ်။ Tx နဲ့ Ground ကြားမှာ ပုံမှန်အားဖြင့် -10V လောက်တွေ့ရမှာဖြစ်ပြီး၊ Rx နဲ့ Ground ကြားမှာ ဗို့မရှိပါဘူး။ RS232 ကို unbalanced lines လို့ဆိုပါတယ်။ Tx ဝါယာနဲ့ Ground ဝါယာ ကြားက ဗို့ဟာ transmit voltage ဖြစ်ပြီး၊ Rx ဝါယာနဲ့ Ground ဝါယာကြားက ဗို့ဟာ receive voltage ဖြစ်ပါတယ်။

RS232 communication မှာ ပုံမှန်အားဖြင့် data transmit line (Tx) နဲ့ data receive line (Rx) ကိုပဲ သုံး ပေမယ့် တစ်ခုနဲ့ တစ်ခု handshaking လုပ်ဖို့ အတွက် control and status lines တွေကိုလဲ သုံးတတ်ကြပါတယ်။ Primary Communication lines တွေထဲမှာဆို Tx နဲ့ RTS က အထွက်ဖြစ်ပြီး၊ Rx နဲ့ CTS က အဝင်ဖြစ်ပါတယ်။ Status and Control lines တွေမှာဆိုရင်တော့ DTR က အထွက်လိုင်းဖြစ်ပြီး၊ DSR နဲ့ CD က အဝင်လိုင်း ဖြစ်ပါတယ်။ သူတို့ အကြောင်းအောက်မှာ ဆက်ပြောပါမယ်။ RS232 device တွေ အကြောင်းပြောတဲ့ အခါမှာ ကွန်ပျူတာကို DTE ( Data Terminal Equipment) လို့ခေါ်ပြီး၊ ကွန်ပြူတာနဲ့ ဆက်သုံးတဲ့ Modem သို့ device ကို DCE (Data Circuit-Terminating Equipment) လို့ခေါ်ပါတယ်။
RTS- Request To Send signal ကတော့ DTE ကနေ DCE ကို ပို့ချင်တဲ့ အကြောင်း လှမ်း request လုပ်တာပါ။ ပုံမှန် အားဖြင့် logic 1 အနုတ်ဗို့ မှာ ပဲရှိပြီး request လုပ်တာနဲ့ logic 0 အပေါင်း ဗို့ ထုတ်ပေးပါတယ်။
CTS- Clear To Send signal ကတော့ DCE က ပို့ဖို့ ready ဖြစ်တဲ့ အတွက် စပို့တော့ ဆိုတဲ့အကြောင်း DTE ကို အကြောင်းပြန်တာပါ။ ပုံမှန် အားဖြင့် logic 1 အနုတ်ဗို့ မှာ ပဲရှိပြီး DCE ကနေအကြောင်းပြန်ဖို့ logic 0 အပေါင်း ဗို့ ထုတ်ပေးပါတယ်။
DSR- DCE Ready (Data Set Ready) ကတော့ DCE (device) က turn on ဖြစ်ပြီး ready ဖြစ်နေပြီဆိုတဲ့ အကြောင်း DTE ကွန်ပျူတာကို လှမ်းပြောတာပါ။ Ready ဖြစ်ပြီဆို DCE ကနေ logic 0 အပေါင်း ဗို့ ထုတ်ပေးပါတယ်။
DTR- DTE Ready ကတော့ DTE ကွန်ပျူတာကနေ communication ကိုလုပ်ချင်လို့ အသင့်ပြင်တော့ လို့ DCE (device) ကို လှမ်းပြောတာပါ။ ပုံမှန် အားဖြင့် logic 1 အနုတ်ဗို့ မှာ ပဲရှိပြီး DTE ကနေ DTR လိုင်းကို true လုပ်တဲ့အခါ logic 0 အပေါင်း ဗို့ ထုတ်ပေးပါတယ်။
CD- Carrier Detect (Received Line Signal Detector) ကတော့ DCE က modem ဖြစ်တဲ့အခါမှာ သုံးပါတယ်။ တယ်လီဖုန်းလိုင်းကို တခြားဖက် အဝေးမှာရှိတဲ့ modem က ဖြေလိုက်တဲ့ answer tone ကို ရတဲ့အခါမှာ ဒီဖက် modem က ကွန်ပျူတာ ကို logic 0 အပေါင်း ဗို့ ထုတ်ပေးပါတယ်။
RI- Ring Indicator ကတော့ ring signal ကို ရတဲ့အခါ modem က ကွန်ပျူတာ ကို logic 0 အပေါင်း ဗို့ ထုတ်ပေးပါတယ်။ Ring signal ရတဲ့ အချိန်ပဲ အပေါင်းထုတ်ပေးပြီး ring signal အချင်းချင်းကြားနဲ့ ring signal မရှိတဲ့ အချိန်တွေမှာ အနုတ်ဖြစ်နေပါတယ်။
RS232 ရဲ့ ဝါယာ connectors တွေ အကြောင်းဆက်ပြောပါမယ်။

ပုံမှာ ပြထားတဲ့ အတိုင်း ကွန်ပျူတာ (DTE) မှာ RS232 အတွက် Male DB9 ပါပြီး သူနဲ့ ဆက်သုံးရမယ့် (DCE) device မှာ Female DB9 connector ပါလေ့ရှိပါတယ်။ (ကွန်ပျူတာဘက်က) DTE ဘက် male connector ရဲ့ pin connection တွေကို အောက်ကပုံမှာ ဖော်ပြထားပါတယ်။

pin 1 = CD- Carrier Detect (input)
pin 2 = Rx- Receive Data (input)
pin 3 = Tx- Transmit Data (output)
pin 4 = DTR- Data Terminal Ready (output)
pin 5 = GND- System Ground
pin 6 = DSR- Data Set Ready (input)
pin 7 = RTS- Request To Send (output)
pin 8 = CTS- Clear To Send (input)
pin 9 = RI - Ring Indicator (input)

(Device ဘက်က) DCE ဘက် female connector ရဲ့ pin connection တွေကိုလဲ အောက်က ပုံမှာ ကြည့်နိုင်ပါတယ်။

pin 1 = CD- Carrier Detect (output)
pin 2 = Tx- Transmit Data (output)
pin 3 = Rx- Receive Data (input)
pin 4 = DTR- Data Terminal Ready (input)
pin 5 = GND- System Ground
pin 6 = DSR- Data Set Ready (output)
pin 7 = CTS- Clear To Send (input)
pin 8 = RTS- Request To Send (output)
pin 9 = RI - Ring Indicator (output

RS422 and RS485


RS422 နဲ့ RS485 နှစ်ခုက ဝါယာနှစ်ခု ကြားက difference voltage ကိုပဲ ကြည့်ပြီး ခြားနားချက် 0.4V လောက်ရှိရင်ကို လုပ်ဆောင်နိုင်ပါတယ်။ ထုတ်ပေးတဲ့ ဗို့ကတော့ +12V နဲ့ -12V ကြားရှိရမယ်လို့ပြောပါတယ်။ +Tx နဲ့ -Tx ကြားကအထွက်ဗို့ဖြစ်ပြီး၊ +Rx နဲ့ -Rx ကြားကဗို့က အဝင်ဗို့ဖြစ်ပါတယ်။ သူက Ground နဲ့ transmit လိုင်းကြားက ဗို့ကို မကြည့်ပဲ၊ +Tx, -Tx လိုင်းနှစ်လိုင်းကြားက ဗို့ကိုကြည့်တဲ့အတွက် balance လိုင်းလို့ခေါ်ပါတယ်။ Common mode noise တွေကို ပိုခံနိုင်ရည်ရှိ်ပါတယ်။ RS232 နဲ့ ယှဉ်ရင် ဒေတာတွေကို မြန်မြန်နဲ့၊ ဝေးဝေး ပို ပို့ ပေးနိုင်ပါတယ်။

Note:
-200mV to +200mV = 0.4 V
-6V to +6V = 12V
RS485 နဲ့ ကွာခြားတဲ့ အချက်ကတော့ RS232 တို့၊ RS422 တို့က ဝါယာ bus တစ်ခုမှာ လက်ခံတဲ့ receiver အများကြီးရှိလို့ ရပေမယ့် transmit လုပ်ပေးတဲ့ driver circuit တစ်ခုပဲ ရှိလို့ရပါတယ်။ RS485 မှာတော့ transmit လုပ်မယ့် driver circuit ကို enable, disable လုပ်လို့ရတဲ့ data enable ပါတဲ့အတွက် ဝါယာ bus တစ်ခုမှာ လက်ခံတဲ့ receiver အများကြီးရှိလို့ ရသလို၊ ပို့တဲ့ transmitter တွေလဲ အများကြီး ထားလို့ရပါတယ်။ ပုံမှန်အားဖြင့် RS422 က transmit အတွက် ဝါယာနှစ်ခု (+Tx, -Tx)၊ receive အတွက် ဝါယာနှစ်ခု (+Rx, -Rx) စုစုပေါင်း ဝါယာလေးခုသုံးပြီး၊ RS485 မှာတော့ transmit အတွက်ရော၊ receive အတွက်ရော ဝါယာနှစ်ခုထဲကိုပဲ တလှည့်စီ share ပြီး half duplex သုံးလေ့ရှိပါတယ်။ RS485 ကို ဝါယာလေးခုနဲ့ Full duplex သုံးချင်ရင်လဲရပါတယ်။ အောက်က ပုံမှာ MAX481 transceiver IC ကို သုံးပြီး RS485 ဆက်သွယ်ပုံကို ပြထားပါတယ်။ ဝါယာ နှစ်လိုင်းထဲ ကိုပဲ သုံးထားတဲ့ အတွက် တစ်ခုက ပို့နေရင် တခြားတစ်ခုက ပို့လို့မရတဲ့အတွက် half duplex ပဲရပါတယ်။

RS485 မှာ transmit အတွက် ဝါယာ ၂ လိုင်း၊ receive အတွက် ဝါယာ ၂ လိုင်း စုစုပေါင်း ဝါယာ လေးလိုင်း သုံးမယ်ဆိုရင် Transmit, Receive ပြိုင်တူလုပ်လို့ရတဲ့ အတွက် Full duplex ဖြစ်ပါတယ်။ အောက်မှာ RS422 အတွက်ရော၊ RS485 အတွက်ရော သုံးလို့ရတဲ့ အသုံးများတဲ့ transceiver IC MAX491 ရဲ့ ဆက်သွယ်ပုံကို ပြထားပါတယ်။ MAX491 ကို half duplex သုံးချင်ရင် +Tx နဲ့ +Rx လိုင်းကိုပူး၊ -Tx နဲ့ -RX လိုင်းကိုပူးလိုက်ရင် ရပါတယ်။

ပြောရမယ်ဆိုရင် RS485 ကို Full duplex ဝါယာလေးခုသုံးပြီး transmit driver circuit ကို အမြဲ enable အသေလုပ်ထားလိုက်ရင် RS422 ဖြစ်သွားတာပါပဲ။ RS422 ကို RS232 ရဲ့ အကွာအဝေး ကို ပိုများအောင် extend လုပ်ဖို့ အတွက်သုံးလေ့ ရှိကြတာပါ။ ပို့ရမယ့် အကွာအဝေးက အရမ်းဝေးတဲ့ အခါ RS232 နဲ့ အဆင်မပြေတဲ့အခါမျိုးမှာ RS422 converter ကိုသုံးပို့ပြီး လက်ခံတဲ့ဘက်မှာလဲ converter နဲ့ RS232 ပြန်ပြောင်းသုံးကြပါတယ်။
RS232 ရဲ့ အထွက်ကို RS422/RS485 ရဲ့ အဝင်နဲ့ ဝါယာနှစ်ကြိုးထဲသုံးပြီး တန်းဆက်ပြီးသုံးကြည့်ဘူးတာ အဆင်ပြေပါတယ်။ RS232 ရဲ့ Tx ကို RS422 ရဲ့ -Rx နဲ့ဆက်ပြီး၊ RS232 ရဲ့ Ground ကို RS422 ရဲ့ +Rx လိုင်းနဲ့ဆက်တာပါ။
အောက်မှာ RS422, RS485 half duplex နဲ့ RS485 full duplex တို့ရဲ့ ဆက်သွယ်ပုံတွေကို ယှဉ်ပြထားပါတယ်။
ပထမ တစ်ခုက RS422 ပါ။ တစ်ခု တစ်ခု ချင်းပဲ ဆက်သွယ်လေ့ရှိပါတယ်။ Bus တစ်လိုင်းမှာ receiver အများကြီးရှိနိုင်ပေမယ့် transmitter တစ်ခုထဲပဲရှိနိုင်ပါတယ်။ Transmit driver ကိုထိန်းလို့မရပါဘူး။

RS485 half duplex ပါ။ Driver Enable, Receiver Enable ပါတာကို သတိပြုပါ။ Bus တစ်ခုမှာ Node တွေအများကြီး (ပုံမှန်အားဖြင့် ၃၂ ခုလောက်ထိ) ဆက်လို့ရပါတယ်။

RS485 full duplex ပါ။