AVR USART-problem

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
PaNiC
Inlägg: 2610
Blev medlem: 15 augusti 2003, 22:16:15
Ort: Skånelandet

Re: AVR USART-problem

Inlägg av PaNiC »

Men vad fanken-ögonblicket har uppenbarat sig.

Anledningen till att processorn startade om sig var för att fel timerinterrupt var aktiverat, anledningen till fel inledande byte var att den sändes innan USARTen var konfigurerad riktigt.

Nu fungerar saker, tack för hjälpen.
Användarvisningsbild
Swech
EF Sponsor
Inlägg: 4750
Blev medlem: 6 november 2006, 21:43:35
Ort: Munkedal, Sverige (Sweden)
Kontakt:

Re: AVR USART-problem

Inlägg av Swech »

Nu är mina C kunskaper inte vad de borde men....

Kod: Markera allt

   result = (ADCH<<8 | ADCL);
   /* workaround for reading ADCH last */
   t = ADCH; 
   return result;
Tappar du inte bort ADCH i detta fallet? Du läser ju ADCH till t för att köra din "workaround" men sen
returnerar du ju result som inte innehåller "t" s läsning? utan snarare den som blir tokig om man läser
i fel ordning

Swech
snigelen
Inlägg: 815
Blev medlem: 8 maj 2009, 11:02:14
Ort: Lund

Re: AVR USART-problem

Inlägg av snigelen »

"return ADC;" brukar funka, så fixar kompilatorn (gcc iaf) att saker och ting blir lästa i rätt ordning.
Användarvisningsbild
PaNiC
Inlägg: 2610
Blev medlem: 15 augusti 2003, 22:16:15
Ort: Skånelandet

Re: AVR USART-problem

Inlägg av PaNiC »

Swech skrev:Nu är mina C kunskaper inte vad de borde men....

Kod: Markera allt

   result = (ADCH<<8 | ADCL);
   /* workaround for reading ADCH last */
   t = ADCH; 
   return result;
Tappar du inte bort ADCH i detta fallet? Du läser ju ADCH till t för att köra din "workaround" men sen
returnerar du ju result som inte innehåller "t" s läsning? utan snarare den som blir tokig om man läser
i fel ordning

Swech
Men inten result innehåller ju både ADCH och ADCL, och det är den jag returnerar. Jag lovar att det fungerar iaf :).

snigelen: Hums. Så kan man kanske göra!
Användarvisningsbild
Swech
EF Sponsor
Inlägg: 4750
Blev medlem: 6 november 2006, 21:43:35
Ort: Munkedal, Sverige (Sweden)
Kontakt:

Re: AVR USART-problem

Inlägg av Swech »

Jo men inten result skapas ju av att den läser ADCH och ADCL.
"result = (ADCH<<8 | ADCL);" Men ADCH måste läsas sist för att det skall funka 100%
och det är vad din workaround skall försöka göra. Så den läser sist och stoppar i t
men sen hoppar du över svaret.....

Anledningen till detta är att AVR har ett mellanlagringsregister som används vid 16 bits access
Det kommer att kunna funka till 99% om man bortser från denna funktion men du kan, alltså inte säkert,
få mystiska buggar om det läses fel. Den allra värsta typen av bugg är att den kan komma då du lägger
till kod för något helt annat så som t.ex. 16 bits timers och då blir det riktigt svårt att förstå varför det blir fel.

Swech
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: AVR USART-problem

Inlägg av jesse »

Jag lovar att det fungerar iaf
ja, kanske... Men så som du läser dom nu så *kan* det bli fel. Men du kanske inte märker felet för att det kommer så sällan?
If the result is left adjusted and no more than 8-bit precision is required, it is sufficient to read
ADCH. Otherwise, ADCL must be read first, then ADCH, to ensure that the content of the Data
Registers belongs to the same conversion. Once ADCL is read, ADC access to Data Registers
is blocked. This means that if ADCL has been read, and a conversion completes before ADCH is read, neither register is updated and the result from the conversion is lost. When ADCH is read,
ADC access to the ADCH and ADCL Registers is re-enabled.
Så om du inte kör kontinuerlig (automatisk) konvertering så är det ingen risk att det blir fel i det här fallet. Men det är inte någon snygg lösning.

Om return ADC; fungerar så är det ju det bästa (jag hade ingen aning om det!), men annars får man göra så här:

Kod: Markera allt

   result = ADCL;
   /* workaround for reading ADCH last */
   result |= ADCH << 8;
   return result;
Om det finns risk att kompilatorn optimerar om det hela så att ADCH ändå läses först så gör man result till en volatile int.
snigelen
Inlägg: 815
Blev medlem: 8 maj 2009, 11:02:14
Ort: Lund

Re: AVR USART-problem

Inlägg av snigelen »

> Om return ADC; fungerar så är det ju det bästa (jag hade ingen aning om det!)

Jo, ADC eller ADCW (ADC Word) funkar. Jag försökte hitta lämplig referens till var det är dokumenterat, men har inte lyckats. Det kommer i alla fall upp titt som tätt på AVRFreaks. Detta är en snutt från exempelprogrammet largedemo.c från AVR-libc, där ADCW används för att läsa alla tio bitar

Kod: Markera allt

/*
 * ADC conversion complete.  Fetch the 10-bit value, and feed the
 * PWM with it.
 */
ISR(ADC_vect)
{
  adcval = ADCW;
  ADCSRA &= ~_BV(ADIE);		/* disable ADC interrupt */
  intflags.adc_int = 1;
}
Användarvisningsbild
mri
Inlägg: 1165
Blev medlem: 15 mars 2007, 13:20:50
Ort: Jakobstad, Finland
Kontakt:

Re: AVR USART-problem

Inlägg av mri »

"Jag försökte hitta lämplig referens till var det är dokumenterat"

Det är väl bara att titta i system header filen var detta makro, pekare eller vad det nu kan tänkas vara, är deklarerat.
snigelen
Inlägg: 815
Blev medlem: 8 maj 2009, 11:02:14
Ort: Lund

Re: AVR USART-problem

Inlägg av snigelen »

Jovisst. Det har jag gjort. T.ex. megax8 har

Kod: Markera allt

#ifndef __ASSEMBLER__
#define ADC     _SFR_MEM16 (0x78)
#endif
#define ADCW    _SFR_MEM16 (0x78)
#define ADCL    _SFR_MEM8 (0x78)
#define ADCH    _SFR_MEM8 (0x79)
i iomx8.h där

Kod: Markera allt

sfr_defs.h:#define _SFR_MEM16(mem_addr) _MMIO_WORD(mem_addr)
(om _SFR_ASM_COMPAT inte är sann). Vidare är

Kod: Markera allt

sfr_defs.h:#define _MMIO_WORD(mem_addr) (*(volatile uint16_t *)(mem_addr))
Men om detta innebär att byten läses i rätt ordning eller ej är inte uppenbart för mig i alla fall.

Det jag sökte var någonstans i dokumentationen det står svart på vitt att byten läses i rätt ordning och det har jag inte lyckats hitta (jag har inte letat speciellt mycket dock).
Men av t.ex. denna tråd (med EW som ansvarar för WinAVR och Jörg som är en av de som skriver avr-libc): http://www.avrfreaks.net/index.php?name ... c&p=425667 tycker jag det framgår att det normalt skall funka OM de två byten ligger i följd (vilket de oftast gör, annars är väl inte 16-bitarsvarianten definierad).
Användarvisningsbild
mri
Inlägg: 1165
Blev medlem: 15 mars 2007, 13:20:50
Ort: Jakobstad, Finland
Kontakt:

Re: AVR USART-problem

Inlägg av mri »

Med reservation för att jag inte "kan" AVR arkitekturen, så mappas 'ADC' alt. 'ADCW' till en enkel 16 bitars minnesaccess med *(uint16 *). Dvs det finns inget behov av att läsa Low eller High i nån speciell ordning, eller hur?

Det tråden du länkade till däremot handlar om är när Low och High befinner sig på sådana adresser att en enkel 16 bitars minnesaccess inte är möjlig. I dessa fall har dock AVR speciell hårdvara som gör att 16 bitars registret han läsas korrekt om man läser Low och High i en specifik ordning. Och som du säger så antyder de att om Word varianten av makrona finns deklarerade så är enkel 16 bitars access möjlig.
snigelen
Inlägg: 815
Blev medlem: 8 maj 2009, 11:02:14
Ort: Lund

Re: AVR USART-problem

Inlägg av snigelen »

Ja det mappas till en 16 bitars minnesaccess. Men ordningen är fortfarande viktig. Ur databladet för t.ex megax8 står.
The ADC generates a 10-bit result which is presented in the ADC Data Registers, ADCH and
ADCL. By default, the result is presented right adjusted, but can optionally be presented left
adjusted by setting the ADLAR bit in ADMUX.
If the result is left adjusted and no more than 8-bit precision is required, it is sufficient to read
ADCH. Otherwise, ADCL must be read first, then ADCH, to ensure that the content of the Data
Registers belongs to the same conversion. Once ADCL is read, ADC access to Data Registers
is blocked. This means that if ADCL has been read, and a conversion completes before ADCH is
read, neither register is updated and the result from the conversion is lost. When ADCH is read,
ADC access to the ADCH and ADCL Registers is re-enabled.
Men då man använder ADC eller ADCW sker läsningen i rätt ordning, men det är det jag inte kan hitta en klartextreferens till. (Men det kanske är självlart?)

Jo tråden jag länkade till handlar ju om att detta inte funkar då de två byten inte ligger i följd (och indirekt att det gör det då de ligger i följd) utan man får då läsa dem i två steg, i rätt ordning förståss.
thebolt
Inlägg: 248
Blev medlem: 10 februari 2008, 17:41:40
Ort: Taipei Taiwan

Re: AVR USART-problem

Inlägg av thebolt »

Kod: Markera allt

   result = (ADCH<<8 | ADCL);
Värt att notera är att ordningen i läsningen av ADCH och ADCL i det fallet är odefinierat och helt upp till kompilatorn. Troligen, men inte säkert, kommer det bli samma sätt varje gång du kompilerar iaf, men om man optimerar för storlek är inte ens det säkert.
Skriv svar