реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Запуск одного таймера от другого, stm32f103
Quantum1
сообщение Aug 7 2014, 06:47
Сообщение #1


Частый гость
**

Группа: Участник
Сообщений: 111
Регистрация: 4-09-12
Пользователь №: 73 381



Добрый день!

Пытаюсь на камне stm32f103 сделать следующее.

Первый таймер считает, на процовой частоте к примеру, досчитав до определенного значения запускает еще два таймера в режиме одного импульса.
Основная цель что бы эти 2 таймера запускались точно в заданный момент и одновременно. А и еще, это должно происходить автоматически, т.е. не програмно - настроил таймеры запустил первый и забыл.

Пытаюсь с триггеры таймеров крутить, но черт возьми - ничего не выходит.

Если подскажите как это сделать буду крайне благодарен, желательно на spl*)

Спасибо!

Сообщение отредактировал Quantum1 - Aug 7 2014, 06:48
Go to the top of the page
 
+Quote Post
Haamu
сообщение Aug 8 2014, 06:39
Сообщение #2


Частый гость
**

Группа: Участник
Сообщений: 90
Регистрация: 12-12-13
Пользователь №: 79 587



Цитата(Quantum1 @ Aug 7 2014, 10:47) *
Основная цель что бы эти 2 таймера запускались точно в заданный момент и одновременно. А и еще, это должно происходить автоматически, т.е. не програмно - настроил таймеры запустил первый и забыл.


Почему бы не запустить эти два таймера в прерывании от первого? Будет конечно разница в несколько системных тиков. Или синхронность абсолютная нужна? Поясните задачу целиком.
Go to the top of the page
 
+Quote Post
adnega
сообщение Aug 8 2014, 07:28
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(Quantum1 @ Aug 7 2014, 10:47) *
Если подскажите как это сделать буду крайне благодарен, желательно на spl*)

Нужно использовать каскадное включение таймеров. Первый таймер будет мастером для двух других таймеров, которые будут слейвами. Есть так называемый "Gated Mode" или как Вы уже правильно заметили "Trigger Mode".
Распишите поробнее TRGO мастер-таймера и TRGI слейвов.
Типа TIM1->PWM1->TRGO
TRGI_TIM1->ITR0->TIM2
TRGI_TIM1->ITR0->TIM3

Второй вариант TIM->CR2: MMS
Цитата
Enable - the Counter Enable signal CNT_EN is used as trigger output (TRGO). It is
useful to start several timers at the same time or to control a window in which a slave timer is
enable. The Counter Enable signal is generated by a logic OR between CEN control bit and
the trigger input when configured in gated mode. When the Counter Enable signal is
controlled by the trigger input, there is a delay on TRGO, except if the master/slave mode is
selected (see the MSM bit description in TIMx_SMCR register).
Go to the top of the page
 
+Quote Post
Quantum1
сообщение Aug 8 2014, 11:24
Сообщение #4


Частый гость
**

Группа: Участник
Сообщений: 111
Регистрация: 4-09-12
Пользователь №: 73 381



Цитата(adnega @ Aug 8 2014, 11:28) *
Нужно использовать каскадное включение таймеров. Первый таймер будет мастером для двух других таймеров, которые будут слейвами. Есть так называемый "Gated Mode" или как Вы уже правильно заметили "Trigger Mode".
Распишите поробнее TRGO мастер-таймера и TRGI слейвов.
Типа TIM1->PWM1->TRGO
TRGI_TIM1->ITR0->TIM2
TRGI_TIM1->ITR0->TIM3

Второй вариант TIM->CR2: MMS


А может сумеете подсказать какой-нить рабочий пример?



Цитата(Haamu @ Aug 8 2014, 10:39) *
Почему бы не запустить эти два таймера в прерывании от первого? Будет конечно разница в несколько системных тиков. Или синхронность абсолютная нужна? Поясните задачу целиком.


с прерываниями не вариант - нужно, что бы запустил и забыл.
Go to the top of the page
 
+Quote Post
adnega
сообщение Aug 8 2014, 11:46
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(Quantum1 @ Aug 8 2014, 15:24) *
А может сумеете подсказать какой-нить рабочий пример?

Собственно, я его и привел.
Хоите конкретики, вначале сами дайте конкретику.
Какие таймеры доступны, какие интервалы нужны, вплоть до конкретных пинов МК и т.п?
Go to the top of the page
 
+Quote Post
Quantum1
сообщение Aug 12 2014, 11:53
Сообщение #6


Частый гость
**

Группа: Участник
Сообщений: 111
Регистрация: 4-09-12
Пользователь №: 73 381



Цитата(adnega @ Aug 8 2014, 15:46) *
Собственно, я его и привел.
Хоите конкретики, вначале сами дайте конкретику.
Какие таймеры доступны, какие интервалы нужны, вплоть до конкретных пинов МК и т.п?


А зачем интервалы и тем более пины?

Нужен просто пример где один таймер, к примеру при CNT=CCR1, запускает другие два таймера, к примеру в режиме одиночного импульса. Какая разница будет там секунда или микросекунда в периоде.
Сама идея что нужно делать понятна...
Я пробовал играться с SPL, но результат нулевой... вообще некоторые функции связанные с триггерами мне мало понятны, у сожалению*)
Да, я пытался расписывать все эти мастеры, слейвы, экстернал триггеры и клоки, что бы вывести сигнал с одного таймера на его выходной триггер, а потом подключить к нему два других итд... но только еще больше запутался.

Если поможите буду очень благодарен.

я к сожалению плохо зная stm32 (знал бы хорошо вопросов бы не было конечно*))
Знаю по опыту, если тупик, можно и неделю биться и все бестолку.
А можно один ма-а-аленький примерчик глянуть и за 5 минут все решить*)

Сообщение отредактировал Quantum1 - Aug 12 2014, 12:03
Go to the top of the page
 
+Quote Post
adnega
сообщение Aug 12 2014, 12:52
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(Quantum1 @ Aug 12 2014, 15:53) *
А можно один ма-а-аленький примерчик глянуть и за 5 минут все решить*)

Не согласен, но можете поробовать. Это самый маленький пример каскадного использования сразу 4 таймеров, DMA и SPI.
К сожалению, на вопросы отвечать не готов. И стандартной библиотекой я не пользуюсь.
Пять минут пошли... )))
CODE
#ifdef TABLO_MODE_DYNAMIC2
//-----------------------------------------------------------------------------
// void __inline init_DMA1_CH6(int phase)
//-----------------------------------------------------------------------------
void __inline init_DMA1_CH6(int phase)
{
volatile int i;
// con_str("*");
// con_start();

TIM3->CR1 = 0;
TIM1->CR1 = 0;
TIM1->DIER = (0 << TIM_DIER_CC1DE);

DMA1_Channel6->CCR =
(DMA_PL_HIGH << DMA_CCR_PL) // приоритет высокий
| (DMA_SIZE_BYTE << DMA_CCR_MSIZE) // размер памяти 8-бит
| (DMA_SIZE_BYTE << DMA_CCR_PSIZE) // размер периферии 8-бит
| (1 << DMA_CCR_DIR)
| (1 << DMA_CCR_MINC) // автоинкремент памяти
| (0 << DMA_CCR_CIRC) // циклический буфер
| (0 << DMA_CCR_HTIE) // прерывание полузаполнения
| (0 << DMA_CCR_TCIE) // прерывание полного заполнения
| (0 << DMA_CCR_EN); // канал выключен

DMA1_Channel6->CPAR = SPI1_DR; // адрес периферийного регистра

DMA1_Channel6->CMAR = (vu32)&dynamic_video_trans[0]; // адрес буфера в памяти

DMA1_Channel6->CNDTR = DYNAMIC_VIDEO_SIZE; // размер буфера памяти

T1_STB_bit = 0;

DMA1->IFCR = (1 << DMA_ISR_TCIF6);
TIM1->DIER = (1 << TIM_DIER_CC1DE);
TIM1->CNT = 0;
TIM1->EGR = (1 << TIM_EGR_UG);
TIM1->SR = 0;

DMA1_Channel6->CCR =
(DMA_PL_HIGH << DMA_CCR_PL) // приоритет высокий
| (DMA_SIZE_BYTE << DMA_CCR_MSIZE) // размер памяти 8-бит
| (DMA_SIZE_BYTE << DMA_CCR_PSIZE) // размер периферии 8-бит
| (1 << DMA_CCR_DIR)
| (1 << DMA_CCR_MINC) // автоинкремент памяти
| (0 << DMA_CCR_CIRC) // циклический буфер
| (0 << DMA_CCR_HTIE) // прерывание полузаполнения
| (0 << DMA_CCR_TCIE) // прерывание полного заполнения
| (1 << DMA_CCR_EN); // канал включен

TIM15->CNT = 0;
TIM15->EGR = (1 << TIM_EGR_UG);
TIM15->CR1 =
(1 << TIM_CR1_CEN)
| (1 << TIM_CR1_OPM)
| (1 << TIM_CR1_ARPE);

TIM3->CNT = 0;
TIM3->EGR = (1 << TIM_EGR_UG);
TIM3->SR = 0;

TIM1->CR1 = (1 << TIM_CR1_CEN);
TIM3->CR1 = (1 << TIM_CR1_CEN);

TIM17->CNT = 0;
}

//-----------------------------------------------------------------------------
// void __inline init_TIMER1(void)
//-----------------------------------------------------------------------------
void __inline init_TIMER1(void)
{
TIM1->CR1 = 0;

if(rcc_state == RCC_STATE_PLL)
{
TIM1->PSC = (FPLL / FHSI) - 1;
}
else
{
TIM1->PSC = 0;
}

TIM1->ARR = (300) - 1;
TIM1->EGR = (1 << TIM_EGR_UG);

TIM1->CCR1 = 1; // импульс "DMA транзакция"
TIM1->CCER = (1 << TIM_CCER_CC1E); // импульс "DMA транзакция"
TIM1->CCMR1 = (OC_MODE_PWM1 << TIM_CCMR1_OC1M); // импульс "DMA транзакция"
TIM1->CCMR2 = 0;
TIM1->CR2 = 0;
TIM1->SMCR =
(0 << TIM_SMCR_TS) // ITR0 = TIM15
| (5 << TIM_SMCR_SMS); // GATED_MODE

TIM1->BDTR = (1 << TIM_BDTR_MOE);
TIM1->DIER = (1 << TIM_DIER_CC1DE);
}

//-----------------------------------------------------------------------------
// void __inline init_TIMER15(void)
//-----------------------------------------------------------------------------
void __inline init_TIMER15(void)
{
TIM15->CR1 = 0;
TIM15->EGR = (1 << TIM_EGR_UG);
TIM15->PSC = 0;
TIM15->ARR = 0xFFFF;
TIM15->SMCR =
(7 << TIM_SMCR_SMS) // EXTERNAL_CLOCK
| (1 << TIM_SMCR_TS); // ITR1 = TIM3

TIM15->CCR1 = (DYNAMIC_VIDEO_SIZE / DYNAMIC_VIDEO_N) + 0;

TIM15->CCER = (1 << TIM_CCER_CC1E);
TIM15->CCMR1 = (OC_MODE_PWM1 << TIM_CCMR1_OC1M);
TIM15->CCMR2 = 0;
TIM15->CR2 = (4 << TIM_CR2_MMS); // TRGO = OC1REF
TIM15->DIER = 0;
TIM15->BDTR = (1 << TIM_BDTR_MOE);
TIM15->CR1 =
(0 << TIM_CR1_CEN)
| (1 << TIM_CR1_OPM)
| (1 << TIM_CR1_ARPE);
}

//-----------------------------------------------------------------------------
// void __inline init_TIMER3(void)
//-----------------------------------------------------------------------------
void __inline init_TIMER3(void)
{
TIM3->CR1 = 0;

if(rcc_state == RCC_STATE_PLL)
{
TIM3->PSC = (FPLL / FHSI) - 1; // запись периода
TIM3->ARR = (300 * 32) - 1; // запись базы
TIM3->CCR3 = TIM3->ARR - 100; // импульс "сдвиг"
TIM3->CCR4 = TIM3->ARR - 200; // импульс "защелка"
}
else
{
TIM3->PSC = 0; // запись периода
TIM3->ARR = (300 * 32) - 1; // запись базы
TIM3->CCR3 = 1; //TIM2->ARR - 2; // импульс "сдвиг"
TIM3->CCR4 = TIM3->ARR - 1; // импульс "защелка"
}
TIM3->EGR = (1 << TIM_EGR_UG);

TIM3->CCR1 = 8; // импульс "DMA транзакция"
TIM3->CCR2 = TIM3->ARR - 200; // импульс "счет"
TIM3->CCER =
(1 << TIM_CCER_CC1E) // импульс "DMA транзакция"
| (1 << TIM_CCER_CC2E) // импульс "счет"
| (1 << TIM_CCER_CC3E) // импульс "защелка"
| (1 << TIM_CCER_CC4E); // импульс "сдвиг"

TIM3->CCMR1 =
(OC_MODE_PWM2 << TIM_CCMR1_OC1M) // импульс "DMA транзакция"
| (OC_MODE_PWM2 << TIM_CCMR1_OC2M); // импульс "счет"

TIM3->CCMR2 =
(OC_MODE_PWM2 << TIM_CCMR2_OC3M) // импульс "защелка"
| (OC_MODE_PWM2 << TIM_CCMR2_OC4M); // импульс "сдвиг"

TIM3->CR2 = (5 << TIM_CR2_MMS); // TRGO = OC2REF
TIM3->SMCR =
(2 << TIM_SMCR_TS) // ITR2 = TIM15
| (5 << TIM_SMCR_SMS); // GATED_MODE

TIM3->DIER = 0;

}

//-----------------------------------------------------------------------------
// void __inline init_TIMER16(void)
//-----------------------------------------------------------------------------
void __inline init_TIMER16(void)
{
if(rcc_state == RCC_STATE_PLL)
TIM16->PSC = (10 * FPLL / FHSI) - 1;
else
TIM16->PSC = (10) - 1;
TIM16->ARR = (800000 / FDYNAMIC_REFRESH) - 1;
TIM16->CR1 = 0;
TIM16->CCMR1 = 0;
TIM16->CCER = 0;
TIM16->SMCR = 0;
TIM16->DIER = (1 << TIM_DIER_UIE);
TIM16->BDTR = (1 << TIM_BDTR_MOE);
TIM16->CR1 = (1 << TIM_CR1_CEN);
}

//-----------------------------------------------------------------------------
// void __inline init_SPI1(void)
//-----------------------------------------------------------------------------
void __inline init_SPI1(void)
{
SPI1->CR1 =
(0 << SPI_CR1_SPE)
| (0 << SPI_CR1_DFF)
| (1 << SPI_CR1_SSM)
| (1 << SPI_CR1_SSI)
| (1 << SPI_CR1_MSTR)
| (3 << SPI_CR1_BR);

SPI1->CR2 =
(0 << SPI_CR2_RXNEIE)
| (0 << SPI_CR2_TXDMAEN)
| (1 << SPI_CR2_SSOE);

SPI1->CR1 =
(1 << SPI_CR1_SPE)
| (0 << SPI_CR1_DFF)
| (1 << SPI_CR1_SSM)
| (1 << SPI_CR1_SSI)
| (1 << SPI_CR1_MSTR)
| (3 << SPI_CR1_BR);
}
//-----------------------------------------------------------------------------
// void TIM1_TRG_COM_TIM17_IRQHandler(void)
//-----------------------------------------------------------------------------
void TIM1_TRG_COM_TIM17_IRQHandler(void) __attribute__((interrupt("IRQ")));
void TIM1_TRG_COM_TIM17_IRQHandler(void)
{
static int phase = 0;
static int dyn_cnt = 0;
int i;

if(TIM17->SR & (1 << TIM_SR_UIF))
{
TIM17->SR &= ~(1 << TIM_SR_UIF);

// DYNAMIC

for(i = 0; i < 40; i++) T1_STORE_bit = 0;

T1_STORE_bit = 1;
T1_STORE_bit = 0;

if(dyn_cnt > 7)
{
T1_STB_bit = 1;
T1_CLK_bit = 1;
T1_CLK_bit = 0;
T1_STB_bit = 0;
dyn_cnt = 0;
}
else
{
T1_CLK_bit = 1;
T1_CLK_bit = 0;
}

SPI1->CR2 =
(0 << SPI_CR2_RXNEIE)
| (0 << SPI_CR2_TXDMAEN)
| (1 << SPI_CR2_SSOE);

DMA1_Channel3->CCR =
(DMA_PL_HIGH << DMA_CCR_PL) // приоритет высокий
| (DMA_SIZE_BYTE << DMA_CCR_MSIZE) // размер памяти 8-бит
| (DMA_SIZE_BYTE << DMA_CCR_PSIZE) // размер периферии 8-бит
| (1 << DMA_CCR_DIR)
| (1 << DMA_CCR_MINC) // автоинкремент памяти
| (0 << DMA_CCR_CIRC) // циклический буфер
| (0 << DMA_CCR_HTIE) // прерывание полузаполнения
| (1 << DMA_CCR_TCIE) // прерывание полного заполнения
| (0 << DMA_CCR_EN); // канал выключен

DMA1_Channel3->CPAR = SPI1_DR; // адрес периферийного регистра

DMA1_Channel3->CMAR =
(vu32)&dynamic_video_trans[DYNAMIC_VIDEO_N * dyn_cnt]; // адрес буфера в памяти
DMA1_Channel3->CNDTR = DYNAMIC_VIDEO_N; // размер буфера памяти

DMA1_Channel3->CCR =
(DMA_PL_HIGH << DMA_CCR_PL) // приоритет высокий
| (DMA_SIZE_BYTE << DMA_CCR_MSIZE) // размер памяти 8-бит
| (DMA_SIZE_BYTE << DMA_CCR_PSIZE) // размер периферии 8-бит
| (1 << DMA_CCR_DIR)
| (1 << DMA_CCR_MINC) // автоинкремент памяти
| (0 << DMA_CCR_CIRC) // циклический буфер
| (0 << DMA_CCR_HTIE) // прерывание полузаполнения
| (1 << DMA_CCR_TCIE) // прерывание полного заполнения
| (1 << DMA_CCR_EN); // канал включен

SPI1->CR2 =
(0 << SPI_CR2_RXNEIE)
| (1 << SPI_CR2_TXDMAEN)
| (1 << SPI_CR2_SSOE);

dyn_cnt++;
}
}
Go to the top of the page
 
+Quote Post
Quantum1
сообщение Aug 13 2014, 05:00
Сообщение #8


Частый гость
**

Группа: Участник
Сообщений: 111
Регистрация: 4-09-12
Пользователь №: 73 381



Цитата(adnega @ Aug 12 2014, 16:52) *
Не согласен, но можете поробовать. Это самый маленький пример каскадного использования сразу 4 таймеров, DMA и SPI.
К сожалению, на вопросы отвечать не готов. И стандартной библиотекой я не пользуюсь.
Пять минут пошли... )))
CODE
#ifdef TABLO_MODE_DYNAMIC2
//-----------------------------------------------------------------------------
// void __inline init_DMA1_CH6(int phase)
//-----------------------------------------------------------------------------
void __inline init_DMA1_CH6(int phase)
{
volatile int i;
// con_str("*");
// con_start();

TIM3->CR1 = 0;
TIM1->CR1 = 0;
TIM1->DIER = (0 << TIM_DIER_CC1DE);

DMA1_Channel6->CCR =
(DMA_PL_HIGH << DMA_CCR_PL) // приоритет высокий
| (DMA_SIZE_BYTE << DMA_CCR_MSIZE) // размер памяти 8-бит
| (DMA_SIZE_BYTE << DMA_CCR_PSIZE) // размер периферии 8-бит
| (1 << DMA_CCR_DIR)
| (1 << DMA_CCR_MINC) // автоинкремент памяти
| (0 << DMA_CCR_CIRC) // циклический буфер
| (0 << DMA_CCR_HTIE) // прерывание полузаполнения
| (0 << DMA_CCR_TCIE) // прерывание полного заполнения
| (0 << DMA_CCR_EN); // канал выключен

DMA1_Channel6->CPAR = SPI1_DR; // адрес периферийного регистра

DMA1_Channel6->CMAR = (vu32)&dynamic_video_trans[0]; // адрес буфера в памяти

DMA1_Channel6->CNDTR = DYNAMIC_VIDEO_SIZE; // размер буфера памяти

T1_STB_bit = 0;

DMA1->IFCR = (1 << DMA_ISR_TCIF6);
TIM1->DIER = (1 << TIM_DIER_CC1DE);
TIM1->CNT = 0;
TIM1->EGR = (1 << TIM_EGR_UG);
TIM1->SR = 0;

DMA1_Channel6->CCR =
(DMA_PL_HIGH << DMA_CCR_PL) // приоритет высокий
| (DMA_SIZE_BYTE << DMA_CCR_MSIZE) // размер памяти 8-бит
| (DMA_SIZE_BYTE << DMA_CCR_PSIZE) // размер периферии 8-бит
| (1 << DMA_CCR_DIR)
| (1 << DMA_CCR_MINC) // автоинкремент памяти
| (0 << DMA_CCR_CIRC) // циклический буфер
| (0 << DMA_CCR_HTIE) // прерывание полузаполнения
| (0 << DMA_CCR_TCIE) // прерывание полного заполнения
| (1 << DMA_CCR_EN); // канал включен

TIM15->CNT = 0;
TIM15->EGR = (1 << TIM_EGR_UG);
TIM15->CR1 =
(1 << TIM_CR1_CEN)
| (1 << TIM_CR1_OPM)
| (1 << TIM_CR1_ARPE);

TIM3->CNT = 0;
TIM3->EGR = (1 << TIM_EGR_UG);
TIM3->SR = 0;

TIM1->CR1 = (1 << TIM_CR1_CEN);
TIM3->CR1 = (1 << TIM_CR1_CEN);

TIM17->CNT = 0;
}

//-----------------------------------------------------------------------------
// void __inline init_TIMER1(void)
//-----------------------------------------------------------------------------
void __inline init_TIMER1(void)
{
TIM1->CR1 = 0;

if(rcc_state == RCC_STATE_PLL)
{
TIM1->PSC = (FPLL / FHSI) - 1;
}
else
{
TIM1->PSC = 0;
}

TIM1->ARR = (300) - 1;
TIM1->EGR = (1 << TIM_EGR_UG);

TIM1->CCR1 = 1; // импульс "DMA транзакция"
TIM1->CCER = (1 << TIM_CCER_CC1E); // импульс "DMA транзакция"
TIM1->CCMR1 = (OC_MODE_PWM1 << TIM_CCMR1_OC1M); // импульс "DMA транзакция"
TIM1->CCMR2 = 0;
TIM1->CR2 = 0;
TIM1->SMCR =
(0 << TIM_SMCR_TS) // ITR0 = TIM15
| (5 << TIM_SMCR_SMS); // GATED_MODE

TIM1->BDTR = (1 << TIM_BDTR_MOE);
TIM1->DIER = (1 << TIM_DIER_CC1DE);
}

//-----------------------------------------------------------------------------
// void __inline init_TIMER15(void)
//-----------------------------------------------------------------------------
void __inline init_TIMER15(void)
{
TIM15->CR1 = 0;
TIM15->EGR = (1 << TIM_EGR_UG);
TIM15->PSC = 0;
TIM15->ARR = 0xFFFF;
TIM15->SMCR =
(7 << TIM_SMCR_SMS) // EXTERNAL_CLOCK
| (1 << TIM_SMCR_TS); // ITR1 = TIM3

TIM15->CCR1 = (DYNAMIC_VIDEO_SIZE / DYNAMIC_VIDEO_N) + 0;

TIM15->CCER = (1 << TIM_CCER_CC1E);
TIM15->CCMR1 = (OC_MODE_PWM1 << TIM_CCMR1_OC1M);
TIM15->CCMR2 = 0;
TIM15->CR2 = (4 << TIM_CR2_MMS); // TRGO = OC1REF
TIM15->DIER = 0;
TIM15->BDTR = (1 << TIM_BDTR_MOE);
TIM15->CR1 =
(0 << TIM_CR1_CEN)
| (1 << TIM_CR1_OPM)
| (1 << TIM_CR1_ARPE);
}

//-----------------------------------------------------------------------------
// void __inline init_TIMER3(void)
//-----------------------------------------------------------------------------
void __inline init_TIMER3(void)
{
TIM3->CR1 = 0;

if(rcc_state == RCC_STATE_PLL)
{
TIM3->PSC = (FPLL / FHSI) - 1; // запись периода
TIM3->ARR = (300 * 32) - 1; // запись базы
TIM3->CCR3 = TIM3->ARR - 100; // импульс "сдвиг"
TIM3->CCR4 = TIM3->ARR - 200; // импульс "защелка"
}
else
{
TIM3->PSC = 0; // запись периода
TIM3->ARR = (300 * 32) - 1; // запись базы
TIM3->CCR3 = 1; //TIM2->ARR - 2; // импульс "сдвиг"
TIM3->CCR4 = TIM3->ARR - 1; // импульс "защелка"
}
TIM3->EGR = (1 << TIM_EGR_UG);

TIM3->CCR1 = 8; // импульс "DMA транзакция"
TIM3->CCR2 = TIM3->ARR - 200; // импульс "счет"
TIM3->CCER =
(1 << TIM_CCER_CC1E) // импульс "DMA транзакция"
| (1 << TIM_CCER_CC2E) // импульс "счет"
| (1 << TIM_CCER_CC3E) // импульс "защелка"
| (1 << TIM_CCER_CC4E); // импульс "сдвиг"

TIM3->CCMR1 =
(OC_MODE_PWM2 << TIM_CCMR1_OC1M) // импульс "DMA транзакция"
| (OC_MODE_PWM2 << TIM_CCMR1_OC2M); // импульс "счет"

TIM3->CCMR2 =
(OC_MODE_PWM2 << TIM_CCMR2_OC3M) // импульс "защелка"
| (OC_MODE_PWM2 << TIM_CCMR2_OC4M); // импульс "сдвиг"

TIM3->CR2 = (5 << TIM_CR2_MMS); // TRGO = OC2REF
TIM3->SMCR =
(2 << TIM_SMCR_TS) // ITR2 = TIM15
| (5 << TIM_SMCR_SMS); // GATED_MODE

TIM3->DIER = 0;

}

//-----------------------------------------------------------------------------
// void __inline init_TIMER16(void)
//-----------------------------------------------------------------------------
void __inline init_TIMER16(void)
{
if(rcc_state == RCC_STATE_PLL)
TIM16->PSC = (10 * FPLL / FHSI) - 1;
else
TIM16->PSC = (10) - 1;
TIM16->ARR = (800000 / FDYNAMIC_REFRESH) - 1;
TIM16->CR1 = 0;
TIM16->CCMR1 = 0;
TIM16->CCER = 0;
TIM16->SMCR = 0;
TIM16->DIER = (1 << TIM_DIER_UIE);
TIM16->BDTR = (1 << TIM_BDTR_MOE);
TIM16->CR1 = (1 << TIM_CR1_CEN);
}

//-----------------------------------------------------------------------------
// void __inline init_SPI1(void)
//-----------------------------------------------------------------------------
void __inline init_SPI1(void)
{
SPI1->CR1 =
(0 << SPI_CR1_SPE)
| (0 << SPI_CR1_DFF)
| (1 << SPI_CR1_SSM)
| (1 << SPI_CR1_SSI)
| (1 << SPI_CR1_MSTR)
| (3 << SPI_CR1_BR);

SPI1->CR2 =
(0 << SPI_CR2_RXNEIE)
| (0 << SPI_CR2_TXDMAEN)
| (1 << SPI_CR2_SSOE);

SPI1->CR1 =
(1 << SPI_CR1_SPE)
| (0 << SPI_CR1_DFF)
| (1 << SPI_CR1_SSM)
| (1 << SPI_CR1_SSI)
| (1 << SPI_CR1_MSTR)
| (3 << SPI_CR1_BR);
}
//-----------------------------------------------------------------------------
// void TIM1_TRG_COM_TIM17_IRQHandler(void)
//-----------------------------------------------------------------------------
void TIM1_TRG_COM_TIM17_IRQHandler(void) __attribute__((interrupt("IRQ")));
void TIM1_TRG_COM_TIM17_IRQHandler(void)
{
static int phase = 0;
static int dyn_cnt = 0;
int i;

if(TIM17->SR & (1 << TIM_SR_UIF))
{
TIM17->SR &= ~(1 << TIM_SR_UIF);

// DYNAMIC

for(i = 0; i < 40; i++) T1_STORE_bit = 0;

T1_STORE_bit = 1;
T1_STORE_bit = 0;

if(dyn_cnt > 7)
{
T1_STB_bit = 1;
T1_CLK_bit = 1;
T1_CLK_bit = 0;
T1_STB_bit = 0;
dyn_cnt = 0;
}
else
{
T1_CLK_bit = 1;
T1_CLK_bit = 0;
}

SPI1->CR2 =
(0 << SPI_CR2_RXNEIE)
| (0 << SPI_CR2_TXDMAEN)
| (1 << SPI_CR2_SSOE);

DMA1_Channel3->CCR =
(DMA_PL_HIGH << DMA_CCR_PL) // приоритет высокий
| (DMA_SIZE_BYTE << DMA_CCR_MSIZE) // размер памяти 8-бит
| (DMA_SIZE_BYTE << DMA_CCR_PSIZE) // размер периферии 8-бит
| (1 << DMA_CCR_DIR)
| (1 << DMA_CCR_MINC) // автоинкремент памяти
| (0 << DMA_CCR_CIRC) // циклический буфер
| (0 << DMA_CCR_HTIE) // прерывание полузаполнения
| (1 << DMA_CCR_TCIE) // прерывание полного заполнения
| (0 << DMA_CCR_EN); // канал выключен

DMA1_Channel3->CPAR = SPI1_DR; // адрес периферийного регистра

DMA1_Channel3->CMAR =
(vu32)&dynamic_video_trans[DYNAMIC_VIDEO_N * dyn_cnt]; // адрес буфера в памяти
DMA1_Channel3->CNDTR = DYNAMIC_VIDEO_N; // размер буфера памяти

DMA1_Channel3->CCR =
(DMA_PL_HIGH << DMA_CCR_PL) // приоритет высокий
| (DMA_SIZE_BYTE << DMA_CCR_MSIZE) // размер памяти 8-бит
| (DMA_SIZE_BYTE << DMA_CCR_PSIZE) // размер периферии 8-бит
| (1 << DMA_CCR_DIR)
| (1 << DMA_CCR_MINC) // автоинкремент памяти
| (0 << DMA_CCR_CIRC) // циклический буфер
| (0 << DMA_CCR_HTIE) // прерывание полузаполнения
| (1 << DMA_CCR_TCIE) // прерывание полного заполнения
| (1 << DMA_CCR_EN); // канал включен

SPI1->CR2 =
(0 << SPI_CR2_RXNEIE)
| (1 << SPI_CR2_TXDMAEN)
| (1 << SPI_CR2_SSOE);

dyn_cnt++;
}
}


это разве самый маленький пример? знать бы еще для начала какой таймер куда... т.е. хотя бы что там каждый таймер делает.. тем более что комментариев там практически нет... да и мне полезны из этого примеры на максимум 5-6 строчек, если не меньше*))


Раз уж вы так хотите пины*)) без проблем... берем TIM1 - он будет ведущим, каждые 500мкс при CNT=CCR1, он инициирует один запуск TIM3_CH1(длительность импульса 40мкс, выводится на PA6) и TIM3_CH2(длительность импульса 5мкс, выводится на PA7).

Сообщение отредактировал Quantum1 - Aug 13 2014, 05:15
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Aug 13 2014, 06:30
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



почему всегда все так сложно?
я скачал реф мануал от 32f103c6, и в нем поглядел раздел таймеры. И там очень быстро нашел ссылку как сделать один таймер запускателем второго
Using one timer to enable another timer, страница 392.
куда уж лучшие примеры? Там и описано все по шагам чего куда настроить и так далее... Ну да без библиотек идиотских с кучей функций перекрывающих друг друга, зато по сути, настроил регистры так, эти сяк, этот досчитал, эти поехали...

Go to the top of the page
 
+Quote Post
adnega
сообщение Aug 13 2014, 07:22
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(Quantum1 @ Aug 13 2014, 09:00) *
Раз уж вы так хотите пины*)) без проблем... берем TIM1 - он будет ведущим, каждые 500мкс при CNT=CCR1, он инициирует один запуск TIM3_CH1(длительность импульса 40мкс, выводится на PA6) и TIM3_CH2(длительность импульса 5мкс, выводится на PA7).

Т.е. процесс должен быть периодическим, или нужен ручной запуск однократной последовательности?
Это для периодической генерации
CODE
TIM1->CR1 = 0;
TIM1->CR2 = (4 << TIM_CR2_MMS); // OC1REF -> TRGO
TIM1->PSC = 72 - 1;
TIM1->ARR = 500 - 1;
TIM1->EGR = (1 << TIM_EGR_UG);
TIM1->CCMR1 = (OC_MODE_PWM2 << TIM_CCMR1_OC1M);
TIM1->CCER = (1 << TIM_CCER_CC1E);
TIM1->BDTR = (1 << TIM_BDTR_MOE);
TIM1->CCR1 = 100;

TIM3->CR1 = 0;
TIM3->PSC = 72 - 1;
TIM3->ARR = 0xffff;
TIM3->EGR = (1 << TIM_EGR_UG);
TIM3->CCMR1 = (OC_MODE_PWM1 << TIM_CCMR1_OC1M) | (OC_MODE_PWM1 << TIM_CCMR1_OC2M);
TIM3->CCER = (1 << TIM_CCER_CC1E) | (1 << TIM_CCER_CC2E);
TIM3->SMCR =
(0 << TIM_SMCR_TS) // TRGI -> ITR0 (TIM1)
| (4 << TIM_SMCR_SMS); // Reset Mode

TIM3->CCR1 = 40;
TIM3->CCR2 = 5;
TIM3->CR1 = (1 << TIM_CR1_CEN);

TIM1->CR1 = (1 << TIM_CR1_CEN);


Для однократного запуска

CODE
// pulse
TIM1->CR1 = 0;
TIM1->CR2 = (4 << TIM_CR2_MMS); // OC1REF -> TRGO
TIM1->PSC = 72 - 1;
TIM1->ARR = 500 - 1;
TIM1->EGR = (1 << TIM_EGR_UG);
TIM1->CCMR1 = (OC_MODE_PWM2 << TIM_CCMR1_OC1M);
TIM1->CCER = (1 << TIM_CCER_CC1E);
TIM1->BDTR = (1 << TIM_BDTR_MOE);
TIM1->CCR1 = 100 - 1; // на один такт меньше

TIM3->CR1 = 0;
TIM3->PSC = 72 - 1;
TIM3->ARR = 0xffff;
TIM3->EGR = (1 << TIM_EGR_UG);
TIM3->CCMR1 = (OC_MODE_PWM1 << TIM_CCMR1_OC1M) | (OC_MODE_PWM1 << TIM_CCMR1_OC2M);
TIM3->CCER = (1 << TIM_CCER_CC1E) | (1 << TIM_CCER_CC2E);
TIM3->SMCR =
(0 << TIM_SMCR_TS) // TRGI -> ITR0 (TIM1)
| (5 << TIM_SMCR_SMS); // Gated Mode

TIM3->CCR1 = 40;
TIM3->CCR2 = 5;
TIM3->CR1 = (1 << TIM_CR1_CEN);

while(1)
{
if(pulse)
{
TIM3->CNT = 0xffff; // -1 для генерации события UR
TIM1->CR1 = (1 << TIM_CR1_CEN) | (1 << TIM_CR1_OPM);
pulse = 0;
}
}


Проверено в железе (STM32F103T8U6 @ 72MHz) - работает.

Цитата(Golikov A. @ Aug 13 2014, 10:30) *
почему всегда все так сложно?
я скачал реф мануал от 32f103c6, и в нем поглядел раздел таймеры. И там очень быстро нашел ссылку как сделать один таймер запускателем второго
Using one timer to enable another timer, страница 392.
куда уж лучшие примеры? Там и описано все по шагам чего куда настроить и так далее... Ну да без библиотек идиотских с кучей функций перекрывающих друг друга, зато по сути, настроил регистры так, эти сяк, этот досчитал, эти поехали...

Там есть тонкости в работе ШИМ для однокрытного запуска. По сути при сработке UR (досчитал до конца) уровень ШИМ выставляется, при достижении сравнения - снимается.
Так вот, когда таймер стартует UR не происходит, а выставляется уровень только после окончания счета (CNT > ARR). Это надо прочувствовать))
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Aug 13 2014, 09:29
Сообщение #11


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(adnega @ Aug 13 2014, 13:22) *
Код
...
    TIM1->BDTR = (1 << TIM_BDTR_MOE);
...

Глаз споткнулся на вашем примере. В stm32f10x.h TIM_BDTR_MOE определён как 0x8000. (1 << 0x8000) = 0. И так во всём вашем коде.
Вы переопределили все маски в номера битов что ли?


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
adnega
сообщение Aug 13 2014, 12:46
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(AHTOXA @ Aug 13 2014, 13:29) *
Глаз споткнулся на вашем примере. В stm32f10x.h TIM_BDTR_MOE определён как 0x8000. (1 << 0x8000) = 0. И так во всём вашем коде.
Вы переопределили все маски в номера битов что ли?

Ага. Я в define указываю номера битов.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Aug 13 2014, 15:11
Сообщение #13


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



С тем же именем, что и у маски в stm32f10x.h? Вы прямо этот файл переделали?
Кстати, аккуратнее писать (1UL << BIT_NUM), чтобы не иметь проблем со старшим битом.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Aug 13 2014, 17:44
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



жестоко штатный хедер переписать под свой стильsm.gif....

при сдвиге влево вроде как пофиг на старший бит, гораздо важнее что L - то есть лонг, а то найдется компилятор который 16 бит по умолчанию делает, и при сдвиге дальше 16 все обнулится...
хотя после всей этой пляски с битностью инта перехожу на явные типы (((uint32_t) 0x01) << SHIFT)
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Aug 13 2014, 19:19
Сообщение #15


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(Golikov A. @ Aug 13 2014, 23:44) *
при сдвиге влево вроде как пофиг на старший бит, гораздо важнее что L

Нет, не пофиг. По умолчанию будет int. И при сдвиге int-а на 31 влево получится фигня.

Цитата(Golikov A. @ Aug 13 2014, 23:44) *
хотя после всей этой пляски с битностью инта перехожу на явные типы (((uint32_t) 0x01) << SHIFT)

1UL тоже явный тип. И выглядит поприличнее, чем приведение типа. ИМХО конечно.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 20:56
Рейтинг@Mail.ru


Страница сгенерированна за 0.01558 секунд с 7
ELECTRONIX ©2004-2016