Membuat PIN Tx UART 8N1 dari PORT Biasa Mikrokontroler AVR (CodeVision AVR)

Berikut header file yang digunakan untuk mengirim data. Pada header file di bawah, PORT yang digunakan adalah PORTD, tapi bisa diganti dengan PORT yang lainnya. K_error delay adalah variabel yang diatur untuk mendapatkan lebar perioda yang tepat untuk start bit. Sedangkan K_error_delay_data adalah variabel yang diatur untuk mendapatkan lebar perioda yang tepat untuk bit data. Kedua variabel tersebut diatur dengan cara membandingkan lebar signal yang dilihat pada osiloskop. Cara yang cukup sederhana bisa menggunakan software simulasi.

//============================================
//AUTHOR : wangready.wordpress.com
//FORMAT UART:  8 bit data
//              None Parity
//              1 Stop bit
//Setting PORET ditentukan pada header file UART_8N1_TX.h.
//sedangkan nomor PORT yang digunakan bisa diakses dari
//peosedur init_my_putchar(unsigned int baud_rate, unsigned int BIT).
//K_error_delay dan K_error_delay_data diatur agar mendapatkan
//baudrate yang sesuai.     
//============================================

#ifndef UART_8N1_TX
#define UART_8N1_TX

#include <delay.h>

#define _PORT_TX PORTD  //SET PORT TX
#define _DDR_TX DDRD    //SET DDR TX

void my_delay_us(unsigned int n)
{
    while(n--)
    {
        delay_us(1);
    };   
}

unsigned int    K_delay,
                K_error_delay = 100,                
                K_error_delay_data = -6,
                K_delay_data,
                BIT_global;
void init_my_putchar(unsigned int baud_rate, unsigned int BIT)
{
    BIT_global = BIT;
    _PORT_TX |= (0x01<<BIT);
    _DDR_TX |= (0x01<<BIT);  

    K_delay = (1000000/baud_rate) - K_error_delay;
    K_delay_data = K_delay - K_error_delay_data;
}

void my_putchar(unsigned char data)
{
unsigned char ii;
    _PORT_TX &= ~(0x01<<BIT_global);  //START BIT  
    my_delay_us(K_delay);

    for(ii = 0;ii < 8;ii++)
    {             
        if((data & 0x01) == 0x01)
        {
            _PORT_TX |= (0x01<<BIT_global);
        }else
        {
            _PORT_TX &= ~(0x01<<BIT_global);
        }
        data = (data>>1);   
        my_delay_us(K_delay_data);
    }

    _PORT_TX |= (0x01<<BIT_global);    //SET HIGH
    my_delay_us(K_delay);
}

#endif

Berikut contoh program utama untuk mikrokontroler ATmega8 dengan xtal 16MHz yang akan mengirim data karakter dari huruf ‘R’ dengan PIN TX menggunakan PORTD.7 setiap 500 ms.

#include <mega8.h>
#include "UART_8N1_TX.h"

void main(void)
{
init_my_putchar(4800, 7);
while (1)
      {
      my_putchar('R');
      delay_ms(500);
      };
}

Berikut project file dari program diatas yang bisa di download.

http://www.mediafire.com/file/hams5878vnscoka/UART%20PORT%20Tx.rar

Untuk simulasi bisa digunakan software Proteus dan untuk menghubungkan Proteus ke hyperterminal bisa digunakan Virtual Serial Port Emulator.

18 Responses to Membuat PIN Tx UART 8N1 dari PORT Biasa Mikrokontroler AVR (CodeVision AVR)

  1. Pingback: Mengirim Ulang Data UART 8N1 dengan Baud Rate Berbeda (CodeVision AVR) « WanGReadY

  2. jojo says:

    pak,,
    kalau aktifkan transmiternya kita input angkat dengan keyboard bagaimana ya?
    lewat hyperterminal pak. . ?terimakasih

  3. indra says:

    enggak bikin get charnya juga pak?
    saya kebingungan untuk berkomukikasi dengan 24 mikro atmega8535, bisa kasi saran dan contoh pake spi master slave pak? termimakasih
    kurniawan.indral@gmail.com

    • wangready says:

      klo yg get charnya gk buat.
      komunikasi dng 24 mikro menurut sya mending pake 1 serial biasa aja, dibuat bus. jd data yg dikirim ada 2:
      1.alamat device yg dituju
      2.data
      klo lebih bagus lagi pake parity data atau check sum untuk memastikan data yg dikirim rusak atau tidak. mungkin bisa dicoba link berikut.http://robosavvy.com/RoboSavvyPages/Support/Bioloid/AX-12(english).pdf
      Pola transfer datanya, master yg menentukan alur transfer data. master secara bebas mengirim data. sedang slave menunggu giliran – diatur oleh master. jd seperti metode scaning. sedang transfer data seperti metode broadcast.
      klo SPI, sya belum nyoba….

  4. Ridla says:

    Mas klo buat RXnya selain di port uart mau di port biasa gmna ya? yg TX ini udah saya coba. tapi bingung buat RXnya.mohon bantuannya mas.termiakasih..

    • wangready says:

      coba kodingan ini mas….

      #include delay.h
      #define my_RXport PINC.0 //set pin rx
      #define my_RXport_dir DDRC.0 //direksi port

      void my_delay_us(int n)
      {
      while(- -n)
      delay_us(1);
      }

      int perioda_baudrate;
      void rx_init()
      {
      int baudrate = 9600; //set baudrate
      int konstanta_error = 0; //ditunning sampai mendapat hasil optimal
      my_RXport_dir = 0; //set sebagai input
      perioda_baudrate = (1000000/baudrate) + konstanta_error; //dalam mikro second
      }

      unsigned char my_getchar()
      {
      unsigned char urut_data
      ,data=0;
      while(my_RXport){}; //tunggu kepada data logic LOW
      my_delay_us(perioda_baudrate);
      for(urut_data=0;urut_data<8;urut_data++)
      {
      data = data << 1;
      if(my_RXport)
      data += 1;
      else
      data += 0;
      my_delay_us(perioda_baudrate);
      }
      return(data);
      }

      • Ridla says:

        makasih mas,dicoba dlu.ntar saya nanya2 lagi😀

      • Ridla says:

        oya mas kalo rx_init() itu dipakenya pas apa? kan gini program saya.
        while(1){
        sprintf(buffer,”%c”,my_getchar());
        lcd_gotoxy(0,0);
        lcd_puts(buffer);
        };
        nah rx_init nya disimpan sebelah mana?saya pake ATMega16.
        makasih mas sebelumnya

      • wangready says:

        rx_init() disimpan sebelum while(1), diatasnya, itu fungsi untuk inisialisasi PORT dan baudrate yg digunakan…

      • Ridla says:

        ga bisa mas,karakternya aneh rubah2.
        maaf mas masih newbie😀
        bingung nyari program rx nya ga nemu2..

      • wangready says:

        nilai konstanta errornya mas diubah2, coba kasih nilai minus dikit2, coba dulu dari -1 dst…cari yg cocok…
        karena pada codevision delay_us gk bisa dikasih variabel, sya bikin my_delay_us, jadinya nilainya gk presisi…
        kalo pake AVR GCC, nilai delay_us nya mungkin bisa langsung pake dari library bawaan, bisa diisi variabel…

      • Ridla says:

        tetep aja mas udah min berapa kali juga ga cocok. atau karena xtalnya gitu mas,saya pake 11,0592Mhz. uCnya ATMega16.
        Saya langsung ga pake proteus.

      • wangready says:

        coba cek pada bagian while(–n)
        void my_delay_us(int n)
        {
        while(- -n)
        delay_us(1);
        }
        itu tanda minusnya 2kali, tanda decrement…
        kalo diposting kodenya jadi salah — – –

        oya, maaf, ada yg salah, ralat, ini kode yg bisa, sya dapet konstanta error nya -54

        /*****************************************************
        Chip type : ATmega16
        Program type : Application
        AVR Core Clock frequency: 11.059200 MHz
        Memory model : Small
        External RAM size : 0
        Data Stack size : 256
        *****************************************************/

        #include mega16.h>
        #include delay.h>
        #include stdio.h>

        // Alphanumeric LCD Module functions
        #asm
        .equ __lcd_port=0x1B ;PORTA
        #endasm
        #include lcd.h>

        unsigned char kata[16];

        // Declare your global variables here
        #define my_RXport PINC.0 //set pin rx
        #define my_RXport_dir DDRC.0 //direksi port

        void my_delay_us(int n)
        {
        while(--n)
        delay_us(1);
        }

        int perioda_baudrate;
        void rx_init()
        {
        int baudrate = 9600; //set baudrate
        int konstanta_error = -54; //ditunning sampai mendapat hasil optimal
        my_RXport_dir = 0; //set sebagai input
        perioda_baudrate = (1000000/baudrate) + konstanta_error; //dalam mikro second
        }

        unsigned char my_getchar()
        {
        unsigned char urut_data
        ,data=0;
        while(my_RXport){}; //tunggu kepada data logic LOW
        my_delay_us(perioda_baudrate);
        for(urut_data=0;urut_data> 1;
        if(my_RXport)
        data += 128;
        else
        data += 0;
        my_delay_us(perioda_baudrate);
        }
        return(data);
        }

        void main(void)
        {
        // Declare your local variables here

        // Input/Output Ports initialization
        // Port A initialization
        // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
        // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
        PORTA=0x00;
        DDRA=0x00;

        // Port B initialization
        // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
        // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
        PORTB=0x00;
        DDRB=0x00;

        // Port C initialization
        // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
        // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
        PORTC=0x00;
        DDRC=0x00;

        // Port D initialization
        // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
        // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
        PORTD=0x00;
        DDRD=0x00;

        // Timer/Counter 0 initialization
        // Clock source: System Clock
        // Clock value: Timer 0 Stopped
        // Mode: Normal top=FFh
        // OC0 output: Disconnected
        TCCR0=0x00;
        TCNT0=0x00;
        OCR0=0x00;

        // Timer/Counter 1 initialization
        // Clock source: System Clock
        // Clock value: Timer1 Stopped
        // Mode: Normal top=FFFFh
        // OC1A output: Discon.
        // OC1B output: Discon.
        // Noise Canceler: Off
        // Input Capture on Falling Edge
        // Timer1 Overflow Interrupt: Off
        // Input Capture Interrupt: Off
        // Compare A Match Interrupt: Off
        // Compare B Match Interrupt: Off
        TCCR1A=0x00;
        TCCR1B=0x00;
        TCNT1H=0x00;
        TCNT1L=0x00;
        ICR1H=0x00;
        ICR1L=0x00;
        OCR1AH=0x00;
        OCR1AL=0x00;
        OCR1BH=0x00;
        OCR1BL=0x00;

        // Timer/Counter 2 initialization
        // Clock source: System Clock
        // Clock value: Timer2 Stopped
        // Mode: Normal top=FFh
        // OC2 output: Disconnected
        ASSR=0x00;
        TCCR2=0x00;
        TCNT2=0x00;
        OCR2=0x00;

        // External Interrupt(s) initialization
        // INT0: Off
        // INT1: Off
        // INT2: Off
        MCUCR=0x00;
        MCUCSR=0x00;

        // Timer(s)/Counter(s) Interrupt(s) initialization
        TIMSK=0x00;

        // Analog Comparator initialization
        // Analog Comparator: Off
        // Analog Comparator Input Capture by Timer/Counter 1: Off
        ACSR=0x80;
        SFIOR=0x00;

        // LCD module initialization
        lcd_init(16);
        rx_init();
        while (1)
        {
        // Place your code here
        sprintf(kata,"%c",my_getchar());
        lcd_puts(kata);
        };
        }

  5. intan says:

    Halo, posting yang bermanfaat.. Tp saya masih gak paham dgn konsep pengiriman datanya berdasarkan program di atas. Saya punya modul Jy MCU 3208 Clock dan rencananya mau saya ubah si tampilan dot matriksnya. Modul tsb menggunakan ic HT1632c sbg driver dot matriks. IC HT1632 terdapat pin CS , WR, dan DATA buat ke mikrokontroler, dimana DATA adalah i/o data secara serial. Jadi bagaimana cara memrogram ATMega 16 utk menampilkan karakter2 pada modul yg menggunakan ic tersebut?

    • wangready says:

      program di atas untuk mengirim data serial lewat pin biasa dengan cara manipulasi program… untuk pengiriman data HT1632 beda lagi gan, tapi prinsipnya keknya sama, data char digeser, lalu dibaca bit ujungnya, kemudian di set ke pin IO dan di delay sesuai nilai baudrate…
      sebenernya kalo pake delay biasanya kurang presisi signal timing nya, kalo di artikel di internet yg lain mereka pakai timer…

  6. wahyu perdana says:

    selamat malam mas saya mau tanya ini kalo msialnya port D0 pada rx dan port D! tx diganti dengan port a atau port b atau port c bisa tidak ya mas? email cocoperdana@gmail.com

    • wangready says:

      kalo diganti gk bisa gan, itu memang konfigurasi bawaan dari mikrokontroller…. tp kita bisa memanfaatkan port yg lainnya untuk Tx/Rx dengan membuat semacam memanipulasi bit data lewat kodingan… contohnya udah ane post di blog ini gan, search aja…

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s