|
Запуск одного таймера от другого, stm32f103 |
|
|
|
Aug 8 2014, 06:39
|
Частый гость
 
Группа: Участник
Сообщений: 90
Регистрация: 12-12-13
Пользователь №: 79 587

|
Цитата(Quantum1 @ Aug 7 2014, 10:47)  Основная цель что бы эти 2 таймера запускались точно в заданный момент и одновременно. А и еще, это должно происходить автоматически, т.е. не програмно - настроил таймеры запустил первый и забыл. Почему бы не запустить эти два таймера в прерывании от первого? Будет конечно разница в несколько системных тиков. Или синхронность абсолютная нужна? Поясните задачу целиком.
|
|
|
|
|
Aug 8 2014, 07:28
|
Гуру
     
Группа: Свой
Сообщений: 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).
|
|
|
|
|
Aug 8 2014, 11:24
|
Частый гость
 
Группа: Участник
Сообщений: 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)  Почему бы не запустить эти два таймера в прерывании от первого? Будет конечно разница в несколько системных тиков. Или синхронность абсолютная нужна? Поясните задачу целиком. с прерываниями не вариант - нужно, что бы запустил и забыл.
|
|
|
|
|
Aug 12 2014, 11:53
|
Частый гость
 
Группа: Участник
Сообщений: 111
Регистрация: 4-09-12
Пользователь №: 73 381

|
Цитата(adnega @ Aug 8 2014, 15:46)  Собственно, я его и привел. Хоите конкретики, вначале сами дайте конкретику. Какие таймеры доступны, какие интервалы нужны, вплоть до конкретных пинов МК и т.п? А зачем интервалы и тем более пины? Нужен просто пример где один таймер, к примеру при CNT=CCR1, запускает другие два таймера, к примеру в режиме одиночного импульса. Какая разница будет там секунда или микросекунда в периоде. Сама идея что нужно делать понятна... Я пробовал играться с SPL, но результат нулевой... вообще некоторые функции связанные с триггерами мне мало понятны, у сожалению*) Да, я пытался расписывать все эти мастеры, слейвы, экстернал триггеры и клоки, что бы вывести сигнал с одного таймера на его выходной триггер, а потом подключить к нему два других итд... но только еще больше запутался. Если поможите буду очень благодарен. я к сожалению плохо зная stm32 (знал бы хорошо вопросов бы не было конечно*)) Знаю по опыту, если тупик, можно и неделю биться и все бестолку. А можно один ма-а-аленький примерчик глянуть и за 5 минут все решить*)
Сообщение отредактировал Quantum1 - Aug 12 2014, 12:03
|
|
|
|
|
Aug 12 2014, 12:52
|
Гуру
     
Группа: Свой
Сообщений: 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++; } }
|
|
|
|
|
Aug 13 2014, 05:00
|
Частый гость
 
Группа: Участник
Сообщений: 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
|
|
|
|
|
Aug 13 2014, 07:22
|
Гуру
     
Группа: Свой
Сообщений: 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). Это надо прочувствовать))
|
|
|
|
|
Aug 13 2014, 09:29
|

фанат дивана
     
Группа: Свой
Сообщений: 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. И так во всём вашем коде. Вы переопределили все маски в номера битов что ли?
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Aug 13 2014, 19:19
|

фанат дивана
     
Группа: Свой
Сообщений: 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 тоже явный тип. И выглядит поприличнее, чем приведение типа. ИМХО конечно.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|