ATmega88A PWM

Všetko čo sa týka mikropočítačov + Sekcia Arduino

Moderátori: psichac, Moderátori

DanielK
Stály člen
Stály člen
Príspevky: 282
Dátum registrácie: 28 Feb 2015, 14:55

ATmega88A PWM

Príspevok od používateľa DanielK » 02 Máj 2022, 16:12

Ahoj,
nedaří se mi rozběhat HW PWM na ATmega88. Nejsem si jist zda nechci něco, co není proveditelné.

Používám Timer counter 0 pro generování 1ms pulzů. Na portech PB1 a PB2 potřebuji dva na sobě nezávisle říditelné PWM kanály. Ty jsou taky řízené pomocí TC0.

Mám nastaveno TCTN0 na hodnotu 127 znamená to že: PWM bude už jen 7 bitové?
Pokud jsem správně pochopil tak zápis do TCCR0A udělá:
(1<<COM0A0) // při přetečení invertuje pin mcu PB1
(1<<COM0B0) // při přetečení invertuje pin mcu PB2
(1<<WGM00) | (1<<WGM01) // nastaví mode 3 Fast PWM
OCR0A // přednastaví hodnotu, která se bude inkrementovat až do přetečení

Nějak se v tom ztrácím, ocením jakoukoliv nápovědu.

Kód: Vybrať všetko

#define F_CPU 8000000
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <stdio.h>	

uint16_t a =0;
uint8_t dispupdate =0;
uint16_t c =0;


ISR (TIMER0_OVF_vect){
TCNT0 =127;
	PORTC ^= (1 << PC1);  // Invert
	a++;
	dispupdate--;
	c--;
}

int main(void)
{
	DDRC = 0b00111110;
	DDRD = 0b11111111;
	DDRB = 0b00000111;
	PORTB |= (1 << PB5); // pull up
	PORTB |= (1 << PB4); // pull up
	PORTB |= (1 << PB3); // pull up


	uint8_t i =0;
	uint16_t j = 0;
    uint8_t charakter =0;
	uint8_t tlPB5 =0;
	uint8_t tlPB4 =0;
	uint8_t tlPB3 =0;
	uint8_t dPB5 =0;
	uint8_t dPB4 =0;
	uint8_t dPB3 =0;
	uint8_t start =0;
 
    // ?íslice na 7 segmentovem displayi {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
	uint8_t segments[10] = {0xDE, 0x88, 0x5D, 0x9D, 0x8B, 0x97, 0xD7, 0x8C, 0xDF, 0x9F };
	
	TCNT0 = 127; // pocatecni hodnota
	TCCR0B |= (1<<CS01) | (1<<CS00); // PRESCALER 8
	TCCR0A |= (1<<COM0A0) | (1<<COM0B0) | (1<<WGM00) | (1<<WGM01); 
	TIMSK0 = (1<<TOIE0); //Timer/Counter0 Overflow Interrupt Enable
	
	OCR0A = 200;
	OCR0B = 200;
	
	
	sei();
    while (1){
	if(dispupdate==0){
		if(charakter == 0){
			PORTC |= (1 << PC2);  // VCC
			PORTC &= ~(1 << PC3);  // VCC
			i = j / 1000;
			PORTD = segments[i];
		}

		if(charakter == 1){
			PORTC |= (1 << PC5);  // VCC
			PORTC &= ~(1 << PC2);  // VCC
			i = j % 1000 /100;
			PORTD = segments[i];
		}		

		if(charakter == 2){
			PORTC |= (1 << PC4);  // VCC
			PORTC &= ~(1 << PC5);  // VCC
			i = j % 100 /10;
			PORTD = segments[i];
		}

		if(charakter == 3){
			PORTC |= (1 << PC3);  // VCC
			PORTC &= ~(1 << PC4);  // VCC
			i = j % 10;
			PORTD = segments[i];
		}

		if(charakter < 3){
			charakter ++;
		}
		else{
			charakter =0;
		}
		dispupdate=4;
	}
	
	if(c==0){

		if((PINB & (1 << PB5)) == 0){ 
			tlPB5++;
			if((tlPB5>=10) & (dPB5==0)){
				j++;
				dPB5=1;
			}
			
		}
		else{
			tlPB5=0;
			dPB5=0;
		}

		if((PINB & (1 << PB3)) == 0){
			tlPB3++;
			if((tlPB3>=10) & (dPB3==0)){
				j--;
				dPB3=1;
			}
	
		}
		else{
			tlPB3=0;
			dPB3=0;
		}

		if((PINB & (1 << PB4)) == 0){
			tlPB4++;
			if((tlPB4>=10) & (dPB4==0)){
				start++;
				dPB4=1;
			}
			
		}
		else{
			tlPB4=0;
			dPB4=0;
		}



	c=1;
	}

		if (start >= 2){
			start=0;
		}

		if(j==0){
			start=0;	
		}

		if((a>=1000) & (start == 1) & (j>=1)){
			a=0;
			j--;
		}	

    }//while
} // int main
0

miso156
Pokročilý člen
Pokročilý člen
Príspevky: 648
Dátum registrácie: 06 Dec 2020, 11:46
Bydlisko: Banska Stiavnica
Vek: 38

Re: ATmega88A PWM

Príspevok od používateľa miso156 » 02 Máj 2022, 16:29

Ak si dobre pamatam, premenne zdielane medzi hl. programom a prerusenim musia byt definovane ako volatile.


OCR0A // přednastaví hodnotu, která se bude inkrementovat až do přetečení

To asi nemas pravdu, OCR0A sa neinkrementuje, je to komparacna hodnota ktora udava duty.
Inkrementuje sa TCNT0.
0
"No pain, no gain." (KC238)

Používateľov profilový obrázok
balu
Pokročilý člen
Pokročilý člen
Príspevky: 539
Dátum registrácie: 21 Feb 2022, 12:06

Re: ATmega88A PWM

Príspevok od používateľa balu » 02 Máj 2022, 19:09

Asi by to chtělo pozorněji si prohlédnout datasheet ...
1) OCR čítače 0 NEJSOU připojeny k pinům PB1 a PB2 - tam jsou připojeny OCR čítače 1. Tedy pokud nechceš PWM generovat softwarově.
2) Když se podíváš pozorně, tak zjistíš, že jsou v datasheetu i obrázky, které ukazují, jak se čítač a OCR chovají v jednotlivých režimech.
3) Když chceš PWM výstup v plném rozsahu, tak nesmíš přednastavovat TCNTx - pokud přednastavuješ TCNT0 na 127 a do OCR dáš 126 nebo méně, nebude se PWM signál generovat.

Mimochodem - Co je proměnná "a", co je proměnná "c" ? Co takhle proměnné pojmenovat nějak smysluplně ? Třeba místo "a" napsat "PocitaniOvecek" a místo "c" napsat "ZbyvaKroku" ...


Myslím, že by bylo vhodné rozdělit to na dva čítače :

Přerušení každou 1 ms

Nejdřív je potřeba spočítat, jak po kolika tikách hodin potřebuješ zavolat obsluhu přerušení.
Tedy znáš
- F_CPU = 8000000 (radši používám F_CPU = 8000000.0)
- PozadovanyPocetPreruseniZaSekundu = 1000 (1ms = 1000 pulzů)
- Je třeba zvolit PrescalerHodin (1,8,16,256,1024) nastavený tak, abychom se vešli do šířky čítače (čítač 0 a 2 je 0-255, čítač 1 je 0-65535) a je třeba aby vyšlo celé číslo (ne vždy to lze s 8-bitovým čítačem provést)

A jdeme počítat :

PocetCyklu = F_CPU/PozadovanyPocetPreruseniZaSekundu/PrescalerHodin

PrescalerHodin dosadíš 1 :
PocetCyklu = 8000000/1000/1 = 8000 - to je víc, než 256
PrescalerHodin dosadíš 8 :
PocetCyklu = 8000000/1000/8 = 1000 - to je víc, než 256
PrescalerHodin dosadíš 64 :
PocetCyklu = 8000000/1000/64 = 125 - vyhovuje => (125*64)/8000000 = 0,001 = 1ms
PrescalerHodin dosadíš 256 :
PocetCyklu = 8000000/1000/256 = 31,25 => 31 - desetinné číslo - bude to nepřesné => (31*256)/8000000 = 0,000992 = 0,992ms

Potřebujeme tedy, aby čítač odpočítal při prescaleru 64 přesně 125 cyklů.

OCR0A = 124 (čítač bude čítat 0 - 124 => 125 cyklů)

Nastavíš čítač na CTC režim, povolíš přerušení od OCR0A, nastavíš prescaler na 64.
Přerušení od OCR0A přijde každou 1ms.



PWM signály na PB1 a PB2

Nastaviš COM1x na "Clear OC1A/OC1B on Compare Match, set OC1A/OC1B at BOTTOM (non-inverting mode)" nebo "Set OC1A/OC1B on Compare Match, clear OC1A/OC1B at BOTTOM (inverting mode)" podle potřeby, čítač nastavíš do FAST PWM v 8, 9 nebo 10-bitovém režimu a spustíš s požadovaným prescalerem. Výhodou tohoto řešení podle datasheetu je, že nemusíš řešit, kdy do OCR1x registrů zapíšeš, protože zápis do se registru synchronizuje s čítačem (double buffering).
1
Obrázok 1

DanielK
Stály člen
Stály člen
Príspevky: 282
Dátum registrácie: 28 Feb 2015, 14:55

Re: ATmega88A PWM

Príspevok od používateľa DanielK » 03 Máj 2022, 18:17

Díky chlapi

S takovouhle nápovědou je to brnkačka. Musím se nějak naučit číst v těch jejich registrech a bitech, pořád v tom mám hroznej guláš.

Kód: Vybrať všetko

#define F_CPU 8000000
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <stdio.h>

volatile uint16_t counter1s =0;
volatile uint8_t dispupdate =0;
volatile uint16_t counter1ms =0;
volatile uint8_t blikaniznaku =0;

ISR (TIMER0_COMPA_vect){  //992us
	//PORTC ^= (1 << PC1);  // Invert
	counter1s++;
	dispupdate--;
	counter1ms--;
	blikaniznaku++;
}

int main(void)
{
	DDRC = 0b00111100;
	DDRD = 0b11111111;
	DDRB = 0b00000111;
	PORTB |= (1 << PB5); // pull up
	PORTB |= (1 << PB4); // pull up
	PORTB |= (1 << PB3); // pull up
	PORTC |= (1 << PC1); // pull up


	uint8_t hodnotasegmentu =0;
	uint16_t vteriny = 0;
	uint8_t charakter =0;
	uint8_t tlPB5 =0;
	uint8_t tlPB4 =0;
	uint8_t tlPB3 =0;
	uint8_t dPB5 =0;
	uint8_t dPB4 =0;
	uint8_t dPB3 =0;
	uint8_t start =0;
	uint8_t vykonLED =0;
	
	// ?íslice na 7 segmentovem displayi {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, P};
	uint8_t segments[] = {0xDE, 0x88, 0x5D, 0x9D, 0x8B, 0x97, 0xD7, 0x8C, 0xDF, 0x9F, 0x4F };

	/* Timer Counter 0 */
	TCNT0 = 0; // pocatecni hodnota
	TCCR0B |= (1<<CS01) | (1<<CS00); // PRESCALER 64
	TCCR0A |= (1<<WGM01); // mode 2, CTC
	TIMSK0 = (1<<OCIE0A); //Timer /CTC
	OCR0A = 124;
	
	/* Timer Counter 1 */
	TCCR1A |= (1<<COM1A1) | (1<<COM1B1) | (1<<WGM12) | (1<<WGM10); // Clear OC1A/OC1B on Compare Match (non-inverting mode), Fast PWM, 8-bit
	TCCR1B |= (1<<CS10); // clk I/O/1 (No prescaling)
	OCR1B = 127; //Nastaveni 50PWM PB2
	

	sei();
	while (1){
		if(dispupdate==0){ //LED display update time
			
			if(charakter == 0){
				PORTC |= (1 << PC2);  // VCC
				PORTC &= ~(1 << PC3);  // VCC
				hodnotasegmentu = vteriny / 1000; // vteriny -> [hodnotasegmentu,X,X,X]
				if((blikaniznaku <= 127) & (start == 3)){ //blikani segmentu vteriny
					PORTD = segments[hodnotasegmentu]; 
				}
				else if ((blikaniznaku >= 128) & (start == 3)){ // blikani segmentu 
					PORTD = 0x00;
				}
				else if((start == 4) | (start == 5) | (start == 6)){ // vypis znaku P
					PORTD = segments[10];
				}
				else{
					PORTD = segments[hodnotasegmentu]; // zobrazeni znaku
				}
			}

			if(charakter == 1){
				PORTC |= (1 << PC5);  // VCC
				PORTC &= ~(1 << PC2);  // VCC
				hodnotasegmentu = vteriny % 1000 /100; // vteriny -> [X,hodnotasegmentu,X,X]
				if((blikaniznaku <= 127) & (start == 0)){ //blikani segmentu vteriny
					PORTD = segments[hodnotasegmentu];
				}
				else if ((blikaniznaku >= 128) & ((start == 2) | (start == 6))){ //blikani segmentu
					PORTD = 0x00;
				}
				else if((blikaniznaku <= 127) & (start == 6)){ //blikani segmentu PWM
					PORTD = segments[(vykonLED %1000 /100)]; 
				}				
				else if((start ==5) | (start ==46)){ // vypis segmentu PWM
					PORTD = segments[(vykonLED %1000 /100)];
				}				
				else{
					PORTD = segments[hodnotasegmentu]; // vypis segmentu vteriny
				}

			}

			if(charakter == 2){
				PORTC |= (1 << PC4);  // VCC
				PORTC &= ~(1 << PC5);  // VCC
				hodnotasegmentu = vteriny % 100 /10; //vteriny -> [X,X,hodnotasegmentu,X]
				if((blikaniznaku <= 127) & (start == 0)){ //blikani segmentu vteriny
					PORTD = segments[hodnotasegmentu];
				}
				else if ((blikaniznaku >= 128) & ((start == 1) | (start == 5))){
					PORTD = 0x00;
				}
				else if((blikaniznaku <= 127) & (start == 5)){ //blikani segmentu PWM
					PORTD = segments[(vykonLED %100 /10)];
				}
				else if((start ==4) | (start ==6)){
					PORTD = segments[(vykonLED %100 /10)];
				}
				else{
					PORTD = segments[hodnotasegmentu];
				}
			}

			if(charakter == 3){
				PORTC |= (1 << PC3);  // VCC
				PORTC &= ~(1 << PC4);  // VCC
				hodnotasegmentu = vteriny % 10;     //vteriny -> [X,X,X,hodnotasegmentu]
				if((blikaniznaku <= 127) & (start == 0)){ //blikani segmentu vteriny
					PORTD = segments[hodnotasegmentu];
				}
				
				else if ((blikaniznaku >= 128) & ((start == 0) | (start == 4))){ //blikani segmentu PWM
					PORTD = 0x00;
				}
				else if((blikaniznaku <= 127) & (start == 4)){
					PORTD = segments[(vykonLED %10)];
				}
				else if((start ==5) | (start ==6)){
					PORTD = segments[(vykonLED %10)];
				}
				
				else{
					PORTD = segments[hodnotasegmentu];
				}
			}

			if(charakter < 3){ //cyklování charakteru
				charakter ++;
			}
			else{
				charakter =0;
			}
			
			dispupdate=4; //LED display update time (ms)
		}
		
		if(counter1ms==0){ //1ms pro tlacitka

			if((PINB & (1 << PB5)) == 0){ // stisk tlačítka + osetreni zakmitu pri stisku
				tlPB5++;
				if((tlPB5>=30) & (dPB5==0)){
					if(start == 0){
						vteriny++;
					}
					if(start == 1){
						vteriny = vteriny +10;
					}
					if(start == 2){
						vteriny = vteriny +100;
					}
					if(start == 3){
						vteriny = vteriny + 1000;
					}
					if(start == 4){
						vykonLED = vykonLED + 1;
					}
					if(start == 5){
						vykonLED = vykonLED + 10;
					}
					if(start == 6){
						vykonLED = vykonLED + 100;
					}					
					dPB5=1;
				}
			}
			else{ tlPB5=0; dPB5=0; }

			if((PINB & (1 << PB3)) == 0){ // stisk tlačítka + osetreni zakmitu pri stisku
				tlPB3++;
				if((tlPB3>=30) & (dPB3==0)){
					if(start == 0){
						vteriny--;
					}
					if(start == 1){
						vteriny = vteriny -10;
					}
					if(start == 2){
						vteriny = vteriny -100;
					}
					if(start == 3){
						vteriny = vteriny -1000;
					}
					if(start == 4){
						vykonLED = vykonLED - 1;
					}
					if(start == 5){
						vykonLED = vykonLED - 10;
					}
					if(start == 6){
						vykonLED = vykonLED - 100;
					}					
					dPB3=1;
				}
			}
			else{ tlPB3=0; dPB3=0; }

			if((PINB & (1 << PB4)) == 0){ // stisk tlačítka + osetreni zakmitu pri stisku
				tlPB4++;
				if((tlPB4>=30) & (dPB4==0)){
					start++;
					dPB4=1;
				}
			}
			else { tlPB4=0; dPB4=0; }

			counter1ms=1;
		}

		if (start >= 8){ // zastavení časovače
			start=0;
		}

		if(vteriny==0){ // zastavení časovače
			//	start=0;
			OCR1A = 0; // vynulovani PWM PB1
		}
		
		if((vteriny == 0) & (start == 7)){ // odpoet dokoncen, 1s piezo
			if(counter1s>=1007){
			PORTB ^= (1 << PB0);  // Piezo
			counter1s =0;
			}
		}

		if((PINC & (1 << PC1)) != 0){ // reakce na otevrene viko 
			start = 0;
			PORTB &= ~(1 << PB0); // ztiseni pieza	
		}
		
		if(start == 0){  //pocatecni stav, ztiseni pieza, nastaveni PWM = 0, reset prednastaveneho vykonu
			PORTB &= ~(1 << PB0); // GND
			OCR1A = 0;
			vykonLED = 0;
		}

		if (vykonLED >=101){ // Perpetuum mobile neexistuje
			vykonLED = 100;
		}
		
			

		if((counter1s>=1007) & (start == 7) & (vteriny>=1)){ //1s, odpocet casovace, nastaveni vykonu
			counter1s=0;
			vteriny--;
		OCR1A = (vykonLED * 2.55);
		}
		
	 	
	
	}//while
} // int main
0

Používateľov profilový obrázok
balu
Pokročilý člen
Pokročilý člen
Príspevky: 539
Dátum registrácie: 21 Feb 2022, 12:06

Re: ATmega88A PWM

Príspevok od používateľa balu » 03 Máj 2022, 19:54

Jenom malý detail :

Kód: Vybrať všetko

ISR (TIMER0_COMPA_vect){  //992us
S tímhle nastavením by mělo být přerušení každou 1ms a ne 992us - já vím, je to jen komentář.

Jinak dobrý zvyk je, že čítač spouštíš (nasavuješ prescaler - CSxx bity) až jako poslední krok.

Totéž, když měníš režim čítače, tak jej zastavíš (vynuluješ CSxx bity), vypneš jeho nastavená přerušení, vynuluješ TIFRx registr (v datasheetu najdeš jak), přenastavíš režim (celý čítač) - tady má smysl vynulovat TCNTx registr a nakonec čítač spustíš (nastavíš CSxx bity). Pravdou je, že režim čítačů se během chodu programu zase tak často nemění.
0

DanielK
Stály člen
Stály člen
Príspevky: 282
Dátum registrácie: 28 Feb 2015, 14:55

Re: ATmega88A PWM

Príspevok od používateľa DanielK » 03 Máj 2022, 20:26

PocetCyklu = F_CPU/PozadovanyPocetPreruseniZaSekundu/PrescalerHodin
8 000 000 / 1000 / 64 = 125
Pravda je to 1ms.

U tohoto zařízení není ta absolutní přesnost, až tak kritická. Zda se tam při dočasování 2 min ukáže rozdíl +-2s, tak to není nic zásadního.

Momentálně mě více trápí HW. Nečekal jsem odběr 60mA, 0,42W pro SMD 7805 je celkem dost. Asi budu muset zvýšit odpory pro display.
A to že Mosfet bude mít při 1k na Gate tak ošklivý náběh, a tím pádem se bude zahřívat jsem nečekal už vůbec, takže buď snížím frekvenci PWM nebo hodnotu rezistoru.

EDIT:
Totéž, když měníš režim čítače, tak jej zastavíš (vynuluješ CSxx bity), vypneš jeho nastavená přerušení, vynuluješ TIFRx registr (v datasheetu najdeš jak), přenastavíš režim (celý čítač) - tady má smysl vynulovat TCNTx registr a nakonec čítač spustíš (nastavíš CSxx bity). Pravdou je, že režim čítačů se během chodu programu zase tak často nemění.
Takže toto použiju, kdybych třeba dělal změnu v předěličce nebo měnil mod, ale pro změnu v OCR1x to není potřeba. rozumím tomu správně?
0

Používateľov profilový obrázok
balu
Pokročilý člen
Pokročilý člen
Príspevky: 539
Dátum registrácie: 21 Feb 2022, 12:06

Re: ATmega88A PWM

Príspevok od používateľa balu » 03 Máj 2022, 21:29

U tohoto zařízení není ta absolutní přesnost, až tak kritická. Zda se tam při dočasování 2 min ukáže rozdíl +-2s, tak to není nic zásadního.
Pokud používáš interní RC oscilátor, pak stejně frekvence není přesná a je závislá na okolní teplotě. Šlo hlavně o to ukázat, jak se počítá určitá frekvence pro přerušení.
Takže toto použiju, kdybych třeba dělal změnu v předěličce nebo měnil mod, ale pro změnu v OCR1x to není potřeba. rozumím tomu správně?
U změny předděličky není nutné nulovat čítač a přerušení. A vynulování CSxx a nové nastavení je spíš doporučení, než nutnost. Pokud neměníš režim čítače, ale jen předděličku, tak stav čítače se nemění, jen pak pokračuje jinou rychlostí. Důležité je to jenom u změny režimu čítače.
A to že Mosfet bude mít při 1k na Gate tak ošklivý náběh, a tím pádem se bude zahřívat jsem nečekal už vůbec, takže buď snížím frekvenci PWM nebo hodnotu rezistoru.
Nevím k čemu tam ten MOSFET používáš, ale pokud pro refresh displeje, tak kmitočet stačí tak, aby se celý displej vystřídal tak 100x za sekundu. Jinak do MOSFET tranzistoru je podle mně 1k příliš mnoho. Já dávám tak maximálně 10R-100R podle toho, jak výkonný ten MOSFET je.

Pro segmenty displeje většinou stačí proud do 5mA/segment. Většinou to počítám na 1-2 mA na segment. U nových displejů to většinou bohatě stačí. Ale mám tu i staré segmentovky, které na rozumné rozsvícení potřebovaly i 10mA a víc - to už je pak masakr. Jinak pro 5V napájení používám 7805 - provedení pordle náročnosti odběru. Pokud vím, že budu potřebovat vyšší odběr, používám buď tohle nebo na DPS pak zdroj s LM2576 (+3 externí součástky - zapojení podle datasheetu) - ten zvládne 3A bez nutnosti chlazení - napájím s ním v jednom zařízení RaspberryPi - tam se 7805-ka málem upekla i s chladičem. Ale jsou to obojí pulzní zdroje, tak pokud potřebuješ použít AD převodník, je potřeba dobrá filtrace - obzvlášť u toho čínskýho modulu.





Ještě si dovolím jeden tip ...

Kód: Vybrať všetko

uint8_t segments[] = {0xDE, 0x88, 0x5D, 0x9D, 0x8B, 0x97, 0xD7, 0x8C, 0xDF, 0x9F, 0x4F };

Když definici segentů necháš v programové paměti :

Kód: Vybrať všetko

const PROGMEM uint8_t segments[] = {0xDE, 0x88, 0x5D, 0x9D, 0x8B, 0x97, 0xD7, 0x8C, 0xDF, 0x9F, 0x4F };
a data budeš číst místo :

Kód: Vybrať všetko

PORTD = segments[hodnotasegmentu];
takto :

Kód: Vybrať všetko

PORTD = pgm_read_byte(&segments[hodnotasegmentu]);

Můžeš ušetřit docela velké množství RAM. Obzvlášť, když budeš pracovat s velkými nebo více poli (typicky znaková sada pro použití s grafickým displejem). Česká znaková sada s diakritikou má 1784 bytů (výška znaku 8 bodů, šířka maximálně 7 bodů - proporcionální font). Když to necháš v RAM, tak už se prakticky s ničím nehneš.

Navíc RAM potřebuješ i pro stack, takže se pak může stát, že SW začne dělat nesmysly a chovat se nepředvídatelně.
0

DanielK
Stály člen
Stály člen
Príspevky: 282
Dátum registrácie: 28 Feb 2015, 14:55

Re: ATmega88A PWM

Príspevok od používateľa DanielK » 03 Máj 2022, 23:08

Tím mosfetem se spíná 100 LED, celkový odběr cca 700mA. Jde o UV LED osvitku a toto je časovač, který to bude řídit.

Dokumentace PDF v příloze.

Zítra u toho LED displeje nahradím 220R za 1k. K mosfetu AOT414 zkusím dát něco kolem 50R.

U té funkce PROGMEM je nějaký rozdíl v době přístupu oproti SRAM? Čtení z paměti Flash paměti má neomezenou životnost?
Prílohy
TIMER WITH PWM V1.0 D.K..PDF
(2.1 MiB) 50 stiahnutí
0

Používateľov profilový obrázok
balu
Pokročilý člen
Pokročilý člen
Príspevky: 539
Dátum registrácie: 21 Feb 2022, 12:06

Re: ATmega88A PWM

Príspevok od používateľa balu » 03 Máj 2022, 23:32

Opět - datasheet ...

Instrukce LD nebo LDD, která se používá na čtení z RAM trvá 2 takty procesoru. Instrukce LPM, která čte z programové paměti trvá 3 instrukce. Zbytek zálezí na kompilátoru, jak připraví čtení. Co se životnosti a čtení z Flashe týká, tak procesor čte z flashe každou instrukci, kterou provádí...
0

Napísať odpoveď
  • Podobné témy
    Odpovedí
    Zobrazení
    Posledný príspevok