Obsluha přerušeni - program nevstupuje do hlavní smyčky

Ahoj
mam program ktery zajistuje sowtwarovy pwm vcelku dobre.Jediny problem nastane kdyz chci aby soft vykonaval kod v hlavni smycce.Pri simulaci v AVR studio i v realu skace jen po obsluze preruseni a do MAIN LOOPU vubec nezabrousi :frowning:[code]#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

char RED,PWM = 0;

//Obsluha preruseni TIMER0 pri preteceni
ISR(TIMER0_OVF_vect)
{
TCNT0 = 250;
if ((PWM == 0) && (RED != 0)) PORTB |= 0x01;
if (PWM == RED) PORTB &=~(0x01);
PWM++;

}

void main (void)
{
// inicializace mcu
DDRA = 0xFF; // port A jako vystup
DDRB = 0xFF; // port B jako vystup
DDRC = 0xFF; // port C jako vystup
DDRD = 0xFF; // port D jako vystup

//zhasne vsechny LED
PORTA = 0x00;
PORTB = 0x00;
PORTC = 0x00;
PORTD = 0x00;

//Globalni povoleni preruseni
sei();

//Nastaveni TIMER0 a Preruseni
RED = 255;
TCNT0 = 255;
TIMSK |= (1<<TOIE0) ;
TCCR0 |= (1<<CS01);

//MAIN LOOP
for(;:wink:
{
RED++;
_delay_ms(100);
}

}[/code]

:arrow_right: administrator: přejmenováno z "Obsluha preruseni a hlavni smycka"

V mainu pouze inkrementuješ proměnnou “red”. Jelikož s ní dále jinak nepracuješ, optimalizátor to pravděpodobně odstraní jako zbytečný zdržující kód. Že to využíváš v přerušení a přistupuje se k ní tedy v asynchronní události on nemuže tušit, protože jsi mu to neřekl. Stačí mu to dát vědět, a on si to už odoptimalizovat nedovolí :wink:
To zařídíš vložením “volatile” před deklaraci proměnné.
Proměnné RED a PWM mají být znaménkové <-128;127>? (ikdyž defaultní nastavení projektu často char bere jako neznaménkový)
S “PWM” se procuje pouze v přerušení, bylo by tedy vrámci lepší čitelnosti kódu ji deklarovat uvnitř onoho přerušení.
Aby si zachovala hodnotu i po jeho opuštění, stačí použít slovo “static” před deklarací.

Tedy globální:
volatile unsigned char red;

V přerušení:
static unsigned char pwm;

Aha :slight_smile: Diky.No samozrejme maji byt promenne <0;255> ,to sem si moh uvedomit sam ze tam mam dat unsigned,ale stim ze mi optimalizator odstrani kod se setkavam poprve…

Ovšem pravděpodobně né naposledy tak to nezapomeň :slight_smile:
To samý by se ti stalo, kdyby sis chtěl třeba v mainu udělat pomocí for zpožďovací smyčku -> zbytečný zdržování -> delete :slight_smile:
Když uděláš promenný volatile (ikdyž je třeba jinde nevyužíváš), tak to začne fungovat.
Snaž se to ovšem používat jen tam, kde je to nutné, jinak musí totiž překladač místo jednocyklových operací s registry ještě navíc provádět přesuny z/do ram, což program zpomaluje.

Pamatuju a znovu si to procitam v knizce.Pac kdyz to clovek cte aniz by to zrovna potreboval tak si poradne nepredstavim ani k cemu se ktera vec hodi a zapomenu to.Neni nad konkretni pripad…
Dalsi problem je ze definuju promenou: volatile unsigned char RED = 255;
Ta ma ale po definici hodnotu 0.Nechapu…
Dale kdyz umyslne nastavim frekvenci PWM signalu na nizkou uroven ze de ocima videt jak to krasne blika a pak nastavim RED na 255 aby to stale svitilo tak by ani pri nizkych frekvenci PWM nemelo nic problikavat,ale to se deje,jakoby tam na okamzik byla nula,nepatrne se to zachviva jakoby…

[code]#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

#define REG_TCNT0 10
#define BITPOS_0 1
#define BITPOS_1 2
#define BITPOS_2 4

volatile unsigned char RED,GREEN,BLUE = 255;

//Obsluha preruseni TIMER0 pri preteceni
ISR(TIMER0_OVF_vect)
{
static unsigned char PWM;

TCNT0 = REG_TCNT0;
PWM++;

if ((PWM == 0) && (RED != 0)) PORTB |= BITPOS_0;
if (PWM == RED) PORTB &=~(BITPOS_0);
}

void main (void)
{
// inicializace mcu
DDRA = 0xFF; // port A jako vystup
DDRB = 0xFF; // port B jako vystup
DDRC = 0xFF; // port C jako vystup
DDRD = 0xFF; // port D jako vystup

//zhasne vsechny LED
PORTA = 0x00;
PORTB = 0x00;
PORTC = 0x00;
PORTD = 0x00;

//Globalni povoleni preruseni
sei();

//Nastaveni TIMER0 a Preruseni
TCNT0 = REG_TCNT0;
TIMSK |= (1<<TOIE0) ;
TCCR0 |= (1<<CS01);

//MAIN LOOP
for(;:wink:
{

RED = 255;
//_delay_ms(5);

}

}
[/code]

Inicializuj si globální prom. v mainu :wink:.

“if (PWM == RED) PORTB &=~(BITPOS_0);”
V posledním průchodu je “PWM” = 255, podmínka je splněna -> dioda zhasne :wink:

Když používáš makra, zkus zvážit, jesli nebude přehlednější něco na způsob tohoto:

[code]#define LED_PORT PORTB
#define LED_RED 0

#define LED_OFF(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
#define LED_ON(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))

// pouziti
LED_ON(LED_PORT, LED_RED);[/code]
Definicí pro vlastní diodu, ale ponecháním názvu portu v kódu se výhoda používání preprocesoru jaksi vytrácí :wink:

Mimochodem - fórum má funkci editace vlastního textu - abs nemusel psát novej když něco zapomeneš. Občas edituju třeba 5x :smiley:

Globální proměnné jsou automaticky inicializovány na hodnotu 0.

Tvoje deklarace

volatile unsigned char RED,GREEN,BLUE = 255; 

je totéž jako

volatile unsigned char RED; volatile unsigned char GREEN; volatile unsigned char BLUE = 255;

Asi jsi chtěl toto

volatile unsigned char RED=255,GREEN=255,BLUE=255; 

To AB: Diky tj vončo.

To Piityy:Stema makrama mi to nak nevali.Hazi mi ti errory,proto to zatim nepouzivam.Davam kod mrkni na to…

[code]#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

// Konstanty
#define TIME 1
#define REG_TCNT0 255

// Pozice
#define BITPOS_0 1
#define BITPOS_1 2
#define BITPOS_2 4
#define PORT_1 PORTA

// Makra
#define SET_BIT ( BYTE,BIT ) ( BYTE |= ( 1<<BIT ))
#define CLEAR_BIT( BYTE,BIT ) ( BYTE &=~( 1<<BIT ))

volatile unsigned char RED = 0,GREEN = 0,BLUE = 0;

// Obsluha preruseni TIMER0 pri preteceni
ISR(TIMER0_OVF_vect)
{
static unsigned char PWM;

TCNT0 = REG_TCNT0;
PWM++;

if ((PWM == 0) && (RED != 0)) SET_BIT(PORT_1,BITPOS_0);
if ((PWM == RED) && (PWM != 255)) PORTB &=~(BITPOS_0);

if ((PWM == 0) && (GREEN != 0)) PORTB |= BITPOS_1;
if ((PWM == GREEN) && (PWM != 255)) PORTB &=~(BITPOS_1);

if ((PWM == 0) && (BLUE != 0)) PORTB |= BITPOS_2;
if ((PWM == BLUE) && (PWM != 255)) PORTB &=~(BITPOS_2);
}

void main (void)
{
// Inicializace mcu
DDRA = 0xFF; // port A jako vystup
DDRB = 0xFF; // port B jako vystup
DDRC = 0xFF; // port C jako vystup
DDRD = 0xFF; // port D jako vystup

// Zhasne vsechny LED
PORTA = 0x00;
PORTB = 0x00;
PORTC = 0x00;
PORTD = 0x00;

// Globalni povoleni preruseni
sei();

// Nastaveni TIMER0 a Preruseni
TCNT0 = REG_TCNT0;
TIMSK |= (1<<TOIE0) ;
TCCR0 |= (1<<CS01);

// MAIN LOOP
for(;:wink:
{
RED = 0,GREEN = 0,BLUE = 0;

_delay_ms(50);    

for (; RED != 255 ; RED++)			{ _delay_ms(TIME); }
for (; GREEN != 255 ; GREEN++) 		{ _delay_ms(TIME); }
for (; RED != 0 ; RED--) 			{ _delay_ms(TIME); }
for (; BLUE != 255 ; BLUE++) 		{ _delay_ms(TIME); }
for (; GREEN != 0 ; GREEN--) 		{ _delay_ms(TIME); }
for (; RED != 255 ; RED++)			{ _delay_ms(TIME); }	
for (; GREEN != 255 ; GREEN++) 		{ _delay_ms(TIME); }
 
_delay_ms(50);		

}

}[/code]

Jinak RGB ledka uz mi pekne projizdi celou duhu.Obcas ale jakoby stale problikne zniceho nic,nepravidelne nekdy vickrat nekdy jednou… :frowning:

V definicích pro preprocesor si nemůžeš stříhat mezery a tabelátory jak se ti zlíbí. [code]#define BITPOS_0 1
#define BITPOS_1 2
#define BITPOS_2 4
#define PORT_1 PORTA

// Makra
#define SET_BIT(BYTE,BIT) (BYTE |= ( 1<<BIT ))
#define CLEAR_BIT(BYTE,BIT) (BYTE &=~( 1<<BIT ))[/code]