Ik ben bezig met 'n programma voor m'n laatsteproject: het aansturing van een rgbdotmatrix. Alle leds zitten aangesloten op de schuifregisters: 74hc595

Het werkt helemaal perfect, behalve de snelheid. Ipv PWM knipperen mijn leds zichtbaar.

Nu weet ik dat jullie absoluut geen zin hebben in een lap code, maar hier komt die toch:


#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>

// Lagen definieëren
#define L0		PD0
#define L1		PD1
#define L2		PD2
#define L3		PD3
#define L4		PD4
#define L5		PD5
#define L6		PD6
#define L7		PD7



// Schuifregisters definieëren
#define SR_DAT  PC1
#define SR_CLK   PC0
#define SR_LAT   PC2
#define SR_MR	 PC3
#define SR_OE    PC4


//leds definieëren
char l11=10;
char l12=50;
char l13=100;
char l14=170;
char l15=250;
char l16=190;
char l17=115;
char l18=8;




void setshift(char RED,char GREEN,char BLUE) {
	PORTC&=~(1<<SR_LAT);
	char x;
	for (x=0; x<8; x++) {
		if ((GREEN & 0x80) == 0x80) {	// een '1'
			PORTC|=(1<<SR_DAT);
		} else {
			PORTC&=~(1<<SR_DAT);
		}
		GREEN = GREEN << 1;
		PORTC|=(1<<SR_CLK);
		_delay_us(6);
		PORTC&=~(1<<SR_CLK);
		_delay_us(6);
	}
	for (x=0; x<8; x++) {
		if ((RED & 0x80) == 0x80) {	// een '1'
			PORTC|=(1<<SR_DAT);
		} else {
			PORTC&=~(1<<SR_DAT);
		}
		RED = RED << 1;
		PORTC|=(1<<SR_CLK);
		_delay_us(6);
		PORTC&=~(1<<SR_CLK);
		_delay_us(6);
	}
	for (x=0; x<8; x++) {
		if ((BLUE & 0x80) == 0x80) {	// een '1'
			PORTC|=(1<<SR_DAT);
		} else {
			PORTC&=~(1<<SR_DAT);
		}
		BLUE = BLUE << 1;
		PORTC|=(1<<SR_CLK);
		_delay_us(6);
		PORTC&=~(1<<SR_CLK);
		_delay_us(6);
	}
	PORTC|=(1<<SR_LAT);
}



int main(void) {

	//richting aangeven
	DDRD=0xff;
	DDRC=0xff;
	PORTC&=~(1<<SR_OE);
	PORTC|=(1<<SR_MR);
	unsigned char timer;
	char shiftreg;
	PORTD|=(1<<L0);
	PORTD|=(1<<L1);
	PORTD|=(1<<L2);
	PORTD|=(1<<L3);
	PORTD|=(1<<L4);
	PORTD|=(1<<L5);
	PORTD|=(1<<L6);
	PORTD|=(1<<L7);


	PORTD&=~(1<<L3);
	while(1) {
	
	for(timer=0; timer<250; timer++) {
		shiftreg=0;
		if(l11<timer) {
			shiftreg = shiftreg+1;
		}
		if(l12<timer) {
			shiftreg = shiftreg+2;
		}
		if(l13<timer) {
			shiftreg = shiftreg+4;
		}
		if(l14<timer) {
			shiftreg = shiftreg+8;
		}
		if(l15<timer) {
			shiftreg = shiftreg+16;
		}
		if(l16<timer) {
			shiftreg = shiftreg+32;
		}
		if(l17<timer) {
			shiftreg = shiftreg+64;
		}
		if(l18<timer) {
			shiftreg = shiftreg+128;
		}
		setshift(0,shiftreg,0);
	}
	}
return 0;
}

Dit programma is gemaakt voor het aansturen van de 3, aan elkaar doorgelinkte, schuifregister en laat maar 1 rij branden in maar 1 kleur op het display, maar deze dus met meerdere mogelijke 'grijstinten'

Ik heb ook al een andere kristal gebruikt. Het geheel zit trouwens aangesloten op een atmega8-16mhz versie

Ik denk zelf dat de functie setshift te traag is maar dat zou eigenlijk niet moeten kunnen.
Ziet iemand de reden waarom het zo traag gaat?

Staan je fusebits wel goed? Standaard werken AVRs namelijk op de interne oscillator.

Ik zat er net naar te kijken in de datasheet.
Die fuses heb ik dus niet ingesteld. Even kijken hoe dat moet :)

-edit-
Hmm kan ik deze ook instellen in avr studio of moet dat in de programmer?

-edit2-
Met het programma quickprog een 'externen quatz' geactiveerd.. Het gaat nu wel sneller, maar het knippers nog steeds

-edit3-
Delay's allemaal weggehaald en gewoon een simpele monocolor greyscale regalaar (loopt automatisch op).
Het PWM-t nu in ieder geval, maar volgens mij nog heel traag... Maar dat is voor morgen!

[Bericht gewijzigd door ken536 op (24%)]

Sommige AVR's (ATmega88, ATtiny2313, ...) hebben de mogelijkheid om hun klok door 8 te delen. Dat is dan meestal de fabrieks-configuratie.
Op volle toeren draaien kan dan op 2 manieren:
Het CKDIV8-fusebit deactiveren.
Dit stukje code in main() plaatsen:


    CLKPR = (1 << CLKPCE);
    CLKPR = 0;			// Set max. system-clk

Ik heb perongelijk nu de fuse bits naar external, low frequentie kristal gezet.. Nu doet het allemaal helemaal niks meer en ik kan het ook niet meer programmeren

Hoe kan ik het weer terug krijgen?

Dan heb je nu direct geleerd heel zorgvuldig te zijn met het setten/resetten van fuse bits. Sluit extern een low-frequency kristal aan (zie datasheet hoeveel dat precies is) en je kan weer programmeren. Een programmer die parallel programmeert (STK500) is ook een optie omdat die zijn eigen programmeer clock aanbied.

Misschien eens in de rommeldoos zoeken naar een horlogekristal? Weet niet of het werkt, maar proberen kan geen kwaad, dunkt me.

Belangrijk in dit geval, is het feit dat de programmer-software moet weten dat de AVR op lage snelheid draait. Bij avrdude volstaat het "-i 1000" (of desnoods "-i 100000") als extra-argument op te geven.

Voor de snelheid gewoon even de avr zelf veranderd. Besteld wel een keer een 32k... kristal mee om hem weer op te lappen..
(als die nog leeft na het desolderen in ieder geval)

Als je dan toch bezig bent, zet er een voetje in de plaats. Mocht er ooit nog weer iets gebeuren, dan kan je de AVR eenvoudig vervangen. Ik zet IC's bijna altijd in een voetje. Het gaat bijna nooit mis, maar als het dan toch mis gaat is het zo makkelijk.

Waarom gebruik je geen hardware PWM? De ATmega8 biedt deze functionaliteit wel.

Maar niet voor het aantal benodigde kanalen.

je probleem is dagt je 3 afzonderlijke loops hebt ....
terwijl 1 loop draait slapen de andere 2 ... vandaar dat de boel 'knippert'

merge je code in 1 loop.
( je hebt nu 3 for-next constructies ) terwijl de for-next voor rood draait slapen groen en blauw....
en dan zijn die leds af ...

dus : 1 for next maken waarbinnn alles draait.

zal al een flink stum minder knipperen en je haalt bijna 3x snelheids winst..

Voetjes is een beetje moeilijk met tqfp ;)
En de loops lopen niet afzonderlijk maar gelijk. Ik laat nu gelijk het doorschuiven van de data in de loop gebeuren en ik heb de 'bithoogtje' veranders van 8 (255) naar 5(32). Hierhoor kan ik nog >32000 kleuren maken, wat meer dan genoeg is.

Hardware pwm heb ik nu inderdaad lang niet genoeg aan..