STM32-ПДП+ЦАП+ЦАП

19 Апреля 2011 К комментариям

Касательно вопросов о генерировании сигналов сразу с двух ЦАП, возможны несколько решений. Рассмотрим три:

  • синхронная работа двух ЦАП с одной таблицей данных
  • синхронная работу двух ЦАП с двумя таблицами данных
  • “асинхронная” работа двух ЦАП с двумя таблицами данных
  • </ul> Синхронная работа двух ЦАП с одной таблицей данных В данном режиме значение на выходе обоих ЦАП устанавливается синхронно, по сигналу от одного таймера. Данные содержатся в одном массиве. Для работы необходим один канал ПДП. Исходный код:
    const uint32_t sinus_12bit[] =
    { 0 | 3968 << 16, 128 | 3840 << 16, 256 | 3712 << 16, 384 | 3584 << 16, 512
    		| 3456 << 16, 640 | 3328 << 16, 768 | 3200 << 16, 896 | 3072 << 16,
    		1024 | 2944 << 16, 1152 | 2816 << 16, 1280 | 2688 << 16, 1408 | 2560
    				<< 16, 1536 | 2432 << 16, 1664 | 2304 << 16, 1792 | 2176 << 16,
    		1920 | 2048 << 16, 2048 | 1920 << 16, 2176 | 1792 << 16, 2304 | 1664
    				<< 16, 2432 | 1536 << 16, 2560 | 1408 << 16, 2688 | 1280 << 16,
    		2816 | 1152 << 16, 2944 | 1024 << 16, 3072 | 896 << 16, 3200 | 768
    				<< 16, 3328 | 640 << 16, 3456 | 512 << 16, 3584 | 384 << 16,
    		3712 | 256 << 16, 3840 | 128 << 16, 3968 | 0 << 16 };
    
    //------------------------------------------------------------------------------
    int main(void)
    {
    	DAC_InitTypeDef DAC_InitStructure;
    	DMA_InitTypeDef DMA_InitStructure;
    	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    
    	// инициализируем систему тактирования
    	RCC_Configuration();
    
    	// настраиваем линии ввода-вывода
    	PIN_CONFIGURATION(DAC1_OUTPUT);
    	PIN_CONFIGURATION(DAC2_OUTPUT);
    
    	// конфигурируем таймер 7
    	TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
    	TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
    	TIM_TimeBaseStructure.TIM_Period = 0x300;
    	TIM_TimeBaseStructure.TIM_Prescaler = 0;
    	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    	TIM_TimeBaseInit(TIM7, &TIM_TimeBaseStructure);
    
    	TIM_SelectOutputTrigger(TIM7, TIM_TRGOSource_Update);
    
    	// конфигурируем ПДП1 канал 3
    	DMA_DeInit(DMA1_Channel3);
    	DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) & DAC->DHR12RD;
    	DMA_InitStructure.DMA_MemoryBaseAddr = (u32) &sinus_12bit;
    	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
    	DMA_InitStructure.DMA_BufferSize = ARRAY_LENGHT(sinus_12bit);
    	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
    	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
    	DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
    	DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    	DMA_Init(DMA1_Channel3, &DMA_InitStructure);
    
    	DMA_Cmd(DMA1_Channel3, ENABLE);
    
    	// конфигурируем ЦАП
    	DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = 0;
    	DAC_InitStructure.DAC_Trigger = DAC_Trigger_T7_TRGO;
    	DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
    	DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;
    	DAC_Init(DAC_Channel_1, &DAC_InitStructure);
    	DAC_Init(DAC_Channel_2, &DAC_InitStructure);
    
    	DAC_Cmd(DAC_Channel_1, ENABLE);
    	DAC_Cmd(DAC_Channel_2, ENABLE);
    
    	DAC_DMACmd(DAC_Channel_1, ENABLE);
    
    	// разрешаем работу таймера 7
    	TIM_Cmd(TIM7, ENABLE);
    
    	while (1)
    	{
    	}
    
    	return 0;
    }
    Синхронная работа двух ЦАП с двумя таблицами данных В данном режиме значение на выходе обоих ЦАП устанавливается синхронно, по сигналу от одного таймера. Данные содержатся в двух массивах (могут иметь разный размер). Для работы необходимо два канала ПДП. Исходный код:
    const uint16_t table_dac1_12bit[] =
    { 0, 128, 256, 384, 512, 640, 768, 896, 1024, 1152, 1280, 1408, 1536, 1664,
    		1792, 1920, 2048, 2176, 2304, 2432, 2560, 2688, 2816, 2944, 3072, 3200,
    		3328, 3456, 3584, 3712, 3840, 3968 };
    
    const uint16_t table_dac2_12bit[] =
    { 2432, 2304, 2176, 2048, 1920, 1792, 1664, 1536, 1408, 1280, 1152, 1024, 896,
    		768, 640, 512, 384, 256, 128, 0 };
    
    //------------------------------------------------------------------------------
    int main(void)
    {
    	DAC_InitTypeDef DAC_InitStructure;
    	DMA_InitTypeDef DMA_InitStructure;
    	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    
    	// инициализируем систему тактирования
    	RCC_Configuration();
    
    	// настраиваем линии ввода-вывода
    	PIN_CONFIGURATION(DAC1_OUTPUT);
    	PIN_CONFIGURATION(DAC2_OUTPUT);
    
    	// конфигурируем таймер 7
    	TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
    	TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
    	TIM_TimeBaseStructure.TIM_Period = 0x300;
    	TIM_TimeBaseStructure.TIM_Prescaler = 0;
    	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    	TIM_TimeBaseInit(TIM7, &TIM_TimeBaseStructure);
    
    	TIM_SelectOutputTrigger(TIM7, TIM_TRGOSource_Update);
    
    	// конфигурируем ПДП1 канал 3
    	DMA_DeInit(DMA1_Channel3);
    	DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) & DAC->DHR12R1;
    	DMA_InitStructure.DMA_MemoryBaseAddr = (u32) &table_dac1_12bit;
    	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
    	DMA_InitStructure.DMA_BufferSize = ARRAY_LENGHT(table_dac1_12bit);
    	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
    	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
    	DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
    	DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    	DMA_Init(DMA1_Channel3, &DMA_InitStructure);
    
    	DMA_Cmd(DMA1_Channel3, ENABLE);
    
    	// конфигурируем ПДП1 канал 4
    	DMA_DeInit(DMA1_Channel4);
    	DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) & DAC->DHR12R2;
    	DMA_InitStructure.DMA_MemoryBaseAddr = (u32) &table_dac2_12bit;
    	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
    	DMA_InitStructure.DMA_BufferSize = ARRAY_LENGHT(table_dac2_12bit);
    	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
    	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
    	DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
    	DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    	DMA_Init(DMA1_Channel4, &DMA_InitStructure);
    
    	DMA_Cmd(DMA1_Channel4, ENABLE);
    
    	// конфигурируем ЦАП
    	DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = 0;
    	DAC_InitStructure.DAC_Trigger = DAC_Trigger_T7_TRGO;
    	DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
    	DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;
    	DAC_Init(DAC_Channel_1, &DAC_InitStructure);
    	DAC_Init(DAC_Channel_2, &DAC_InitStructure);
    
    	DAC_Cmd(DAC_Channel_1, ENABLE);
    	DAC_Cmd(DAC_Channel_2, ENABLE);
    
    	DAC_DMACmd(DAC_Channel_1, ENABLE);
    	DAC_DMACmd(DAC_Channel_2, ENABLE);
    
    	// разрешаем работу таймера 7
    	TIM_Cmd(TIM7, ENABLE);
    
    	while (1)
    	{
    	}
    
    	return 0;
    }
    Синхронная работа двух ЦАП с двумя таблицами данных В данном режиме значение на выходе обоих ЦАП устанавливается “асинхронно”, по сигналам от двух таймеров. Данные содержатся в двух массивах (могут иметь разный размер). Для работы необходимо два канала ПДП. Исходный код:
    const uint16_t table_dac1_12bit[] =
    { 0, 128, 256, 384, 512, 640, 768, 896, 1024, 1152, 1280, 1408, 1536, 1664,
    		1792, 1920, 2048, 2176, 2304, 2432, 2560, 2688, 2816, 2944, 3072, 3200,
    		3328, 3456, 3584, 3712, 3840, 3968 };
    
    const uint16_t table_dac2_12bit[] =
    { 1920, 1792, 1664, 1536, 1408, 1280, 1152, 1024, 896, 768, 640, 512, 384, 256,
    		128, 0 };
    
    //------------------------------------------------------------------------------
    int main(void)
    {
    	DAC_InitTypeDef DAC_InitStructure;
    	DMA_InitTypeDef DMA_InitStructure;
    	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    
    	// инициализируем систему тактирования
    	RCC_Configuration();
    
    	// настраиваем линии ввода-вывода
    	PIN_CONFIGURATION(DAC1_OUTPUT);
    	PIN_CONFIGURATION(DAC2_OUTPUT);
    
    	// конфигурируем таймер 7 и 6
    	TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
    	TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
    	TIM_TimeBaseStructure.TIM_Period = 0x300;
    	TIM_TimeBaseStructure.TIM_Prescaler = 0;
    	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    	TIM_TimeBaseInit(TIM7, &TIM_TimeBaseStructure);
    	TIM_TimeBaseStructure.TIM_Period = 0x600;
    	TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);
    
    	TIM_SelectOutputTrigger(TIM6, TIM_TRGOSource_Update);
    	TIM_SelectOutputTrigger(TIM7, TIM_TRGOSource_Update);
    
    	// конфигурируем ПДП1 канал 3
    	DMA_DeInit(DMA1_Channel3);
    	DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) & DAC->DHR12R1;
    	DMA_InitStructure.DMA_MemoryBaseAddr = (u32) &table_dac1_12bit;
    	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
    	DMA_InitStructure.DMA_BufferSize = ARRAY_LENGHT(table_dac1_12bit);
    	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
    	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
    	DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
    	DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    	DMA_Init(DMA1_Channel3, &DMA_InitStructure);
    
    	DMA_Cmd(DMA1_Channel3, ENABLE);
    
    	// конфигурируем ПДП1 канал 4
    	DMA_DeInit(DMA1_Channel4);
    	DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) & DAC->DHR12R2;
    	DMA_InitStructure.DMA_MemoryBaseAddr = (u32) &table_dac2_12bit;
    	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
    	DMA_InitStructure.DMA_BufferSize = ARRAY_LENGHT(table_dac2_12bit);
    	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
    	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
    	DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
    	DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    	DMA_Init(DMA1_Channel4, &DMA_InitStructure);
    
    	DMA_Cmd(DMA1_Channel4, ENABLE);
    
    	// конфигурируем ЦАП
    	DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = 0;
    	DAC_InitStructure.DAC_Trigger = DAC_Trigger_T7_TRGO;
    	DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
    	DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;
    	DAC_Init(DAC_Channel_1, &DAC_InitStructure);
    	DAC_InitStructure.DAC_Trigger = DAC_Trigger_T6_TRGO;
    	DAC_Init(DAC_Channel_2, &DAC_InitStructure);
    
    	DAC_Cmd(DAC_Channel_1, ENABLE);
    	DAC_Cmd(DAC_Channel_2, ENABLE);
    
    	DAC_DMACmd(DAC_Channel_1, ENABLE);
    	DAC_DMACmd(DAC_Channel_2, ENABLE);
    
    	// разрешаем работу таймера 7
    	TIM_Cmd(TIM7, ENABLE);
    	TIM_Cmd(TIM6, ENABLE);
    
    	while (1)
    	{
    	}
    
    	return 0;
    }
    Необходимо так же разрешить тактирование таймера 6
    	RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC | RCC_APB1Periph_TIM7
    			| RCC_APB1Periph_TIM6, ENABLE);
    К сожалению под рукой кроме “древнего” мобильника ни чего не оказалось :( Первый режим работы: img004 Второй режим работы: img005 Третий режим работы: img007


comments powered by Disqus