ATmega16: PWM bez pouziti OCpinu

Aho

Sel by pouzit rychly PWM rezim s odpojenym OC2 pinem,a signal generovat na kterem koliv pinu pomoci obysluhy preruseni??

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


//Obsluha preruseni TIMER2 pri TCNT0=OCR0
ISR(TIMER2_COMP_vect)
{
  PORTD &=~(0x80);
}
//Obsluha preruseni TIMER2 pri preteceni
ISR(TIMER2_OVF_vect)
{
  PORTD |=0x80;
}
 
void main (void)
{  
  // inicializace mcu
  DDRD |= 0xFF;   // port D jako vystup
  //zhasne vsechny LED
  PORTD |= 0x00;   // zapis "255" na port D
  //Globalni povoleni preruseni
  sei();
  //Nastaveni TIMER2 a Preruseni
  TIMSK = 0xC0;
  OCR2 = 0x00;
  TCCR2 =0x4A;
  
 
  //MAIN LOOP
  for(;;)
  {
    OCR0=0x00;
	_delay_ms (400);

    OCR0=0x0F;
	_delay_ms (400);

    OCR0=0xFF;
	_delay_ms (400);

  } 

 
}

Ano, slo by to. Ak Ti nebude vadit neurcitost obsluhy prerusenia +/- par stoviek nanosekund kym sa vykona potencionalne najdlhsia instrukcia a az po jej vykonani sa zacne realizovat kod pod prerusenim. Ak chces generovat signaly s periodou 100us a krokom 1us, potom by ti to nemalo moc vadit.

Ten kod mi, ale buhuzel nefunguji.Dioda mi stabilne sviti!!

Tak skousim ciste klasicky PWM a dioda mi stabilne lehce sviti.Ale nemela by!

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

///Obsluha preruseni TIMER2 pri TCNT2=OCR2
ISR(TIMER2_COMP_vect)
{
PORTA &=~(0x80);
}
//Obsluha preruseni TIMER2 pri preteceni
ISR(TIMER2_OVF_vect)
{
PORTA |=0x80;
}
/

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 TIMER2 a Preruseni
TIMSK = 0xC0; //povolim preruseni preteceni a shody (u PWM rezimu neni nutno asi… ?)
OCR2 = 0x00;
TCCR2 =0x6B; // Rzchly PWM,neinvertujici,delicka 32

//MAIN LOOP
for(;:wink:
{
OCR2=0x00;
_delay_ms (800);

OCR2=0x0F;

_delay_ms (800);

OCR2=0xFF;

_delay_ms (800);

}

}[/code]

kod som neprezeral. So litle time :slight_smile:
Ale princip je dobry :slight_smile:

ale len tak na prvy kuk vidim

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

tieto prikazy nic nerobia,lebo si procesoru prikazal aby hodnotu z portov zORoval s nulami. Takze na vystupe sa nic nezmeni. Skus dat prec to |.

Nj dik,jen skoda ze v tom neni ta chyba,potrebuju aby nekdo kouk na to PWM,me se to zda dobre ale delam stim podruhy vzivote a to jeste po strasny dobe!!

Bych ti na to i kouk, jen kdybys při nastavování periferií místo všelijakých hausnumer používal názvy bitů :wink:.

Neumim nastavit bit :blush: krome poziti bitovejch masek.Tagze vypisu ktery sou nastaveny:

TIMSK - COIE2,TOIE2
TCCR2 - WGM20,COM21,WGM21,CS21,CS20

takhle by to melo stacit…

Bez bitu COM21 a s odkomentovanými obsluhami přerušení by ti to mělo chodit. Nemám po ruce m16, ale nic špatnýho tam nevidím :confused: .

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

//Obsluha preruseni TIMER2 pri TCNT2=OCR2
ISR(TIMER2_COMP_vect)
{
PORTA &= ~(1<<PA7);
}

//Obsluha preruseni TIMER2 pri preteceni
ISR(TIMER2_OVF_vect)
{
PORTA |= (1<<PA7);
}

void main (void)
{
// inicializace mcu
DDRA |= (1<<PA7);

//Nastaveni TIMER2 a Preruseni
TIMSK |= (1<<OCIE2) | (1<<TOIE2);
/* TCCR2 |= (1<<WGM20) | (1<<WGM21) | (1<<COM21) | (1<<CS21) | (1<<CS20);
// wgm: Fast pwm, ok
// com: non-inverting - pokud tvoříš polo-sw pwm => OC2 disconnected, nepoužíváš OC2 pin
// cs: clkt2s/32, AS2 in ASSR = 0 => clkt2s=clkio, ok */
TCCR2 |= (1<<WGM20) | (1<<WGM21) | (1<<CS21) | (1<<CS20);

//Globalni povoleni preruseni
sei();

//MAIN LOOP
for(;:wink:
{
OCR2=0x00;
_delay_ms(800);

OCR2=0x80; 

_delay_ms(800);

OCR2=0xFF; 

_delay_ms(800);

}

}[/code]

Skus pouzivat takuto stabnu kulturu

#define MOJ_BITIK  3 // poradie bitu v cisle pocitany od 0, miesto MOJ_BITIK si vloz co len chces :-)
#define PORT_MOJ_BITIK PORTB // napriklad
#define DDR_MOJ_BITIK DDRB  // napriklad
#define PIN_MOJ_BITIK PINB // napriklad

//nastavi pin ako vstupny
#define IN_MOJ_BITIK  (DDR_MOJ_BITIK &= ~(1<<MOJ_BITIK))

//nastavi pin ako vystupny
#define OUT_MOJ_BITIK  (DDR_MOJ_BITIK |= (1<<MOJ_BITIK))

// ak je pin nastaveny na vystup, nastavi hodnotu log.1
#define SET_MOJ_BITIK  (PORT_MOJ_BITIK |= (1<<MOJ_BITIK))

// ak je pin nastaveny na vystup, nastavi hodnotu log.0
#define RES_MOJ_BITIK  (PORT_MOJ_BITIK &= ~(1<<MOJ_BITIK))

// vrati nenulovu hodnotu ak je pin v stave log.1
#define GET_MOJ_BITIK  (PIN_MOJ_BITIK &= (1<<MOJ_BITIK)) 

// priklad
//...
static char i = 0;

// programik v nekonecnej slucke cvici s Tvojim bitikom ako sibnuty :-)
OUT_MOJ_BITIK;
while(1) {
   i++;
   if(i & 0x01) SET_MOJ_BITIK;
   else RES_MOJ_BITIK;
}

// alebo sa to da aj takto

// Definice makier s parametrami

#define SET(PREMENNA,BIT) ((PREMENNA) |= (1<<(BIT)))
#define RES(PREMENNA,BIT) ((PREMENNA) &= ~(1<<(BIT)))

// neguje hodnotu bitu v premennej
#define NEG(PREMENNA,BIT) ((PREMENNA) ^= (1<<(BIT)))
#define TST(PREMENNA,BIT) ((PREMENNA) & (1<<(BIT)))

// ...
static char nejaka_hodnota
static char nejaky_bit = 2;

//...

  SET(nejaka_hodnota, nejaky_bit);

//...

  RES(nejaka_hodnota, nejaky_bit);

// ...
 
// podmienka je splnena, ak je bit nenulovy
// vsimni si, ze TST() uz nemusi byt ozatvorkovane. Preco je to tak, to je na domacu ulohu :-)
 if TST(nejaka_hodnota, nejaky_bit) {
//...
}

pre nastavovanie bitov v registri sa pouzivaju nasledovne zapisy a im podobne:


// uryvok z rozsiahlejsieho cyklu

	#define SPI0_ENABLE_MASTER SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)
	#define SPI0_DATA_REGISTER SPDR
	#define SPI0_PRENOS_UKOCENY  (SPSR & (1<<SPIF))
// alebo
	#define AKTIVUJ_AD 			SET(ADCSRA,ADEN)
	#define SPUSTI_AD_PREVOD	SET(ADCSRA,ADSC)
	#define AUTOTRIGER_AD		SET(ADCSRA,ADATE)

//...


   SPI0_ENABLE_MASTER;
   if  SPI0_PRENOS_UKOCENY {

    // bla bla bla

   }

takyto pristup Ti umozni vytvorit si pre kazdy procesor (aj z nejakym uplne inym jadrom) header v ktorom budu na konkretnom mieste ine nazvy bitikov a registrov. Tvoj C-ckovy kod vsak ostane bezo zmeny.

A vo vo vo tom to je :slight_smile:

To martin: dik.
To Pitty:

Kdyz tam dam tu osluhu preruseni tak najednou funguje,ale myslel sem ze tam obsluhu vubec davat nemusim kdyz pouzivam pin CO2.Ale ma to proad chybu.Pri OCR2=0x00; to slabe sviti !!!

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

//Obsluha preruseni TIMER2 pri TCNT2=OCR2
ISR(TIMER2_COMP_vect)
{
}
//Obsluha preruseni TIMER2 pri preteceni
ISR(TIMER2_OVF_vect)
{
}

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 TIMER2 a Preruseni

TIMSK |= (1<<OCIE2) | (1<<TOIE2); //povolim preruseni preteceni a shody (u PWM rezimu neni nutno asi… ?)
TCCR2 |= (1<<WGM20) | (1<<WGM21) | (1<<COM21) | (1<<CS21) | (1<<CS20); // Rzchly PWM,neinvertujici,delicka 32

//MAIN LOOP
for(;:wink:
{
OCR2=0x00;
_delay_ms(800);

OCR2=0x80;
_delay_ms(800);

OCR2=0xFF;
_delay_ms(800); 

}

}[/code]

Pokud používáš pin OC2, tak tam obsluhy být nemusí (a přerušení by neměla být povolená pokud je nevyužíváš ikdyž překladač se postará), pin ovšem musí být nastaven jako výstup. OC2 je na PD7.

“slabě svítí”:

Esi sem to dobre pochopil tak u rychlyho modu nikdy nedosahnu uplny nuly!!protote pro kazdy MAX+1 hodinovy cyklus to vylitne nahoru… ??

Tak parada fazovej to nedela,diky moc!!!Cetl sem nekde ze ten rychlej ma zakmity ale ze to pude tak hodne videt me teda nenapadlo!

Druhá možnost by byla použít inverzní a zapojit diodu obráceně :slight_smile:.
Na jiných součástkách bys to asi neviděl, ale dioda je mrcha.

Kdybys to dělal programově (bez OC pinu), tak bys měl být taky schopen ty špičky eliminovat (přidáním podmínky do přerušení).