MSP430 Dersleri 10 – USART Haberleşme

Merhaba Arkadaşlar,
Bu ders serisinin sonuna gelmiş bulunmaktayız. Son olarak bir haberleşme dersi anlatmak istedim ve haberleşme protokollerinin en basiti olan USART’ı anlatmanın doğru olacağını düşündüm. Şimdiden uyarıyorum protokol kolay olmasına rağmen kod kısmı bir miktar karmaşık, ben de anlamakta zorlandım. Kodlar konusundaki bu ön uyarıdan sonra genel olarak kablolu haberleşmeyi inceleyerek başlayalım.

Kablolu haberleşme temel olarak “Seri” ve “Paralel” olmak üzere iki sınıfa ayrılabilir. Seri haberleşmede göndermek istediğimiz bitler bir hat üzerinden sırayla, paralel haberleşmede ise gönderilecek bitler birden fazla hat üzerinden aynı anda gönderilir. Bu iki türün birbirine göre avantajları ve dezavantajları vardır. Temel olarak paralel haberleşme seriye göre daha hızlı bir haberleşmedir, ancak birden fazla hat kullanılması sistemin karmaşıklığını arttırmaktadır. Yüksek hıza ihtiyaç duyulan yerlerde, örneğin ilk derste değindiğimiz CPU ile modüller arasındaki “Main Data Bus”ta, paralel haberleşme kullanılır. Hızın kritik seviyede önemli olmadığı yerlerde ise, örneğin sensör ile işlemci arasında, genellikle seri haberleşme tercih edilmektedir. Şekil 1’de genel olarak seri ve paralel haberleşmenin hat yapısı ve verinin hatlar üzerinden gönderilme şekli görülmektedir.

Şekil 1. Seri ve paralel haberleşmede hat yapısı

Pek çok seri haberleşme protokolü bulunmaktadır. Bunlardan en önemlileri USART, SPI, I2C, RS232 protokolleridir. Hepsine teker teker değinmek isterdim ama konuyu çok uzatmak istemiyorum. Bu nedenle sadece USART üzerinden ilerleyelim. Zaten bir tanesini öğrendikten sonra diğerlerini anlamakta zorlanmayacağınızı düşünüyorum.

USART’ın açılımı “Universal Synchronous and Asynchronous Receiver-Transmitter”dir. Burada “Senkron” ve “Asenkron” kelimelerini görüyoruz. Haberleşmede senkron olmak veri ile birlikte verinin zaman bilgisinin de alıcıya gönderilmesi anlamına gelmektedir. Bu genellikle bir clock işareti ile gerçekleştirilir. Bir örnek verecek olursak. Verici sistem verileri gönderirken kendi clock işaretinin yükselen kenarında bit geçişlerini yaptığını düşünelim. Verici clock işaretini alıcıya gönderdiği durumda, alıcı her bitin başlangıç noktasını yani zaman bilgisini almış olur. Böylelikle senkron haberleşme yapılır. Asenkron haberleşmede ise clock işareti gönderilmediği için alıcı tarafın bit süresi, haberleşme başlangıç noktası gibi bilgileri bilmesi gerekmektedir. Bu konuya birazdan tekrar geleceğim. Şimdi USART’ın bağlantı şeklini tanıyalım.

USART’da “Rx” ve “Tx” olmak üzere iki haberleşme hattı bulunmaktadır. “Rx” sistemin haberleşeceği sistemden bilgi almak için, “Tx” ise haberleşilecek sisteme bilgi göndermek için kullanılan hattır. Buradan anlaşılacağı gibi bağlantı çapraz şekilde yapılmalı, yani birinci sistemin “Rx” hattı ikinci sistemin “Tx” hattına, “Tx” hattı ise ikinci sistemin “Rx” hattına bağlanmalıdır. Bunu anlatırken her zaman biz insanların iletişiminden örnek veririm. Birisiyle konuştuğumuzu düşünelim. Biz bilgiyi ağzımızdan (Tx) gönderiyoruz, karşımızdaki ise kulağıyla (Rx) bilgiyi algılıyor (Şekil 2). Görüldüğü gibi USART insanlardan esinlenerek oluşturulmuş bir protokoldür. 🙂

Şekil 2. İnsanlar arasındaki konuşarak haberleşme yöntemi

Asenkron haberleşmedeki zamanlama bilgilerinin alıcıya nasıl iletildiğine dönecek olursak. Bu işlem basit olarak bir başlangıç biti ve bit sürelerinin haberleşen iki sistem tarafından da bilinmesi ile gerçekleştirilmektedir. Bu bit süresi “Baudrate” olarak adlandırılmakta ve saniyede gönderilen bit sayısını vermektedir. Örneğin 9600 baudrate saniyede 9600 adet bit gönderilebilecek kadar bit süresi (104,16 µs) ile haberleşme yapıldığı anlamına gelir. Şimdi USART protokolünün haberleşme adımlarına bakacak olursak.

  • Haberleşmenin olmadığı durumda hat lojik 1 seviyesinde bekler. (İdela Durum)
  • Haberleşmeyi başlatmak için hat bir bit süresi boyunca lojik 0 seviyesine çekilir. (Başlangıç Biti)
  • Başlangıç bitinden sonra bilgi bitleri (8 bit) en anlamsız bit önce gidecek şekilde sırasıyla gönderilir.
  • İsteğe bağlı olarak hata kontrolü için Parity biti gönderilebilir.
  • Haberleşmeyi bitirmek için son olarak bir bit süresi boyunca hat lojik 1 seviyesine çekilir. (Stop Biti)
  • Tekrar haberleşme yapılana kadar hat lojik 1 seviyesinde kalır. (İdeal Durum)

Şekil 3’de USART protokolünün paket yapısı görülmektedir.

Şekil 3. USART protokolü paket yapısı

Böylelikle kabaca USART haberleşmesi konusunda bilgi sahibi olduk. Şimdi gelelim MSP430 için yazılan kodlara. Yazılan diyorum çünkü bu kodlar Texas Insturments’in örnek kodları. Kodların nasıl çalıştığını anlatmayacağım çünkü bu aşamada kodu inceleyerek anlayabilecek seviyeye geldiğinizi düşünüyorum. Gerçi incelediğinizde yukarıda anlatılan protokolden farklı bir şey görmeyeceksiniz.

RXD EQU 002h ; RXD on P1.1 
TXD EQU 020h ; TXD on P1.5 

; CPU Registers Used 
#define  RXTXData R4 
#define  BitCnt   R5 

; Conditions for 2400 Baud SW UART, ACLK = 32768 
Bitime_5  EQU 06  ; ~0.5 bit length + small adjustment 
Bitime    EQU 014 ; 427us bit length ~ 2341 baud 

#include <msp430.h> 
;------------------------------------------------------------------------------- 
ORG  0F800h ; Program Reset 
;------------------------------------------------------------------------------- 
RESET    mov.w #0280h,SP              ; Initialize stackpointer 
StopWDT  mov.w #WDTPW+WDTHOLD,&WDTCTL ; Stop Watchdog Timer 
SetupTA  mov.w #TASSEL_1+MC_2,&TACTL  ; ACLK, continuous mode 
SetupC0  mov.w #OUT,&CCTL0            ; TXD Idle as Mark 
SetupP1  bis.b #TXD+RXD,&P1SEL 
         bis.b #TXD,&P1DIR 

Mainloop call #RX_Ready               ; UART ready to RX one Byte 
         bis.w #LPM3+GIE,SR           ; Enter LPM3 w/ int until Byte RXed 
         call #TX_Byte                ; TX Back RXed Byte Received 
         jmp Mainloop 
;------------------------------------------------------------------------------- 
TX_Byte ; Subroutine Transmits Character from RXTXData Buffer 
;------------------------------------------------------------------------------- 
TX_1     mov.w &TAR,&CCR0                  ; Current state of TA counter 
         cmp.w &TAR,&CCR0                  ; !!Prevent async capature!! 
         jne TX_1 
         add.w #Bitime,&CCR0               ; Some time till first bit 
         bis.w #0100h, RXTXData            ; Add mark stop bit to RXTXData 
         rla.w RXTXData                    ; Add space start bit 
         mov.w #10,BitCnt                  ; Load Bit counter, 8data + ST/SP 
         mov.w #CCIS0+OUTMOD0+CCIE,&CCTL0  ; TXD = mark = idle 
TX_Wait  bit.w #CCIE,&CCTL0                ; Wait for TX completion 
         jnz TX_Wait 
         ret 
;------------------------------------------------------------------------------- 
RX_Ready ; Subroutine Readies UART to Receive Character into RXTXData Buffer 
;------------------------------------------------------------------------------- 
         mov.w #08,BitCnt                        ; Load Bit Counter, 8 data bits 
SetupRX  mov.w #CM1+SCS+OUTMOD0+CAP+CCIE,&CCTL0  ; Neg Edge,Sync,cap 
         ret 
;------------------------------------------------------------------------------- 
TA0_ISR ; RXTXData Buffer holds UART Data 
;------------------------------------------------------------------------------- 
         add.w #Bitime,&CCR0                ; Time to next bit 
         bit.w #CCIS0,&CCTL0                ; RX on CCI0B? 
         jnz UART_TX                        ; Jump --> TX 
UART_RX  bit.w #CAP,&CCTL0                  ; Capture mode = start bit edge 
         jz RX_Bit                          ; Start bit edge? 
RX_Edge  bic.w #CAP,&CCTL0                  ; Switch to compare mode 
         add.w #Bitime_5,&CCR0              ; First databit 1.5 bits from edge reti 
RX_Bit   bit.w #SCCI,&CCTL0                 ; Get bit waiting in receive latch 
         rrc.b RXTXData                     ; Store received bit 
RX_Test  dec.w BitCnt                       ; All bits RXed? 
         jnz RX_Next                        ; Next bit? 
;>>>>>>>>>> Decode of Received Byte Here <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 
RX_Comp  bic.w #CCIE,&CCTL0                 ; All bits RXed, disable interrupt 
         mov.w #GIE,0(SP)                   ; Decode byte = active in Mainloop 
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 
RX_Next  reti UART_TX 
         cmp.w #00h,BitCnt 
         jne TX_Next                        ; Next bit? 
         bic.w #CCIE,&CCTL0                 ; All Bits TX or RX, Disable Int. 
         reti 
TX_Next  bic.w #OUTMOD2,&CCTL0              ; TX Mark 
         rra.w RXTXData                     ; LSB is shifted to carry 
         jc TX_Test                         ; Jump --> bit = 1 
TX_Space bis.w #OUTMOD2,&CCTL0              ; TX Space TX_Test 
         dec.w BitCnt                       ; All bits sent (or received)? 
         reti 
;------------------------------------------------------------------------------- 
; Interrupt Vectors 
;------------------------------------------------------------------------------- 
         ORG 0FFFEh                        ; MSP430 RESET Vector 
         DW RESET 
         ORG 0FFF2h                        ; Timer_A0 Vector 
         DW TA0_ISR END

Şu düzene bakar mısınız? Gerçekten şiir gibi yazmışlar. 🙂 Bu güzel eser ile yazı serimizin sonuna geldik. Bundan sonra sizin sorularınıza göre yazılar gelebilir. Elimden geldiği kadar bildiklerimi paylaşmaya çalıştım umarım faydalı olabilmişimdir. Anlamadığınız yerleri mesaj atarsanız bildiğim kadarıyla cevaplamaya çalışırım. Başka yazılarda görüşmek üzere kendinize iyi bakın efendim. 🙂

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir