Микроконтроллеры

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Микроконтроллеры » Архив » DMA по переполнению таймера


DMA по переполнению таймера

Сообщений 1 страница 19 из 19

1

Пытаюсь сделать захват счетчика таймера,по другому таймеру переполнения.Настраиваю таймер и DMA вот так :

Код:
    //TIM3 500 mS DMA1 Chanel6 
    TIM3->ARR=Period3;
    TIM3->PSC=Prescaler3;
    
    
    DMA1_Channel6->CPAR = (uint32_t)&(TIM2->CNT); //
    DMA1_Channel6->CMAR = (uint32_t)&test; //
    DMA1_Channel6->CCR &= ~DMA_CCR1_DIR; // 
    DMA1_Channel6->CNDTR = 0x01; // 
    DMA1_Channel6->CCR &= ~DMA_CCR1_PINC; // 
    DMA1_Channel6->CCR |= DMA_CCR1_MINC; // 
    DMA1_Channel6->CCR |= DMA_CCR1_PSIZE_0; // 
    DMA1_Channel6->CCR |= DMA_CCR1_MSIZE_0; // 
    DMA1_Channel6->CCR |= DMA_CCR1_PL; // 
    DMA1_Channel6->CCR |= DMA_CCR1_CIRC; // 
    DMA1_Channel6->CCR |= DMA_CCR1_EN; // Enable chanel DMA
    
    TIM3->DIER |= TIM_DIER_UDE;
    TIM3->DIER |= TIM_DIER_UIE;
    TIM3->CR1 |= TIM_CR1_CEN;

Таймер 3 все считает,переполняется,а вот захвата нет в переменную test

Отредактировано CERGEI (2018-02-08 12:50:37)

2

Какой чип!!!!!!!!

Если 103 то на 6 канале нет реквеста TIM3_UP он на 3 канале.

3

Сори не указал,да 103 . Спасибо,пытаюсь свое тут придумывать ))
А я пытаюсь с 1 каналом TIM3_CH1 работать,спасибо.
На второй таймер посадил энкодер,а считываю через пол секунды с помощью DMA 3 таймера.

Вот весь настройки и все заработало.

Код:
DMA1_Channel3->CPAR = (uint32_t)&(TIM2->CNT); //
    DMA1_Channel3->CMAR = (uint32_t)&test; //
    DMA1_Channel3->CCR &= ~DMA_CCR1_DIR; // 
    DMA1_Channel3->CNDTR = 0x01; // 
    DMA1_Channel3->CCR &= ~DMA_CCR1_PINC; // 
    DMA1_Channel3->CCR |= DMA_CCR1_MINC; // 
    DMA1_Channel3->CCR |= DMA_CCR1_PSIZE_0; // 
    DMA1_Channel3->CCR |= DMA_CCR1_MSIZE_0; // 
    DMA1_Channel3->CCR |= DMA_CCR1_PL; // 
    DMA1_Channel3->CCR |= DMA_CCR1_CIRC; // 
    DMA1_Channel3->CCR |= DMA_CCR1_EN; // Enable chanel DMA
    
    TIM3->SR &= ~TIM_SR_UIF;
    TIM3->DIER |= TIM_DIER_UDE;
    //TIM3->DIER |= TIM_DIER_UIE;
    TIM3->CR2 |= TIM_CR2_CCDS;
    TIM3->CR1 |= TIM_CR1_CEN;

Отредактировано CERGEI (2018-02-08 13:38:29)

4

CERGEI написал(а):

А я пытаюсь с 1 каналом TIM3_CH1 работать,спасибо.

Реквест TIMx_CHx не от UPDATE а от достижения в Counter значения равному в TIMX_CCRx

5

Уже сообразил в чем ошибка.

Еще сразу вопросик по 1 таймеру это какое событие COMDE: COM DMA request enable ?

Смотрю еще по триггеру есть запрос DMA,тока пока не сообразил зачем по триггеру. Смотреть когда запускает таймер по внешнему таймеру или событию?

6

14.3.14 6-step PWM generation

When complementary outputs are used on a channel, preload bits are available on the
OCxM, CCxE and CCxNE bits. The preload bits are transferred to the shadow bits at the
COM commutation event. The user can thus program in advance the configuration for the
next step and change the configuration of all the channels at the same time. COM can be
generated by software by setting the COM bit in the TIMx_EGR register or by hardware (on
TRGI rising edge).

На счет триггера смотри картинку Figure 52. Advanced-control timer block diagram, если RM свежий Rev 17

7

CERGEI т.е. ты хочешь состояние энкодера считывать по ДМА? Другим таймером? Это какой-то промышленный энкодер?

Отредактировано MasterElectric (2018-02-08 20:39:45)

8

Да нет,энкодер для меню там с кнопочкой.
Энкодер
Может неправильно обзываю его,но чтоб с кнопочками не возится.Я и считываю его через дма,просто таймер читаю и делю на сколько мне нужно. Минус небольшой это возня там через FreeRtos для получения атомарности доступа.
http://s3.uploads.ru/t/6g5KO.jpg

Отредактировано CERGEI (2018-02-09 03:20:09)

9

http://s7.uploads.ru/t/EZcaU.png
То есть COM commutation event это просто одновременное изменение OCxM, CCxE and CCxNE bits при следующем начале периода сравнения с TIMX_CCRx вручную через TIMx_EGR или по триггеру возрастающему фронту?

Отредактировано CERGEI (2018-02-09 07:54:20)

10

CERGEI Не могу понять зачем для энкодера использовать ДМА, т.е. получаеться что обрабатываемые данные не будут данными реального времени. Я бы просто пытался достич прерывания по каждому шагу наверное.

11

почему не будут реальными? ведь передачу через дма я делаю раз в 100 мс,а для отображения для человека и установки уставки думаю быстрей не нужно.
Прерывание по каждому увеличению таймера? зачем? и есть ли оно такое прерывание?
Чем мне еще интересно дма,можно большую половину задач переложить на него в автомате,считай что второй процессор.

Отредактировано CERGEI (2018-02-10 05:01:42)

12

я кстати тоже все больше и больше использую DMA. и spi и uart. основной процесс лишь считает данные, следит за событиями и формирует буфера для dma.

13

CERGEI нету, но его как раз можно сделать на 2х каналах сравнения, если настроить прирост на -+4 тика. Ну я думал о таком решении у себя, но пока энкодер отложил.

14

MasterElectric написал(а):

CERGEI нету, но его как раз можно сделать на 2х каналах сравнения, если настроить прирост на -+4 тика. Ну я думал о таком решении у себя, но пока энкодер отложил.

То есть увеличение канал сравнения,другой на уменьшение ? потом прерывание на каждый и какую то переменную увеличивать или уменьшать в зависимости от прерывания. Кажись много мороки,если хотите конечно сэкономить таймер лишний.
А тут уже аппаратно под энкодер сделано,никаких извращений.
Каждый сам выбирает каким ему путем идти.

Тема наверно окончена. Приведу свой код настройки таймеров и дма для stm32f103.

Код:
 // TIM2 enkoder
    // remap input in PA0- TIM_CH1   PA1-TIM_CH2
        // enkoder
    // input float a0,a1
	  GPIOA->CRL&=~GPIO_CRL_MODE1;  // input
	  GPIOA->CRL&=~GPIO_CRL_CNF1;     
	  GPIOA->CRL|=GPIO_CRL_CNF1_0;  // 01- input float
	
    GPIOA->CRL&=~GPIO_CRL_MODE0;  // input
	  GPIOA->CRL&=~GPIO_CRL_CNF0;     
	  GPIOA->CRL|=GPIO_CRL_CNF0_0;  // 01- input float
    
    //TIM2 encoder
    TIM2->ARR=202;
    //AFIO->MAPR |= AFIO_MAPR_TIM2_REMAP_PARTIALREMAP1; /*!< Partial remap (CH1/ETR/PA15, CH2/PB3, CH3/PA2, CH4/PA3) */
	  TIM2->CCMR1|= TIM_CCMR1_CC1S_0|TIM_CCMR1_CC2S_0 ; // IC2 is mapped on TI2
                                                    	// IC1 is mapped on TI1
	  TIM2->CCMR1 |= TIM_CCMR1_IC1F | TIM_CCMR1_IC2F;   // filtr
	  TIM2->SMCR |= TIM_SMCR_SMS_0 | TIM_SMCR_SMS_1 ;  // SMS=011
	  TIM2->CR1|=TIM_CR1_CEN;
    
    //TIM3 100 mS DMA1 Chanel3 
    TIM3->ARR=Period3;
    TIM3->PSC=Prescaler3;
    
    
    DMA1_Channel3->CPAR = (uint32_t)&(TIM2->CNT); //
    DMA1_Channel3->CMAR = (uint32_t)&test; //
    DMA1_Channel3->CCR &= ~DMA_CCR1_DIR; // 
    DMA1_Channel3->CNDTR = 0x01; // 
    DMA1_Channel3->CCR &= ~DMA_CCR1_PINC; // 
    DMA1_Channel3->CCR |= DMA_CCR1_MINC; // 
    DMA1_Channel3->CCR |= DMA_CCR1_PSIZE_0; // 
    DMA1_Channel3->CCR |= DMA_CCR1_MSIZE_0; // 
    DMA1_Channel3->CCR |= DMA_CCR1_PL; // 
    DMA1_Channel3->CCR |= DMA_CCR1_CIRC; // 
    DMA1_Channel3->CCR |= DMA_CCR1_EN; // Enable chanel DMA
    DMA1_Channel3->CCR |= DMA_CCR1_TCIE;
    
    TIM3->DIER |= TIM_DIER_UDE;
    //TIM3->DIER |= TIM_DIER_UIE;
    TIM3->CR2 |= TIM_CR2_CCDS;
    TIM3->CR1 |= TIM_CR1_CEN;

15

CERGEI Я и не утверждал что у меня правильно, а у тебя нет. Опиши еще логику работы кода, и приведи код обработчика прерываний, а то не полная  картина. Мне например не все понятно.

16

Все просто,настраиваем один таймер TIM2 для работы с энкодером.Второй таймер TIM3 делаем как событие для дма по переполнению и дма забирает TIM2->CNT и записывает в переменную  test каждые 100 mS по дма.
Прерывание по окончании записи дма и отправка сообщением FreeRtos задаче которая отображает шим и меняет его скважность.
Просто боюсь я запутаю еще больше если буду описывать свою main.c, главное принцип понять что один таймер TIM2 работает с энкодером,а таймер TIM3 создает событие для передачи дма значения(TIM2->CNT) в переменную test.

http://s5.uploads.ru/t/FDqdX.png

Прерывание

Код:
void DMA1_Channel3_IRQHandler(void)
{
	if(DMA1->ISR & DMA_ISR_TCIF3)
	{
    //-------------------------------------------
    static BaseType_t xHigherPriorityTaskWoken;
    //-------------------------------------------
    
    DMA1->IFCR |= DMA_IFCR_CTCIF3;
    
    xHigherPriorityTaskWoken = pdFALSE;
    xQueueSendFromISR( xQueue_HIM, &test, &xHigherPriorityTaskWoken );
    portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
	}
	
	
}

Задача которая принимает сообщение

Код:
for( ;; )
	{
    sprintf(temp_2,"   шим= %d    ",ucHim);
    ssd1306_Puts(temp_2,1);  // text and stroka
	  ssd1306_update(1);
    
    if(xQueueReceive( xQueue_HIM, &( temp_queue ), 0 ))
    {
    	ucHim=temp_queue/2;
    	if(ucHim>=100)
        ucHim=100;
    }
     
     vTaskDelayUntil( &xLastWakeTime, 100/portTICK_PERIOD_MS );
	}

Отредактировано CERGEI (2018-02-11 12:35:11)

17

CERGEI Спасибо, теперь я понял суть. Вся фишка в использовании с ОС.

Отредактировано MasterElectric (2018-02-11 12:38:46)

18

При чем тут ОС :)

19

CERGEI Если бы не ОС, то я вообще не вижу смысла забирать 1 значение по ДМА. Это же все можно делать в прерывании по таймеру TIM3, а считать регистр CNT много времени не надо и кода тоже. ИМХО это лишнее, а с ОС ну вроде как да автоматом передает переменную в задачу где идет обработка.


Вы здесь » Микроконтроллеры » Архив » DMA по переполнению таймера