Ynt: STM32F4 Std_LIB Kullanımı (Örnek)

Başlatan Klein, 26 Ekim 2012, 16:10:47

Klein

Uzun zamandır forumda bu konuda sorular var.  Ama genelde cevapsız kalmış. Ya kimse bilmiyor, ya da benim gibi zaman bulup ilgilenemiyor.  HAzır bayram arası fırsat bulmuşken biraz ilgilenebildim.

ST kütüphanesinin projeye dahil edilip derlenmesini adım adım anlatmaya çalışacağım. Bir ledi yakıp söndüren (toggle) kod yazacağız. İşi karmaşıklaştırmama adına, sistemi başlatmak için gerekli clock ayarlamaları gibi kodlar için kütüphane fonksiyonlarını kullanmadım.  Başlatma kodlarımız yine @bunalmıs hocanın standart başlatma kodları.

Öncelikle yeni bir proje oluşturup , standart ayarlamalarımızı  yapıyoruz. main.c dosyasını registerleri kullanarak kart üzerindeki ledlereden birini yakıp söndürecekmişiz gibi düzenliyoruz.  Ledimizin yanıp söndüğünü gördükten sonra  kütüphaneyi dahil etmeye başlayabiliriz.

1. adım.
proje yönetiminden  projemize aşağıdaki dosyaları ekliyoruz.

Kütüphane klasörü\STM32F4xx_DSP_StdPeriph_Lib_V1.0.1\Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_gpio.c
Kütüphane klasörü\Utilities\STM32F4-Discovery\stm32f4_discovery.c
Kütüphane klasörü\Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_rcc.c
Kütüphane klasörü\Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_exti.c
Kütüphane klasörü\Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_syscfg.c
Kütüphane klasörü\Libraries\STM32F4xx_StdPeriph_Driver\src\misc.c

Bu dosyaları ekledikten sonra, proje ağacımız aşağıdaki gibi görünecek.


mesaj birleştirme:: 26 Ekim 2012, 16:19:08

2. adım
Projemizin ayarlarını yapacağız. 
Proje opsiyonlarında C/C++ sekmesine gidiyoruz.
"PreprocessorSymbols" gurubunun aldındaki "Defines:" kutusuna USE_STDPERIPH_DRIVER,STM32F4XX   yazıyoruz.


3. adım.
Kütüphaneni yolunu bildiriyoruz.
yine C/C++ sekmesinden "Include Paths" kutusunun yanındaki butona basıp açılan pencereden kütüphane klasörlerinin yollarını ekliyoruz.


mesaj birleştirme:: 26 Ekim 2012, 16:21:30

4. adım.  "main.c" dosyasının içeriğini aşağıdaki kodlarla değiştiriyoruz.  Derleyip çalıştırıyoruz.

main.c
#include "stm32f4_discovery.h" 

/*********************************************************************************
 CPU frekansi 168Mhz
 AHB frekansi 84 Mhz
 APB frekansi 42 Mhz
*********************************************************************************/
uint32_t ledtime=0;
uint8_t timer_update=0;


void SystemInit()
{
unsigned int i;
      for (i=0;i<0x00100000;i++);     // OSC oturtma ve kurtarma rutini
      RCC->CFGR |= 0x00009400;        // AHB ve APB hizlarini max degerlere set edelim
      RCC->CR |= 0x00010000;          // HSE Xtal osc calismaya baslasin        
      while (!(RCC->CR & 0x00020000));// Xtal osc stabil hale gelsin
      RCC->PLLCFGR = 0x07402A04;      // PLL katsayilarini M=4, N=168, P=2 ve Q=7 yapalim   168 Mhz 
      RCC->CR |= 0x01000000;          // PLL calismaya baslasin  (Rehber Sayfa 95)
      while(!(RCC->CR & 0x02000000)); // Pll hazir oluncaya kadar bekle
      FLASH->ACR = 0x00000605;        // Flash ROM icin 5 Wait state secelim ve ART yi aktif edelim (Rehber Sayfa 55)
      RCC->CFGR |= 0x00000002;        // Sistem Clk u PLL uzerinden besleyelim
      while ((RCC->CFGR & 0x0000000F) != 0x0000000A); // Besleninceye kadar bekle
      RCC->AHB1ENR |= 0x00000017;     // GPIO A,B,C,D,E clock'u aktif edelim 
	 
	 RCC->APB1ENR|=0x00000020;       // Timer7 CLK'u aktif edelim (84 Mhz)
	 TIM7->CR1=0x0080;               // Otomatik Reload
     TIM7->PSC =4199;                 // Prescaler degerimiz 839, Count frekansimiz = fCK_PSC / (Yuklenen Deger + 1) 84E6 / (840) = 100 KHz
     TIM7->ARR =1;                   // Counter, Decimal 1 olunca basa donsun. Her 20 mikrosaniye de bir timer int olusacak.
     TIM7->DIER=0x0001;              // Update Int enable
     TIM7->CR1|=0x0001;              // Counter Enable
     NVIC->ISER[1] = 0X00800000;     // NVIC de Timer 7 interrupta izin verelim
} 


 
void TIM7_IRQHandler(void)
{
TIM7->SR=0;    
timer_update=1;
}

 
 

int main(void)
{
GPIO_InitTypeDef  GPIO_InitStructure;

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_15;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOD, &GPIO_InitStructure);

  while (1)
  {

  	  	if(timer_update){
			timer_update=0;

			if(++ledtime > 5000){
	  			ledtime =0;
				GPIO_ToggleBits(GPIOD,GPIO_Pin_12);
				GPIOD->ODR ^= 0x0000008000;	
			}
		}

  }
}


mesaj birleştirme:: 26 Ekim 2012, 16:47:04

Gelelim kodların açıklamasına.

SystemInit() kodları , eski örneklerde kullandığımız init kodları. Buradaki tek değişiklik aşağıdaki bölümde.
RCC->AHB1ENR |= 0x00000017;     // GPIO A,B,C,D,E clock'u aktif edelim

Port D'nin clok iznini iptal ettim ki , kütüphane kodları ile nasıl açacağımızı görelim.

GPIO_InitTypeDef  GPIO_InitStructure;

GPIO_InitTypeDef  tipi kütüphanede daha önceden tanımlanmış bir tip. Biz bu tipten yeni bir değişken oluşturuyoruz.

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

Bilidiği üzere  donanımlarınregisterleri üzerinde herhangi bir işlem yapmadan önce, o dananıma saat sinyali sağlamamız gerekiyor. Bunun için RCC registerinden ilgili donanımın saat kaynağını aktif ediyoruz.

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_15;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOD, &GPIO_InitStructure);


GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_15;


Burada GPIO nun hangi pinlerini init edeceğimizi bildiriyoruz.  Dikkat edin hangi port olduğunun şimdilik bir önemi yok. Sadece hangi pinler olduğu önemli.  Sıralamanın da bir önemi yok.  biz aynı kodu
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15 | GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_12;


şeklinde de yazabilirdik.  daha fazla sayıda pini init edeceksek aralarına '|' or işareti koyarak pinlerimizi ekliyoruz.
Burada dikkat edilmesi gereken şey, init ederken yapacağımız ayarlamaların burada seçtiğimiz tüm pinler üzerinde etkili olacağıdır.
Yani  buraya girdiğimiz pinlerin bir kısmını input bir kısmını output yapamayız. Ya da bir kısmını push-pull bir kısmını open drain yapamayız.


  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

Bu kodla  seçtiğimiz pinlerin özelliklerini ayarlıyoruz.  Seçtiğimiz pinler Output olacak , PushPull olacak, 100Mhz hızında olacak, Pullup veya Pulldown olmayacak.

Artık protumuzu init edebiliriz.
GPIO_Init(GPIOD, &GPIO_InitStructure);

GPIOD portunun seçtiğimiz pinlerinin başlangıç ayarlarını yaptık.

Şimdi de portu toggle edelim.
                
GPIO_ToggleBits(GPIOD,GPIO_Pin_12);
GPIOD->ODR ^= 0x0000008000;

Üstteki satırda D portunun 12. pinini Kütüphane fonksiyonu kullanarak toggle ediyoruz.
Alttaki satırda ise D portunun 15. pinini kütüphane kullanmadan eski yöntemlerle toggle ediyoruz. 

SpeedyX

Hocam teşekkürler, basit ve kullanışlı. TI CCS kodlamasına benzettim.
Bu kütüphaneler STM32F103-107 de de kullanılabiliyor mu? Örneğin bu kütüphaneyle F407 için yazılmış bir kodu F103 için derleyebilir miyiz?

muhittin_kaplan

Hayır Olmuyor. Her Serinin Kütüphanesi Farklı.

Klein

Kütüphenyi öğrenmeye bu gün başladım. Bu yüzden kesin cevaplar veremem.
Daha önce SDM32F103 için yazılmış bir koda göz atmıştım.  Port init aynı şekilde yapılıyordu. 
Muhtemelen sadece ütüphane değiştirilerek
örn: stm32f4xx_gpio.c yerine stm32f1xx_gpio.c kullanılarak , uyumlu fonksiyonlar derlenebilir. Bu şimdilik sadece tahmin.
Birazdan bir STM32F1 kodu bulup inceleyeceğim.

muhittin_kaplan

#4
Hocam Teşekkür ederim.
Ama lütfen Hiç Bilmeyen birine anlatıyor gibi anlatınız. Keza Atladığımız Noktalar var.
1. Keil de Project Tree ye neden dosya ekleriz neden eklemeyiz ?
2. Kullandığımız Dosyalar neler yapar (örnek system_stm32f10x.)
3. Eklediğimiz Dosyalarla alakalı olarak Fonksiyon lara gidecek parametreler nelerdir, nereden öğrenilir ?

Savaşım devam edecek bu lib lerle

mesaj birleştirme:: 26 Ekim 2012, 17:20:28

http://www.st.com/internet/com/SOFTWARE_RESOURCES/SW_COMPONENT/FIRMWARE/stm32f10x_stdperiph_lib.zip

Klein

#5
Şimdi bir kod buldum.
Port init şu şekilde yapılmış

void GPIO_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  
  RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB , ENABLE); 						 
/**
 *  LED1 -> PB15 , LED2 -> PB14 , LED3 -> PB13 , LED4 -> PB12
 */					 
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 
  GPIO_Init(GPIOB, &GPIO_InitStructure);
}

Yöntem aynı.  Bazı parametrelerde farklılık var.  F4 te moder Otype registerleri ayrı olduğu için buları ayrı ayrı ayarlıyoruz.
  
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;


F1 de tek registerden ayarlanıyor.
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;


mesaj birleştirme:: 26 Ekim 2012, 17:57:17

Alıntı yapılan: muhittin_kaplan - 26 Ekim 2012, 17:14:44
Hocam Teşekkür ederim.
Ama lütfen Hiç Bilmeyen birine anlatıyor gibi anlatınız. Keza Atladığımız Noktalar var.
1. Keil de Project Tree ye neden dosya ekleriz neden eklemeyiz ?
2. Kullandığımız Dosyalar neler yapar (örnek system_stm32f10x.)
3. Eklediğimiz Dosyalarla alakalı olarak Fonksiyon lara gidecek parametreler nelerdir, nereden öğrenilir ?

Savaşım devam edecek bu lib lerle

mesaj birleştirme:: 26 Ekim 2012, 17:20:28

http://www.st.com/internet/com/SOFTWARE_RESOURCES/SW_COMPONENT/FIRMWARE/stm32f10x_stdperiph_lib.zip

1. Detaylara girdiğimizde konu çok dallanıyor. Bu yüzden soru gelmedikçeçoğumuzun bildiğini varsaydığım konuları atlıyorum. soru gelirse cevaplamaya çalışırım.
2. Bu dosyalar ne yapar  ben de bilmiyorum. İnceleme aşamasındayım. Öğrendikçe buradan anlatmaya çalışacağım.
3. Genellikle örnek kodları ve kütüphane dosyalarını inceleyerek çıkarmaya çalışıyorum. Çıkardıkça burada paylaşırım. Eğer zaman bulabilirsem derli toplu hale getirmeye çalışacağım.

X-Fi

Bende geçen haftalarda buna benzer bir döküman hazırlamıştım kendime unutmayayım diye yeni başlayanlara faydalı olabilir anlaşılmıyan biyer varsa yardımcı olurum.

http://www.coskunergan.com/wp-content/uploads/2012/10/Keil_Proje.pdf
http://www.coskunergan.dev/    (Yürümekle varılmaz, lakin varanlar yürüyenlerdir.)

memo333

Alıntı yapılan: muhittin_kaplan - 26 Ekim 2012, 17:14:44
Hocam Teşekkür ederim.
Ama lütfen Hiç Bilmeyen birine anlatıyor gibi anlatınız. Keza Atladığımız Noktalar var.
1. Keil de Project Tree ye neden dosya ekleriz neden eklemeyiz ?
2. Kullandığımız Dosyalar neler yapar (örnek system_stm32f10x.)
3. Eklediğimiz Dosyalarla alakalı olarak Fonksiyon lara gidecek parametreler nelerdir, nereden öğrenilir ?


1. Dosya eklemezseniz derlemeyi hangi dosyalarla yapacak?
2. Belirttiğiniz dosya ilk kurulum için gerekli olan SystemInit fonkisyonu var istediğiniz hızda clocku otomatik olarak set eder. Siz sadece fonksiyonu çağırırsınız. Bunun dışında clock yönetimi ile ilgili bi-iki fonk. içerir.



3. parametreler Kütüphaneyi indirdiğiniz zip dosyasının içindeki *.chm dosyasında...


---------------------------------

Klein hocam;

Clock kurulumunu ben genelde system_stm32fxxx .c dosyasındaki SystemInit fonksiyonu ile hallediyorum. Keza sizde *.s dosyasını eklediğinizde keil otomatik olarak o fonksiyonu çağıracak şekilde derliyor.

Clock değişimi yapmak istersem stm32xxx_rcc.c dosyasındaki kütüphane fonksiyonlarını da kullanabilirsiniz.

Önemli: ilgili kütüphaneyi kullanabilmek için stm32f10x_conf.h dosyasından *.h dosyasını uncomment yapmanız gerek...

Gömülü Linux Notları --> http://linuxedu.xyz/

muhittin_kaplan

#8
hocam bu cocox u bende inceliyorum. bir bilinky örneği verebilmeniz mümkün mü

mesaj birleştirme:: 26 Ekim 2012, 23:05:09

Ayrıca 1. Soruya verdiğiniz Soruya Ek Olarak

Alıntı Yap"1. Dosya eklemezseniz derlemeyi hangi dosyalarla yapacak?"
demişsiniz ama bazen oraya eklemediğimiz ama include deyimi ile main.c ye import ettiğimiz dosya da derleniyor. Ve hatta ne Project tree de nede include ile eklemeden dosya işe dahil oluyor. örneğin stm32f10x_conf.h

yani bazı olaylar havada kalıyor.

memo333

Alıntı yapılan: muhittin_kaplan - 26 Ekim 2012, 23:00:36
hocam bu cocox u bende inceliyorum. bir bilinky örneği verebilmeniz mümkün mü

mesaj birleştirme:: 26 Ekim 2012, 23:05:09

Ayrıca 1. Soruya verdiğiniz Soruya Ek Olarak
demişsiniz ama bazen oraya eklemediğimiz ama include deyimi ile main.c ye import ettiğimiz dosya da derleniyor. Ve hatta ne Project tree de nede include ile eklemeden dosya işe dahil oluyor. örneğin stm32f10x_conf.h

yani bazı olaylar havada kalıyor.

coocox'u picprojeye yaymak lazım. 2-3 aydır kullanıyorum sorunsuz... kurulumunda bir iki nokta var onları gösteren birşeyler hazırlamam lazım...

"stm32f10x_conf.h" dosyası bir yerden include ediliyordur. örneğin



diğer dosyalarda include ettiğiniz birşeylerin içinden geliyordur...
Gömülü Linux Notları --> http://linuxedu.xyz/

muhittin_kaplan

Hocam bence Buradaki Konu dağılmadan Coocox la alakalı başlık açınız. bedava Olunca Hoş Oluyor..

Klein

@muhittin.
Dosyayı #include ile eklemekle  ayrıca derlemek , yani proje yöneticisinden aklemek arasında biraz fark var.
bir dosya #include doğrudan koda bağlanırsa, tüm dosyalar include edilme sırasıyla tek bir dosya gibi derlenir.

Temsili bir anlatımla şöyle diyebiliriz: Derleme komutu verdiğimizde derleyici bir tane yeni dosya  oluşturuyor. bu dosyaya  include edilmiş tüm dosyaların kodunu yazıyor.  böylece elimizde tüm kodları hiç başka header file veya kaynak dosya kullanmadan yazmışız gibi bir kaynak kod oluyor. Derleyici bu dosyayı derleyip  hex kod oluşturuyor.

Bu dosyaları #include yerine  linker ile birleştirirsek , yani proje yönetiminden projeye eklersek, önce tüm kaynak kodlar ayrı ayrı derleniyor çıktı olarak hex yerine obje dosyası üretiliyor. Sonra link esnasında bu obje dosyaları birbirlerine bağlanarak hex dosya üretiliyor.

Peki neden #include etmek yerine link esnasında birleştiriyoruz?
Eğer proje küçükse, birkaç modülden oluşuyorsa ,  #include etmek çok sorun olmaz.  Çünkü kim kimin içinde include edilmiş, hangi sırada include edilmiş takip etmek çok zor değildir. Ama projede çok sayıda kaynak kod ve bunların arasında grift bir ilişki varsa o zaman takip zorlaşır.  Aynı dosyadaki kodları birkaç modül birden kullanması gerekir , üst satırda  #include ettiğiniz dosyadaki fonksiyonlar,alt satırda #include edilen dosyadaki fonksiyon ya da değişkenleri görmez , bunların sırasını değiştirirsiniz başkasıyla sorun yaşarsınız, bir dosyanınaynı anda birkaç modül içinde include edilmesi gerekir o zaman derlemede sıkıntı olur  vs.. vs..

Bu gibi sorunlarla uğraşmamak için proje küçük de olsa , büyük de olsa dosyaları link esnasında bağlamayı alışkanlık haline getirmekte fayda var. Hatta kullanacağınız kütüphaneleri seçip onları library haline getirip derlerseniz, kodunuzu başka makinalara veya platformlara taşımak daha da kolaylaşır.


Klein

UART KULLANIMI

#include "stm32f4_discovery.h" 

/*********************************************************************************
 CPU frekansi 168Mhz
 AHB frekansi 84 Mhz
 APB frekansi 42 Mhz
*********************************************************************************/
uint32_t ledtime=0;
uint8_t timer_update=0;


void SystemInit()
{
unsigned int i;
      for (i=0;i<0x00100000;i++);     // OSC oturtma ve kurtarma rutini
      RCC->CFGR |= 0x00009400;        // AHB ve APB hizlarini max degerlere set edelim
      RCC->CR |= 0x00010000;          // HSE Xtal osc calismaya baslasin        
      while (!(RCC->CR & 0x00020000));// Xtal osc stabil hale gelsin
      RCC->PLLCFGR = 0x07402A04;      // PLL katsayilarini M=4, N=168, P=2 ve Q=7 yapalim   168 Mhz 
      RCC->CR |= 0x01000000;          // PLL calismaya baslasin  (Rehber Sayfa 95)
      while(!(RCC->CR & 0x02000000)); // Pll hazir oluncaya kadar bekle
      FLASH->ACR = 0x00000605;        // Flash ROM icin 5 Wait state secelim ve ART yi aktif edelim (Rehber Sayfa 55)
      RCC->CFGR |= 0x00000002;        // Sistem Clk u PLL uzerinden besleyelim
      while ((RCC->CFGR & 0x0000000F) != 0x0000000A); // Besleninceye kadar bekle
      RCC->AHB1ENR |= 0x00000017;     // GPIO A,B,C,D,E clock'u aktif edelim 
	 
	 RCC->APB1ENR|=0x00000020;       // Timer7 CLK'u aktif edelim (84 Mhz)
	 TIM7->CR1=0x0080;               // Otomatik Reload
     TIM7->PSC =4199;                 // Prescaler degerimiz 839, Count frekansimiz = fCK_PSC / (Yuklenen Deger + 1) 84E6 / (840) = 100 KHz
     TIM7->ARR =1;                   // Counter, Decimal 1 olunca basa donsun. Her 20 mikrosaniye de bir timer int olusacak.
     TIM7->DIER=0x0001;              // Update Int enable
     TIM7->CR1|=0x0001;              // Counter Enable
     NVIC->ISER[1] = 0X00800000;     // NVIC de Timer 7 interrupta izin verelim
} 


 
void TIM7_IRQHandler(void)
{
TIM7->SR=0;    
timer_update=1;
}

 

void init_gpio(void){
GPIO_InitTypeDef  GPIO_InitStructure;
/*  Ledlerin bağlı olduğu port ve pinlerin başlatma işlemi */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_15;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOD, &GPIO_InitStructure);

/*  USATT3 pinlerinin başlatma işlemi */

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
  GPIO_PinAFConfig(GPIOB,10,GPIO_AF_USART3);
  GPIO_PinAFConfig(GPIOB,11,GPIO_AF_USART3);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
}

void init_usart(void){
USART_InitTypeDef USART_InitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);

  USART_InitStructure.USART_BaudRate = 19200;
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  USART_InitStructure.USART_StopBits = USART_StopBits_1;
  USART_InitStructure.USART_Parity = USART_Parity_No;
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

  USART_Init(USART3, &USART_InitStructure);

}

void SendChar(char Tx) 
{
      while(!(USART3->SR&0x80));  // TX Buffer dolu ise bekle (Rehber Sayfa 646)
      USART3->DR=Tx;
}
 
void SendTxt(char *Adr)
{
      while(*Adr) 
        {
          SendChar(*Adr);
          Adr++;
        }  
}

int main(void)
{
  init_gpio();
  init_usart();
  USART_Cmd(USART3,ENABLE);
  while (1)
  {

  	  	if(timer_update){
			timer_update=0;

			if(++ledtime > 5000){
	  			ledtime =0;
				GPIO_ToggleBits(GPIOD,GPIO_Pin_12);
				GPIOD->ODR ^= 0x0000008000;
				SendTxt("USART Test\r\0");	
			}
		}

  }
}


Kütüphane ile uart init etme. kodları.
Baud hızı seçtiğim hızın iki katı çıkıyor. Sebebini daha sonra araştırırım.
Kod açıklamaları:
/*  USATT3 pinlerinin başlatma işlemi */

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
  GPIO_PinAFConfig(GPIOB,10,GPIO_AF_USART3);
  GPIO_PinAFConfig(GPIOB,11,GPIO_AF_USART3);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOB, &GPIO_InitStructure);

Önce "RCC_AHB1PeriphClockCmd()" fonksiyonu ile, kullanacağımız seri portların bulınduğu portun veya portların saat kaynaklarını aktif ediyoruz.
"GPIO_PinAFConfig()"  fonksiyonu ile, ilgili pinleri , ilgili USART ile ilişkilendiriyoruz. Daha sonrasında işletilen komutlar , yukarıdaki port init kodları ile aynı. Tek fark modu AF seçmemiz.

Daha sonra USART ayarlamalarını yapıyoruz.
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);

  USART_InitStructure.USART_BaudRate = 19200;
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  USART_InitStructure.USART_StopBits = USART_StopBits_1;
  USART_InitStructure.USART_Parity = USART_Parity_No;
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

  USART_Init(USART3, &USART_InitStructure);


Öncelikle Kullanacağımız USART için saat kaynağını aktif ediyoruz. Daha sonra koddan da anlaşılacağı üzere, baud, bit sayısı, Flow kontrol vs... özellikleri ayarlıyoruz.

USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

Bu kod RX ve TX enable kodu. Eğer Sadece TX yapacak RX yapmayacaksak buraya sadece USART_Mode_Tx yazıyoruz.

Son olarak da
USART_Cmd(USART3,ENABLE); ile USART'ı aktif ediyoruz. Eğer kapatmak istersek USART_Cmd(USART3,DISABLE);  yapıyoruz.

SpeedyX

Sıradaki örnek ADC ve DAC ile alakalı olursa seviniriz :)
Bu lib lerle çalışmak işi çok kolaylaştırıyor anlaşılan...

Klein

Usart örneğinde baud hızı istediğimizin iki katı çıkıyordu.
Sorun "stm32f4xx.h" dosyasındaki bir satırdan kaynaklanıyor. Baud hızı hesaplayan rutin , bu değeri kullanıyor. Bu değer devreye takılı kristalimizin frekansı. Stm32f4Discovery örneklerinde default 4000000 geliyor. Bazı kütüphanelerde 25000000 geliyor.  Biz bu değeri kendi kristal frekansımız ile değiştiriyoruz. Stm32F4 kitinin kristal frekansı 8MHz. Bu değeri 8000000 yapıyoruz.

#if !defined  (HSE_VALUE) 
  #define HSE_VALUE    ((uint32_t)4000000) /*!< Value of the External oscillator in Hz */
#endif /* HSE_VALUE */


#if !defined  (HSE_VALUE) 
  #define HSE_VALUE    ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */
#endif /* HSE_VALUE */