ARM Uygulamaları – STM32F411 USART Haberleşmesi

 

USART nedir ne değildir gibi soruları nette bulabileceğiniz için bilgi kirliliği yapmak istemedim.

USART haberleşmesi için USB-TTL kullanacağız.

Bu arada ben USB-TTL almaya gerek duymadım elimde onlarca Arduino kartları vardı. Bunları bir kaç işlemle kullanılabilir hale getirdim. Arduino’nun RESET pinini GND’ye çektiğinizde üzerindeki mikrodenetleyici deaktif olup USB-TTL Seri Port haberleşmesi yapabilecek moda düşecektir. Bu sayede herhangi bir terminal ile COMx portuna bağlanıp Arduino üzerinden STM32F4 ile mektuplaşabileceğiz.

 


 

STM32F4 üzerinden bir den fazla USART birimi bulunmaktadır. Her USART birimi birden fazla pin ile kontrol edilebilmektedir.

Stm32f411 datasheetinde sayfa 43 de tablo halinde AF modundaki tüm pinlerin listesi verilmiş. (İndirmek için tıklayınız.)

Bu tablo incelendiğinde aşağıdaki gibi özetlenebilir;

usart-tablo

Ben bu uygulamada USART1 birimini ve Pin A9 ve Pin A10‘u kullanmak istedim ancak alternatif modu USB olarak kullanıldığından düzgün haberleşme sağlayamadım. Veri göndermek istediğimde PA9‘a bağlı USB ledi (LD7) yanıyordu sürekli. Hatta bununla ilgi sorunu olan bir kaç kişinin gönderisini gördüm. Bu nedenle USART1 B portu pin düzenini yani PB6, PB7 kullanacağım.

StdPeriph_Driver grubuna USART kütüphanesi eklemeyi unutmayın. stm32f4xx_conf.h dosyasınında da usart’ın başındaki yorum satırı operatörünü kaldırmayı da unutmayın.

StdPeriph Driver klasöründe USART kaynak kodlarına baktığınızda kütüphanenin en üst kısmında aşağıdaki açıklama bulunmaktadır.

howtouse

 

Yorumlamak gerekirse basit bir USART haberleşmesi için izlenilecek yol adımları;

  1. USART modulü için clock (RCC) aktifleştir,
  2. USART haberleşmesi için kullanacağın pinlerin de clocklarını (RCC) aktifleştir,
  3. Kullanacağın pinleri alternatif mode olarak ayarla, GPIO ayarlarını yap, GPIO_Init fonksiyonunu çağır,
  4. USART ayarlarını yap, baud rate, stop bits, hardware flow gibi…
  5. Senkron kullanacaksan clock ayarlaması yap,
  6. İnterrupt kullanacaksan ayarlamalarını yap,
  7. DMA mode’da kullanacaksan ayarlamalarını yap,
  8. USART_Cmd() ile usart’ı başlat,

şeklinde özetlenebilir.

 

Başlıyoruz..


 

  • Öncelikle USART kurulumların yapılacağı bir fonksiyon açalım, temiz temiz çalışalım.
void USART1_Setup(void){

// buraya yazacağız kodları

}

 

  • İlk yapacağımız işlem USART için ve GPIO için clockları (RCC) aktifleştirmek. RCC kütüphanesinde ufak bir inceleme ile USART1 modulü için hangi bus’ı, kullandığımız RX, TX pinleri için hangi bus’ı açmanız gerektiğini bulabilirsiniz.
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); 
 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); 

 

  • GPIO ayarlarında hangi pinleri kullanacağımızı ve GPIO_Mode’u AF (alternative function) olarak seçilmesi gerek.
 GPIO_InitTypeDef GPIO_InitStructure; 
 
 GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_USART1); 
 GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_USART1);
 
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; 
 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; 
 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; 
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
 
 GPIO_Init(GPIOB, &GPIO_InitStructure); 

 

  • USART ayarlarını yapmak için USART kütüphanesi içerisinde StructInit() fonksiyonuna göz atabilirsiniz.
 USART_InitTypeDef USART_InitStructure;
 
 USART_InitStructure.USART_BaudRate = 9600;
 USART_InitStructure.USART_WordLength = USART_WordLength_8b;
 USART_InitStructure.USART_StopBits = USART_StopBits_1;
 USART_InitStructure.USART_Parity = USART_Parity_No;
 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
 
 USART_Init(USART1, &USART_InitStructure);

 

  • Veri geldiğinde kesme oluşturması için Kesme ayarlarını RXNE registerına bağlamamız gerekmektedir.
 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); 
 
 NVIC_InitTypeDef NVIC_InitStructure; 
 
 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; 
 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; 
 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; 
 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
 
 NVIC_Init(&NVIC_InitStructure);

 

  • Son olarak tüm bu işlemlerimizden sonra USART’ı açabiliriz.
 USART_Cmd(USART1, ENABLE);

 

USART veri yollama fonksiyonu;

Pointerların aslında bir dizi olduğunu söylememe gerek yok sanırım. Orta düzey bir C bilgisine sahip olduğunuzu varsayıyorum. Bir fonksiyona argüman tipi olarak char pointer‘a sahip bir değişken veriyoruz. Bu değişken yer kapladığı sürece (0’dan büyük olacacaktır) while döngüsünde birer birer paketini yollamasını sağlayacağız.

TXE (Transmit Data Register Empty) iletilen data registerı boş mu bilgisini tutan bir registerdır. İletilen data registerı boş değilse while döngüsünde takılı kalacaktır. Register boş ise 1 değilse 0 döndürür. Çünkü henüz yollanmamış bilgi vardır. RESET değeri 0 değerine denk gelmektedir bu arada.

Örneğin sırada bir veri yok, iletilen data registerı boş ve TXE ise 1 döndürdü. 1 eşit mi 0 değerine bakılıyor, mantık olarak 0 döndüreceği için while girmeden bir sonraki satıra geçiyor Program Counter (PC).

USART_SendData fonksiyonu ile USART1 üzerinden veriyi yolluyor. Bu fonksiyon USART kütüphanesi içerisinde hazırlanmış hazır bir fonksiyondur. Bu işlemler son elemana kadar devam ediyor.

void USART1_Send(char* data){
  while(*data) {
   while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
   USART_SendData(USART1, *data);
   data++;
  }
}

 

Usart interrupt ile veri alma fonksiyonu;

RXNE (Receive Data Register Not Empty) gelen verilerin saklandığı registerın boş olup olmadığı bilgisini tutan registerdır. Eğer veri alınmış ise (boş değil anlamında) 1, veri alınmamış ise (boş anlamı olarak) 0 değeri döndürür.

Şimdi senaryo kuralım daha iyi anlamak için… Herhangi bir veri almadık RXNE (not empty) bize boş değil yani dolu olduğunun bilgisini verecek. Ancak boş olduğu için RXNE 0 değeri döndürecektir. RESET değerimiz de 0 olduğunda göre 0 == 0 değeri mantık olarak doğru olduğu için while döngüsünde takılı kalacaktır.

Aksi yöndeki senaryoda ise okuma işlemi yapıp gelenVeri’ye kaydedecektir.

Sonra tekrar gelenVeri‘ yi bize geri yollayacaktır.

 

void USART1_IRQHandler(void){
 // Okunan data registeri bos ise
 // yani herhangi veri gelmediyse bekle
 // RXNE: RX data register not empty
 while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);
 
 // Data registeri dolu ise okunan veriyi gelenVeri'ye kaydet
 char gelenVeri = USART_ReceiveData(USART1);
 
 // Gelen veriyi ekrana basmak icin
 // Yollanan data registerin bos olup olmamasini denetle
 while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
 USART_SendData(USART1, gelenVeri);
}

 


Kod

httpc://github.com/haknkayaa/STM32F4-Uygulamalari/blob/master/5.0-USARTHaberlesmesi/main.c

 

Video

 

Proje dosyaları için tıklayınız.

Hakan Kaya
Yarı zamanlı mühendis. Yarı zamanlı eğitmen. Biraz da film sever.
error: 5846 sayılı Fikir ve Sanat Eserleri Kanunu tarafında içeriklerin izinsiz kopyalanması, paylaşılması ve çoğaltılması yasaktır.