Кто любит RISC в жизни, заходим, не стесняемся.
Ответить

Re: stm32f103 Dual mode ADC+DMA по таймеру4

Вс дек 04, 2022 17:42:43

куда именно

:shock:
Стесняюсь спросить - а вы вообще рефмануал открывали?
В ДМА совсем немного регистров.
Например в F0 для второго канала DMA это будет DMA1_Channel2->CNDTR.
Например в F4 для первого потока второго контроллера DMA это будет DMA2_Stream1->NDTR.

Re: stm32f103 Dual mode ADC+DMA по таймеру4

Вс дек 04, 2022 17:58:21

Стесняюсь спросить - а вы вообще рефмануал открывали?
В ДМА совсем немного регистров.
Например в F0 для второго канала DMA это будет DMA1_Channel2->CNDTR.
Например в F4 для первого потока второго контроллера DMA это будет DMA2_Stream1->NDTR.

Нет, но понял к чему вы ведете, эти регистры хрянят число, и оно по кругу изменяется до переполнения и опять обнуляется. Читал где то, уже не помню. Будет читать по DMA что к чему)

Re: stm32f103 Dual mode ADC+DMA по таймеру4

Вс дек 04, 2022 18:23:15

оно по кругу изменяется до переполнения

Нет, оно ДЕКРЕМЕНТИРУЕТСЯ до нуля. Для однократного режима. В непрерывном режиме оно автоматически восстанавливается одновременно с автоматическим перезапуском ДМА.
Рефмануал надо читать полностью, а не только про ДМА. Значительная часть сопряженной информации находится в других модулях. Так при работе АЦП с ДМА нужно в модуле АЦП включить реквесты от АЦП, например... Помимо выбора канала или стрима работающего с реквестами АЦП в модуле ДМА.

Re: stm32f103 Dual mode ADC+DMA по таймеру4

Вт янв 10, 2023 12:47:30

Продолжаю ковыряться, плюнул я CUBE IDE... решил сразу с CMSIS начать, т.к. в кубе много не понятного для меня... и вообще держать в голове байду от куба не хочется... Вообщем поизучал и настроил через CMSIS - RCC, системный таймер, таймер 4 с тем же конфигом, порты ввода/вывода, а вот с ацп+дма у меня проблемы начались.... Точнее с ацп2, при отладке я не вижу в регистрах CR2 установок которые я задал((( Ставлю 0110: Dual regular simultaneous mode only по факту вижу 0000. Гляньте профессиональным взглядом что не так делаю или я может чего не дочитал в референс мануале? Вообщем пытяюсь запустить парный режим преобразования ацп + дма по таймеру 4.

Спойлер
Код:
void DMA1_Init(void) {
   SET_BIT(RCC->AHBENR, RCC_AHBENR_DMA1EN); //(1)Включение тактирования DMA1
   DMA1_Channel1->CPAR = (uint32_t)&(ADC1->DR); //Задаем адрес периферийного устройства
   DMA1_Channel1->CMAR = (uint32_t)ADC_Data; //Задаем адрес в памяти, куда будем кидать данные.
   DMA1_Channel1->CNDTR = 1; //Настроим количество данных для передачи. После каждого периферийного события это значение будет уменьшаться.
   MODIFY_REG(DMA1_Channel1->CCR, DMA_CCR_PL_Msk, 0b00 << DMA_CCR_PL_Pos); //(00) Зададим приоритет канала на LOW
   CLEAR_BIT(DMA1_Channel1->CCR, DMA_CCR_DIR); //(0) Чтение будем осуществлять с периферии
   SET_BIT(DMA1_Channel1->CCR, DMA_CCR_CIRC); //(1) Настроим DMA в Circular mode
   MODIFY_REG(DMA1_Channel1->CCR, DMA_CCR_PSIZE_Msk, 0b10 << DMA_CCR_PSIZE_Pos); // (10) Размер данных периферийного устройства 32 бит
   MODIFY_REG(DMA1_Channel1->CCR, DMA_CCR_MSIZE_Msk, 0b10 << DMA_CCR_MSIZE_Pos); //(10) Размер данных в памяти 32 бит
   SET_BIT(DMA1_Channel1->CCR, DMA_CCR_TCIE); //(1)Включим прерывание по полной передаче
   CLEAR_BIT(DMA1_Channel1->CCR, DMA_CCR_HTIE); //(0)Отключим прерывание по половинной передаче
   SET_BIT(DMA1_Channel1->CCR, DMA_CCR_TEIE); //(1)Включим прерывание по ошибке передачи.
   SET_BIT(DMA1_Channel1->CCR, DMA_CCR_MINC); //(1)Включим инкрементирование памяти
   SET_BIT(DMA1_Channel1->CCR, DMA_CCR_EN); //(1) DMA Вкл
}


void ADC1_Init(void) {
   
   SET_BIT(RCC->APB2ENR, RCC_APB2ENR_ADC1EN); //Включение тактирования ADC1
   
   SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPAEN); //Включение тактирования PORT А
   //Настраиваем 3 порт
   MODIFY_REG(GPIOC->CRL, GPIO_CRL_CNF3_Msk, 0b00 << GPIO_CRL_CNF3_Pos); //(00) Analog mode
   MODIFY_REG(GPIOC->CRL, GPIO_CRL_MODE3_Msk, 0b00 << GPIO_CRL_MODE3_Pos); //(00) Input mode (reset state)

   /*11.12 ADC registers(страница 237)*/
   //11.12.2 ADC control register 1 (ADC_CR1)(страница 238)
   CLEAR_BIT(ADC1->CR1, ADC_CR1_EOCIE);   //(0) Вкл/Вылк прерывания по окончанию преобразования
   CLEAR_BIT(ADC1->CR1, ADC_CR1_AWDIE);   //(0) Прерывания от Ватчдога
   CLEAR_BIT(ADC1->CR1, ADC_CR1_JEOCIE);   //(0) Прерывания от инжекктированых каналов
   SET_BIT(ADC1->CR1, ADC_CR1_SCAN);      //(1) Вкл/Выкл режима сканирования
   
   /* Примечание:
   * Прерывание EOC или JEOC генерируется только в конце преобразования последнего канала,
   * если установлен соответствующий бит EOCIE или JEOCIE.*/
   CLEAR_BIT(ADC1->CR1, ADC_CR1_AWDSGL);   //(0) Analog watchdog enabled on all channels
   CLEAR_BIT(ADC1->CR1, ADC_CR1_JAUTO);   //(0) Automatic injected group conversion disabled
   CLEAR_BIT(ADC1->CR1, ADC_CR1_DISCEN);   //(0) Discontinuous mode on regular channels disabled
   CLEAR_BIT(ADC1->CR1, ADC_CR1_JDISCEN);   //(0) Discontinuous mode on injected channels disabled
   MODIFY_REG(ADC1->CR1, ADC_CR1_DUALMOD_Msk, 0b0110 << ADC_CR1_DUALMOD_Pos); //0110: Dual regular simultaneous mode only
   CLEAR_BIT(ADC1->CR1, ADC_CR1_JAWDEN);   //(0) Analog watchdog disabled on injected channels
   CLEAR_BIT(ADC1->CR1, ADC_CR1_AWDEN);   //(0) Analog watchdog disabled on regular channels
   
   /*11.12.3 ADC control register 2 (ADC_CR2)(страница 240)*/
   SET_BIT(ADC1->CR2, ADC_CR2_ADON); //(1) Запустить АЦП
   
   /* Примечание:
   * Если в этот же момент изменяется какой-либо другой бит в этом регистре,
   * кроме ADON, то конверсия не запускается.
   * Это сделано для предотвращения ошибочного преобразования.*/
   CLEAR_BIT(ADC1->CR2, ADC_CR2_CONT);   //(0) Continuous conversion mode(непрерывные преобразования)
   SET_BIT(ADC1->CR2, ADC_CR2_CAL);   //(1) Enable calibration (Калибровка)
   
   /*Примечание:
    * Этот бит устанавливается программой для запуска калибровки.
    * Он сбрасывается аппаратно после завершения калибровки.*/
   while (READ_BIT(ADC1->CR2, ADC_CR2_CAL)) ;//Подождем окончания калибровки
   Delay_ms(1); //Задержка
   
   SET_BIT(ADC1->CR2, ADC_CR2_DMA);      //(1) режима использования DMA
   SET_BIT(ADC1->CR2, ADC_CR2_ALIGN);      //(1) Выравнивание по левому краю
   MODIFY_REG(ADC1->CR2, ADC_CR2_EXTSEL_Msk, 0b101 << ADC_CR2_EXTSEL_Pos); //101: Timer4 CC4
   SET_BIT(ADC1->CR2, ADC_CR2_EXTTRIG);   //(1) Conversion on external event disabled
   SET_BIT(ADC1->CR2, ADC_CR2_SWSTART);   //(1) Начать преобразование
   CLEAR_BIT(ADC1->CR2, ADC_CR2_TSVREFE);   //(0)Temperature sensor and VREFINT channel enabled
   
   // 11.12.5 ADC sample time register 2 (ADC_SMPR2)(страница 245)
   MODIFY_REG(ADC1->SMPR2, ADC_SMPR2_SMP3_Msk, 0b000 << ADC_SMPR2_SMP3_Pos); //(000) - 1.5 cycles
   
   // 11.12.9 ADC regular sequence register 1 (ADC_SQR1)(страница 247)
   MODIFY_REG(ADC1->SQR1, ADC_SQR1_L_Msk, 0b0000 << ADC_SQR1_L_Pos); //1 преобразования - т.к. 1 преобразования
   
   // 11.12.11 ADC regular sequence register 3 (ADC_SQR3)(страница 249)
   MODIFY_REG(ADC1->SQR3, ADC_SQR3_SQ1_Msk, 3 << ADC_SQR3_SQ1_Pos); //линии ввода, которую нужно подключить к каналу x группы обычных каналов   
}

void ADC2_Init(void) {
      
   SET_BIT(RCC->APB2ENR, RCC_APB2ENR_ADC2EN); //Включение тактирования ADC2
   
   //Настраиваме 4 порт
   MODIFY_REG(GPIOC->CRL, GPIO_CRL_CNF4_Msk, 0b00 << GPIO_CRL_CNF4_Pos); //(00) Analog mode
   MODIFY_REG(GPIOC->CRL, GPIO_CRL_MODE4_Msk, 0b00 << GPIO_CRL_MODE4_Pos); //(00) Input mode (reset state)
   
   /*11.12 ADC registers(страница 237)*/
   //11.12.2 ADC control register 1 (ADC_CR1)(страница 238)
   
   CLEAR_BIT(ADC2->CR1, ADC_CR1_EOCIE); //(0) Вкл/Вылк прерывания по окончанию преобразования
   CLEAR_BIT(ADC2->CR1, ADC_CR1_AWDIE); //(0) Прерывания от Ватчдога
   CLEAR_BIT(ADC2->CR1, ADC_CR1_JEOCIE); //(0) Прерывания от инжекктированых каналов
   SET_BIT(ADC2->CR1, ADC_CR1_SCAN); //(1) Вкл/Выкл режима сканирования
   
   /* Примечание:
   * Прерывание EOC или JEOC генерируется только в конце преобразования последнего канала,
   * если установлен соответствующий бит EOCIE или JEOCIE.*/
   
   CLEAR_BIT(ADC2->CR1, ADC_CR1_AWDSGL); //(0) Analog watchdog enabled on all channels
   CLEAR_BIT(ADC2->CR1, ADC_CR1_JAUTO); //(0) Automatic injected group conversion disabled
   CLEAR_BIT(ADC2->CR1, ADC_CR1_DISCEN); //(0) Discontinuous mode on regular channels disabled
   CLEAR_BIT(ADC2->CR1, ADC_CR1_JDISCEN); //(0) Discontinuous mode on injected channels disabled
   MODIFY_REG(ADC2->CR1, ADC_CR1_DUALMOD_Msk, 0b0110 << ADC_CR1_DUALMOD_Pos); //0110: Dual regular simultaneous mode only
   CLEAR_BIT(ADC2->CR1, ADC_CR1_JAWDEN); //(0) Analog watchdog disabled on injected channels
   CLEAR_BIT(ADC2->CR1, ADC_CR1_AWDEN); //(0) Analog watchdog disabled on regular channels
   
   /*11.12.3 ADC control register 2 (ADC_CR2)(страница 240)*/
   SET_BIT(ADC2->CR2, ADC_CR2_ADON); //(1) Запустить АЦП
   
   /* Примечание:
   * Если в этот же момент изменяется какой-либо другой бит в этом регистре,
   * кроме ADON, то конверсия не запускается.
   * Это сделано для предотвращения ошибочного преобразования.*/
   CLEAR_BIT(ADC2->CR2, ADC_CR2_CONT); //(0) Continuous conversion mode(непрерывные преобразования)
   SET_BIT(ADC2->CR2, ADC_CR2_CAL); //(1) Enable calibration (Калибровка)
   
   /*Примечание:
    * Этот бит устанавливается программой для запуска калибровки.
    * Он сбрасывается аппаратно после завершения калибровки.*/
   while (READ_BIT(ADC2->CR2, ADC_CR2_CAL)) ;//Подождем окончания калибровки
   Delay_ms(1); //Задержка
   
   CLEAR_BIT(ADC2->CR2, ADC_CR2_ALIGN); //(0) Выравнивание по правому краю
   /* Примечание:
   * В двойном режиме при настройке преобразования для запуска внешним событием пользователь должен установить триггер
   * только для ведущего(ADC1) и установить программный триггер для ведомого (ADC2), чтобы предотвратить ложные триггеры для запуска
   * нежелательного преобразования ведомого. Однако внешние триггеры должны быть включен как на ведущем, так и на ведомом АЦП.*/
   MODIFY_REG(ADC2->CR2, ADC_CR2_EXTSEL_Msk, 0b111 << ADC_CR2_EXTSEL_Pos); // 111: бит SWSTART регистра ADC_CR2
   SET_BIT(ADC2->CR2, ADC_CR2_EXTTRIG); //(1) Conversion on external event disabled
   SET_BIT(ADC2->CR2, ADC_CR2_SWSTART); //(1) Начать преобразование
   CLEAR_BIT(ADC2->CR2, ADC_CR2_TSVREFE); //(0)Temperature sensor and VREFINT channel enabled
   
   // 11.12.5 ADC sample time register 2 (ADC_SMPR2)(страница 245)
   MODIFY_REG(ADC2->SMPR2, ADC_SMPR2_SMP4_Msk, 0b000 << ADC_SMPR2_SMP4_Pos); //(000) - 1.5 cycles
   
   // 11.12.9 ADC regular sequence register 1 (ADC_SQR1)(страница 247)
   MODIFY_REG(ADC2->SQR1, ADC_SQR1_L_Msk, 0b0000 << ADC_SQR1_L_Pos); //1 преобразования - т.к. 1 преобразования
   
   // 11.12.11 ADC regular sequence register 3 (ADC_SQR3)(страница 249)
   MODIFY_REG(ADC2->SQR3, ADC_SQR3_SQ1_Msk, 4 << ADC_SQR3_SQ1_Pos); //линии ввода, которую нужно подключить к каналу x группы обычных каналов
}

Re: stm32f103 Dual mode ADC+DMA по таймеру4

Ср янв 11, 2023 19:26:49

kote52, я не силен в этом, может быть и можно посадить ADC1 на T4_CC4, но как выходит из моих экспериментов с f030, нужен бит Tx_TRGO, а он только у TIM3.

То есть в ADC1 в External Trigger Conversion нужно поставить Timer 3 Trigger Out event,
а в TIM3 в Trigger Event Selection нужно поставить Update Event.

или в регитрах ADC1 ищите бит ADC_ExternalTrigConv_T3_TRGO, а в TIM3->CR2 бит TIM_TRGOSource_Update.

Re: stm32f103 Dual mode ADC+DMA по таймеру4

Ср янв 11, 2023 20:25:46

kote52, я не силен в этом, может быть и можно посадить ADC1 на T4_CC4, но как выходит из моих экспериментов с f030, нужен бит Tx_TRGO, а он только у TIM3.

То есть в ADC1 в External Trigger Conversion нужно поставить Timer 3 Trigger Out event,
а в TIM3 в Trigger Event Selection нужно поставить Update Event.

или в регитрах ADC1 ищите бит ADC_ExternalTrigConv_T3_TRGO, а в TIM3->CR2 бит TIM_TRGOSource_Update.

Приветствую Dimon456! Я понял о вашем подходе. Это один из методов как можно прицепиться к таймеру. Свой пытаю как запуск в режиме сравнения на определённом канале таймера 4. Таймер будет переполнятся, а сравнение будет происходить в момент обнуления и «толкать» АЦП.

и там есть регистры:
ADC->CR2
EXTSEL[2:0]: выбор внешнего события для срабатывания триггера запуска оцифровки обычных каналов. Для ADC1,2:
000: Timer1 CC1
001: Timer1 CC2
010: Timer1 CC3
011: Timer2 CC2
100: Timer3 TRGO
101: Timer4 CC4 //выбран
110: EXTI line11/TIM8_TRGO
111: бит SWSTART регистра ADC_CR2

Вот кое что почитав нашел - что, хоть сэмплирования и по таймеру, но первый старт вручную... т.е.
Код:
ADC1->CR2 |=ADC_CR2_SWSTART;
SET_BIT(ADC1->CR2, ADC_CR2_EXTTRIG);
ADC2->CR2 |=ADC_CR2_SWSTART;
SET_BIT(ADC2->CR2, ADC_CR2_EXTTRIG);

так по кирпичику можеи и дойду :))
Ответить