hallo,

ik probeer bij een ATMEGA32 met de UART een 8 bits code naar buiten te sturen (om wat te kunnen testen).
alleen zie ik op mijn logic analyzer een andere code verschijnen, dus in 1e instantie vertrouwde ik die analyzer niet, dus heb ik het signaal ook op de scoop gezet, die dezelfde code weergeeft als de logic analyzer.
dus er gaat ergens iets fout, en waarschijnlijk in de atmega32.

ik heb een foto gemaakt waar alle 3 de schermen op te zien zijn, mischien ziet iemand wat ik fout doe ?

ik zal de code er ook eens los bij zetten. (met de comments verwijderd)


	#define F_CPU 8000000UL // 8 MHz clock speed

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

	#define USART_BAUDRATE 9600
	#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)


int main(void)
{
		DDRA  = 0b11111111;		
		DDRD  = 0b00000000;

			UCSRB = (1 << RXEN) | (1 << TXEN); //| (1 << UCSZ2);   // Turn on the transmission and reception circuit
			UCSRC = (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1); 
						
			UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate value into the high byte of the UBRR register
			UBRRL = BAUD_PRESCALE; // Load lower 8-bits of the baud rate value into the low byte of the UBRR register								
																	
				while ((UCSRA & (1 << UDRE)) == 0) {}; // do nothing till the UDR is ready to receive
				UDR = 0b10101010; // Fetch the received byte value into the variable "ReceivedByte"
		
} 

[Bericht gewijzigd door trix op (45%)]

Het is nuttig om te weten dat een UART het least significant bit als eerste uitstuurt, de datalijn normaal gesproken hoog is en de data geïnverteerd op de lijn staat...

Wat ik op de scoop zie is
1) het initialiseren van de poort van de UART (de korte puls aan het begin)
2) het startbit (altijd 1, dus L op de lijn)
2a) het eerste databit (LSB, schijnt 1 te zijn)
3) opeenvolgende wisselende bits 0101010
4) stopbits (altijd 0) en een lijn in rust; het is niet mogelijk om het aantal stopbits te zien.

Wat er verzonden wordt is de bitstroom 10101010 welke het databyte 01010101 zou moeten opleveren.

De code bevat voorzover ik kan overzien alleen een receive en geen transmit deel, maar dat kan aan mijn beperkte kennis van de dienstdoende taal liggen...

while ((UCSRA & (1 << UDRE)) == 0) {}; 

Dit is een wachtlus die wacht totdat het transmit register leeg is en nieuwe data kan ontvangen. Dus die is correct.

UDR = 0b10101010;

En hier schrijf je dan nieuwe data in de uart. Die gaat dat meteen verzenden.

En die data zie ik ook op het scherm van de skoop, voorafgegaan door een laag start-bit en opgevolgd door een hoog stop-bit. Dus dat klopt.

Maar ergens gaat er iets mis. Normaal blijft de uart lijn hoog tussen transmissies, maar hier wordt de lijn juist laag. Zou kunnen dat de processor gereset wordt door de watchdog bijv?

Correctie.
De beelden geven blijkbaar een éénmalige transmit, direct na de reset. Dus dan heb je een beetje een probleem. De lijn is in eerste instantie niet geinitialiseerd en dus laag. De ontvangende uart ziet dat als continue start-bit.

Dan begint de feitelijke transmissie met een laag start-bit, maar de lijn was al laag dus een ontvangende uart kan daar geen chocola van maken. Wat je dus moet doen is eerst de uart initialiseren, dan minstens een volle character-tijd (1 milliseconde) wachten, en dan pas je eerste byte versturen. Dat geeft de ontvangende uart tijd om te synchroniseren en het start-bit te herkennen.

Of hij valt gewoon uit main(), er is geen while(1) rond main.



	#define F_CPU 8000000UL // 8 MHz clock speed

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

	#define USART_BAUDRATE 9600
	#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)


int main(void)
{
//setup
		DDRA  = 0b11111111;		
		DDRD  = 0b00000000;

			UCSRB = (1 << RXEN) | (1 << TXEN); //| (1 << UCSZ2);   // Turn on the transmission and reception circuit
			UCSRC = (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1); 
						
			UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate value into the high byte of the UBRR register
			UBRRL = BAUD_PRESCALE; // Load lower 8-bits of the baud rate value into the low byte of the UBRR register								
	while(1){ //loop							
				while ((UCSRA & (1 << UDRE)) == 0) {}; // do nothing till the UDR is ready to receive
				UDR = 0b10101010; // Fetch the received byte value into the variable "ReceivedByte"
		}
} 

(Hm. de indentation wil niet echt lekker in het post edit window, en je wilt waarschijnlijk nog andere dingen in die loop ook, maar het idee is denk ik duidelijk)

[Bericht gewijzigd door Henry S. op (0%)]

ik ga straks eens proberen om na het initialiseren 1 miliseconden te wachten.
maar ook als ik meerdere byte achter elkaar vezend gaat het niet goed, is het dan de bedoeling om tussen de afzonderlijke bytes ook een wachttijd te plaatsen ?

je ziet in mijn code op het scherm dat die while loop als commentaar er staat (zoals lucky lucke aanhaalde), dat heb ik dus ook getest.

[Bericht gewijzigd door trix op (23%)]

Ik zit niet in deze hardware, maar voor de zekerheid; wilt u data in RS232 formaat verzenden, of enkel losse bits / bytes? In het laatste geval lijkt dit geen handige benadering. (en in het eerste eigenlijk ook niet. Voor gewoon RS232 zijn vast libraries)

het gaat mij om de losse bits, elk bit staat voor een IR transistor die wel of niet belicht (een "1" of een "0") is geweest.
de data gaat via een MAX485 naar een raspberry pico.

Mocht de microcontroller nog helemaal factory default zijn, dan is de DIV8 fuse geprogrammeerd. Dat maakt je 8MHz clock nog maar 1MHz.

nee die draait op 8 Mhz, ext. X-tal.

zet me wel aan het denken, als de klok instellingen kloppen, en je stuurt met 9600 baudrate, wat is dan de lengte van 1 byte versturen dus incl. start en stop bit ?
is dat iets meer of iets minder dan 1 mSec ?

marginaal (4%) meer...

ik meet nu incl start/stop bit 1,04 mSec.
en tussen de bytes, dus tussen de stop en de start bit 20 uSec.

net even getest, ik had dus inderdaad (zoals dekees opperde)een 2 mSec. delay nodig om het goed te laten gaan, 1 mSec. bleek te weinig.

met een for lus een array van 10 bytes versturen gaat ook goed.

kan weer even vooruit, bedankt zover.

@trix, ik heb een testprogrammaatje gemaakt in LDmicro en omgezet in een hex-file die je in de Atmega32 kunt programmeren en het doet 2 dingen.

1. Maakt een output 1ms hoog en 1ms laag, daarvoor moet je mij een poortnr geven waar je kunt aan meten. Daarmee kun je zien of de xtal instelling juist is.

2. Het zend op de TX-pin10 elke seconde 1 byte (0x05, 0b0101) zodat je ook hier kunt meten.
Als je iets anders wilt zeg het maar.

Je moet wel zelf de fuses instellen.
Ik ben een PIC-man en dus niet op de hoogte van die AVR-dinges.

Het werkt perfect in de simulatie en mijn ervaring zegt dat het 99% zou moeten werken in de opstelling.

Ik verwacht dus een poortnr als je wilt testen vooraleer ik het kan posten.

edit: ben telaat goed dat het werkt. :z

ik zou hetgeen wel in een klein protocolletje stoppen als je het verzend tussen 2 micro's.
Je wilt toch ergens kunnen synchroniseren if detecteren dat je maar een half pakketje hebt ontvangen, hoe weet je dan precies welk bitje bij welke foto transistor hoort?

normaal doe ik iets met een DLE, STX, aantal bytes, data bytes, eventueel crc, DLE , ETX

hoeft niet, als het nu werkt, maar het is denk ik iets robuuster

dat zijn een hoop afkortingen waar ik nog nooit van gehoord heb :?
ik ga er eens over nadenken :)

het zijn gewoon wat gedefinieerde karakters uit de ascii tabel (2,3 en 16)

Er zijn verschillende manier om de ontvangende kant te laten weten dat er een nieuw pakket binnen komt.
Je kan ook met een vaste lengte werken en een timeout, dat zal hier ook wel volstaan denk ik

Is er een mogelijkheid van het (deel)schema eens online te zetten? ik zou uit pure interesse graag eens weten welke pinnen van de Atmega32 aangesloten zijn en hoe je het veranderd hebt tov de vorige versie.
Als je er weigerachtig over staat is dat geen probleem hoor.

ik heb er niet een echt schema van, het geheel is eigenlijk zo simpel dat ik in een keer de PCB teken.
er is ook niet echt iets veranderd t.o.v. de versie die werkte, alleen word alles een stuk kleiner dan eerst.
de poorten A B en C zijn in geval van:
transmitter, IR leds.
receiver, IR transistoren.
waarbij PB5, PB6 en PB7 ook worden gebruikt om met SPI te programmeren
pin 9 en 10 is de UART
pin 14, 15 en 16 zijn status led's
X-tal is een externe uitvoering.

"bottem pad should be soldered to ground"
(staat in het plaatje hierboven).

is dat echt nodig ? ik weet niet of ik dat wel kan met mijn soldeer apparatuur.
of zou gewoon er tegen aan "klemmen" ook voldoende kunen zijn ?
ik weet ook wel dat de datasheet leidend is, maar die voor ziet dan ook wanneer de controller tot op het randje word gebruikt.
en mijn toepassing is niet zo veel eisend.

bij de QFN wel gewenst, of het een echte must is weet ik niet, dat is met een boutje lastig te doen. Wat je wel kan proberen om er wat naked via's onder te designen en dan nadat je de micro erop hebt gesoldeerd via de via en een klots flux de onderkant kan verbinden.
MAar kun je de andere (niet hebbende) pootjes van de qfn wel met je boutje solderen dan?

Wat is momenteel nog het probleem dat je ervaart met je uart? want dat lees ik eigenlijk nergens exact terug.

Bij sommige chips is het een must, bij anderen sterk aan te raden (al was het alleen maar om te garanderen dat het een stabiel potentiaal heeft).
Vrijwel altijd is het een koelingsmechanisme.

Ik zet er (als er ruimte voor is tenminste) een oversized via onder, waar ik met de punt van de soldeerbout in kan.

De kleine qfn20 en qfn24 doe ik met hetelucht, gaat prima, ook het groundpad. (o.a. de ADP5062 en NAU8814, 4x4mm)

Op dinsdag 20 augustus 2024 15:08:27 schreef fatbeard:
Ik zet er (als er ruimte voor is tenminste) een oversized via onder, waar ik met de punt van de soldeerbout in kan.

+1

Op dinsdag 20 augustus 2024 14:46:30 schreef Stijnos:
Wat is momenteel nog het probleem dat je ervaart met je uart? want dat lees ik eigenlijk nergens exact terug.

ik ben er nog mee aan het testen.
zoals ik al vaker heb gemeld heeft dat gewoon gewerkt, alleen krijg ik het nog niet zo "mooi" binnen op de raspberry pico, als voorheen met de atmegaXX (weet even het nummer niet uit mijn hoofd, ben op het werk) waar dat wat makkelijker ging, waarna ik het ook zonder problemen kon door sturen naar mijn laptop.
omdat ik het voorheen "probleemloos" kon implementeren heb ik ook niet zoveel aandacht geschonken over hoe het nu precies werkte.......immers het werkte gewoon.

Op dinsdag 20 augustus 2024 15:08:27 schreef fatbeard:
Ik zet er (als er ruimte voor is tenminste) een oversized via onder, waar ik met de punt van de soldeerbout in kan.

is een goed idee natuurlijk, maar als het doel van dat vlak warmte overdracht i.p.v. electrisch overdracht heeft het mischien niet zo heel veel zin.

Op dinsdag 20 augustus 2024 15:22:36 schreef trix:
is een goed idee natuurlijk, maar als het doel van dat vlak warmte overdracht i.p.v. electrisch overdracht heeft het mischien niet zo heel veel zin.

Doel is beide...