STM32F103 External Int Sorunum

Başlatan SB7, 30 Kasım 2022, 09:56:05

SB7

Selamlar,

STM32F103c8 Blue Pill mikrodenetleyicisi ile harici kesme uygulaması yapmak istiyorum. Kesme kaynağını 0-1-5 olarak denedim hepsinde de sonuç aynı.Pending bitini sıfırlamama rağmen yeni kesme oluşmuyor ve MCU donuyor.Kodlar bu şekilde:

#include <stm32f10x.h>
#include <stm32f10x_gpio.h>
#include <stm32f10x_rcc.h>
#include <stm32f10x_exti.h>
#include <stm32f10x_tim.h>
#include <stdio.h>
#include <misc.h>
#include "delay.h"
#include "lcd16x2.h"

void GPIO_Configuration(void);
void EXTI0_Init(void);

float deger = 0.0000;

void EXTI0_IRQHandler(void) 
{
	if (EXTI_GetITStatus(EXTI_Line0) != RESET)
	{
GPIO_SetBits(GPIOC,GPIO_Pin_13); DelayMs(500);
GPIO_ResetBits(GPIOC,GPIO_Pin_13);  DelayMs(500);
		
EXTI_ClearITPendingBit(EXTI_Line0);
	}
}

int main(void)
{
	
	char buffer[80] = {' '};
	
	DelayInit();
  EXTI0_Init();
	GPIO_Configuration();
	
	lcd16x2_init(LCD16X2_DISPLAY_ON_CURSOR_OFF_BLINK_OFF);
	lcd16x2_clrscr();
	DelayMs(500);
	
	while (1)
	{
		
	//	deger = ADCConvertedValue * 90;
	//	deger = deger / 4096.0;
uint8_t new_val = deger;
sprintf(buffer, "Tetik.Aci:%2d'", new_val);
lcd16x2_gotoxy(0,0);//sut sat
lcd16x2_puts(buffer);
//lcd16x2_gotoxy(0,1);//sut sat
//lcd16x2_puts("Frekans:50.0 Hz");
DelayMs(500);
// Clear display
//lcd16x2_clrscr();
//DelayMs(500);
	}
}

void GPIO_Configuration(void) 
{
	GPIO_InitTypeDef GPIO_InitStruct;
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

	
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13; 
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOC, &GPIO_InitStruct);
}

void EXTI0_Init()
{
	GPIO_InitTypeDef GPIO_InitStruct;
	EXTI_InitTypeDef EXTI_InitStruct;
	NVIC_InitTypeDef NVIC_InitStruct;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStruct);
	
	NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x00;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x00;
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStruct);
	
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);
	
	EXTI_InitStruct.EXTI_Line = EXTI_Line0;
	EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
	EXTI_InitStruct.EXTI_LineCmd = ENABLE;
	EXTI_Init(&EXTI_InitStruct);
	
}

İnterrupt rutini içindeki gecikme debug için. Flag set edip ana programda flag durumuna göre de denedim sonuç aynı 1 kez kesmeye girince MCU donuyor.Sorunun kaynağını bulamadım.
Yardımcı olursanız sevinirim. Teşekkürler.
-SB7

quarko

Donuyor derken, hardfault a mı düşüyor ? Debug modunda test ederseniz, dondu dediğiniz anda durdurup nerede olduğuna bakabilirsiniz. Hardfault a düşmüş olabilir. Bir de o beklemeleri kaldırıp, exti interruptının girişine breakpoint koyup deneyebilir misiniz?
"Vicdanın ziyası ulum-u diniyedir. Aklın nuru fünun-u medeniyedir. İkisinin imtizacıyla hakikat tecelli eder."

Kırambor

#2
Interruptı rising trigger olarak tetikliyorsunuz. Kodunuzda tam olarak ne interruptı tetikliyor ? Yani belki de konfigürasyondan vs değil sizin interruptı sadece 1 defa tetiklediğinizden falan olabilir mi ? Yanlış okumadıysam PB0'ı external interrupt olarak tanımlamışsınız. Eğer osiloskobunuz varsa o portu izleyebilir misiniz ?

flowchartx

while içinde ki herşeyi silip o halde de aynı şeyi yapıyor mu bakar mısın

esdevhk

Delay_Ms kaynağı SysTick ISR ise ve systick önceliği external interrupt önceliği ile aynı ise programınız kesme içerisinde Delay_Ms sebebiyle bloklanıyor olabilir mi?

ST'nin HAL kütüphanesindeki gibi mesela?

SB7

#5
Alıntı yapılan: quarko - 30 Kasım 2022, 10:33:30Bir de o beklemeleri kaldırıp, exti interruptının girişine breakpoint koyup deneyebilir misiniz?
@quarko hocam bunu denedim dediğiniz gibi gecikmelerde sorun varmış DelayUs fonksiyonuna dallanıp oradan çıkamıyormuş.



Gecikmeleri kaldırıp breakpoint ekledim sayaç değişkeni düzgün artmıyor bu kez de.Pull donwn direnci bağladığım butona 1 kez bastığımda bazen normal artışlar bazen de çok fazla sayıda artış oluyor.
 
static uint16_t sayac=0;

void EXTI0_IRQHandler(void) 
{
    if (EXTI_GetITStatus(EXTI_Line0) != RESET)
    {
GPIO_SetBits(GPIOC,GPIO_Pin_13); 
GPIO_ResetBits(GPIOC,GPIO_Pin_13);

        sayac++;
        if(sayac >= 10) sayac = 0;
EXTI_ClearITPendingBit(EXTI_Line0);
    //    EXTI_ClearFlag(EXTI_PR_PR0);
    }
}

Bana garip gelen birşey daha var C13 pinine bağlı led için interrupttan çıkarken resetlenmesi gerekiyor ancak program çalışırken led hep yanıyor ve kesme olduğunda sönüyor.Kesmeden çıkarken tekrar yanıyor.(Program içinde C13 ü sadece interrupt fonksiyonunda debug için kullanıyorum başka yerde set edilme durumu yok.)

@Kırambor hocam evet zero crossing için kullanacağım. Şuan butonla deniyorum, yükselen kenarda tetikleme yapılmasını istiyorum o kısımda sorun yok.

@flowchartx hocam denedim yine aynı yerde sorun oldu.



30 Kasım 2022, 18:57:25
Alıntı yapılan: huseyink - 30 Kasım 2022, 18:41:55Delay_Ms kaynağı SysTick ISR ise ve systick önceliği external interrupt önceliği ile aynı ise programınız kesme içerisinde Delay_Ms sebebiyle bloklanıyor olabilir mi?

ST'nin HAL kütüphanesindeki gibi mesela?

Hocam ben yazarken siz göndermişsiniz, galiba problem dediğiniz gibi son resimde DelayUs fonksiyonuna dallanıp donuyor. Ama ne yapmam gerektiğini bilmiyorum. Birkaç kesme daha kullanacağım kesme öncelikleri için ne yapmalıyım?
-SB7

esdevhk


Alıntı YapHocam ben yazarken siz göndermişsiniz, galiba problem dediğiniz gibi son resimde DelayUs fonksiyonuna dallanıp donuyor. Ama ne yapmam gerektiğini bilmiyorum. Birkaç kesme daha kullanacağım kesme öncelikleri için ne yapmalıyım?

Öncelikle harici kesme rutinleri içerisinde delay vb. gibi kodu bloklayan yapılardan kesinlikle uzak durmalısınız. Eğer kesme sonrası yapılacak bir işlem varsa bunu kesme içerisinde bir bayrak set edip, bayrağın durumuna göre işleminizi main loop içerisinde yapmanız daha doğru olur.

Eğer debug amaçlı bir işlem yapıyorsanız şimdilik böyle olsun derseniz, EXT interrupt önceliğini SysTick önceliğinden daha düşük öncelikli ayarlarsanız kesme içerisinde Delay fonksiyonunuz çalışacaktır ama etkin bir yöntem değildir.

SB7

Cevaplar için herkese çok teşekkür ederim. Kodu bu şekilde yapınca çalışıyor. Butona basılmaları sorunsuz algılayabiliyorum şuan. Butona basınca kesme oluşuyor ve flag set ediliyor. Flag setse C13 e bağlı LED 250ms yanıp sönüyor. Set-Reset tam tersi çalışsa da istediğim gibi oldu. Tekrar çok teşekkür ederim.

#include <stm32f10x.h>
#include <stm32f10x_gpio.h>
#include <stm32f10x_rcc.h>
#include <stm32f10x_exti.h>
#include <stm32f10x_tim.h>
#include <stdio.h>
#include <misc.h>
#include "delay.h"
#include "lcd16x2.h"

void GPIO_Configuration(void);
void EXTI0_Init(void);

float deger = 0.0000;
static uint16_t sayac=0;

void EXTI0_IRQHandler(void) 
{
    if (EXTI_GetITStatus(EXTI_Line0) != RESET)
    {
        sayac=1;
        
EXTI_ClearITPendingBit(EXTI_Line0);
    //    EXTI_ClearFlag(EXTI_PR_PR0);
    }
}

int main(void)
{
    
    char buffer[80] = {' '};
    
    DelayInit();
  EXTI0_Init();
    GPIO_Configuration();
    
    lcd16x2_init(LCD16X2_DISPLAY_ON_CURSOR_OFF_BLINK_OFF);
    lcd16x2_clrscr();
    DelayMs(500);
    
    while (1)
    {
        
        if(sayac == 1){ sayac = 0;
        GPIO_ResetBits(GPIOC,GPIO_Pin_13);  DelayMs(250);}
        
GPIO_SetBits(GPIOC,GPIO_Pin_13); 

        
    }
}

void GPIO_Configuration(void) 
{
    GPIO_InitTypeDef GPIO_InitStruct;
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

    
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13; 
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_Init(GPIOC, &GPIO_InitStruct);
}

void EXTI0_Init()
{
    GPIO_InitTypeDef GPIO_InitStruct;
    EXTI_InitTypeDef EXTI_InitStruct;
    NVIC_InitTypeDef NVIC_InitStruct;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStruct);
    
    NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x00;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x00;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStruct);
    
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);
    
    EXTI_InitStruct.EXTI_Line = EXTI_Line0;
    EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
    EXTI_InitStruct.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStruct);
    
}
-SB7