Перейти к содержанию

STM32F103 ШИМ, АЦП, таймер


strifonoff

Рекомендуемые сообщения

Вопрос по ШИМ.
Если у PA3 альтернативная функция TIM2_CH4, то для ШИМ его ремапить не надо?

  GPIOA->CRL &= ~GPIO_CRL_MODE3;
  GPIOA->CRL |= GPIO_CRL_MODE3_1;
  
  TIM2->PSC = 0;
  TIM2->ARR = 1800-1;
  TIM2->CCR4 = 900;
  TIM2->BDTR |= TIM_BDTR_MOE;
  TIM2->CCMR2 = TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4M_1;
  TIM2->CCER |= TIM_CCER_CC4E;
  TIM2->CR1 |= TIM_CR1_CEN;

Этот код верный?

Тактирование включено так:
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;

Изменено пользователем strifonoff
Ссылка на комментарий
Поделиться на другие сайты

Сравнительное тестирование аккумуляторов EVE Energy и Samsung типоразмера 18650

Инженеры КОМПЭЛ провели сравнительное тестирование аккумуляторов EVE и Samsung популярного для бытовых и индустриальных применений типоразмера 18650. 

Для теста были выбраны аккумуляторы литий-никельмарганцевой системы: по два образца одного наименования каждого производителя – и протестированы на двух значениях тока разряда: 0,5 А и 2,5 А. Испытания проводились в нормальных условиях на электронной нагрузке EBD-USB от ZKEtech, а зарядка осуществлялась от лабораторного источника питания в режиме CC+CV в соответствии с рекомендациями в даташите на определенную модель. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

25.09.2020 в 10:13, strifonoff сказал:

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

А это потому что их не нужно включать.

Ссылка на комментарий
Поделиться на другие сайты

Новый аккумулятор EVE серии PLM для GSM-трекеров, работающих в жёстких условиях (до -40°С)

Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре. 

Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств. Подробнее параметры и результаты тестов новой серии PLM по ссылке.

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

2 часа назад, BARS_ сказал:

Нужно оба бита MODE выставлять

 


TIM2->BDTR |= TIM_BDTR_MOE;

Не требуется в принципе.

А зачем мне 50MHz, или я не о том думаю.

BDTR в мануале для таймеров кроме 1-го не нашел в принципе...

Ссылка на комментарий
Поделиться на другие сайты

Литиевые батарейки и аккумуляторы от мирового лидера  EVE в Компэл

Компания Компэл, официальный дистрибьютор EVE Energy, бренда №1 по производству химических источников тока (ХИТ) в мире, предлагает продукцию EVE как со склада, так и под заказ. Компания EVE широко известна в странах Европы, Америки и Юго-Восточной Азии уже более 20 лет. Недавно EVE была объявлена поставщиком новых аккумуляторных элементов круглого формата для электрических моделей «нового класса» компании BMW.

Продукция EVE предназначена для самого широкого спектра применений – от бытового до промышленного. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

вопрос по ШИМ, про старт и останов.
как я понял генерация ШИМ определяется работой таймера на котором ШИМ висит, в моём случае это TIM2_CH4 (нога PA3). 
т.е. TIM2->CR1 |= TIM_CR1_CEN стартует, TIM2->CR1 ?= ~TIM_CR1_CEN останавливает. Но там же есть счётчик, который сверяется с регистром CCR4, этот счётчик нужно обнулить, а какой регистр за это отвечает? Я что-то запутался.

Ссылка на комментарий
Поделиться на другие сайты

@strifonoff  Если условия удовлетворяют можно просто в CCR4 записать значение больше ARR, т.е. если выход при апдейте в нужном состоянии, то можно и так и не нужно останавливать таймер. Можно остановить, обнулить, форсированно перевести выход ШИМ в нужное состояние.  

@strifonoff почитай http://dimoon.ru/category/obuchalka  https://hubstub.ru/stm32/

Изменено пользователем MasterElectric
Ссылка на комментарий
Поделиться на другие сайты

18 часов назад, strifonoff сказал:

Его и надо будет обнулить?

По желанию. В момент остановки таймера в этом регистре останется то, до чего таймер успел досчитать.

Ссылка на комментарий
Поделиться на другие сайты

Подскажите по режиму StandBy.
Пишут, что выход из него аналогичен сбросу. Это значит что он начинает снова с точки входа main или всё-таки с места где его усыпили/разбудили?

Ссылка на комментарий
Поделиться на другие сайты

А ещё вопрос. по ШИМ. как настроить ШИМ на определенное время выполнения используя тот же таймер? 
Сделать прерывание на том же таймере и там считать?

С этим разобрался, как думал так и сделал.

Изменено пользователем strifonoff
Ссылка на комментарий
Поделиться на другие сайты

Но что-то пошло не так.

Совсем не могу понять что именно

#include "stm32f10x.h"
#define BUF_SIZE 1000

void Init_RCC(void);
void Init_TIM4(void);
void Init_ADC1(void);
void Init_ADC2(void);
void Init_ADC_DMA(void);
void Init_PWM(void);
void Init_USART1(void);
void _delay_10(void);

vu16 _timer_pwm;
vu8 WorkSensor;
vu8 WorkADC;
vu32 _tim4cnt;
vu8 _timer;
vu32 _timer_hour;
vu16 ADC_Buf[BUF_SIZE] = {0};

int main()
{
  SystemInit();
  Init_RCC();
  Init_TIM4();
//  Init_ADC2();
//  Init_USART1();
//  __enable_irq();
  
  while(1){
    _timer_hour = 0;
    for(u8 i=0; i<5; i++){
      Init_ADC1();
      Init_PWM();
      _timer = 0;
      TIM4->CNT = 0;

      WorkADC=1;
      WorkSensor = 1;

      _timer_pwm = 0;

      TIM2->CNT = 0; 
      DMA1_Channel1->CCR |= DMA_CCR1_EN;
      ADC1->CR2 |= ADC_CR2_SWSTART;
      TIM2->CR1 |= TIM_CR1_CEN;

      while (WorkSensor) {}
      TIM2->CR1 &= ~TIM_CR1_CEN;

      while(WorkADC) {}
      ADC1->CR2 &= ~ADC_CR2_SWSTART;
      
      while(_timer) {} // wait for next measurement
    }
    // math + usart
    while(_timer_hour) {} // wait 1 hour
  }
}

void Init_RCC(void){
  RCC->AHBENR  |= RCC_AHBENR_DMA1EN;    // DMA1 
  RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;   // TIM2 
  RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;   // TIM4 
  RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;   // GPIOA
  RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;   // AF IO
  RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;   // ADC1
  RCC->APB2ENR |= RCC_APB2ENR_ADC2EN;   // ADC2
  RCC->CFGR    |= RCC_CFGR_ADCPRE_DIV6; // ADC clock prescaler (/6) 12 MHz
  RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
}

void Init_TIM4(void){

  TIM4->PSC = 3600-1;
  TIM4->ARR = 10-1;
  TIM4->DIER |= TIM_DIER_UIE;
  TIM4->CR1 |= TIM_CR1_CEN;
  NVIC_EnableIRQ(TIM4_IRQn);
  
}

void TIM2_IRQHandler(void){
  if(TIM2->SR & TIM_SR_UIF){
    _timer_pwm++;
    if (_timer_pwm == 20) {
      WorkSensor = 0;
    }
    TIM2->SR &= ~TIM_SR_UIF;
  }
}

void TIM4_IRQHandler(void){
  if(TIM4->SR & TIM_SR_UIF){
    _timer = (250-_timer) ? _timer+1 : 0;
    _timer_hour = (3600000-_timer_hour) ? _timer_hour+1 : 0;
    TIM4->SR &= ~TIM_SR_UIF;
  }
}

void DMA1_Channel1_IRQHandler(void){
  if(DMA1->ISR & DMA_ISR_TCIF1){
    DMA1_Channel1->CCR &= ~DMA_CCR1_EN;
    DMA1->IFCR |= DMA_IFCR_CTCIF1;
    WorkADC=0;
  }
}

void Init_ADC_DMA(void){
  DMA1_Channel1->CCR = 0;
  DMA1_Channel1->CPAR = (uint32_t) &ADC1->DR; 
  DMA1_Channel1->CMAR = (uint32_t) &ADC_Buf[0];
  DMA1_Channel1->CNDTR = BUF_SIZE;
  DMA1_Channel1->CCR |= DMA_CCR1_MINC | DMA_CCR1_MSIZE_1 | DMA_CCR1_PSIZE_1 | DMA_CCR1_TCIE;
  NVIC_EnableIRQ (DMA1_Channel1_IRQn);
}

void Init_ADC1(void){

  GPIOA->CRL &= ~GPIO_CRL_MODE1;
  GPIOA->CRL &= ~GPIO_CRL_CNF1;

  Init_ADC_DMA();	

  // 
  ADC1->SQR1 = 0;
  ADC1->SQR3 |= 1;
  ADC1->CR2 |= ADC_CR2_CONT;
  ADC1->CR1 &= ~ADC_CR1_SCAN;
  ADC1->CR2 |= ADC_CR2_EXTSEL | ADC_CR2_EXTTRIG | ADC_CR2_DMA;
  ADC1->CR2 |= ADC_CR2_ADON;
  
  _delay_10();
  
  ADC1->CR2 |= ADC_CR2_CAL;
  while (!(ADC1->CR2 & ADC_CR2_CAL)){};
}

void Init_PWM(void){
  
  GPIOA->CRL &= ~GPIO_CRL_MODE3;
  GPIOA->CRL |= GPIO_CRL_MODE3_1;
  GPIOA->CRL &= ~GPIO_CRL_CNF3;
  GPIOA->CRL |= GPIO_CRL_CNF3_1;
  
  TIM2->PSC = 9-1;
  TIM2->ARR = 500-1;
  TIM2->CCR4 = 250;
  TIM2->CR1 |= TIM_CR1_ARPE;
  TIM2->CCER |= TIM_CCER_CC4E;
  TIM2->CCMR2 |= (TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4M_1);
  TIM2->DIER |= TIM_DIER_UIE;
  NVIC_EnableIRQ(TIM2_IRQn);
//  TIM2->CR1 |= TIM_CR1_CEN;
}

void Init_ADC2(void){
  
  GPIOA->CRL &= ~GPIO_CRL_MODE2;
  GPIOA->CRL &= ~GPIO_CRL_CNF2;
  
  ADC2->SQR1 = 0;
  ADC2->SQR3 |= 2;
  ADC2->CR2 |= ADC_CR2_EXTSEL | ADC_CR2_EXTTRIG;
  
  ADC2->CR2 |= ADC_CR2_ADON;
  _delay_10();
  ADC2->CR2 |= ADC_CR2_CAL;
  while (!(ADC2->CR2 & ADC_CR2_CAL)){};
  
}

void Init_USART1(void) {
  //A9  - TX
  //A10 - RX
  
  GPIOA->CRH &= ~(GPIO_CRH_MODE9 | GPIO_CRH_MODE10);
  GPIOA->CRH &= ~(GPIO_CRH_CNF9 | GPIO_CRH_CNF10);
  GPIOA->CRH |= (GPIO_CRH_CNF9_1 | GPIO_CRH_MODE9_0);   // PA9 output 10 MHz, AFPP
  GPIOA->CRH |= GPIO_CRH_CNF10_1;                       // PA10 input
  GPIOA->BSRR |= GPIO_ODR_ODR10;                        
  USART1->CR1 = USART_CR1_UE;
  USART1->BRR = 7500;
  USART1->CR1 |= USART_CR1_TE | USART_CR1_RE ;
  USART1->CR2 = 0;
  USART1->CR3 = 0;
}

void _delay_10(void){
  for(u8 i=0;i<10;i++) {}
}

Вот код. Работает не так как я хочу.
Мне надо запустить "одновременно" ШИМ и АЦП. ШИМ на 500 мкс, АЦП на 1000 измерений (это 1.17 мс получается).
Но по отладке вижу, что ДМА в массив ADC_Buf записывает только 18 значений, причем через одну. (может где-то с размерами напутал?)
ЧЯДНТ?

Ссылка на комментарий
Поделиться на другие сайты

Поймал какую-то странность.
ШИМ делает 20 импульсов в частотой 40 кГц и скважностью 50%. АЦП работает с начала работы таймера ШИМ и до 1000 измерений.

Подключил напрямую ногу ШИМ и ногу АЦП, и получил следующую картину:
перед первым импульсом и после последнего АЦП ловит короткие (2 мкс) всплески, в массиве поучается что-то типа:
4095,4095,0,0,4095....тут все нормально, импульсы ШИМ идут поочерёдно, с заданной скважностью, после последнего импульса идёт низкий уровень и потом ещё 2 раза 4095 и опять нули до конца измерений.  

TIM3->CNT = 0;
TIM3->CR1 |= TIM_CR1_CEN;
ADC1->CR2 |= ADC_CR2_SWSTART;

while (_timer_pwm) {}
//TIM3->CNT = TIM3->CCR2+1;
TIM3->CCR2 = 0;
TIM3->CR1 &= ~TIM_CR1_CEN;

while(_work.adc) {}
ADC1->CR2 &= ~ADC_CR2_ADON;

_timer_pwm декрементируется в обработчике прерывания счётчика TIM3

Что за фича такая? Как убрать эти "всплески"? Почему ШИМ не начинает работать сразу?

Инициализация ШИМ:

RCC->APB1RSTR |= RCC_APB1RSTR_TIM3RST;
RCC->APB1RSTR &= ~RCC_APB1RSTR_TIM3RST;

GPIOA->CRL |= GPIO_CRL_MODE7;
GPIOA->CRL &= ~GPIO_CRL_CNF7;
GPIOA->CRL |= GPIO_CRL_CNF7_1;

uint32_t freq = 56000000;
uint32_t f = 40000;
uint32_t arr = 200;
uint32_t ccr = arr/2;

TIM3->PSC = freq/arr/f-1;
TIM3->ARR = arr-1;
TIM3->CCR2 = ccr;
TIM3->CR1 |= TIM_CR1_ARPE;
TIM3->CCER |= TIM_CCER_CC2E;
TIM3->CCMR1 |= (TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_1);
TIM3->DIER |= TIM_DIER_UIE;
NVIC_EnableIRQ(TIM3_IRQn);

 

Ссылка на комментарий
Поделиться на другие сайты

Перенёс выключение ШИМ в другое прерывание (TIM_DIER_CC2IE). Хвост пропал. 

Но "всплеск" в начале остался... Есть идеи как его убрать?

Изменено пользователем strifonoff
Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...