#include "init.h" // Прямой адрес регистра данных ЦАП (12 бит, правое выравнивание, канал 1) #define DAC_DHR12R1_ADDR 0x40007408 // Инициализация светодиода для индикации void LEDs_ini(void) { GPIO_InitTypeDef GPIO_Init_LED; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); GPIO_Init_LED.GPIO_Pin = GPIO_Pin_12; GPIO_Init_LED.GPIO_Mode = GPIO_Mode_OUT; GPIO_Init_LED.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init_LED.GPIO_OType = GPIO_OType_PP; GPIO_Init_LED.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOD, &GPIO_Init_LED); } // PA4 - Выход ЦАП void GPIO_Ini(void) { GPIO_InitTypeDef gpio; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); gpio.GPIO_Pin = GPIO_Pin_4; gpio.GPIO_Mode = GPIO_Mode_AN; // Аналоговый вход/выход gpio.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOA, &gpio); } // Таймер 6 (специально для ЦАП) или Таймер 2 // Используем TIM2, он надежнее на всех платах void TIM_Ini(void) { TIM_TimeBaseInitTypeDef tim; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); TIM_TimeBaseStructInit(&tim); tim.TIM_Prescaler = 0; // Период = 4200. При частоте шины 84МГц, частота выборки = 20 кГц. // Это даст очень стабильную картинку. tim.TIM_Period = 210 - 1; tim.TIM_ClockDivision = TIM_CKD_DIV1; tim.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &tim); // Триггер на обновление (TRGO) TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update); TIM_Cmd(TIM2, ENABLE); } // Настройка ЦАП void DAC_Ini(void) { DAC_InitTypeDef dac; RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE); dac.DAC_Trigger = DAC_Trigger_T2_TRGO; // Запуск от TIM2 dac.DAC_WaveGeneration = DAC_WaveGeneration_None; dac.DAC_OutputBuffer = DAC_OutputBuffer_Enable; dac.DAC_LFSRUnmask_TriangleAmplitude = DAC_TriangleAmplitude_4095; // Не используется, но инициализируем DAC_Init(DAC_Channel_1, &dac); DAC_Cmd(DAC_Channel_1, ENABLE); // Разрешаем DMA запросы от ЦАП DAC_DMACmd(DAC_Channel_1, ENABLE); } // Настройка DMA void DMA_Ini(uint16_t *buffer, uint32_t size) { DMA_InitTypeDef dma; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE); // Сброс настроек потока (Stream 5 Channel 7 = DAC1) DMA_DeInit(DMA1_Stream5); dma.DMA_Channel = DMA_Channel_7; dma.DMA_PeripheralBaseAddr = (uint32_t)DAC_DHR12R1_ADDR; // Прямой адрес dma.DMA_Memory0BaseAddr = (uint32_t)buffer; dma.DMA_DIR = DMA_DIR_MemoryToPeripheral; dma.DMA_BufferSize = size; dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // ЦАП на месте dma.DMA_MemoryInc = DMA_MemoryInc_Enable; // Массив листаем // ВАЖНО: Работаем с 16-битными данными (HalfWord) dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; dma.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; dma.DMA_Mode = DMA_Mode_Circular; // Бесконечный цикл dma.DMA_Priority = DMA_Priority_High; dma.DMA_FIFOMode = DMA_FIFOMode_Disable; dma.DMA_MemoryBurst = DMA_MemoryBurst_Single; dma.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_Init(DMA1_Stream5, &dma); DMA_Cmd(DMA1_Stream5, ENABLE); }