ga ik bekijken, tnx.
Op 24 april 2020 11:29:30 schreef deKees:
Met 9600 baud komt de data binnen met 1 byte per milliseconde.Als je die binnen die milliseconde kunt verwerken dan zijn interrupts niet nodig en kun je alles in de mainloop afhandelen.
Maar dan helpt het wel als je de SPI wat sneller instelt met een kleinere prescaler, en je de _delay_ms(2); weghaalt.
Ik zou het wel doen. Ik neem aan dat hij in main meer wil doen en anders blokt alles de hele main loop.
wat je in die interrupts moet doen?
Nu check je bij de uart met een while loop of er ene byte in het UDR register staat.
Als je uart via interrupts doet dan wordt de functie ISR(UART_RX) ofzo uitgevoerd op het moment dat die vlag gezet wordt. Ongeacht waar je processor op dat moment mee bezig is.
Ik ga je code niet controlleren, maar het lijkt er nu op dat je elke byte die je ontvangt los in je externe RAM gaat schrijven. Voor elke byte ga je de chip select hoog laag maken, 3 adres bytes schrijven en dan pas de ene data byte. Snap je zelf hoeveel overhead je dan creëert?
volgens mij is het idee van de sequential write dat je enkel data bytes hoeft te schrijven en dat de adres pointer in het ram vanzelf ophoogt.
dan nog deze 3 regels code:
code:
if (TSOP_read == 1) {RAM_adress_temp_2 = 0;}
if (TSOP_read == 2) {RAM_adress_temp_2 = 600;}
if (TSOP_read == 3) {RAM_adress_temp_2 = 1200;}
kan in 1 regel zonder conditional checks
code:
RAM_adress_temp_2 = (TSOP_read - 1) * 600;
ohja, en begin for loops gewoon lekker bij 0
Golden Member
Op 24 april 2020 16:13:44 schreef Stijnos:
volgens mij is het idee van de sequential write dat je enkel data bytes hoeft te schrijven en dat de adres pointer in het ram vanzelf ophoogt.
klopt, die hoef ik inderdaad niet zelf op te hogen, ik hoef alleen maar een begin adres te geven.
Op 24 april 2020 16:13:44 schreef Stijnos:
[...]
Nu check je bij de uart met een while loop of er ene byte in het UDR register staat.
dan heb ik die while loop dus niet nodig, ik wist er al niet zo goed raad mee.
ik gebruik nu voor de adressering v/d ext. RAM decimale getallen (dat kan ik beter visualiseren) mag/kan dat ?
stijnos, bedankt.
[Bericht gewijzigd door trix op 24 april 2020 18:23:03 (100%)
Ja, je mag best decimale getallen gebruiken.
Die zie je alleen in de source file. De compiler vertaalt alles naar binair.
Je mag zelfs ook floating point gebruiken, al heeft dat geen nut.
of je nu typt
code:
address = 0x20;
of
code:
address = 32;
dat maakt gene bal uit.
Als de waarde maar matched met het type variabele.
ik gebruik meestal hex als het een register met losse bits ofzo voorstelt, maar het wordt doorgaans gebruikelijk door elkaar gebruikt, afhankelijk van de situatie.
floats werken toch wel even iets anders, maar daar zou ik me nu ook helemaal niet druk om maken
Golden Member
ik ben bezig met de ISR en maak daar een variabele aan die ik in de "main" wil gebruiken. op een of andere manier wil dat niet lukken.
moet ik de variabele wel buiten de ISR en met volatile declareren ?
c code:
int receivedbyte = 0; // needed for incoming data from TSOP's
int TSOP_byte_transfer_counter = 0;
volatile int TSOP_byte_1 = 0;
volatile int TSOP_byte_2 = 0;
volatile int TSOP_byte_3 = 0;
ISR(USART0_RX_vect) // receving data form TSOP's
{
receivedbyte = UDR0; // copy the received byte value into the variable "receivedbyte
TSOP_byte_transfer_counter = TSOP_byte_transfer_counter + 1;
if (TSOP_byte_transfer_counter < 300) // = 0 t/m 299
{
TSOP_byte_1 = 1;
}
if ((TSOP_byte_transfer_counter > 299) && (TSOP_byte_transfer_counter < 600 )) // = 300 t/m 599
{
TSOP_byte_2 = 1;
}
if ((TSOP_byte_transfer_counter > 599) && (TSOP_byte_transfer_counter < 900 )) // = 600 t/m 899
{
TSOP_byte_3 = 1;
}
}
.
.
.
.
int main(void)
{
if (TSOP_byte_1 == 1)
{
PORTH |= (1 << PINH7); // LED = 1 just for checking ROOD ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}
if (TSOP_byte_2 == 1)
{
}
if (TSOP_byte_3 == 1)
{
PORTB |= (1 << PINB7); // LED = 1 just for checking GEEL ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TSOP_byte_transfer_counter = 0;
}
In ieder geval ben je de "volatile" voor receivedbyte vergeten.
Als jij wacht op een byte met:
code:
recievedbyte = -1; // vorige is verwerkt
while (recievedbyte == -1)
/* do nothing */
... // verwerk de ontvangen byte.
dan vertaalt de compiler dat effectief naar:
code:
recievedbyte = -1; // vorige is verwerkt
R3 = recievedbyte;
while (R3 == -1)
/* do nothing */
... // verwerk de ontvangen byte.
waarbij R3 een register in de CPU is. Zonder volatile gaat ie niet iedere loop in het geheugen kijken of daar soms wat veranderd is. Hij WEET dat hij (zelf) niets veranderd heeft aan die variabele dus die moet nog steed hetzelfde zijn de volgende keer door de loop. Hier dus niet juist. Volatile geeft aan dat ie niet mag aannemen dat die variabele niet achter z'n reet om aangepast wordt.
Golden Member
Op 26 april 2020 11:46:30 schreef rew:
In ieder geval ben je de "volatile" voor receivedbyte vergeten.
die gebruik ik toch alleen in de ISR, net als: TSOP_byte_transfer_counter
ald ik die LED's in de ISR zet werkt het wel zoals verwacht.
[Bericht gewijzigd door trix op 26 april 2020 12:53:04 (12%)
Als je geen loop in je main() hebt dan doet die het maar 1 keer.
Als je een groot deel van de code weglaat, kan ik niet zeker weten of dingen wel of niet nog gebruikt worden.
Als ie alleen in de ISR gebruikt wordt, zet je de variabele in de ISR met "static" er voor.
Zoals het er staat is het logisch dat het niet werkt. De ISR wordt nooit aangezet, de code om de variabelen te bekijken runt VOORDAT de ISR eventueel voorbij het stuk wat je gepost hebt aangezet wordt.
Golden Member
er is natuurlijk wel een loop
als ik die 2 LED's die in de main staan in de ISR zet gaan ze wel volgens verwachting aan. dit bewijst dat de ISR wel word aan geroepen,TSOP_byte_transfer_counter hoogt dan op en de LED's gaan volgens verwachtin na elkaar aan.
alleen zodra ik die LED's in de main ga zetten (zoals ik heb gepost) gaan ze niet volgens verwachting aan.
Dan zit het probleem toch in het stuk dat je hebt weggelaten.
Trix, had jij niet ook zo'n 8-kanaals logic analyser?
Ik heb van de week ook een stuk embedded code zitten debuggen. Ik heb twee draadjes aan ongebruikte pootjes zitten solderen (0.5mm pitch) en aan een ongebruikte connector gemaakt. Nu kan ik die twee signalen gebruiken om te debuggen.
Dus eerst wil je weten of ie wel in de interrupt komt. En of ie de variabele zet.
Daarna wil je weten of ie wel door je mainloop loopt. De "toggle debugouput 1" of "set debug output 2" calls kan je door je code verplaatsen om te zien of bepaalde plekken uitgevoerd worden.
Ik heb nog een klein timing dingetje in m'n systeempje zitten maar dat hoeft niet met de code op de microcontroller gefixed te worden.
Golden Member
16 kanaals zelfs, ik zal eens verder kijken.
ik had een beetje gehoopt op: dat gaat niet met een volatile of zo, of een simpele tik/denk fout.
maar ik begrijp dat de methode op zich goed is.
dat debuggen doe ik trouwens met LED's, kijken hoever het programma komt.
zit net te bedenken dat je dan geen timing kunt zien, en met een LA wel.
[Bericht gewijzigd door trix op 26 april 2020 17:05:58 (12%)
Golden Member
ik zit al een paar uur te testen, maar ik krijg het niet voor elkaar om een variabele uit een ISR, te gebruiken in de main.
van alles geprobeerd zonder succes.
het gekke is dat dit wel gaat wanneer ik het vanuit: ISR(USART0_TX_vect) doe, dan gaat het zelfs zonder volatile?????
maar van uit: ISR(USART0_RX_vect) werkt het dus niet.
dus ik denk: dan doe ik het schrijven v/d data naar de ext. RAM wel in de ISR. maar dan heb ik eigenlijk ook variabele die ik buiten de ISR wil gebruiken.
voor de duidelijkheid: de ISR word 100% zeker aan geroepen, zie een paar posts van mij terug.
heeft iemand nog een tip ????
Golden Member
Heb je de variabele wel "Global" gedeclareerd ?
Golden Member
ja, net voor de ISR.
wacht er zit vooruit gang in
[Bericht gewijzigd door trix op 27 april 2020 14:58:06 (49%)
Zet de ISR code eens hier neer, met de variable declaraties.
Zeker niks in een externe spi ram opslaan in de ISR zelf, is kansloos.
Golden Member
dat was ik eigenlijk nu wel van plan, uit nood gedreven.
maar op een of andere manier werkt dat variabele vanuit ISR, dus ik ga even terug naar wat ik eigenijk van plan was: de eigenlijk schrijf actie buiten de ISR.
weet even niet hoever ik vandaag kom, maar ik zal het nog wel posten.
Golden Member
ben er niet meer aan toe toe gekomen, word waarschijnlijk donderdag.
maar ik zat me af te vragen hoe de master weet of hij alles van de slave heeft ontvangen. hoe gaat dat gewoonlijk. ik weet in mij situatie dat hij 900 bytes gaat verzenden, en die kan ik dus gewoon tellen.
maar mischien is het wel beter om achter aan een soort sluitbyte mee te sturen. of wellicht om de honderd bytes, dan kan je tussentijds nog corigeren.
Dat is nu precies wat ik bedoel dat je een soort protocol moet maken om te zorgen dat alles goed aankomt.
Maar omdat je die speciale addresseer mode gebruikt heb je 9 bits en kun je dus zien wanneer er weer een adresbyte komt. Je zou bijvoorbeeld een adres kunnen sturen wat niet bestaat in je systeem (met 9-de bitje aan dus) wat het stop teken is. De vraag is even of je kunt zien in je atmel wat er in het adres match register staat, want daarna ontvang je dus niets meer.
De kans ik groot dat je met timeouts moet gaan klungelen, anders een echt protocol maken. Dat is lastiger om dat echt goed te doen.
Dat is ook een van de redenen waarom ik eigenlijk nooit meer iets probeer te doen met seriele poorten. Bij voorkeur maak ik iets nieuws met CAN.
Daar kun je allerlei systemen voor verzinnen. Dat begint met een bericht definitie met afspraken over hoe je kunt zien waar een bericht begint en wanneer het is afgelopen.
Bijvoorbeeld
Beginnen met STX (0x02)
en eindigen met ETX (0x03)
Maar dat is lastig als je data ook 0x02 en 0x03 kan zijn. Dan moet je daar weer iets voor verzinnen met escape sequences of zo.
En vaak begint een bericht dan (na de STX) met een header, met daarin een MsgId zodat je verschillende berichten kunt sturen. En op het eind dan een checksum ter controle.
Golden Member
maar bij mij is het eigenlijk heel simpel, het zijn altijd 900 bytes aan een gesloten. als je dan in de master gewoon gaat tellen wanneer de 900e byte binnen komt weet je wanneer je klaar bent.
maar is er een (grote) kans op fouten wanneer je het op die manier doet ?
Valt wel mee. Zeker over korte afstanden.
Maar dan moet je wel zorgen dat er genoeg tijd tussen de berichten overblijft om te kunnen zien wanneer er een nieuwe cyclus begint.
En je kunt ook niet meer een ander soort berichten tussendoor sturen als je dat al zou willen.
Golden Member
ik zit ook net te bedenken: nu doe ik in een keer 900 bytes.
maar ik kan dat ook simpel opsplitsen in 3x300 bytes.
ik ben nu bezig om dat op te splitsen in de master (van 1x900 naar 3x300). maar als ik dat gewoon in de slave doe, krijg je een kortere "package", nog minder kans op storingen lijkt me.