Best mensen,
Ik zit met een probleem wat waarschijnlijk gewoon een denkfout is. Misschien dat jullie me kunnen helpen.
Met een microcontroller wil ik een 7-segment display aansturen dmv. een shiftregister (595). Dit gaat allemaal prima als ik bit voor bit alles wegschrijf, maar zodra ik dit met een complete byte wil doen gaat het mis. De volgende code gebruik ik:
/*
* 7-Segment display controller
*
* Created: 3/30/2011 9:36:30 AM
* Author: Simon Blok
*/
#include<avr/io.h>
#include<util/delay.h>
#include<avr/interrupt.h>
//Nummers van de pinnen
int SINPUT = 0;
int CLOCK = 1;
int LATCH = 2;
int shiftRegister[8];
void main(void)
{
DDRA = _BV(SINPUT) | _BV(CLOCK) | _BV(LATCH);
shiftByte(0xff);
writeRegister();
while(1)
{
/*
fillRegisterRandom();
writeRegister();
_delay_ms(100);
*/
}
}
int shiftByte(int byteValue)
{
volatile int i;
volatile int index;
index = 0;
for(i=1; i<=128; i=i*2)
{
if(byteValue & _BV(i))
{
shiftBit(index,0);
}
else
{
shiftBit(index,1);
}
index++;
}
}
void fillRegisterRandom()
{
volatile int i;
for(i=0; i<=8; i++)
{
shiftRegister[i] = rand() % 2;
}
}
void shiftBit(int index, int value)
{
shiftRegister[index] = value;
}
void writeBit(int value)
{
//Zet waarde klaar
if(value)
{
PORTA |= _BV(SINPUT);
}
else
{
PORTA &= ~_BV(SINPUT);
}
//Zet waarde in het storage register
PORTA |= _BV(CLOCK);
PORTA &= ~_BV(SINPUT);
PORTA &= ~_BV(CLOCK);
}
void writeRegister()
{
//Loop door het register om alle bits weg te schrijven
volatile int i;
for(i=0; i<=8; i++)
{
if(shiftRegister[i] == 1)
{
writeBit(1);
}
else
{
writeBit(0);
}
}
//Latch...
PORTA |= _BV(LATCH);
PORTA &= ~_BV(LATCH);
}Als ik de functie 'shiftBit' 8 keer gebruik werk alles prima, maar zodra ik een complete byte in één keer in de register-array wil zetten, met de functie shiftByte, gaat het mis (onverwachte segmenten lichten op). Iemand tips voor me?
plantrekker
True story bro!
Ik zie veel te veel code om gewoon een byte naar buiten te shiften. Je kan dit softwarematig doen, zoals je probeert maar het kan veeeeeel korter (zoek maar eens op het forum). Je kan het ook hardwarematig doen via de SPI module (welke AVR gebruik je?)
Het gaat om een Atmega32.
Onderstaande code is ontdaan van de overbodige stukken. De functies shiftbyte en shiftbit schrijven respectievelijk een byte en een bit naar een tijdelijke array. De functie writeRegister stuurt de daadwerkelijke byte naar het shiftregister.
void main(void)
{
DDRA = _BV(SINPUT) | _BV(CLOCK) | _BV(LATCH);
shiftByte(0xff);
writeRegister();
}
int shiftByte(int byteValue)
{
volatile int i;
volatile int index;
index = 0;
for(i=1; i<=128; i=i*2)
{
if(byteValue & _BV(i))
{
shiftBit(index,0);
}
else
{
shiftBit(index,1);
}
index++;
}
}
void shiftBit(int index, int value)
{
shiftRegister[index] = value;
}
void writeRegister()
{
//Loop door het register om alle bits weg te schrijven
volatile int i;
for(i=0; i<=8; i++)
{
if(shiftRegister[i] == 1)
{
writeBit(1);
}
else
{
writeBit(0);
}
}
//Latch...
PORTA |= _BV(LATCH);
PORTA &= ~_BV(LATCH);
}
Lucky Luke
Eluke.nl | handgetypt | I'm a poor, lonesome cowboy, with a long, long way to go.
Ik denk eerder in Basic dan in C, maar kan het niet véél simpeler zo?
[code=C]
// gegarandeerd níet mugvrij!
void shitbyte(int ByteValue){
int i;
for(i=0;1<8;i++){
dataout = ByteValue & 0x01; //dataout zit aan ingang sreg
bytevalue = bytevalue >> 1;
}
latch = 1; // pulsje op latch, gaat dat traag genoeg zo?
latch = 0;
}
[/code]
rew
four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/
Precies. Met 1 typefout, 1 (een) is altijd kleiner dan 8, i (de variabele die steeds opgehoogd wordt, de 8e keer niet meer.. 
(Simon, je hebt te veel code gepost om voor mij (en plantrekker) meteen te begrijpen wat je had willen hebben. Dus dan moet je in gewone taal uitleggen wat je wilt, en wat er mis gaat...)
Wat ik gok dat je zoekt is:
void write_byte (unsigned char b)
{
unsigned char i;
for (i=0;i<8;i++) {
if (b&1) PORTA |= _BV(SINPUT);
else PORTA &= ~_BV(SINPUT);
PORTA |= _BV(CLOCK);
b >>= 1;
PORTA &= ~_BV(CLOCK);
}
PORTA |= _BV(LATCH);
PORTA &= ~_BV(LATCH);
}Op 12 augustus 2011 17:53:54 schreef simonblok:
void writeRegister() { //Loop door het register om alle bits weg te schrijven volatile int i; for(i=0; i<=8; i++) { if(shiftRegister[i] == 1) { writeBit(1); } else { writeBit(0); } }
Even onder voorbehoud, ik ben niet thuis in C, maar moet dat geen
for(i=0; i<8; i++)
zijn i.p.v.
for(i=0; i<=8; i++) ?
[Edit: en for(i=1; i<=128; i=i*2) moet dat ook niet <128 zijn?] Nee, die klopt wel.
plantrekker
True story bro!
Op 12 augustus 2011 17:53:54 schreef simonblok:
Het gaat om een Atmega32.
Dan kan je dit gewoon via de SPI module doen, dat is nu net waarvoor het dient: bytes seriel naar buiten klokken. Je moet je dan niets aantrekken van de data en klok bits, enkel de latch zal je via software moeten doen.
rew
four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/
Op 12 augustus 2011 19:31:17 schreef BVZ:
... maar moet dat geenfor(i=0; i<8; i++)
zijn i.p.v.
for(i=0; i<=8; i++) ?
Nee. Met de for (i=0;i<8;i++) wordt de loop precies 8x doorlopen. 1x met i=0, 1x met i=1 ... en als laatste met i=7.
@ plantrekker: Ik heb altijd een hekel aan dat m'n schema dingen gaat doen als ik de chip ICSP programmeer. Dus ik dedicate de SPI pins aan het "programmeren", met als gevolg dat ik altijd in software moet schuiven. Maar heb ik eenmaal een werkende schuif-routine geschreven dan is het nauwelijks lastiger....
[Bericht gewijzigd door rew op (34%)]
Op 12 augustus 2011 19:31:17 schreef BVZ:
[...]
Even onder voorbehoud, ik ben niet thuis in C, maar moet dat geenfor(i=0; i<8; i++)
zijn i.p.v.
for(i=0; i<=8; i++) ?
Dat klopt zoals je zegt, want met i<=0 en i=0 initieel, doorloop je bij een i++ de loop 9 keer(namelijk 0,1,2,3,4,5,6,7,8) en dus kom je buiten het bereik van die byte..
Maar ik zie dat de ts de ene keer i = 1 doet en de andere keer i = 0. Maak er een goede gewoonte van om bij 0 te beginnen.
[Bericht gewijzigd door LED-Maniak op (13%)]
Op 12 augustus 2011 21:09:53 schreef rew:
[...]
Nee. Met de for (i=0;i<8;i++) wordt de loop precies 8x doorlopen. 1x met i=0, 1x met i=1 ... en als laatste met i=7.
Ja dus. Je bevestigd zelfs zelf mijn statement. 
TS heeft namelijk staan:
for (i=0;i<=8;i++)
plantrekker
True story bro!
rew,
Als je niet wil dat je SPI slaves meeluisteren tijdens het programmeren, gebruik je toch gewoon een jumper, of een pullup aan de CS pin van de slave hangen en die met de AVR naar massa trekken wanneer je wil... Je kan bij de ATmega32 ook de USART synchroon laten werken, je hebt dan een SPI op andere pinnen. Keuze genoeg 
rew
four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/
BVZ, sorry, ik had je statement verkeerdom gelezen. Sorry. Plantrekker, gelijk heb je. Het kan allemaal wel opgelost worden, maar het is eenvoudiger (hoef ik er niet over na te denken) als je de pins gewoon vrij houdt. En bij 595 schuifregisters laat je soms de "enable" pin gewoon actief. Gewoon aan GND knopen o.i.d. Die gaan dus wel gewoon schuiven als je niet uitkijkt. Maar je hebt gelijk dat je dan geen "latch" krijgt met een goede pulldown of pullup, dus dan gebeurt er ook niet al te veel spectaculairs....
henri62
1-st law of Henri: De wet van behoud van ellende. 2-nd law of Henri: Ellende komt nooit alleen.
P.S. Gooi ook alle volatile declaraties eruit, die horen er in dit geval helemaal niet thuis en zorgen ervoor dat de compiler niet meer kan optimaliseren.