STM32F051_DMA_NORMAL_MOD_USART_Örneği

Başlatan cesimkaol, 20 Ekim 2014, 23:42:58

cesimkaol

//Bu uygulama Standart Peripheral Kullanılarak yapılmıştır , Uygulama Keil ortamında geliştirilmiştir.
//DMA Normal Mode yani USART modülü dma request gönderir . DMA data transmit işlemini bitirir  ve interrupt üretilir.
//Normal modda DMA data count registeri her bir transmit işleminden sonra  tekrar  yüklenmelidir.
//STM32f051 üzerindeki C portuna bağlı pin de test amaçlı kullanılmıştır.

#include "main.h"
#include "stm32f0xx_gpio.h"
#include "stm32f0xx_usart.h"
#include "stm32f0xx_dma.h"

GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitTypeDef GPIO_InitStructureUSART;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitTypeDef NVIC_InitStructureUSART;
DMA_InitTypeDef DMA_InitStructure;

volatile char Buffer[] = "Ne mutlu Türküm diyene!\r\n";
 
void DMA_Configuration(void)
{ 
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // DMA için clock aktif edildi.
  DMA_DeInit(DMA1_Channel2);  //Reference manual'den bakılır ise USART1 DMA1 channel2 üzerinde belirtilmiş.
 
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->TDR;  //Dataların yazılaccağı hedef register(Transmit Data Reg.'in adresi)
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Buffer; //Dataların alınacağı source arrayın adresi
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //Memory'den peripherale data iletileceği için peripheral destination.
  DMA_InitStructure.DMA_BufferSize = sizeof(Buffer) - 1; // toplam iletilecek datanın boyutu , her bir kesmede güncellenecek.
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //Peripheral'e data yazacağımız için, TDR'inin adresi sabit olacak bu yüzden disable
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //Memory'den okuyacağız her bir byte'data iletiminden sonra bir sonraki için artış enable
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //Yazılacak datalar byte büyüklüğünde yazılacak
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;  // Okunacak datalar sırayla byte büyüklüğünde okunacak
  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //Tek çevirim, tüm datalar iletilecek ve DMA transmit int. üretilecek. 
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;  
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //Mem'den Mem'e olmadığı için disable
  
	
	NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_3_IRQn;  //DMA'transmit işlemi bitince Channel2 ve 3 için ortak kesme aktif ediliyor.
	NVIC_InitStructure.NVIC_IRQChannelPriority = 0x01;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
		
	DMA_Init(DMA1_Channel2, &DMA_InitStructure);  //DMA Modülü belirtilen parametreler ile init ediliyor.

  DMA_ITConfig(DMA1_Channel2, DMA_IT_TC, ENABLE);  //DMA için transmit complete kesmesi aktif ediliyor.
  DMA_Cmd(DMA1_Channel2, ENABLE);  //DMA modülünün control registerinin sfırıncı biti set edilerek çalıştırılıyor .
  //Yukarda işlem başlatıldığında DMA USart'dan request bekler duruma geçiyor.

}

void GPIO_Configuration(void)
{
	//Aşağıda led için gerekli config var (Test amaçlı) :)
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
	
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;
	GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8;
	GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOC,&GPIO_InitStructure);	

}
void USART_Configuration(void)
{    
  /* USART1 için GPIOA clock'u açılıyor */
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
 
  /*USART1 için clock açılıyor  */
    RCC_APB2PeriphClockCmd(RCC_APB2ENR_USART1EN, ENABLE);	
	
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1);  //USART1 GPIOA'nın pin9 ve10'da altarnatif fonksiton olduğu için AF reisterlarında set ediliyor.
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);	  
		
   	GPIO_InitStructureUSART.GPIO_Mode=GPIO_Mode_AF; //Pin configi yapılıyor 
	GPIO_InitStructureUSART.GPIO_Pin=GPIO_Pin_9|GPIO_Pin_10;	      
	GPIO_InitStructureUSART.GPIO_PuPd=GPIO_PuPd_UP;	
	 GPIO_InitStructureUSART.GPIO_Speed=GPIO_Speed_50MHz;		
	 GPIO_Init(GPIOA,&GPIO_InitStructureUSART);	
	
    USART_InitStructure.USART_BaudRate = 9600;    //USART1 için ayarlamalar yapılıyor.
    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_Tx|USART_Mode_Rx;
   
		
	  NVIC_InitStructureUSART.NVIC_IRQChannel = USART1_IRQn; //USART 1 için interrupt ayarları yapılıyor
	  NVIC_InitStructureUSART.NVIC_IRQChannelPriority = 0x00;
	  NVIC_InitStructureUSART.NVIC_IRQChannelCmd = ENABLE;
	  NVIC_Init(&NVIC_InitStructureUSART);		
   
         USART_Init(USART1, &USART_InitStructure);	 //USART1 yukarda verilen parametrelere göre llklendiriliyor.
         	 
        USART_Cmd(USART1, ENABLE); // control registerinin 0.biti set edilerek USART1 başlatılıyor.
        USART_ITConfig(USART1,USART_IT_TC,ENABLE); //Transmit complete kesmesi aktif ediliyor.
        USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE); // USART1 tarafından DMA'ye  talep(in english request) gönderiliyor.
		 
}
 
void delay()
{
						int j=1000000;
						while(j>0)
						{
							--j;
						}	
}

int main(void)
{
	
  
	GPIO_Configuration();	 //LED için ayarlama
	GPIO_WriteBit(GPIOC,GPIO_Pin_8,Bit_SET);	 //LEdi yak
	delay(); //Bekle
	GPIO_WriteBit(GPIOC,GPIO_Pin_8,Bit_RESET);	//LEdi sondür
	DMA_Configuration(); //DMA ayarları 
	USART_Configuration();		 //USART1 ayarları
	
	while(1)
	{
	
	}
}

void USART1_IRQHandler(void)
{
	if (USART_GetITStatus(USART1, USART_IT_TC) == SET) //USART transmit compelete kesmesi
  {
    /* Clear The USART TC flag */
    USART_ClearITPendingBit(USART1, USART_IT_TC);   //Transmit complete bayrağı temizleniyor
		while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET){}				//Transmit buffer'ı boş olana kadar bekleniyor.
  }
}

void DMA1_Channel2_3_IRQHandler(void) // USART1_TX
{
   //DMA channel ikide transmit complete kesmesi olup olmadığı kontrol ediliyor.
  if (DMA_GetITStatus(DMA1_IT_TC2))
  {
		GPIO_WriteBit(GPIOC,GPIO_Pin_8,Bit_SET);  // her bir transmit complete işlemi sonrası led yakılıyor ve söndürülüyor.
		delay();
		GPIO_WriteBit(GPIOC,GPIO_Pin_8,Bit_RESET);
                      		
		DMA_ClearITPendingBit(DMA1_IT_TC2);		//interrupt bayrağı siliniyor.
		
                                //Normal Modda DMA çalıştırılırken her bir transfer complete sonrası yeniden gönderilecek datanın saysının girilmesi gerekiyor.Bunu yapmak için de ilk önce Kanalın disable edilmesi gerekiyor.
//Circular modda aşağıda yağıtığımız işlemleri yapmaya gerek yok.
//Reference manuel bknz.
                                DMA_Cmd(DMA1_Channel2, DISABLE);  
		//Kanal disable edildikten sonra number of transmit giriliyor
                                DMA_InitStructure.DMA_BufferSize = sizeof(Buffer) - 1;
                                //DMA yeniden init ediliyor.  
		DMA_Init(DMA1_Channel2, &DMA_InitStructure);  	
                                //DMA aktif edilerek USART'tan request gönderiliyor.
		DMA_Cmd(DMA1_Channel2, ENABLE);	
                                //USART üzerinden DMA'ya request gönderiliyor.
		USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
  }
}

Proje dosyası istenildiği takdir de keil için  .rar olarak gönderilebilir.
A.Cesim

Gökhan BEKEN

#1
Paylaşımınız için teşekkürler, kodları [ code ] [ / code ] tagları(boşluklar olmadan) arasına alırsanız daha okunaklı olur
ve .rar'lı dosyayı göndermek yerine github'a atabilirseniz(bana yollarsanız ben de yükleyebilirim) daha kalıcı olur.
Özel mesaj okumuyorum, lütfen göndermeyin.

quarko

Normal modda değilde, circular modda kullanırsanız tek tek değilde verilerinizi bütün olarak gönderebilirsiniz. Tamamı gönderildikten sonrada, DMA kesmesi alabilirsiniz.
"Aslanlar kendi hikayelerini yazmadıkça, avcıların kahramanlık hikayelerini dinlemek zorundayız."