AT mega 32 reset problém

Ahoj

Jako obvykle jsem zapojil AT mega 32A na nepájivé pole + standardní zapojení resetovacího tlačítka (tak jako vždycky).
Ale tentokrát se vyskytl problém. V momentě, kdy mám v programu povolené globální přerušení (SREG |= (1<<7);), tak MCU se občas (zcela náhodně bez zjevné příčiny) resetuje a to navíc takovým stylem, že naběhne a hned se resetuje, naběhne, resetuje, naběhne, resetuje až do doby, kdy stisknu tlačítko reset podruhé, poté cyklování ustane až do doby, kdy MCU začne opět samovolně cyklovat.

Cyklování také způsobím záměrně a to dvěma způsoby:

  1. Když stisknu tlačítko reset 1x (začne cyklovat) a při dalším stisku zase naběhne normálně
  2. Mám nakonfigurované externí přerušení na pinu PD3 na sestupnou hranu. Na příslušný pin mám přes odpor 10 kohm přivedeno napájecí napětí a stačí abych se té nožičky MCU jen dotkl multimetrem (pro změření napětí) a hned začne znova cyklovat do doby, než stisknu tlačítko reset.

Toto chování jsem nikdy předtím nepozoroval a přitom toto zapojení jsem realizoval už předtím a šlapalo to bez problémů.

V momentě kdy zakážu globální přerušení, tak je vše opět v pořádku…

Setkal se už někdo s takovým podivným chováním ?

Děkuji

Bych řekl, že máš vadný procesor.
Atmegu32a používám bez zmíněných problémů.
Chtělo by to odzkoušet pro jistotu ještě s jiným procesorem,
zda nemáš problém v zapojení.
Ono stačí mít slabší napájení nebo studeňák a k tomu zapnutý BOD level na 4,0V a o vibrátor máš postaráno. :smiley:

Kontaktní pole umí občas pěkně pozlobit …

Vadný procesor jako zdroj chyby bych viděl jako nejméně pravděpodobné i když ne nemožné.
Jako první bych zkusil poškádlit usazení procesoru v kontaktním poli a pokud problém nezmizí, tak zkusit jiný procesor, jestli ho máš. Osobně si ale myslím, že problém bude spíš v programu. Zkus zakázat to externí přerušení (ne globální), případně přehodit přerušení z INT1 (PD3) na INT0 (PD2) a uvidíš, jestli se to bude chovat stejně. Možná někde zpracováváš v programu data z tohoto přerušení a dochází ke kolizím.

Já už se s něčím podobným setkal, bylo to tím že při řízení procesoru dalších zařízení, byl větší odběr proudu, a zdroj začal kmitat, to vedlo k resetu. nevím ale jestli je to tvůj případ. Jinak bych to taky viděl na nějaký problém jak píše Balů

Ahoj

Problém vyřešen - jde o to, že na přerušení INT0 mám radiový modul RFM12 a ten mimo jiné indikuje příchozí data. Po chvilce experimentování jsem zjistil, že problém není v původně podezřívaném tlačítku, ale v přerušení od radiomodulu, který chytá data z pokojového termostatu. Když je termostat aktivní, tak dochází k aktivaci přerušení, tak jsem tu mrchu termostat kuchnul a opravdu - také obsahuje RFM12 na 433 MHz. Připojil jsem logický nanalyzátor a načetl, že soudruzi použili přesně ten samý kmitočet co já (433,92 MHz :slight_smile:.

Mám ale nový problém - tentokrát blbne zápis do interní EEPROM:

// definice adres v EEPROM
#define		EEPROM_RFMFRQ1_ADR	    0x0011
#define		EEPROM_RFMFRQ2_ADR	    0x0012


// funkce pro nastaveni nosneho kmitoctu RFM12
void RFM12_Frequency_Set (unsigned char index, unsigned char *FREQ1, unsigned char *FREQ2)
{
...
*FREQ1 = 0xA4;
*FREQ2 = 0xC4;
...
return;
}



// nastaveni RFM12
void RFM12_Setup ()
{
unsigned char RFM_FREQ_1_WORKING = RFM_FREQ_1;
unsigned char RFM_FREQ_2_WORKING = RFM_FREQ_2; 
unsigned char *p1 = &RFM_FREQ_1_WORKING;    // ukazatel na RFM_FREQ_1_WORKING
unsigned char *p2 = &RFM_FREQ_2_WORKING;    // ukazatel na RFM_FREQ_2_WORKING
...
RFM12_Frequency_Set(SETUP_INDEX[0],p1,p2);   //volam funkci k nastaveni nosneho kmitoctu radiomodulu
...
EEPROM_Write(EEPROM_RFMFRQ1_ADR,*p1);   // zapis RFM_FREQ_1_WORKING do EEPROM
EEPROM_Write(EEPROM_RFMFRQ2_ADR,*p2);   // zapis RFM_FREQ_2_WORKING do EEPROM
return;
}

Jde o to, že ve funkci RFM12_Setup () si vytvořím proměnné RFM_FREQ_1_WORKING a RFM_FREQ_2_WORKING a vytvořím k nim ukazatele *p1 a *p2.
Ty předám funkci RFM12_Frequency_Set (unsigned char index, unsigned char *FREQ1, unsigned char *FREQ2), kde změním jejich obsah. A ptoté je ve zpátky ve funkci RFM12_Setup () zapíšu do EEPROM. Bohužel se mi zapisuje jen druhý bajt (RFM_FREQ_2_WORKING s ukazatelem *p2). První bajt se vůbec nezmění a zůstavá v EEPROM stále stejný - vůbec nemůžu příjt na to proč …

Nevidíme definici funkce EEPROM_write(). Codevision nemá tuto funkci vestavěnou.

Pro přístup k vnitřní eeprom můžeš použít globální proměnné s klíčovým slovem eeprom. Popis je tady na straně 96:
uni-due.de/~hl271st/Lehre/S … manual.pdf

Funkce pro zápis do EEPROM vychází z datasheetu Atmelu

void EEPROM_Write(unsigned int EEPROM_Address, unsigned char EEPROM_Data)
{
while (EECR & (1<<EEWE));                                   // Wait for completion of previous write
EEAR = EEPROM_Address;                                      // Set up address and data registers
EEDR = EEPROM_Data;
EECR |= (1<<EEMWE);                                         // Write logical one to EEMWE
EECR |= (1<<EEWE);                                          // Start eeprom write by setting EEWE
return;
}

Ve více čístech programu zapisuji řadu bajtů těsně za sebou as všude jinde to jde. Jenom když zapisuji data pro kmitočet, tak se první bajt v EEPROM nezmění (a tudíž ani nezapíše). Jenom nevím, jestli je chyba v samotném zápisu (což se mi nezdá) a nebo v použití toho ukazatele - jenže to mi zase nejde do hlavy proč jeden bajt funguje a druhý ne.

Už jsem zkoušel i měnit optimalizaci kódu (speed / size) a stále nic…

Neměl bys zápis do EEPROM volat
EEPROM_Write(EEPROM_RFMFRQ1_ADR,p1); // zapis RFM_FREQ_1_WORKING do EEPROM
místo
*EEPROM_Write(EEPROM_RFMFRQ1_ADR,p1); // zapis RFM_FREQ_1_WORKING do EEPROM ?

Balů:
Ne, má to správně.
A v simulátoru Avrstudia to funguje.

Akorát je to podle mne zbytečně přepointerované.
Nebo je to úloha na procvičování ukazatelů?

Táák i druhý problém vyřešen.

Nakonec mě na správnou myšlenkou přivedl AB (díky :slight_smile: větou: “Akorát je to podle mne zbytečně přepointerované.”. Řekl jsem si, že má pravdu, že tam fakt používám nějak moc registrů, tak jsem to lehce předělal. Výsledek je, že jsem uspořil 1% FLASH paměti a začalo to fungovat (tentokrát zapisuji přímo obsah globální proměnné, ze kterém jsem si předtím dělal lokální kopii a následně ukazatel).