De afgelopen dagen heb ik geprobeerd om mijn geschreven Uart c code voor mijn Atmega16 aan de praat te krijgen.
Hij weigerd echter om data te verzenden en ik heb echt alles nagekeken, maar ik zie het echt niet.

uart.c


#include <avr/io.h>
#include <avr/interrupt.h>
#include <string.h>
#include "Uart.h"
#include <avr/pgmspace.h>


volatile unsigned char Uart_RxEvent;
char Uart_RxBuf[Uart_RxBufSize];

static unsigned char Uart_RxCount;
static unsigned char Uart_RxTimeout;
static unsigned char Uart_RxStatus;

static const prog_char *Uart_TxBuf;



void Uart_initialise( unsigned int ubrr )
{
	// Set baud rate
	UBRRH = (unsigned char)(ubrr>>8);
	UBRRL = (unsigned char)ubrr;
	// Enable receiver and transmitter
	UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE);
	//Set frame format: 8data, 1stop, no parity 
	UCSRC = (1<<UCSZ0)|(1<<UCSZ1)|(1<<URSEL);	


	Uart_RxCount      = 0;
	Uart_RxEvent      = 0;
	Uart_RxTimeout    = 0;
	Uart_RxStatus     = 0;
	Uart_TxBuf        = 0;


}


ISR(SIG_UART_RECV)
/* signal handler for receive complete interrupt */
{
   volatile unsigned char temp_data;
	
	
	Uart_RxTimeout = 75 / 1; /* 37 dus */
	Uart_RxStatus |= Uart_Rx;

	if(UCSRA & (1<<FE))
		Uart_RxStatus |= Uart_FramingError;
	
	temp_data = UDR;
	
	/*if(USR & (1<OR))
		Uart_RxStatus |= Uart_HwOverflow;
	*/
	
	/* Event not handled??? */
	if(Uart_RxEvent != 0){
		Uart_RxStatus |= Uart_SwOverflow;
		return;
	}
	if(Uart_RxCount < (Uart_RxBufSize-1)){
      Uart_RxBuf[Uart_RxCount] = temp_data;
      Uart_RxCount++;
	  
    }else
      Uart_RxStatus |= Uart_BufOverflow;
	  
	
	
}

ISR(SIG_UART_DATA){
	/* hieronder stond: prg_rdb(Uart_TxBuf)*/
	if(pgm_read_byte(Uart_TxBuf) != 0){
		/*  UDR = PRG_RDB(Uart_TxBuf); */
		UDR = pgm_read_byte(Uart_TxBuf);
		Uart_TxBuf++;
		
		
	}else{
		
		UCSRB &= ~(1<<UDRIE); 
		Uart_TxBuf = 0;
		
		
	}
	
}

unsigned char Uart_send_p(const char * __attribute__ ((__progmem__)) data){
	
	if(Uart_TxBuf)
		return Uart_SwOverflow;
	
	Uart_TxBuf = data;
	
	UCSRB |= (1<<UDRIE); /* Enable UDRE interrupt */
	
	return 0;
}

void Uart_serviceTick(void){
	if(Uart_RxTimeout){
		Uart_RxTimeout--;
		if(Uart_RxTimeout == 0){
			Uart_RxBuf[Uart_RxCount] = 0;
			Uart_RxEvent = Uart_RxStatus | Uart_Rx;
			Uart_RxCount = 0;
			Uart_RxStatus = 0;
		}
	}
}


int main( void )
{
	

	Uart_initialise( 95 );

	sei(); 


	Uart_send("Hello world, dit is een testje!\r");
	
	while(1);
}

uart.h


#ifndef UART_H
#define UART_H
#include <avr/pgmspace.h>

/* set baud rate here */
#define Uart_CpuF			7372800
#define Uart_BaudRate		4800
#define Uart_BaudSelect		Uart_CpuF/16/Uart_BaudRate-1

/* set buffersizes here */
#define Uart_RxBufSize 128

/* RxEvent bitmasks/Uart_send errorcodes */
#define Uart_Rx				0x01
#define Uart_SwOverflow		0x02
#define Uart_HwOverflow		0x04
#define Uart_BufOverflow	0x08
#define Uart_FramingError	0x10

/* attributes */
extern char Uart_RxBuf[Uart_RxBufSize];
extern volatile unsigned char Uart_RxEvent;

/* methods */
void Uart_initialise( unsigned int ubrr );
/*unsigned char Uart_send_p(const prog_char *data);*/
/*#define Uart_send(data) Uart_send_p(PSTR(data));*/

unsigned char Uart_send_p(const char * __attribute__ ((__progmem__)) data);
#define Uart_send(data) Uart_send_p(PSTR(data));

void Uart_serviceTick(void);

#endif 

Het kan nooit een grote fout zijn, maar is wel dermate complex dat ik het gewoon niet meer zie.

klinkt misschien dom, maar alles goed aangesloten??

Had zelf namelijk dat probleem, en speuren in de code terwijl het zo simpel was..

(male/female connector spiegelbeeld?)

Op 24 april 2007 16:49:05 schreef m.devriesjr:
klinkt misschien dom, maar alles goed aangesloten??

Had zelf namelijk dat probleem, en speuren in de code terwijl het zo simpel was..

(male/female connector spiegelbeeld?)

Alles netjes aangesloten op stk500, dus moet weinig mis mee zijn. Ik heb met zelfde opstelling nog wel 1 karakter overgezonden, maar toen ik het aan het uitbreiden ben gegaan, is het misgelopen in de code

geen hyperterminal gebruiken deze werkt slecht naar mijn mening.. ik gebruik zelf terminal v1.9b van Br@y++

en daarnaast heb je gechecked of het voorbeeld uit de datasheet werkt.. ik begin daar meestal mee, en daarna breid ik hem uit tot wat ik wil.. op die manier weetje dat uart werkt en andere delen van je code misschien niet...

daarnaast nog een vraag heb je het gesimuleerd.. dat is de makkelijkste manier om achter fouten te komen..

Op 24 april 2007 17:06:08 schreef TheDuke:
geen hyperterminal gebruiken deze werkt slecht naar mijn mening.. ik gebruik zelf terminal v1.9b van Br@y++

en daarnaast heb je gechecked of het voorbeeld uit de datasheet werkt.. ik begin daar meestal mee, en daarna breid ik hem uit tot wat ik wil.. op die manier weetje dat uart werkt en andere delen van je code misschien niet...

daarnaast nog een vraag heb je het gesimuleerd.. dat is de makkelijkste manier om achter fouten te komen..

Bij het simuleren doorloopt hij maar 2x de interrupt voor het verzenden van de data. Kan de simulator het opslaan van gegevens in flash geheugen ook simuleren?

AVR studio kan alles simuleren.. tot inlezen en uitsturen..
meestal is links een debug sectie waar je alle registers en status dingen kan zien.. hier kun je bijvoorbeeld UDR veranderen en ook de Int genereren voor je UART programma.. gewoon in de data sheet even kijken welke pinnen dat zijn en in welk register ze zitten...

als je dan stap voor stap je programma doorloopt zal bij elke interupt je uart moeten werken en kun je data die je inleest ook weer uitsturen..

ik weet niet precies wat jou programma doet maar ik begin altijd simpel en breid het uit als het werkt..

dus inlezen met RX interrupt en uitsturen met UDRE interupt.. als dat werkt dan kun je alles programmeren
overigens ik gebruik ASM.. jij C.. ik heb me in C nog niet verdiept omdat ik het nooit nodig heb gehad en mijn code in ASM schoner is..

in register UCSRB staan aantal dingen die je kan enablen.
Met TXEN en RXEN geef ik aan dat ik uart poort op AVR wil gebruiken.

Maar er staan ook nog bitjes RXCIE en TXCIE waarmee je volgens mij kan aangeven dat je wilt dat er een interrupt gegenereerd word. Echter heb je ook nog zoiets als sei().
Weet iemand mij hier meer opheldering over te geven?

Verder heb je ook nog UDRIE en UDRE, waar ik ook nog niet zo verschil van zie.

DATASHEET...

RXCIE is de RXC interupt enable zelfde voor TXCIE
RXCIE genereerd een interupt als er data binnenkomt en kan dus gebruikt worden om je programma de data uit te laten lezen..
TXCIE genereerd een interupt als de data verzonden is dus niet heel erg nuttig tenzij je hem Specifiek nodig hebt.
UDRIE genereerd een interupt als het Uart DATA register leeg is.. deze wordt dus geset als je UDR uitleest MAW als je data uitleest.

de makkelijkste interupt uart is

Set Global Interupts >>> SEI

RXC < data komt binnen genereerd interupt
Datauitlezen < genereerd UDRE interupt
TXC < uitsturen data.

hiermee kan je bijvoorbeeld alles wat je in stuurt terug sturen

Ok mensen dank voor al jullie info.
Nadat ik 4 verschillende UART's geprogrammeerd heb, ben ik er eindelijk achter waar mijn fout zit. Ik kan mezelf wel voor mijn kop slaan dat ik door deze fout zoveel tijd kwijt ben.

Wat was namelijk het geval?
Als ik in AVR Studio op button klik om mijn avr te proggen, dan krijg je een klein popup menuutje. Ik ging er helemaal vanuit dat hij hier ook automatisch de hex file kiest waarmee je op datmoment bezig bent. Dat is dus niet het geval, dus ik heb gewoon 2 dagen lang steeds verkeerde HEX file in lopen schieten. :S

idd dat doet ie niet je moet even specificeren welke hij moet proggen anders progt ie de laatst gekozen hex file..

Op 25 april 2007 11:43:03 schreef TheDuke:
idd dat doet ie niet je moet even specificeren welke hij moet proggen anders progt ie de laatst gekozen hex file..

Dit vergeet ik nooit meer :)
Beetje krom dat programma niet zelf zijn hex file kan kiezen.

heb ik nog een klein onduidleijkheidje over mijn eigen programma. Iets wat wel goed gaat, maar ik niet begrijp waarom het eigenlijk goed gaat :P

het volgende:


static const prog_char *Uart_TxBuf;

Bovenstaan zie ik als een pointer die naar flash wijst.


unsigned char Uart_send_p(const char * __attribute__ ((__progmem__)) data){
	
	
	if(Uart_TxBuf)
		return Uart_SwOverflow;
	Uart_TxBuf = data;
	
	UCSRB |= (1<<UDRIE); /* Enable UDRE interrupt */
	
	return 0;
}

Maar in begin van bovenstaande functie is data ook een pointer?

En met Uart_TxBuf = data; zet je dus een pointer in een pointer, altans zo zie ik het.
Wat gebeurd daar eigen precies dan?

Je copieert gewoon de inhoud van de ene pointer (in feite een verwijzing naar een geheugen-adres) naar de andere pointer.

Op 26 april 2007 19:55:05 schreef pros:
Je copieert gewoon de inhoud van de ene pointer (in feite een verwijzing naar een geheugen-adres) naar de andere pointer.

Dus eerst zet je twee variablen in flash geheugen en dan voeg je ze samen?
Beetje omslachtig toch?

Welnee. De compiler gebruikt daar 1 of meer registers voor (als er nog vrij zijn, uiteraard). De kans is trouwens groot, dat de gegenereerde assembler-code iets geheel anders is dan hetgeen jij in gedachten hebt bij het intikken van je C-source.