środa, 30 marca 2016

[10b] STM32F4 - Discovery - DAC, generacja szumu białego

W tym poście chciałbym przedstawić sposób generacji szumu białego z wykorzystaniem konwertera cyfrowo analogowego.

Teoria


Do generacji pseudolosowego szumu wykorzystywany jest jego generator. W tym celu udostępniono rejestr LFSR (ang. linear feedback shift register). Zostaje on wybrany poprzez ustawienie rejestru WAVEx[1:0] na 01. Wartość automatycznie umieszczona w LFSR wynosi 0xAAAA.

Rejestr jest odświeżany co trzy cykle zegara APB1, po każdy zdarzeniu, które wywoła jego wyzwolenie. Proces odbywa się w oparciu o odpowiedni algorytm wyliczeniowy. 

Rys. 1. Rejestr LFSR, schemat algorytmu obliczeniowego



Wartości umieszczone w rejestrze mogą zostać odpowiednio zamaskowane wykorzystując bity MAMPx[3:0] w rejestrze kontrolnym. Jest ona dodawana do rejestru DHR, który przechowuje nie przetworzone dane. Informacja jest ostatecznie przechowywana w rejestrze DOR.

Aby włączyć generator należy pamiętać o włączeniu triggera przez ustawienie bitu TENx w rejestrze DAC_CR.

Rys. 2. Rejestr DAC_CR

Cyfry na końcach nazw rejestrów oznaczają do którego DAC-a należą ustawienia, czy do pierwszego czy do drugiego.

DMAUDRIE - tryb sprawdzenia wystąpienia przerwania

0 - tryb włączony
1 - tryb wyłączony

DMAEN - włączenie lub wyłączenie trybu DMA dla DAC

0 - wyłączony
1 - włączony

MAMP - do wyboru maski przy generatorze szumu lub amplitudy dla sygnału trójkątnego

0000 - Bez maski bit 0 LFSR, amplituda sygnału trójkątnego wynosi 1
0001 - Bez maski bit [1:0] LFSR, amplituda sygnału trójkątnego wynosi 3
0010 - Bez maski bit [2:0] LFSR, amplituda sygnału trójkątnego wynosi 7
0011 - Bez maski bit [3:0] LFSR, amplituda sygnału trójkątnego wynosi 15
0100 - Bez maski bit [4:0] LFSR, amplituda sygnału trójkątnego wynosi 31
0101 - Bez maski bit [5:0] LFSR, amplituda sygnału trójkątnego wynosi 63
0110 - Bez maski bit [6:0] LFSR, amplituda sygnału trójkątnego wynosi 127
0111 - Bez maski bit [7:0] LFSR, amplituda sygnału trójkątnego wynosi 255
1000 - Bez maski bit [8:0] LFSR, amplituda sygnału trójkątnego wynosi 511
1001 - Bez maski bit [9:0] LFSR, amplituda sygnału trójkątnego wynosi 1023
1010 - Bez maski bit [10:0] LFSR, amplituda sygnału trójkątnego wynosi 2047
ponad 1011 - Bez maski bit [11:0] LFSR, amplituda sygnału trójkątnego wynosi 4095

WAVE - uruchomienie generatora szumu bądź sygnału trójkątnego

00 - wyłączenie sygnału
01 - włączenie generatora szumu
1x - włączenie sygnału trójkątnego

TSEL - Służy do ustawiania sposobu wyzwania. Do dyspozycji są trzy bity można je wprowadzić następująco:

000 - Zdarzenie z Timera 6 
001 - Zarezerwowane
010 - Zdarzenie z Timera 7
011 - Zdarzenie z Timera 9
100 - Zdarzenie z Timera 2
101 - Zdarzenie z Timera 4
110 - Przerwanie z line 9
111 - Wyzwalanie programowe

TEN - Służy do ustawiania bądź wyłączania wyzwalania DAC-a

0 - wylaczenie wyzwalania, dane przesyłane są z DHR do DOR w jednym cyklu APB1
1 - włączenie wyzwalania, dane przesyłane z DHR do DOR w trzech cyklach APB1

BOFF - włączania bądź wyłączanie buforu wyjściowego

0 - włączenie bufora wyjściowego
1 - wyłączenie bufora wyjściowego

EN - włączenie bądź wyłączenie DAC-a

0 - wyłączenie DAC
1 - włączenie DAC

Programowanie


Poniżej przedstawię sposób generacji sygnału dla DAC1. Wykorzystywany jest wewnętrzny generator przez co nie ma potrzeby wykorzystywania DMA. Wystarczy odpowiednia konfiguracja GPIO oraz DAC.

  1. void DAC1Init_NoiseGeneration()
  2. {
  3.     DAC_InitTypeDef DACInit;
  4.     GPIO_InitTypeDef GPIOInit;  
  5.     DMA_InitTypeDef DMAInit;
  6.  
  7.     //Wlaczenie zegara dla portu GPIOA
  8.     //RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
  9.     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
  10.    
  11.     //Wlaczenie zegara dla DAC
  12.     //RCC->APB1ENR |= RCC_APB1ENR_DACEN;
  13.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
  14.    
  15.     //Pozostale ustawienia wyprowadzen GPIO
  16.     GPIOInit.GPIO_Pin = GPIO_Pin_4;
  17.     GPIOInit.GPIO_Mode = GPIO_Mode_AN;
  18.     GPIOInit.GPIO_OType = GPIO_OType_PP;
  19.     GPIOInit.GPIO_PuPd = GPIO_PuPd_NOPULL;
  20.     GPIOInit.GPIO_Speed = GPIO_Speed_50MHz;
  21.     GPIO_Init(GPIOA, &GPIOInit);
  22.    
  23.     //Ustawienie opcji dla DAC
  24.     //Sygnal wyzwalajacy
  25.     DACInit.DAC_Trigger = DAC_Trigger_Software;
  26.     //Generacja sygnalu wylaczona
  27.     DACInit.DAC_WaveGeneration = DAC_WaveGeneration_Noise;
  28.     //Bufor wyjsciowy wlaczony
  29.     DACInit.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
  30.     //0x3FF - 1111111111
  31.     DACInit.DAC_LFSRUnmask_TriangleAmplitude = 0x3FF;
  32.     DAC_Init(DAC_Channel_1, &DACInit);
  33.    
  34.     //Wlaczenie DAC-a
  35.     DAC_Cmd(DAC_Channel_1, ENABLE);
  36.     DAC_DMACmd(DAC_Channel_1, ENABLE);
  37.    
  38.     //Inicjacja i wlaczenie wybranego pinu DAC
  39.     DAC_Init(DAC_Channel_1, &DACInit);
  40. }

Po takiej inicjacji i po wywołaniu funkcji sygnał szumu zostaje przekazany na wyjście PA4.