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

strifonoff

Members
  • Постов

    1 199
  • Зарегистрирован

  • Посещение

Сообщения, опубликованные strifonoff

  1. 7 часов назад, Lexter сказал:

    Откуда такое утверждение? Полярность чего он переключает?

    Гирлянда на 220 В?

    Гирлянда 5 вольтовая. 

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

    Переключает полярность на двух проводах. Сначала на одном плюс, а на другом минус. А потом наоборот. Что-то типа н-моста.

    Ещё вопросы? Или в Гугле только про БМВ написано?

  2. Никак не могу получить ровные края генерации ШИМ по двум каналам.
    Инициализация таймера:

     RCC->APB1RSTR |= RCC_APB1RSTR_TIM3RST;
       __NOP();__NOP();__NOP();
       RCC->APB1RSTR &= ~RCC_APB1RSTR_TIM3RST;
    
       GPIOA->ODR &= ~( GPIO_ODR_ODR6 | GPIO_ODR_ODR7 );
       GPIOA->CRL &= ~( GPIO_CRL_CNF6 | GPIO_CRL_CNF7 | GPIO_CRL_MODE6 | GPIO_CRL_MODE7 );
       GPIOA->CRL |= ( GPIO_CRL_MODE6 | GPIO_CRL_CNF6_1 | GPIO_CRL_MODE7 | GPIO_CRL_CNF7_1 );
    
       uint32_t arr = 200;
       uint32_t ccr = arr/2;
       uint32_t syf = 56000000;
    
       TIM3->CR2 |= TIM_CR2_MMS_1; // TRGO trigger
    
       TIM3->PSC = syf/arr/40000 - 1;
       TIM3->ARR = arr - 1;
       TIM3->CCR1 = ccr;
       TIM3->CCR2 = ccr;
       TIM3->CCMR1 |= ( TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_1 ); // TIM3_CH2 PWM mode 1
       TIM3->CCMR1 |= ( TIM_CCMR1_OC1M ); // TIM3_CH1 PWM mode 2
       TIM3->DIER |= TIM_DIER_UIE;
       TIM3->EGR = TIM_EGR_UG;
       TIM3->CR1 |= TIM_CR1_ARPE;
       TIM3->CCER |= ( TIM_CCER_CC1E | TIM_CCER_CC2E );
       TIM3->CR1 |= TIM_CR1_CEN;

    прерывание:

    void TIM3_IRQHandler(void)
    {
       static uint8_t count = 0;
       if (TIM3->SR & TIM_SR_UIF)
       {
          if(++count > 4)
          {
             count = 0;
             TIM3->CCER &= ~( TIM_CCER_CC1E | TIM_CCER_CC2E );
             TIM3->CR1 &= ~TIM_CR1_CEN;
          }
          TIM3->SR &= ~TIM_SR_UIF;
       }
    }

    На старте и финише ситуация на картинках

    Как сделать ровный старт и убрать всплеск в конце?

    не пишите пожалуйста про какие-то теневые регистры. пишите код.
     

     

    start.png

    stop.png

    ровный старт - это равный 12.5 мкс - полуволна 40 кГц

  3. Поймал какую-то странность.
    ШИМ делает 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);

     

  4. это снова я...

    Максимального быстродействия АЦП можно достичь при частоте АЦП 14 МГц, а этого можно добиться только при системной частоте 56 МГц (если внешний кварц на 8 МГц).
    Но возникает проблема со скоростями UART: значение регистра BRR не получится выставить так, что бы скорость была из стандартного ряда.

    Назрели несколько вопросов:
    1) возможно ли менять системную частоту на лету? (чую, что можно, но пока не знаю как) 
    2) критична ли ошибка в скорости UART по сравнению со стандартной? (что будет на другой стороне заранее не известно, т.к. любой может воткнуть свой девайс работающий на какой-то заранее согласованной стандартной скорости)
    3) как поведёт себя железо (состояние ОЗУ, регистров перефирии, состояние ног и т.д.) на изменение частоты? Две части программы () практически независимы, их объединяет только один массив, который наполняется в первой половине, а обрабатывается в другой.
     

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

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

    #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 значений, причем через одну. (может где-то с размерами напутал?)
    ЧЯДНТ?

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

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

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

  8. Вопрос по ШИМ.
    Если у 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;

  9. Т.е. получается так:
    АЦП работает и записывает результат в ADC1->DR, DMA это контролирует и перекидывает в мой массив, как только перекинул заданное количество - срабатывает прерывание? И таймер тут не нужен?

  10. Вопрос по АЦП.
    Если у меня цепочка из 5-ти АЦП каналов (регистры SQR1..3), каждый тратит 14 циклов на преобразование, это получается, что, например, 1-ый канал будет измеряться не каждые 14 циклов как мне надо, а 14*5?

×
×
  • Создать...