#include "stm32f30x.h" void dac_init(void); void init_tim7(void); #define SAMPLES sizeof(wave)/sizeof(wave[0]) uint32_t wave[]={0xfff<<16 | 0, 0<<16 | 0xfff}; // "step" impulz (od nuly do maxima a zpět) #define DAC_DATA_REG &(DAC1->DHR12RD) int main(void){ SystemCoreClockUpdate(); // 72 MHz dac_init(); init_tim7(); // trigger pro DAC DMA_Cmd(DMA1_Channel4, ENABLE); // spustíme DMA DAC_DMACmd(DAC1,DAC_Channel_2,ENABLE); // povolíme DAC posílat requesty do DMA TIM_Cmd(TIM7, ENABLE); // spustit TIM7 - rozběh waveformy while(1){ PWR_EnterSleepMode(PWR_SLEEPEntry_WFI); // tady už není co dělat, tak jdeme spát } } void init_tim7(void){ TIM_TimeBaseInitTypeDef tim; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE); tim.TIM_Prescaler = 9; // 1MHz / 10 = 100kHz (T=10us) tim.TIM_Period = 71; // 72MHz / 72 = 1MHz tim.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM7, &tim); // výstup timeru (TRGO) je update událost (přetečení), signál jde pak jako trigger do DAC TIM_SelectOutputTrigger(TIM7,TIM_TRGOSource_Update); } void dac_init(void){ GPIO_InitTypeDef gp; DAC_InitTypeDef dac; DMA_InitTypeDef dma; // zapnout GPIOA, DAC1, SYSCFG a DMA1 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_DMA1, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC1, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); // kvůli remapu DMA requestů // PA4,5,6 výstupy DAC1 a DAC2 (nepoužíváme všechny) gp.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6; gp.GPIO_Mode = GPIO_Mode_AN; gp.GPIO_OType = GPIO_OType_PP; gp.GPIO_PuPd = GPIO_PuPd_NOPULL; gp.GPIO_Speed = GPIO_Speed_Level_1; GPIO_Init(GPIOA, &gp); /* Pozor ať vás nemate "buffer switch" - název implikuje že funkce zapíná nebo vypíná buffer, to ale není úplně pravda * pro DAC1_OUT1 (PA4) má buffer a switch_enable ho "vypíná" (matoucí že :D) * pro DAC2_OUT1 (PA6) tato funkce pouze připojuje/odpojuje výstup DAC na pin ... žádný buffer na něm není ! * pro DAC1_OUT2 (PA5) tato funkce pouze připojuje/odpojuje výstup DAC na pin ... žádný buffer na něm není ! * * pro DAC1_OUT1: * - "Switch_Disable" = buffer je zapnutý :D * - "Switch_Enable" = buffer vypnutý :D * pro zbylé kanály (DAC1_OUT2 a DAC2_OUT1): * - "Switch_Disable" = výstup DAC je odpojený od pinu (PAx) * - "Switch_Enable" = výstup DAC je připojený k pinu (PAx) */ dac.DAC_Buffer_Switch = DAC_BufferSwitch_Disable; // Zapnout (nevypnout) DAC1_OT1 buffer dac.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0; dac.DAC_Trigger = DAC_Trigger_T7_TRGO; // převod spouští TRGO signál z TIM7 dac.DAC_WaveGeneration = DAC_WaveGeneration_None; DAC_Init(DAC1,DAC_Channel_1,&dac); // nastavit konfiguraci DAC1_OUT1 dac.DAC_Buffer_Switch = DAC_BufferSwitch_Enable; // Zapnout na PA5 Výstup DAC1_OUT2 (buffer nemá) dac.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0; dac.DAC_Trigger = DAC_Trigger_T7_TRGO; // převod spouští TRGO signál z TIM7 dac.DAC_WaveGeneration = DAC_WaveGeneration_None; DAC_Init(DAC1,DAC_Channel_2,&dac); // nastavit konfiguraci DAC1_OUT2 // konfigurace DMA dma.DMA_BufferSize = SAMPLES; // počet vzorků generovaného průběhu dma.DMA_DIR = DMA_DIR_PeripheralDST; // data tečou do periferie dma.DMA_M2M = DMA_M2M_Disable; // přesno paměť-paměť nechceme dma.DMA_MemoryBaseAddr = (uint32_t)wave; // pole se hodnotami pro DAC dma.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; // přenášíme 32bit (data do obou kanálů DAC) dma.DMA_MemoryInc = DMA_MemoryInc_Enable; dma.DMA_Mode = DMA_Mode_Circular; // generovat stále dokola dma.DMA_PeripheralBaseAddr = (uint32_t)DAC_DATA_REG; // do tohoto registru zapisovat data pro DAC dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; // přenášíme 32bit (data do obou kanálů DAC) dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable; dma.DMA_Priority = DMA_Priority_High; DMA_Init(DMA1_Channel4, &dma); // channel 4 jsou requesty od DAC1 channel 2 // hnusný podraz, DAC1 ch2 requesty je potřeba remapovat aby vedly do DMA1Ch4 (ačkoli jiné DMA nemáme :D ) SYSCFG_DMAChannelRemapConfig(SYSCFG_DMARemap_TIM7DAC1Ch2, ENABLE); // spustit obě DAC DAC_Cmd(DAC1,DAC_Channel_1,ENABLE); DAC_Cmd(DAC1,DAC_Channel_2,ENABLE); }