Elektronik / Mikrodenetleyici Projeleri/

MSP430 ve UART Denemesi

Sponsorlu Bağlantılar

Ne zamandır MSP430 ile ilgili bir uygulama yapmıyordum bu yüzden bugün biraz kafamı diğer işlerden uzaklaştırmak ve notlarımı düzenlemek için MSP430’un UART kısmına göz atmaya karar verdim.

Fakat ilk hevesle baktığım bu çevre birimini, MSP430’un datasheet’inden anlamak gerçekten zor. Sanırım bu yüzdendir ki sitesinde her mikrodenetleyici ile ilgili ufak tefek onca kod parçacığı var. Ben de bu kodları inceleyerek bu birimi çözmeyi başardım ve MSP430F2112 ile simülasyonu yaptım.

MSP430 UART Birimi

Bu denememde kullandığım MSP430 için kullanmamız gereken USCI_Ax modülünün UART modunun şemasını aşağıdan görebilirsiniz. Yine aşağıdaki şemadan görebileceğiniz üzere bu birim IrDA için de ayrılmış özelliklere sahip olsa da biz bu uygulamamızda bu noktaya değinmeyeceğiz.

MSP430_UART

Yukarıdaki şekle tekrar bakarsak öncelikli olarak belirlememiz gereken kısım, UART birimi için gerekli olan saat kaynağımızdır. Bu kaynak UCA0CTL1 registerinden ayarlanabilir. Ben uygulamada bu kaynağı SMCLK olarak belirledim ve yapmamız gerekenleri aşağıya şöyle sıraladım.

1) UCA0CTL1‘dan parity, data ve stop bitleri gibi bilgiler belirlenir.
2) (SMCLK Frekansı/Baud Rate) formülünden çıkan sayının 15-8. bitleri UCA0BR1, 7-0. bitleri UCA0BR0 registerlerine yüklenerek baudrate ayarlanır.
3) UCA0MCTL registeri ile tam çıkmayan sonuçlarda oluşabilecek hataları engellemek için hata düzeltme değeri buraya girilir.

Örneğin SMCLK frekansımı 1Mhz, baudrate değerimiz 9600 olursa 1M/9600=104,16.. şeklinde çıkar. Burada ondalıklı kısmın ilk değeri 1’i alırsak modülasyon değerimiz UCA0MCTL=UCBRS0 olur. UCBRS0 değeri UCBRS0..UCBRS7’ye kadar gitmektedir ve değerler binary şekildedir. Örneğin SMCLK frekansımız 32khz olduğunda bu değer 32k/9600=3.33 çıkar. Buradan ondalığın ilk değeri 3 çıkar ve UCA0MCTL=UCBRS1+UCBRS0 şeklinde tanımlanır. Ayrıca hata düzeltilmesi yapılmadan da UART birimi çalışabilmektedir, fakat profesyonel uygulamalarda bu tercih edilmez.
4) Bunları yaptıktan sonra UCA0CTL1 registerindenin 0. biti temizlenmelidir. Bu bit temizlenmez ise UART birimi resette kalır ve birim çalışamaz.

5) Son olarak bilgi almak için UCA0RXBUF ve göndermek için ise UCA0TXBUF registerlerini kullanabilirsiniz. Ayrıca alım ve gönderim FIFO’larının boş olup olmadıklarını ise sırasıyla IFG2 registerinin 0. ve 1. bitlerinden kontrol edebilirsiniz.

Registerlerin daha ayrıntılı kullanımları için kullandığınız MSP430’un datasheet’ine bakabilirsiniz. Yukarıda saydıklarımızı bir kütüphane haline getirirsek UART.h ve UART.c aşağıdaki gibi olmaktadır.

UART.h

#define CLK  			16000000  // SMCLK değeri
#define UART0_BAUD_RATE  	19200	  // Baudrate
#define UART0_WORD_LENGTH  	0	  // 1: 7bit, 0:8bit
#define UART0_STOP_BIT  	0	  // 0: Stop bit=1, 1: Stop bit=2/1.5
#define UART0_PARITY  		0	  // 0: Parity yok, 1: Parity var
#define UART0_PARITY_SEL  	0	  // 0: Odd, 1: Event

extern void uart_init(void);
extern void uart_putch(unsigned char c);
extern char uart_getch(void);
extern void uart_string(const char *st);

UART.c

#include "msp430.h"
#include "UART.h"

void uart_init(void)
{
  UCA0CTL0=0x00;                      // UART mode, asenkron
  UCA0CTL0=(UART0_PARITY < < 7)|(UART0_PARITY_SEL << 6)|(UART0_WORD_LENGTH << 4)|(UART0_STOP_BIT << 3);

  UCA0CTL1 |= UCSSEL_2;               // SMCLK
  UCA0BR1=(CLK/UART0_BAUD_RATE)/256;  // Baudrate hesaplanıyor
  UCA0BR0=(CLK/UART0_BAUD_RATE)%256;

  UCA0MCTL = UCBRS0;                  // Bu baud hesabına göre değişebilir
  UCA0CTL1 &= 0xFE;                   // Software reset kaldırılıyor
}

void uart_putch(unsigned char c)
{
  while(!(IFG2 & 0x02));		// Transmit gönderim FIFO'su boş mu?
    UCA0TXBUF=c;
}

char uart_getch(void)
{
  while(!(IFG2 & 0x01));		// Receive alım FIFO'su boş mu?
    return UCA0RXBUF;
}

void uart_string(const char *st)
{
  while(*st)
    uart_putch(*st++);
}

Görüldüğü üzere UART kütüphanesi oldukça sadedir. Aşağıda ise örnek için kullandığım kodları görebilirsiniz.

#include "msp430.h"
#include "uart.h"

void main( void )
{
    WDTCTL  = WDTPW + WDTHOLD;
    BCSCTL1 = CALBC1_16MHZ;   // Kristal 16MHz'e ayarlanıyor
    DCOCTL  = CALDCO_16MHZ;

    P3SEL = 0x30;             // P3.4 ve P3.5 UART için yönlendirildi
    P3DIR = 0xFF;

    uart_init();
    uart_string("Hello World\r\n");
    uart_string("www.FxDev.org");

    for(;;)
      uart_putch(uart_getch()); // Echo yaptırılıyor
}

Uygulamanın çalışan simülasyonunu da aşağıdaki resimden (tıklarsanız büyür) görebilirsiniz.

MSP430-Uygulama

Yukarıdaki uygulama görüldüğü üzere yazılım kontrollüdür ve amatörcedir. Bu uygulamaya daha fazla işlev katmak için kesmeleri kullanırsak kodumuz aşağıdaki gibi olmaktadır.

#include "msp430.h"
#include "uart.h"

volatile unsigned char i=0;
 
void main( void )
{
    WDTCTL  = WDTPW + WDTHOLD;
    BCSCTL1 = CALBC1_16MHZ;       // Kristal 16MHz'e ayarlanıyor
    DCOCTL  = CALDCO_16MHZ;
    
    P1SEL = 0x00;
    P1DIR = 0xFF;
    P1OUT = 0x00;
    P3SEL = 0x30;                 // P3.4 ve P3.5 UART için yönlendirildi
    P3DIR = 0xFF;

    uart_init();
    uart_string("Hello World\r\n");
    uart_string("www.FxDev.org");
  
    IE2 |= UCA0RXIE + UCA0TXIE ;  // Alım ve gönderim kesmeleri aktif
    
    _EINT();                      // Kesmeler açılıyor             
}

// Gönderim kesmesi
#pragma vector=USCIAB0TX_VECTOR
__interrupt void USCI0TX_ISR(void)
{
   while(!(IFG2 & 0x01));                 // Receive alım FIFO'su boş mu?
    P1OUT = i++;
}

// Alım kesmesi
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void)
{
    while(!(IFG2 & 0x02));		// Transmit gönderim FIFO'su boş mu?
      UCA0TXBUF=UCA0RXBUF;
}

Yukarıdaki kodlara dikkat edilirse gönderim kesmesinde her bir karakter için P1'deki çıkışlar binary olarak aktif edilmektedir.

Yazımı bitirmeden önce MSP430'ların 3.3V gerilim ile çalıştıkları için MAX232 entegresi kullanılamayacaklarını belirtmek isterim. Bu iş için ya kendiniz step-up özellikli bir devre tasarlamalı ya da piyasada 3.3V için özelleştirilmiş MAX3232 entegresini MSP430 uygulamalarınız için kullanabilirsiniz. Bu uygulama ile ilgili tüm dosyalar: MSP430 ve UART Denemesi

Dosya indirme LINK listesi (TXT formatında) link-21515.zip şifre-pass: 320volt.com

Herkese çalışmalarında başarılar dilerim ;)

  • İbrahim YILDIZ

    Güzel bir çalışma olmuş, piclerden artık kurtulmamız lazım diye düşünüyorum bu yüzden çok daha ucuz ve kabiliyetli MSP430 serisi hakkında türkçe kaynak bulmak beni gerçekten umutlandırıyor.

    İyi çalışmalar.

  • Orhan

    Selamlar Fırat hocam. Bu uygulamayı derlediğimde uart_init içindeki tüm tanımlamalar hata veriyor (tanınamıyor) bunun sebebi ne olabilir? bu arada MSP430Gxx sürümü için deniyorum..

  • A. Tahir

    Merhabalar. Bu uygulamayı ben de denemek istiyordum MAX3232 aldım ama bunun için hangi kapasite değerleri bağlamam ve de ne kadar besleme gerilimi varmem gerekir ki TTL 3.3V u 5V a çekebileyim?

    Bu meret -15V/+15V arasına da çekebiildiği için(eğer yanlış anlamadı isem tabiki) sormadan yapamadım :(

  • FxDev

    MAX3232′nin kapasiteleri 0.1uF olması yeterli. 3.3V besleme vereceksiniz. Yani MSP430 ile aynı. MAX3232 kendi -+15V gerilimi kendi sağlayacaktır zaten.

  • A. Tahir

    Benim elimde uart to usb devresi var ancak 0/5V ttl okuyor yani normal rs232 gibi -15/+15 değil.Ben de msp ile 3.3V ttl çıkışını 5V a yukselterek kullanmak istiyorum.Kapasiteler ne olmalı?Bunun için de mi .1uF olması gerekiyor?

  • FxDev

    USB/Seri dönüştürücüler +15/-15V ile uyumlu çalışabiliyorlar. Benim bugüne kadar denediklerim hep böyleydi.

  • serap

    Merhaba,
    bir sorum olacaktı.elimdeki msp430fg4618 den veri göndermek istiyorum.veri gidip gitmediğini kontrol etmek için msp nin TX ucuna scope ile bakıp sinyal var mı diye kontrol etmek amacım.bunun için
    main fonksiyonunda

    for(;;){
    UCA0TXBUF =55;
    }
    yapınca TX ucunda sinyal göremiyorum bu şekilde yapmakla sadece sembolik sabitin değirini mi değiştirmiş oluyorum acaba.TX ucuna nasıl veri gönderebilirim ?

    //******************************************************************************
    // MSP430xG461x Demo – USCI_A0 IrDA Physical Layer Comm, 4MHz SMCLK
    //
    // Description: This example receives bytes through the USCI module
    // configured for IrDA mode, and sends them out using the USART1 module
    // to a PC running a terminal software. Likewise, data received from the PC
    // through the USART1 is transmitted via IrDA.
    //
    // MCLK = SMCLK = DCO = 4MHz, ACLK = 32kHz
    // //* An external 32kHz XTAL on XIN XOUT is required for ACLK *//
    //
    // MSP430xG461x
    // ———————–
    // | |
    // /|\| XIN|-
    // | | | 32kHz
    // –|RST XOUT|-
    // | |
    // GP2W0116YPS /|\ | |
    // ——- | | |
    // | Vcc|—–+ IrDA | |
    // # LED|—–+ 9600 8N1 | |
    // # TxD||P2.5/UCA0RXD UTXD1|–> 115,200 8N1
    // # SD|—–+ | URXD1|<– Terminal SW
    // | GND|—–+ | |
    // ——- | ———————–
    // —
    //
    // A. Dannenberg
    // Texas Instruments Inc.
    // June 2007
    // Built with CCE Version: 3.2.0 and IAR Embedded Workbench Version: 3.42A
    //******************************************************************************
    #include "msp430xG46x.h"

    void main(void)
    {
    WDTCTL = WDTPW + WDTHOLD; // Stop WDT
    P2DIR=0XFF;

    P1DIR=0;
    P2SEL |= 0×30; // Use P2.4/P2.5 for USCI_A0
    P4SEL |= 0×03; // P4.0,1 = USART1 TXD/RXD
    SCFQCTL = 121; // Set FLL to 3.998MHz
    SCFI0 = FLLD0 + FN_2; // Adjust range select
    UCA0CTL1 |= UCSWRST; // Set USCI_A0 SW Reset
    UCA0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
    UCA0BR0 = 26; // 4Mhz/26=153.8kHz
    UCA0BR1 = 0;
    UCA0MCTL = UCBRF_1 + UCOS16; // Set 1st stage modulator to 1
    // 16-times oversampling mode
    UCA0IRTCTL = UCIRTXPL2 + UCIRTXPL0 + UCIRTXCLK + UCIREN;
    // Pulse length = 6 half clock cyc
    // Enable BITCLK16, IrDA enc/dec
    UCA0IRRCTL = UCIRRXPL; // Light = low pulse
    UCA0CTL1 &= ~UCSWRST; // Resume USCI_A0 operation
    IE2 |= UCA0RXIE; // Enable USCI_A0 RX int
    U1CTL |= SWRST; // Set USART1 SW Reset
    ME2 |= UTXE1 + URXE1; // Enable USART1 TXD/RXD
    U1CTL = CHAR + SWRST; // 8-bit characters, keep SW reset
    U1TCTL = SSEL1; // BRCLK = SMCLK
    U1BR0 = 0×22; // 4MHz/115,200=34.72
    U1BR1 = 0×00; //
    U1MCTL = 0xdd; // Modulation
    U1CTL &= ~SWRST; // Release USART1 state machine
    IE2 |= URXIE1; // Enable UART1 RX int
    __bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts

    while(1)
    {
    //P2OUT=0×04;
    U1TXBUF = 0×05;
    }

    }

    bu TI ın sitesinden aldığım kod örneği bunun üzerinde yapmaya çalışıyorum..

  • FxDev

    Şu an için bu konular hakkında bir kitap hazırlığım söz konusu beklerseniz orada cevabınızı bulabilirsiniz.

  • omer

    merhaba firat abi bu uart bolume basladim calismaya 433mhz rc rx alici verici ile kucuk capda bir haberlesme yapicam su anda ustunde urasiyorum takildim bir kac nokta 1 2 gun sonra kodumu atsam bir bakalabilirmisiniz ?