×

Внимание

Форум находится в режиме только для чтения.

STM32F4xx

12 года 7 мес. назад #2781 от ddnik
ddnik создал тему: STM32F4xx
Не любитель писать - но...
Не первый МК на длинном пути и снова приходится ковыряться в бесконечных регистрах, документации с дырами и изучать примитивные примеры :(
Недавний опыт со Stellaris говорит что можно и по другому делать...
Примеры:
С трудом нашел как включить FPU - в документации практически ни слова(по умолчанию выключен). Нашел в примере DSP - надо выставить пару битиков в некотором регистре...

Не нашел ответов (пока ищу методом проб...) по АЦП
1. можно ли независимо запускать 3 АЦП каждый по отдельному каналу DMA?
2. в кристаллах Z (144pin) написано что каналов 24 - но во всей документации описано как делать 16!??+три внутренних t, Vref,Vbat. Где остальные?
3. в DS написано максимальная частота АЦП 36 Мг но все примеры даются как 84/2= 42! Почему?
12 года 7 мес. назад #2786 от ddnik
ddnik ответил в теме Re: STM32F4xx
...все еще мучаюсь с АЦП...
Кое с чем разобрался (методом проб и трассировки)

По 1 вопросу - вроде можно настроить DMA на каждый АЦП отдельно
По 2 - оказывается входные каналы для разных АЦП неравнозначны! Вернее не все каналы равнозначны!
В частности каналы t, Vref,Vbat доступны только для ADC 1, а каналы ADC_Channel_4,5,6,7,8,9,14,15 ADC3 выходят на отдельные пины.
По 3 - на совести написателей.

Обнаружил брак в примерах  >:(
Методика написания библиотечный функций в принципе дурная
для передачи битиков которые потом переносятся в регистры используется структура (почему нельзя сразу сформировать регистр? - только память расходуется!)
Отсюда потенциальная проблема - ВСЕ компоненты структуры должны быть заполнены!
Теперь берем любой пример (выдержка)
void ADC3_CH12_DMA_Config(void)
{
  ADC_InitTypeDef      ADC_InitStructure;
...
  /* ADC3 Init ****************************************************************/
  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
  ADC_InitStructure.ADC_ScanConvMode = DISABLE;
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_NbrOfConversion = 1;
  ADC_Init(ADC3, &ADC_InitStructure);
...
результат - содержимое ADC3-CR2 =  случайное число, оказывается в структуре ADC_InitStructure
есть еще один член uint32_t ADC_ExternalTrigConv, а поскольку сама структура в динамической памяти - в этой переменной "мусор"
Библиотека делает так
  /*
ADCx CR2 Configuration
*/
  /* Get the ADCx CR2 value */
  tmpreg1 = ADCx->CR2;
 
  /* Clear CONT, ALIGN, EXTEN and EXTSEL bits */
  tmpreg1 &= CR2_CLEAR_MASK;
 
  /* Configure ADCx: external trigger event and edge, data alignment and
    continuous conversion mode */
  /* Set ALIGN bit according to ADC_DataAlign value */
  /* Set EXTEN bits according to ADC_ExternalTrigConvEdge value */
  /* Set EXTSEL bits according to ADC_ExternalTrigConv value */
  /* Set CONT bit according to ADC_ContinuousConvMode value */
  tmpreg1 |= (uint32_t)(ADC_InitStruct->ADC_DataAlign | \
                        ADC_InitStruct->ADC_ExternalTrigConv |
                        ADC_InitStruct->ADC_ExternalTrigConvEdge | \
                        ((uint32_t)ADC_InitStruct->ADC_ContinuousConvMode << 1));
                       
  /* Write to ADCx CR2 */
  ADCx->CR2 = tmpreg1;
  /*
ADCx SQR1 Configuration
*/

Как видно принятый мусор по "или" сваливается в CR2...

и удивляйтесь потом почему вдруг стало ADC_DataAlign_Right ???



12 года 7 мес. назад #2787 от ddnik
ddnik ответил в теме Re: STM32F4xx
... пока не разобрался- при попытке запустить в цикле измерения четырех каналов дают результат в памяти четыре измерения первого  :-\
Может кто поможет (голова уже съезжает)

Текст

void ADC_CH_DMA_Config(void)
{
  ADC_InitTypeDef      ADC_InitStructure;
  DMA_InitTypeDef      DMA_InitStructure;
  GPIO_InitTypeDef      GPIO_InitStructure;

  /* Enable ADC3, DMA2 and GPIO clocks ****************************************/
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOC, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);

  /* DMA2 Stream0 channel0 configuration **************************************/
  DMA_InitStructure.DMA_Channel = DMA_Channel_0; 
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_ADDRESS;
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC3ConvertedValue[0];
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
  DMA_InitStructure.DMA_BufferSize = 4;
  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(DMA2_Stream0, &DMA_InitStructure);
  DMA_Cmd(DMA2_Stream0, ENABLE);

  /* Configure ADC3 Channel12 pin as analog input ******************************/
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
  GPIO_Init(GPIOC, &GPIO_InitStructure);

  /* ADC Common Init **********************************************************/
ADC->CCR = ADC_Mode_Independent |
ADC_Prescaler_Div2 |
ADC_DMAAccessMode_1 |
ADC_TwoSamplingDelay_5Cycles |
ADC_CCR_TSVREFE | ADC_CCR_VBATE;

  /* ADC3 Init ****************************************************************/
  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
  ADC_InitStructure.ADC_ScanConvMode = DISABLE;
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_NbrOfConversion = 4;
  ADC_Init(ADC1, &ADC_InitStructure);
// Выставляю CR2 сам из-за ошибки примера 
ADC1->CR2 = ADC_CR2_EOCS|ADC_CR2_CONT|ADC_CR2_DMA|ADC_CR2_DDS;

  /* ADC regular configuration *************************************/
  ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 1, ADC_SampleTime_480Cycles);
  ADC_RegularChannelConfig(ADC1, ADC_Channel_17, 2, ADC_SampleTime_480Cycles);
  ADC_RegularChannelConfig(ADC1, ADC_Channel_18, 3, ADC_SampleTime_480Cycles);
  ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 4, ADC_SampleTime_480Cycles);

/* Enable DMA request after last transfer (Single-ADC mode) */
  //ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);//ENABLE);

  /* Enable ADC3 DMA */
  ADC_DMACmd(ADC1, ENABLE);

  /* Enable ADC3 */
  ADC_Cmd(ADC1, ENABLE);
}

Результат после запуска -  в массиве volatile  WORD ADC3ConvertedValue[32];
в первых четырех ячейках значения  ADC_Channel_12...!!!

12 года 7 мес. назад #2788 от ddnik
ddnik ответил в теме Re: STM32F4xx
Ура - заработало!
Оказывается мало указать что четыре регулярных канала, надо указать что они должны переключаться! :)
...
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
...

Пошел осваивать изделие дальше.... На очереди работа АЦП по прерываниям (примера нет), надо реализовать прерывание после обработки каждой группы регулярных каналов.
12 года 6 мес. назад #2791 от Денис Ягов
Денис Ягов ответил в теме Re: STM32F4xx
Добрый день.

Обычно я поглядываю в форум, но в этот раз не мог ответить.
Вижу вы во всём разобрались.

По поводу примеров и функций.
Да. Примеры заточены под "понятность".
Тот же самый DMA - расписывается отдельной строкой каждый бит регистра.
За то вы пишете: "Инкремент адреса периферии = Энэйбл".

Это затратно с точки зрения написания (физического), расходов тактов и памяти.
Зато читаемый текст.

Именно под читаемость - заточены библиотеки.

На самом деле, дальше надо посмотреть значения регистров в пошаговой отладке (после функций типа XXXXXX_Init) и закомментарить текст программы и напрямую присвоить значение регистра (которое видели в отладчике).

По прерыванию АЦП.
Вам в проект надо включить файл типа startup_stm32f4xx.s (в нём расписаны все прерывания). Подключение этого файла в проект потребует подключения функции System_Init(), она в файле system_stm32f4xx.c. Имейте ввиду, эта функция выставляет тактирование на 168МГц - внешним кварцем с частотой 25МГц... Покопайтесь в ней (если у вас другое тактирование и/или программа - во внешней памяти).
В указанном файле startup_stm32f4xx.s - имеются названия функций, которые будут размещены в векторах прерываний. В том числе и АЦП: ADC_IRQHandler - название функции, которая будет воспринята как "прерывание от АЦП", при поступлении запроса на прерывание.

Функция, которая разрешает прерывание от АЦП:

void ADC_ITConfig  ( ADC_TypeDef *  ADCx, 
  uint16_t  ADC_IT, 
  FunctionalState  NewState 
)
(разберётесь самостоятельно - тут всё просто)

Кроме того надо настроить контроллер прерываний NVIC.
Возьмёте пример настройки, замените применённую в нём периферию на АЦП (чтоб он именно эти прерывания воспринимал и ранжировал по приоритету).

Контроллер прерываний правильно настроить до запуска АЦП (генерящего прерывания).

;)
Время создания страницы: 0.038 секунд
Работает на Kunena форум