|
DAC + DMA в STM32F2xx |
|
|
|
Feb 14 2012, 07:21
|
Знающий
   
Группа: Участник
Сообщений: 998
Регистрация: 27-08-08
Пользователь №: 39 850

|
Пытаюсь запустить DAC STM32f217 в режиме работы от DMA. В некую переменную int ForDAC2Value (переменная в памяти) переносятся данные преобразования ADC (по прерываниям конца преобразования). Инициализирую DAC2 + DMA1 для того, чтобы с помощью DMA1 перенести значение ForDAC2Value в DAC2 CODE __IO uint16_t ForDAC2Value = 0;
void DAC_Config(void) { DAC_InitTypeDef DAC_InitStructure; DMA_InitTypeDef DMA_InitStructure; GPIO_InitTypeDef GPIO_InitStructure;
/* Enable DAC2, DMA1 and GPIO clocks ****************************************/ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1 | RCC_AHB1Periph_GPIOA, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
/* Configure DAC2 pin as analog input ***************************************/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOA, &GPIO_InitStructure);
/* DMA1 Stream6 channel7 configuration **************************************/
DMA_InitStructure.DMA_Channel = DMA_Channel_7; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(DAC->DHR12R2); DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ForDAC2Value; DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; DMA_InitStructure.DMA_BufferSize = 1; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; 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_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_Init(DMA1_Stream6, &DMA_InitStructure); DMA_Cmd(DMA1_Stream6, ENABLE);
// конфигурируем ЦАП DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None; DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable; DAC_Init(DAC_Channel_2, &DAC_InitStructure); /* Enable DAC */ DAC_Cmd(DAC_Channel_2, ENABLE);
DAC_DMACmd(DAC_Channel_2, ENABLE); }
Не работает. Если сделать в прерываниях по концу преобразования ADC просто DAC->DHR12R2 = ForDAC2Value; (перенос данных с пом. процессора) Все работает нормально. Просмотрите код please, кому не лень. В чем тут проблема?
Сообщение отредактировал Acvarif - Feb 14 2012, 08:05
|
|
|
|
|
 |
Ответов
|
Feb 15 2012, 08:48
|
Знающий
   
Группа: Участник
Сообщений: 998
Регистрация: 27-08-08
Пользователь №: 39 850

|
Полная ерунда получается с DAC. Без DMA работает. Стоит подключить DMA все виснет. И вообще не понятно какая все же stream для DAC2 stream5 или 6? В даташите stream6, в примере с библиотекой stream5. Но ни стой ни с другой не работает. Может там и канал другой (не 7)? Просто гайка. Еррату почитать, что ли. Вот инициализация DAC2 + DMA1 канал 7 stream5 (с таймером) для формирования синуса. Не работает... CODE #define DAC_DHR12R2_ADDRESS 0x40007414 const uint16_t Sine12bit[32] = { 2047, 2447, 2831, 3185, 3498, 3750, 3939, 4056, 4095, 4056, 3939, 3750, 3495, 3185, 2831, 2447, 2047, 1647, 1263, 909, 599, 344, 155, 38, 0, 38, 155, 344, 599, 909, 1263, 1647};
void DAC_Config(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; DAC_InitTypeDef DAC_InitStructure; DMA_InitTypeDef DMA_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; // NVIC_InitTypeDef NVIC_InitStructure;
/* Enable DAC reset state */ RCC_APB1PeriphResetCmd(RCC_APB1Periph_DAC, ENABLE); /* Release DAC from reset state */ RCC_APB1PeriphResetCmd(RCC_APB1Periph_DAC, DISABLE);
/* Enable DAC2, DMA1 and GPIO clocks ****************************************/ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1 | RCC_AHB1Periph_GPIOA, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC | RCC_APB1Periph_TIM6, ENABLE);
/* Configure DAC2 pin as analog input ***************************************/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Time base configuration */ TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); TIM_TimeBaseStructure.TIM_Period = 0xFF; TIM_TimeBaseStructure.TIM_Prescaler = 0; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure); /* TIM6 TRGO selection */ TIM_SelectOutputTrigger(TIM6, TIM_TRGOSource_Update); /* TIM6 enable counter */ TIM_Cmd(TIM6, ENABLE);
/* DAC channel2 Configuration */ DAC_InitStructure.DAC_Trigger = DAC_Trigger_T6_TRGO; DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None; DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable; DAC_Init(DAC_Channel_2, &DAC_InitStructure);
/* DMA1_Stream5 channel7 configuration **************************************/ DMA_DeInit(DMA1_Stream5); DMA_InitStructure.DMA_Channel = DMA_Channel_7; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)DAC_DHR12R2_ADDRESS; DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&Sine12bit; DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; DMA_InitStructure.DMA_BufferSize = 32; 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_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_Init(DMA1_Stream5, &DMA_InitStructure); /* Enable DMA1_Stream5 */ DMA_Cmd(DMA1_Stream5, ENABLE); /* Enable DAC Channel2 */ DAC_Cmd(DAC_Channel_2, ENABLE); /* Enable DMA for DAC Channel2 */ DAC_DMACmd(DAC_Channel_2, ENABLE);
}
|
|
|
|
|
Feb 21 2012, 19:15
|
Знающий
   
Группа: Участник
Сообщений: 998
Регистрация: 27-08-08
Пользователь №: 39 850

|
Цитата(Acvarif @ Feb 17 2012, 09:39)  Откликнитесь кто запускал DAC stm32f2xx от DMA. DAC + DMA stm32f1xx наверняка работает. Почему связка DAC + DMA stm32F2xx мертвая? Даже фирменный пример из библиотеки периферии не работает. Где там напутано с каналами и стримами? Похоже с Dac stm32f2xx через DMA никто не работал. Ну да ладно... По ходу возник довольно актуальный вопрос по поводу DMA. Возможно ли с помощью DMA по внешнему событию читать в память 16 бит данных с GPio порта? Согласно документации похоже, что такое не предусмотрено. Но может я невнимательно читал доку? И такой вариант както возможен?
|
|
|
|
|
Feb 21 2012, 19:35
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Цитата(Acvarif @ Feb 21 2012, 23:15)  Похоже с Dac stm32f2xx через DMA никто не работал. Ну да ладно... Наверняка кто-то работал. Я имел дело и с DMA, и с DAC. Только в Ваш код влазить не стану, ибо страдаю аллергией на STишные библиотеки. Цитата(Acvarif @ Feb 21 2012, 23:15)  По ходу возник довольно актуальный вопрос по поводу DMA. Возможно ли с помощью DMA по внешнему событию читать в память 16 бит данных с GPio порта? Согласно документации похоже, что такое не предусмотрено. Но может я невнимательно читал доку? И такой вариант както возможен? Подтверждаю: невнимательно читал. Внешние события могут регистрироваться множеством способов: через USART, SPI, TIMER. Все они могут вызывать транзакцию DMA. Если под "внешним событием" подразумевается просто фронт на входе, то см. в сторону таймеров.
|
|
|
|
|
Feb 22 2012, 06:12
|
Знающий
   
Группа: Участник
Сообщений: 998
Регистрация: 27-08-08
Пользователь №: 39 850

|
Цитата(scifi @ Feb 21 2012, 23:35)  Подтверждаю: невнимательно читал. Внешние события могут регистрироваться множеством способов: через USART, SPI, TIMER. Все они могут вызывать транзакцию DMA. Если под "внешним событием" подразумевается просто фронт на входе, то см. в сторону таймеров. Спасибо. Да, именно фронт на входе. Адрес приемника установить нет проблем. Но как тогда установит адрес источника? Получается, что в качестве адреса источника периферии будет адрес какого либо GPIO. Но в таблице стримов нет такой периферии как GPIO. На какой канал-стрим все подключать? Получается, что на канал и стрим используемого таймера? Так разве пойдет? Работать будет?
|
|
|
|
|
Feb 22 2012, 07:14
|
Знающий
   
Группа: Участник
Сообщений: 998
Регистрация: 27-08-08
Пользователь №: 39 850

|
Цитата(scifi @ Feb 22 2012, 10:49)  В регистр DMA_SxPAR пишем &GPIO_xDR. В регистр DMA_SxM1AR пишем &buffer (адрес приёмного буфера). Стрим выбираем такой, чтобы мог запускаться от выбранного таймера. Всё. Понял. Спасибо. Если это заработает тогда STM_у цены нету. Цитата Вот рабочий код для генераци треугольника или шума: Возврвщаясь к теме: Какой все же стрим у DAC2 stm32f217 - 5 или 6 (в демках ставят 5, в юсер мануале 6) В приведенном коде нет DMA
|
|
|
|
|
Feb 22 2012, 07:23
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Цитата(Acvarif @ Feb 22 2012, 11:14)  Понял. Спасибо. Если это заработает тогда STM_у цены нету. Конечно заработает. И не такое работало. Предвидя дальнейшие вопросы, даю подсказку: таймеры могут формировать запросы DMA по событию Capture, которое может вызываться фронтом на входе таймера. И вообще таймеры в STM32 весьма мощные и позволяют творить чудеса. При условии, что не запутаетесь и правильно их запрограммируете. Цитата(Acvarif @ Feb 22 2012, 11:14)  Какой все же стрим у DAC2 Вопрос не имеет смысла и вскрывает глубинное непонимание принципа работы DMA. Номер стрима определяет выбор источников сигнала запроса DMA. Он не определяет адрес источника и приёмника данных.
|
|
|
|
|
Mar 4 2012, 11:33
|
Участник

Группа: Участник
Сообщений: 61
Регистрация: 13-02-12
Пользователь №: 70 242

|
Цитата(scifi @ Feb 22 2012, 11:23)  Конечно заработает. И не такое работало. Предвидя дальнейшие вопросы, даю подсказку: таймеры могут формировать запросы DMA по событию Capture, которое может вызываться фронтом на входе таймера. И вообще таймеры в STM32 весьма мощные и позволяют творить чудеса. При условии, что не запутаетесь и правильно их запрограммируете.
Вопрос не имеет смысла и вскрывает глубинное непонимание принципа работы DMA. Номер стрима определяет выбор источников сигнала запроса DMA. Он не определяет адрес источника и приёмника данных. Добрый день всем! Мучаюсь с обратной задачей. Из памяти вывести поток данных на параллельный порт с помощью DMA. Конструкция TIM6 + DMA1 Stream1 Channel7 формирует Event. DMA начинает выводить полуслово в порт E ( GPIOE_ODR) после первой же попытки (видно, что DMA_S1NDTR декрементировался) все заканчивается с флагом Stream 1 transfer error interrupt. Прямой вывод данных в GPIOE_ODR из тела программы при этом дает отличный результат! В чем грабли?
|
|
|
|
|
Mar 4 2012, 13:31
|
Участник

Группа: Участник
Сообщений: 61
Регистрация: 13-02-12
Пользователь №: 70 242

|
Цитата(Sekat @ Mar 4 2012, 15:33)  В чем грабли? Подробности к проблеме из предыдущего поста. 1. Процессор - STM32F407 . 2. Инициализация GPIO для вывода в порт Е: Код RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE); GPIO_InitStructure.GPIO_Pin = 0xffff; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOE, &GPIO_InitStructure); 3. Инициализация таймера TIM6: Код TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); TIM_TimeBaseStructure.TIM_Period = 0x200; TIM_TimeBaseStructure.TIM_Prescaler = 0; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);
TIM_Cmd(TIM6, ENABLE); 3. Инициализация DMA: Код RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1 , ENABLE); DMA_DeInit(DMA1_Stream1); DMA_InitTypeDef DMA_InitStructure; DMA_InitStructure.DMA_Channel = DMA_Channel_7; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) GPIOE_ODR; DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&Sine12bit; DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; DMA_InitStructure.DMA_BufferSize = 32; 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_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_Init(DMA1_Stream1, &DMA_InitStructure); DMA_Cmd(DMA1_Stream1, ENABLE); TIM_DMACmd(TIM6, TIM_DMA_Update, ENABLE); Этот код слегка переделанный пример от IAR вывода во внутренний DAC. 4. Что удивительно. Если подставить вместо GPIOE_ODR например адрес встроенного DAC, то DMA начинает пересылать данные без ошибки. 5. Что примечательно. Если реверсировать передачу данных (поменять направление - от порта в память, естественно память разместить в RAM), результат тот же - ошибка передачи DMA! Пункты 4 и 5 внушают пессимизм. Неужели обращение DMA к параллельному порту в STM32F посредством DMA невозможно? Надеюсь все же, что это мои грабли
Сообщение отредактировал Sekat - Mar 4 2012, 13:34
|
|
|
|
Сообщений в этой теме
Acvarif DAC + DMA в STM32F2xx Feb 14 2012, 07:21        Acvarif Цитата(scifi @ Feb 22 2012, 11:23) Номер ... Feb 22 2012, 07:39         scifi Цитата(Acvarif @ Feb 22 2012, 11:39) По п... Feb 22 2012, 07:44          Acvarif Цитата(scifi @ Feb 22 2012, 11:44) Что-то... Feb 22 2012, 07:58         scifi Цитата(Acvarif @ Feb 22 2012, 11:39) (92.... Feb 22 2012, 08:34          Acvarif Цитата(scifi @ Feb 22 2012, 12:34) Я дума... Feb 22 2012, 08:39           scifi Цитата(Acvarif @ Feb 22 2012, 12:39) Уже ... Feb 22 2012, 08:42          Sekat Цитата(Sekat @ Mar 4 2012, 17:31) 4. Что ... Mar 6 2012, 06:15       AHTOXA Цитата(Acvarif @ Feb 22 2012, 13:14) В пр... Feb 22 2012, 07:54 uriy Пытаюсь запустить DAC+DMA на STM32F105 тоже на пол... Feb 22 2012, 05:01 AHTOXA Вот рабочий код для генераци треугольника или шума... Feb 22 2012, 05:20 uriy AHTOXA генератор треугольника у меня тоже работает... Feb 22 2012, 07:56 uriy Как это понимать?
КодTIM2->CR1 = 0; // co... Feb 22 2012, 08:21 AHTOXA Опечатка, должно быть TIM6.
Но и так будет работат... Feb 22 2012, 08:29 uriy AHTOXA спасибо! Все заработало проблема была в... Feb 22 2012, 10:56 Flexz По неработающей периферии - посмотрите раздел ... Mar 6 2012, 06:28 Sekat Цитата(Flexz @ Mar 6 2012, 10:28) По нера... Mar 6 2012, 12:03
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|