Skocz do zawartości
Chev

STM8S - samoczynne resetowanie się układu po kilku poprawnych operacjach

Pomocna odpowiedź

Dzień dobry,

kontynuując swój projekt, natchnąłem się na dziwną sytuację. Jest to timer, który odmierza czas, który ustawiony jest za pomocą trzech klawiszy (na każdym wybieramy 1). Wszystko działa do momentu rozpoczęcia wykonywania się funkcji start();. Mało tego. Do procedury odliczania czasu do rozpoczęcia pracy (countdown) wszystko gra. Problem pojawia się w linii GPIO_WriteHigh(GPIOC, GPIO_PIN_6);, kiedy wystawiam stan wysoki na porcie. Generalnie wszystko działa i program wykonuje się poprawnie, ale zdarzają się sytuacje, kiedy funkcja dochodzi do tej linii, wystawia stan wysoki i resetuje całą funkcje i zaczyna wykonywać ją od pierwszej instrukcji, od początku. Na porcie PC6 klucz tranzystorowy BC817-40LT1G, z rezystorem 1k na bazie, wysterowuje cewkę przekaźnika 12V, która to załącza układ. W tym przypadku lampę LED 230V.

To co zaobserwowałem na oscyloskopie to w momencie pojawienia się tego błędu, pojawia się napięcie na złączu BE napięcie 0,7V przez chwilę, a następie pojawia się szpilka napięcia, zmiany stanu, gdzie normalnie zmiania stanu z wysokiego na niski objawia się łagodnie opadającym zboczem.

Dodam jeszcze, że pisząc na kolanie dwie funkcje for zliczające do 1 mln, bez żadnych timerów, zmieniające co stan logiczny tego portu z wysokiego na niski, ten problem nie występuje.

Jeszcze dodam, że inicjalizując to wyjście jako: GPIO_Init(GPIOC, GPIO_PIN_6, GPIO_MODE_OUT_PP_HIGH_FAST); //  ON/OFF, czyli przypisując mu zegar 16MHz, co jakiś czas podczas tego eksperymentu następowało podwójne kliknięcie przekaźnika, co po zmianie FAST na SLOW (2MHz) już nie następowało.

Pytanie jest następujące. W czym leży problem? Zasilanie jest stabilne, dobrze odfiltrowane. Doszukiwałem się w problemu w przerwaniach timera, którego wykorzystuje, ale nie widzę tu błędu. Prośba jest następująca. Czy jest ktoś w stanie zaglądnąć do mojego kodu i stwierdzić, czy jest w nim coś, co może wywoływać ten reset? Nie dzieje się to często, ale jak się to wydarzy to wszystko się wysypuje.

//////////////////////////////LIBRARIES

#include <stm8s.h>
#include <stm8s_it.h>

//////////////////////////////PRIVATE DEFINITIONS

#define buttonF (GPIO_ReadInputPin(GPIOD, GPIO_PIN_2))
#define button1 (GPIO_ReadInputPin(GPIOB, GPIO_PIN_4))
#define button2 (GPIO_ReadInputPin(GPIOB, GPIO_PIN_5))
#define button3 (GPIO_ReadInputPin(GPIOA, GPIO_PIN_3))

#define contractron (GPIO_ReadInputPin(GPIOC, GPIO_PIN_4))
#define montionSensor (GPIO_ReadInputPin(GPIOC, GPIO_PIN_3))
#define programSelect (GPIO_ReadInputPin(GPIOC, GPIO_PIN_7))

//////////////////////////////CONSTANT OBJECTS

volatile const uint8_t timeWorking_1 = 15; // 1 min (60)
volatile const uint16_t timeWorking_2 = 15; // 15 min (900)
volatile const uint16_t timeWorking_3 = 15; //  30 min (1800)
volatile const uint32_t lifeTime = 28800000; // 8000h (28800000)

//////////////////////////////TIMERS

uint16_t counter = 1;
uint16_t timesUp = 0;
uint16_t countTimeKeyPress = 0;
uint8_t delayToStart = 5; // 30 sek

//////////////////////////////EEPROM
//DATA TO SAVE 
//0x4000 - WORKING TIME 
//0x4001 - REMAINING LIFE TIME 

uint16_t timeWorking;                 // 0x4000
uint32_t remainingLifeTime;           // 0x4001

//////////////////////////////CONTROL INSTRUCTION AND GLOBAL OBJECTS

bool stop = FALSE;
bool detectedMontion = FALSE;
bool isWorking = FALSE;
bool countdown = FALSE;

//////////////////////////////FUNCTIONS

void beeper_setup(void);
void button_setup(void);
void clock_setup(void);
void EEPROM_setup(void);
void GPIO_setup(void);
void interrupt_setup(void);
void pause(void);
void start(void);
void stopU(void);
void TIMER2_setup(void);

void main(void)
{
  GPIO_setup();
  EEPROM_setup();
  interrupt_setup();
  //beeper_setup();  
  clock_setup();
  TIMER2_setup();
  
  start(); // auto start
  
  while(TRUE)
    {  
     // if((isWorking == FALSE) && (countdown == FALSE))
      //  button_setup();
      //else;
      
      for(u32 i = 0; i<500000; i++)
          GPIO_WriteHigh(GPIOC, GPIO_PIN_6);
      for(u32 j = 0; j<500000; j++)
        GPIO_WriteLow(GPIOC, GPIO_PIN_6);
    }  
}

  /* while(TRUE)
    {
       GPIO_WriteHigh(GPIOD, GPIO_PIN_4);
       BEEP_Cmd(ENABLE);
       delay(20000);
                                
       GPIO_WriteLow(GPIOD, GPIO_PIN_4);
       BEEP_Cmd(DISABLE);
       delay(20000);
    };*/
     //GPIO_WriteLow(GPIOD, GPIO_PIN_4);

void beeper_setup(void)
{
  BEEP_DeInit(); 
  BEEP_LSICalibrationConfig(128000);
  BEEP_Init(BEEP_FREQUENCY_1KHZ);
}

void button_setup(void)
{
  if(button1 == 0)
    {
      timeWorking = timeWorking_1;
      FLASH_EraseByte(0x4000);
      FLASH_ProgramByte(0x4000, timeWorking);
      //GPIO_WriteReverse(GPIOD, GPIO_PIN_3); // TEST
    }
  
  else if(button2 == 0)
    {
      timeWorking = timeWorking_2;
      FLASH_EraseByte(0x4000);
      FLASH_ProgramByte(0x4000, timeWorking);
      //GPIO_WriteReverse(GPIOD, GPIO_PIN_3); // TEST
    }
 
  else if(button3 == 0)
    {
      timeWorking = timeWorking_3;
      FLASH_EraseByte(0x4000);
      FLASH_ProgramByte(0x4000, timeWorking);
      //GPIO_WriteReverse(GPIOD, GPIO_PIN_3); // TEST
    }
  
  else if(buttonF == 0)
    {
      while(buttonF == 0){}
      if(countTimeKeyPress > 200 || countTimeKeyPress < 10000)
        {
          start();
          countTimeKeyPress = 0;
        }
      else if(countTimeKeyPress > 10000)  
        {        
          FLASH_EraseByte(0x4001);
          remainingLifeTime = FLASH_ReadByte(0x4001);
          countTimeKeyPress = 0;
        }
      else;
    }
}

void clock_setup(void)
{
////////////////////////////// Configure Quartz Clock
    CLK_DeInit();
    CLK_HSECmd(ENABLE);
    CLK_SYSCLKConfig(CLK_PRESCALER_HSIDIV1);
    CLK_SYSCLKConfig(CLK_PRESCALER_CPUDIV1);
    CLK_PeripheralClockConfig (CLK_PERIPHERAL_TIMER2 , ENABLE);

    /*CLK_LSICmd(ENABLE);
    //while(CLK_GetFlagStatus(CLK_FLAG_LSIRDY) == FALSE);
                
    CLK_ClockSwitchCmd(ENABLE);
    CLK_SYSCLKConfig(CLK_PRESCALER_CPUDIV1);
                
    CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO, CLK_SOURCE_HSI, 
    DISABLE, CLK_CURRENTCLOCKSTATE_ENABLE);
                
     CLK_PeripheralClockConfig(CLK_PERIPHERAL_SPI, DISABLE);
     CLK_PeripheralClockConfig(CLK_PERIPHERAL_I2C, DISABLE);
     CLK_PeripheralClockConfig(CLK_PERIPHERAL_ADC, DISABLE);
     
     CLK_PeripheralClockConfig(CLK_PERIPHERAL_UART1, DISABLE);
     CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER1, DISABLE);
     CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER2, DISABLE);
     CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER4, DISABLE);*/
}

void EEPROM_setup(void)
{
  FLASH_DeInit();
  FLASH_Unlock(FLASH_MEMTYPE_DATA);
  FLASH_SetProgrammingTime(FLASH_PROGRAMTIME_STANDARD);
    
  timeWorking = FLASH_ReadByte(0x4000);
  remainingLifeTime = FLASH_ReadByte(0x4001);
}

void GPIO_setup(void)
{
  GPIO_DeInit(GPIOA);
  GPIO_DeInit(GPIOB);
  GPIO_DeInit(GPIOC);
  GPIO_DeInit(GPIOD);
     
//inputs    
  GPIO_Init(GPIOA, GPIO_PIN_3, GPIO_MODE_IN_PU_NO_IT); // button1
  GPIO_Init(GPIOB, GPIO_PIN_4, GPIO_MODE_IN_PU_NO_IT); // button2
  GPIO_Init(GPIOB, GPIO_PIN_5, GPIO_MODE_IN_PU_NO_IT); // button3
  GPIO_Init(GPIOD, GPIO_PIN_2, GPIO_MODE_IN_PU_NO_IT); // button4
  
  GPIO_Init(GPIOC, GPIO_PIN_7, GPIO_MODE_IN_PU_NO_IT); // programSelect
  GPIO_Init(GPIOC, GPIO_PIN_3, GPIO_MODE_IN_PU_NO_IT); // con
  GPIO_Init(GPIOC, GPIO_PIN_4, GPIO_MODE_IN_PU_NO_IT); // montion sensor
  
//outputs  
  GPIO_Init(GPIOC, GPIO_PIN_6, GPIO_MODE_OUT_PP_HIGH_SLOW); //  ON/OFF
  GPIO_Init(GPIOD, GPIO_PIN_3, GPIO_MODE_OUT_PP_HIGH_FAST); // LED
//GPIO_Init(GPIOD, GPIO_PIN_4, GPIO_MODE_OUT_PP_HIGH_FAST); //BUZZER
  
  GPIO_WriteLow(GPIOD, GPIO_PIN_3);
  GPIO_WriteLow(GPIOC, GPIO_PIN_6);
}

void interrupt_setup(void)
{
  enableInterrupts();
}
                        
void pause(void)
{
  GPIO_WriteLow(GPIOC, GPIO_PIN_6);
  GPIO_WriteLow(GPIOC, GPIO_PIN_6);
  isWorking = FALSE;
  delayToStart = 5;
  
  start();
}

void start(void)
{
  countdown = TRUE;

  while(countdown == TRUE)
    {
      if(delayToStart == 0)
      {
        isWorking = TRUE;
        GPIO_WriteHigh(GPIOC, GPIO_PIN_6);
        while(isWorking == TRUE)
          {
            if(buttonF == 0)
              stopU();
            else if(timeWorking == timesUp)
              stopU();
            else if(detectedMontion == TRUE)
              pause();
            else;
          } 
      }
      else;
    }
}

void stopU(void)
{
  GPIO_WriteLow(GPIOC, GPIO_PIN_6);
  GPIO_WriteLow(GPIOC, GPIO_PIN_6);
  stop = TRUE;
}

void TIMER2_setup(void)
{
  
  TIM2_DeInit();
  TIM2_TimeBaseInit(TIM2_PRESCALER_128, 0x7D); // 127 and 0x7D == Interrupt 1 ms
  TIM2_ITConfig(TIM2_IT_UPDATE, ENABLE);
  TIM2_Cmd(ENABLE);
}

void assert_failed(u8* file, u32 line){}

===========
  
  INTERRUPT_HANDLER(TIM2_UPD_OVF_BRK_IRQHandler, 13)
 {
   TIM2_ClearITPendingBit(TIM2_IT_UPDATE);
  if((isWorking == FALSE) && (countdown == FALSE))
  {
    if(buttonF == 0)
    {
        countTimeKeyPress++;
        TIM2_ClearITPendingBit(TIM2_IT_UPDATE);
    }
      else;
  }

    if((countdown == TRUE) && (detectedMontion == FALSE))
      {
        if(delayToStart > 0)
        {
          counter++;
          if(counter > 1000)
            {
              //GPIO_WriteReverse(GPIOD, GPIO_PIN_3); // TEST
              counter = 1;
              delayToStart--;
              TIM2_ClearITPendingBit(TIM2_IT_UPDATE);
            }
          TIM2_ClearITPendingBit(TIM2_IT_UPDATE);
        }
        else
          countdown = FALSE;
      }
    
    if(isWorking == TRUE)
      {
       
        if(timeWorking > timesUp)
        {
          counter++;
          if(counter > 1000)
            {
              //GPIO_WriteReverse(GPIOD, GPIO_PIN_3); // TEST
              counter = 1;
              timesUp++;
              remainingLifeTime++;
              FLASH_EraseByte(0x4001);
              FLASH_ProgramByte(0x4001, remainingLifeTime);
              TIM2_ClearITPendingBit(TIM2_IT_UPDATE);
            }
          TIM2_ClearITPendingBit(TIM2_IT_UPDATE);
        }
      }
    
    if((montionSensor == 0) || (contractron == 0))
      detectedMontion = TRUE; 
    else
      detectedMontion = FALSE;
    
    if(stop == TRUE)
    {
      counter++;
        if(counter > 1000)
        {
          isWorking = FALSE;
          timesUp = 0;
          delayToStart = 5;
          stop = FALSE;
          TIM2_ClearITPendingBit(TIM2_IT_UPDATE);
        }
        TIM2_ClearITPendingBit(TIM2_IT_UPDATE);
    }
    else;
      
 }

Z góry dziękuję za pomoc.

Udostępnij ten post


Link to post
Share on other sites

A może dodaj do tego przekaźnika diodę zabezpieczającą przed wyindukowanym napięciem, bo stąd może być ta szpilka.

Udostępnij ten post


Link to post
Share on other sites

Przy przekaźniku jest dioda. Problem był prozaiczny. Brak kondensatora 100 nF przy wejściu NRST powodował czasami falowanie napięcia, co wprowadzało reset. Dobry zwyczajem jest podwieszać wszystkie, niewykorzystane porty do przeciwnego stanu, aby nie dopuścić do takich dziwnych sytuacji. Widać, lenistwo dało górę. Najważniejsze, że się poprawiło i jest lekcja na przyszłość 🙂

Udostępnij ten post


Link to post
Share on other sites

@Chev mógł byś napisać czego używasz do programowania stm8? winIDEA czy coś innego? 

Udostępnij ten post


Link to post
Share on other sites
Dnia 8.06.2020 o 22:19, slon napisał:

@Chev mógł byś napisać czego używasz do programowania stm8? winIDEA czy coś innego? 

Jeśli pytasz o środowisko to jest to darmowa wersja IAR EW for STM8 3.11.1. Jest ograniczenie zapisu do 8kB, ale licencja jest nielimitowana, darmowa. Mi osobiście to wystarcza na tą chwilę. Kiedyś pokombinuje jak to przerobić na Eclipsa, bo widziałem, ze się da.

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.


×
×
  • Utwórz nowe...