Picproje Elektronik Sitesi

PICPROJE PROGRAMLAMA DERSLERİ => STM32 Örnekleri => Konuyu başlatan: cesimkaol - 20 Ekim 2014, 23:42:58

Başlık: STM32F051_DMA_NORMAL_MOD_USART_Örneği
Gönderen: cesimkaol - 20 Ekim 2014, 23:42:58
//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.
Başlık: Ynt: STM32F051_DMA_NORMAL_MOD_USART_Örneği
Gönderen: Gökhan BEKEN - 20 Ekim 2014, 23:54:14
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.
Başlık: Ynt: STM32F051_DMA_NORMAL_MOD_USART_Örneği
Gönderen: quarko - 21 Ekim 2014, 08:48:43
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.