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

Настроить TIM2-TIM5 на генерацию ШИМ довольно просто

void PwmInit(void)
{
  //ch1 -PA0
  GPIOA->CRL |= GPIO_CRL_MODE0;  //50Mhz
  GPIOA->CRL &= ~GPIO_CRL_CNF0; //clear CNF[1:0] for PA0 
  GPIOA->CRL |= GPIO_CRL_CNF0_1; //output Push-Pull in alternative function mode
  //ch2 - PA1
  GPIOA->CRL |= GPIO_CRL_MODE1;  //50Mhz
  GPIOA->CRL &= ~GPIO_CRL_CNF1; //clear CNF[1:0] for PA1 
  GPIOA->CRL |= GPIO_CRL_CNF1_1; //output Push-Pull in alternative function mode
  //ch3 - PA2
  GPIOA->CRL |= GPIO_CRL_MODE2;  //50Mhz
  GPIOA->CRL &= ~GPIO_CRL_CNF2; //clear CNF[1:0] for PA2 
  GPIOA->CRL |= GPIO_CRL_CNF2_1; //output Push-Pull in alternative function mode
  //ch4 - PA3
  GPIOA->CRL |= GPIO_CRL_MODE3;  //50Mhz
  GPIOA->CRL &= ~GPIO_CRL_CNF3; //clear CNF[1:0] for PA3 
  GPIOA->CRL |= GPIO_CRL_CNF3_1; //output Push-Pull in alternative function mode
  //TIM2 Settings
  RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
  TIM2->CR1 |= TIM_CR1_ARPE;  //autorelode mode
  TIM2->CCMR1 |= TIM_CCMR1_OC1PE | TIM_CCMR1_OC2PE;  //Output Compare Preload enable
  TIM2->CCMR2 |= TIM_CCMR2_OC3PE | TIM_CCMR2_OC4PE;
  //TIM2->PSC = 71;  //1us
  TIM2->ARR = 8000;  // 8000*14ns = 112us = 8928Hz
  TIM2->CCR1 = 4000; //ch1 1duty cycle = 50%
  TIM2->CCR2 = 4000; //ch2 1duty cycle = 50%
  TIM2->CCR3 = 4000; //ch2 1duty cycle = 50%
  TIM2->CCR4 = 4000; //ch2 1duty cycle = 50%
  //TIM2->CCER |= TIM_CCER_CC2P;  //polarity of output signal
  //Capture/Compare 2 output enable
  TIM2->CCER |= TIM_CCER_CC1E | TIM_CCER_CC2E | TIM_CCER_CC3E | TIM_CCER_CC4E;
  //Output Compare Mode - 110 - PWM mode 1
  TIM2->CCMR1 |= (TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1); 
  TIM2->CCMR1 |= (TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_1);
  TIM2->CCMR2 |= (TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1);
  TIM2->CCMR2 |= (TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4M_1);
  //start counting
  TIM2->CR1 |= TIM_CR1_CEN;  
}

Все просто все понятно.

С TIM1/TIM8 не все так понятно - там другие регистры и я, честно говоря, запутался.

Может кто нибудь работал с этими таймерами и может прояснить ситуацию? Заранее спасибо.

Поделиться сообщением


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

Настраивается все... что именно нужно объяснить?

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

 

Поделиться сообщением


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

void Timer1_Init (void)
{
    RCC->APB2ENR  |= (1<<0);                                                    //вкл. тактиров. таймера1
    TIM1->PSC = 20;                                                                        //делитель чтоб не лезть в даташит если он понадобится
    TIM1->CCMR1 |= (7<<12)|(7<<4);                                        //+ канал 1 и 2 - ШИМ
    TIM1->CCMR2 |= (7<<12)|(7<<4);                                        //+ канал 3 и 4 - ШИМ
    TIM1->CCER  |= (1<<12)|(1<<8)|(1<<4)|(1<<0);            //+
    TIM1->BDTR    |= (1<<15);
    TIM1->CCR1 = 0xFFFF;                                                            //значение ШИМ канал 1 (ТЕМ1.1) чем меньше тем длиннее 1
    TIM1->CCR2 = 0xFFFF;                                                            //значение ШИМ канал 2 (ТЕМ1.2)
    TIM1->CCR3 = 0xFFFF;                                                            //значение ШИМ канал 3 (ТЕМ2.1)
    TIM1->CCR4 = 0xFFFF;                                                            //значение ШИМ канал 4 (ТЕМ2.2)
    TIM1->CR1 |= (1<<0);                                                            //вкл. таймер 1
}

 

Ну и выводы на выход в альтернативном назначении. Это для 207, но там таймер такой же. Регистры только проверьте, но смсл тот же.

Поделиться сообщением


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

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

Регистры TIM2 это просто подмножество регистров TIM1.

У Вас не хватает этой строчки:

TIM1->BDTR |= TIM_BDTR_MOE;

вот прямо из текущего прожекта,

если не нужен DMA, часть текста после //DMA Init можно выбросить, .

void InitTIM1(int enable)
{
 TIM1->CR1 = TIM_CR1_ARPE | TIM_CounterMode_Up;
 TIM1->ARR = 5*24-1; // период повторения, 0 - останов
 TIM1->PSC = 0;      // прескалер на 1, один тик = 1/24 мкс
 TIM1->RCR = 0;      //TIM_RepetitionCounter;

 // OC1
 TIM1->CCR1  = 12;    // 0.5мкс.
 TIM1->CCMR1 = TIM_OCMode_Toggle; //TIM_OCMode_PWM2;  
 TIM1->CCER  = TIM_OCPolarity_High | TIM_OutputState_Enable;
 // OC2
 TIM1->CCR2  = 24;     // 1.0us
 TIM1->CCMR1 |= TIM_OCMode_Toggle << 8;  
 TIM1->CCER  |= (TIM_OCPolarity_High | TIM_OutputState_Enable) <<4;  
 // OC 3
 TIM1->CCR3  = 36;     // 1.5us.
 TIM1->CCMR2 |= TIM_OCMode_PWM1;  
 TIM1->CCER  |= (  TIM_OCPolarity_High | TIM_OutputState_Enable 
                 | TIM_OCNPolarity_Low | TIM_OutputNState_Enable)<<8; 
  // OC4
 TIM1->CCR4  = 24;     // 1us
 TIM1->CCMR2 |= TIM_OCMode_PWM1 << 8;  
 TIM1->CCER  |= (TIM_OCPolarity_High | TIM_OutputState_Enable) <<12;  

 TIM1->EGR   = TIM_EGR_UG; // генерируем update event для загрузки всех теневых регистров
 TIM1->BDTR |= TIM_BDTR_MOE + 12; // разрешение выходных сигналов OCx + dead-time 0.5us

 // DMA Init
 TIM1->DIER = TIM_DIER_UDE;
 TIM1->DCR  =  (0<<8) | (&(TIM1->ARR) - &(TIM1->CR1))/sizeof(TIM1->CR1);
 DMA1_Channel5->CCR = 0
   | 0*DMA_CCR1_EN            // Channel enable
   | 0*DMA_CCR1_TCIE          // Transfer complete interrupt enable
   | DMA_CCR1_DIR           // Data transfer direction 1: Mem --> Periph
   | DMA_CCR1_CIRC          // Circular mode
   | 0*DMA_CCR1_PINC          // Peripheral increment mode
   | DMA_CCR1_MINC          // Memory increment mode
   | DMA_PeripheralDataSize_Word  // DMA_CCR1_PSIZE   PSIZE[1:0] bits (Peripheral size)
   | DMA_MemoryDataSize_HalfWord  // DMA_CCR1_MSIZE   MSIZE[1:0] bits (Memory size)
   | (3<<12)  //*DMA_CCR1_PL      // PL[1:0] bits(Channel Priority level)
   | 0*DMA_CCR1_MEM2MEM;    // Memory to memory mode

 DMA1_Channel5->CNDTR = 2;
 DMA1_Channel5->CPAR = (uint32_t)&(TIM1->DMAR);
 DMA1_Channel5->CMAR = (uint32_t) dmabuf;
 DMA1_Channel5->CCR |= DMA_CCR1_EN;    // Channel enable
 // end DMA Init

 if(enable) TIM1->CR1 |= TIM_CR1_CEN;   // разрешаем счёт
}

Поделиться сообщением


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

спасибо все классно работает. :)

Рад за Вас. Что следующее помочь настроить?

Поделиться сообщением


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

Рад за Вас. Что следующее помочь настроить?

честно говоря опасений много, перевожу апликашку с меги на STM32, пока вобщем камнем доволен, но чувствую еще наступлю на пару граблей - вот тогда и обращусь за помощью. спасибо. :)

off-top: засада с напряжениями - с мегой я работал на 5-ти вольтах, и там сигналы с AB энкодера амплитудой 9 вольт я подавал через резистор напрямую на пины и все работало. Тут же нужен преобразователь уровней. Больше всего понравился CD4050.

Поделиться сообщением


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

...засада с напряжениями - с мегой я работал на 5-ти вольтах, и там сигналы с AB энкодера амплитудой 9 вольт я подавал через резистор напрямую на пины и все работало...

Ерундой страдаете...

1. Сложно пересчитать делитель c 9->5 на 9->3.3?

2. Вы не знаете, что I/O в stm32 “5 V-tolerant”?

Поделиться сообщением


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

Ерундой страдаете...

1. Сложно пересчитать делитель c 9->5 на 9->3.3?

2. Вы не знаете, что I/O в stm32 “5 V-tolerant”?

 

а если всплеск напряжения на входе?

Поделиться сообщением


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

а если всплеск напряжения на входе?

Так диоды по входу стоят в питание. Главное чтобы ток не перевалил за 1 мА. Можете еще стабилитрон поставить, но только чтоб на микротоках не работали.

Поделиться сообщением


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

Так диоды по входу стоят в питание. Главное чтобы ток не перевалил за 1 мА. Можете еще стабилитрон поставить, но только чтоб на микротоках не работали.

то есть в стм так же как и в атмеле? подавай хоть 220 вольт, главное поставь соответствующий резистор по току, а внутренние клампинг диоды вытянут?

Поделиться сообщением


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

то есть в стм так же как и в атмеле? подавай хоть 220 вольт, главное поставь соответствующий резистор по току, а внутренние клампинг диоды вытянут?

В целом да. Но можно еще и своих диодов поставить для надежности. И резисторов не один, а два. Когдато я давал ссілку на hardware design или подобное. Посмотрите руководство и какие-нибудь примеры от ST. Просто для расширения кругозора. Может что более интересное попадется.

Поделиться сообщением


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

Делаю на stm32 (именно на STM32F103C8) кассу для сына, одна из задач - научить кассу говорить.

Взял вот этот готовый плеер: http://projectproto.blogspot.ru/2010/06/mi...dio-player.html

Поправил под библиотечку с карточкой, что заработала, в итоге в оригинальной конфигурации, ШИМ на PB7 - звук отлично играет.

Вот тут и проблема, PB7 у меня изначально занят под I2C для экрана 16х02, попробовал сменить таймер на 1й и ногу на PA8. Получил в итоге шум, треск, скрежет.

Вот в чем различия при инициализации ШИМ:

 

Оригинальный код:

TIM_OCInitTypeDef  TIM_OCInitStructure;

void PWM_init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

	/* TIM4 clock enable */
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE );

	/* GPIOB Configuration:TIM4 Channel 2 as alternate function push-pull */
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;		// PB7
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);

	/* Time base configuration */
	/* PWM frequency = 72MHz / [Period*(Prescaler+1)]  */
	TIM_TimeBaseStructure.TIM_Period = 350;//256;//360;
	TIM_TimeBaseStructure.TIM_Prescaler = 0;
	TIM_TimeBaseStructure.TIM_ClockDivision = 0;
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

	TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);

	/* PWM1 Mode configuration: Channel2 */
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;


	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_Pulse = 128;	//CCR2 Value;	duty cycle =  CCR/Period
	TIM_OC2Init(TIM4, &TIM_OCInitStructure);

	TIM_OC2PreloadConfig(TIM4, TIM_OCPreload_Enable);
	TIM_ARRPreloadConfig(TIM4, ENABLE);
	/* TIM4 enable counter */
	TIM_Cmd(TIM4, ENABLE);

}

void set_pwm_duty(unsigned char duty)
{
	TIM_OCInitStructure.TIM_Pulse = duty;
	TIM_OC2Init(TIM4, &TIM_OCInitStructure);

}

void pwm_output_enable(bool on)
{
	GPIO_InitTypeDef GPIO_InitStructure;

	if(on){
			/* GPIOB Configuration:TIM4 Channel 2 as alternate function push-pull */
			GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;		// PB7
			GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
			GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
			GPIO_Init(GPIOB, &GPIO_InitStructure);
	}
	else{
			/* GPIOB7 as input */
			GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;		// PB7
			GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
			GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
			GPIO_Init(GPIOB, &GPIO_InitStructure);
	}
}

 

вот мой код:

void PWM_init(void)
{
   GPIO_InitTypeDef GPIO_InitStructure;
   TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
/* TIM1 clock enable */
    RCC_APB1PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE );
/* GPIOA Configuration:TIM1 Channel 1 as alternate function push-pull */
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;	// PA8
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Time base configuration */
/* PWM frequency = 72MHz / [Period*(Prescaler+1)]  */
   TIM_TimeBaseStructure.TIM_Period = 350;//256;//360;
   TIM_TimeBaseStructure.TIM_Prescaler = 0;
   TIM_TimeBaseStructure.TIM_ClockDivision = 0;
   TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
   TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
/* PWM1 Mode configuration: Channel */
   TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
   TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
   TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

   TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
   TIM_OCInitStructure.TIM_Pulse = 128;	//CCR2 Value;	duty cycle =  CCR/Period
   TIM_OC2Init(TIM1, &TIM_OCInitStructure);
   TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);
   TIM_ARRPreloadConfig(TIM1, ENABLE);
/* TIM4 enable counter */
   TIM_Cmd(TIM1, ENABLE);
}

void set_pwm_duty(unsigned char duty)
{
   TIM_OCInitStructure.TIM_Pulse = duty;
   TIM_OC2Init(TIM1, &TIM_OCInitStructure);
}

void pwm_output_enable(int on)
{
   GPIO_InitTypeDef GPIO_InitStructure;
   if(1==on){
/* GPIOA Configuration:TIM4 Channel 2 as alternate function push-pull */
       GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;	// PA8
       GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
       GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
       GPIO_Init(GPIOA, &GPIO_InitStructure);
   }
   else{
/* GPIOA8 as input */
       GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; // PB8
       GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
       GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
       GPIO_Init(GPIOA, &GPIO_InitStructure);
   }
}

 

во втором случае без форматирования, отличия выделил жирным.

Помогите, может неправильно таймер/ШИМ иницируется ? Может какие-то различия должны быть между 1м и 4м таймерами ?

Хотя PB8-PB9 вроде свободны, можно ремапом на них I2C. Но может будет ещё решение ?

Я так понял, у меня как и у автора текущего топика проблема с инициализацией таймера.

Только мне бы не напрямую в регистры, а с помощью GPIO библиотеки...

Изменено пользователем IgorKossak
[codebox] для длинного кода, [code] - для короткого!!!

Поделиться сообщением


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

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

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

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

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

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

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

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