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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Генерация ШИМ, STM32 и TIM1/TIM8
Jenya7
сообщение Dec 23 2013, 06:48
Сообщение #1


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Настроить TIM2-TIM5 на генерацию ШИМ довольно просто
CODE
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 не все так понятно - там другие регистры и я, честно говоря, запутался.
Может кто нибудь работал с этими таймерами и может прояснить ситуацию? Заранее спасибо.
Go to the top of the page
 
+Quote Post
smk
сообщение Dec 23 2013, 07:26
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



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


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Dec 23 2013, 07:58
Сообщение #3


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(smk @ Dec 23 2013, 13:26) *
Настраивается все... что именно нужно объяснить?

желательно пример. только не на стандартной библиотеке.
Go to the top of the page
 
+Quote Post
smk
сообщение Dec 23 2013, 08:24
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



Код
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, но там таймер такой же. Регистры только проверьте, но смсл тот же.


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post
SSerge
сообщение Dec 23 2013, 08:33
Сообщение #5


Профессионал
*****

Группа: Свой
Сообщений: 1 719
Регистрация: 13-09-05
Из: Novosibirsk
Пользователь №: 8 528



Цитата(Jenya7 @ Dec 23 2013, 14:58) *
желательно пример. только не на стандартной библиотеке.

Регистры TIM2 это просто подмножество регистров TIM1.
У Вас не хватает этой строчки:
TIM1->BDTR |= TIM_BDTR_MOE;
вот прямо из текущего прожекта,
если не нужен DMA, часть текста после //DMA Init можно выбросить, .
CODE
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; // разрешаем счёт
}


--------------------
Russia est omnis divisa in partes octo.
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Dec 23 2013, 08:46
Сообщение #6


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



спасибо большое. сейчас проверю.
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Dec 23 2013, 19:27
Сообщение #7


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



спасибо все классно работает. sm.gif
Go to the top of the page
 
+Quote Post
smk
сообщение Dec 24 2013, 07:54
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



Цитата(Jenya7 @ Dec 23 2013, 21:27) *
спасибо все классно работает. sm.gif

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


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Dec 24 2013, 16:09
Сообщение #9


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(smk @ Dec 24 2013, 12:54) *
Рад за Вас. Что следующее помочь настроить?

честно говоря опасений много, перевожу апликашку с меги на STM32, пока вобщем камнем доволен, но чувствую еще наступлю на пару граблей - вот тогда и обращусь за помощью. спасибо. sm.gif
off-top: засада с напряжениями - с мегой я работал на 5-ти вольтах, и там сигналы с AB энкодера амплитудой 9 вольт я подавал через резистор напрямую на пины и все работало. Тут же нужен преобразователь уровней. Больше всего понравился CD4050.
Go to the top of the page
 
+Quote Post
bzx
сообщение Dec 24 2013, 23:15
Сообщение #10


Местный
***

Группа: Свой
Сообщений: 482
Регистрация: 5-07-05
Из: Санкт-Петербург
Пользователь №: 6 528



Цитата(Jenya7 @ Dec 24 2013, 20:09) *
...засада с напряжениями - с мегой я работал на 5-ти вольтах, и там сигналы с AB энкодера амплитудой 9 вольт я подавал через резистор напрямую на пины и все работало...

Ерундой страдаете...
1. Сложно пересчитать делитель c 9->5 на 9->3.3?
2. Вы не знаете, что I/O в stm32 “5 V-tolerant”?


--------------------
Для связи email: info собака qbit.su
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Dec 25 2013, 07:00
Сообщение #11


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(bzx @ Dec 25 2013, 05:15) *
Ерундой страдаете...
1. Сложно пересчитать делитель c 9->5 на 9->3.3?
2. Вы не знаете, что I/O в stm32 “5 V-tolerant”?


а если всплеск напряжения на входе?
Go to the top of the page
 
+Quote Post
smk
сообщение Dec 25 2013, 07:52
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



Цитата(Jenya7 @ Dec 25 2013, 09:00) *
а если всплеск напряжения на входе?

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


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Dec 25 2013, 08:04
Сообщение #13


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(smk @ Dec 25 2013, 13:52) *
Так диоды по входу стоят в питание. Главное чтобы ток не перевалил за 1 мА. Можете еще стабилитрон поставить, но только чтоб на микротоках не работали.

то есть в стм так же как и в атмеле? подавай хоть 220 вольт, главное поставь соответствующий резистор по току, а внутренние клампинг диоды вытянут?
Go to the top of the page
 
+Quote Post
smk
сообщение Dec 25 2013, 08:23
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



Цитата(Jenya7 @ Dec 25 2013, 10:04) *
то есть в стм так же как и в атмеле? подавай хоть 220 вольт, главное поставь соответствующий резистор по току, а внутренние клампинг диоды вытянут?

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


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post
Vendict
сообщение Sep 1 2014, 09:01
Сообщение #15





Группа: Новичок
Сообщений: 4
Регистрация: 1-09-14
Пользователь №: 82 696



Делаю на stm32 (именно на STM32F103C8) кассу для сына, одна из задач - научить кассу говорить.
Взял вот этот готовый плеер: http://projectproto.blogspot.ru/2010/06/mi...dio-player.html
Поправил под библиотечку с карточкой, что заработала, в итоге в оригинальной конфигурации, ШИМ на PB7 - звук отлично играет.
Вот тут и проблема, PB7 у меня изначально занят под I2C для экрана 16х02, попробовал сменить таймер на 1й и ногу на PA8. Получил в итоге шум, треск, скрежет.
Вот в чем различия при инициализации ШИМ:

Оригинальный код:
CODE
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);
}
}


вот мой код:
CODE
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 - Sep 2 2014, 11:54
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 18th July 2025 - 09:53
Рейтинг@Mail.ru


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