Merhabalar butona basınca PWM üretmek istiyorum yalnız kesme kısımında biraz kafam karıştı ve danışmak istedim.
Timer kesmesinden mi yola çıkmalıyım yoksa buton için external bir kesmeden mi ?
External kesme olmaz tabiiki timer kullanmalısın.
Enbaşta şöyle bir kod yazmıştım harıcı kesmeyle ilgili. Burada butona basınca pwm i uretiyoruz ama butondan çekınce pwm durmuyor aynen devam ediyor.
void GPIO(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
GPIO_PinAFConfig( GPIOD, GPIO_PinSource12, GPIO_AF_TIM4);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOD, &GPIO_InitStructure);
}
void Timerconf(uint16_t prescaler, uint16_t period, uint16_t pulse )
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
TIM_TimeBaseInitStructure.TIM_Prescaler = prescaler;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = period;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState =TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState =TIM_OutputNState_Disable;
TIM_OCInitStructure.TIM_Pulse =pulse; //duty cycle
TIM_OCInitStructure.TIM_OCPolarity =TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity =TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState =TIM_OCIdleState_Reset;
TIM_OCInitStructure.TIM_OCNIdleState =TIM_OCNIdleState_Reset;
TIM_OC1Init(TIM4,&TIM_OCInitStructure);
TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
TIM_Cmd(TIM4,ENABLE);
}
void buton(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);// BUTON ICIN
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
EXTI_InitStructure.EXTI_Line =EXTI_Line0;
EXTI_InitStructure.EXTI_Mode =EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger =EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd =ENABLE;
EXTI_Init(&EXTI_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void EXTI0_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line0) != RESET)
{
Timerconf(500,9999,7499);
EXTI_ClearITPendingBit(EXTI_Line0);
}
}
int main()
{
GPIO();
buton();
//kesme();
//Timerconf(500,9999,7499);
while(1)
{
}
}
Bir diğer yaklaşımımda tımer kesmesiyledi ama burada kesme fonksiyonunun içine ne yazmam gerektiğini tam belirleyemedim.
void kesme(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void TIM4_IRQHandler(void)
{
if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
}
}
void GPIO(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
GPIO_PinAFConfig( GPIOD, GPIO_PinSource12, GPIO_AF_TIM4);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOD, &GPIO_InitStructure);
}
void Timerconf(uint16_t prescaler, uint16_t period, uint16_t pulse )
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
TIM_TimeBaseInitStructure.TIM_Prescaler = prescaler;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = period;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState =TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState =TIM_OutputNState_Disable;
TIM_OCInitStructure.TIM_Pulse =pulse; //duty cycle
TIM_OCInitStructure.TIM_OCPolarity =TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity =TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState =TIM_OCIdleState_Reset;
TIM_OCInitStructure.TIM_OCNIdleState =TIM_OCNIdleState_Reset;
TIM_OC1Init(TIM4,&TIM_OCInitStructure);
TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
TIM_Cmd(TIM4,ENABLE);
}
void buton(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);// BUTON ICIN
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
int main()
{
GPIO();
buton();
kesme();
Timerconf(500,9999,7499);
while(1)
{
}
}
Doğrusunu istersen ben sadece donanımsal tarafından bakıyorum.
İşlemci ne kullanıyorsun bilmiyorum.
Ama içinde bir PWM aygıtı vardır veya yoktur ve sen onu kontrol ediyorsun. Aygıt varsa Parametrelerini set edip enable ediyosundur. Aygıt yoksa PWM karakteristiklerini timer interrupt ile belirliyorsun. Doğru zamanlama duty ve frekansı interrupt timerına göre ayarlıyorsundur.
Butona basınca PWM i aktive edeceksin. Bırakınca pasif edeceksin.
Yada bir basışta aktif 2. basışta pasif.
Tamamen sana kalmış.
Kod bilen arkadaşlar senin kodları ayrıca yorumlayacaklardır.
void EXTI0_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line0) != RESET)
{
TIM4->CR1 ^= (1<<0);//Timer on --off
Timerconf(500,9999,7499);
EXTI_ClearITPendingBit(EXTI_Line0);
}
Yorumlarınız için teşekkür ederim. External kesmeyle çözdüm
Alıntı Yapvoid EXTI0_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line0) != RESET)
{
sayici=sayici+1;
mode= sayici%2;
if(mode==1)
{
Timerconf(500,9999,7499);
}
else if (mode ==0)
{
TIM_Cmd(TIM4,DISABLE);
}
EXTI_ClearITPendingBit(EXTI_Line0);
}
}