ATTINY4313 versus USART

Diskuze a poradna o programátorech a programování různých obvodů

Moderátor: Moderátoři

Zpráva
Autor
Uživatelský avatar
Ruprecht
Příspěvky: 1114
Registrován: 28 zář 2005, 02:00
Bydliště: ZČ + JM

#16 Příspěvek od Ruprecht »

Znovu: externí krystal?
S vnitřním RC je rozptyl a kolísání frekvence s teplotou příliš velký pro seriózní sériovou komunikaci.

Uživatelský avatar
AB1
Příspěvky: 312
Registrován: 23 lis 2009, 01:00

#17 Příspěvek od AB1 »

Ruprecht:
Tady asi nejde o problém hodin.
Píše:
Pokud je délka pouze 3 znaky přijmou se správně
epes:

Kód: Vybrat vše

UCSRB |= (1 << RXEN) | (0 << TXEN |1<<RXCIE); 
Proč tady zapínáš přerušení RXC?

Měl bys používat funkce pro uart, jak je běžné.
Je také nutné nějak detekovat konec zprávy,
nejlepší je když zpráva má nějaký koncový znak.

Posílám vyzkoušený kód, který přijme max 40 znaků, zakončených znakem '*'.
Na připojeném obrázku je vidět test s terminálem Hercules.
Vyslané znaky jsou červené, přijaté černé.

A možná by stálo za úvahu přejít na jiný překladač než MikroC.

Kód: Vybrat vše

#include <avr/io.h>

//--přijmi bajt ---------------------------
unsigned char uart_getc( void )
{
   while ( !(UCSRA & (1<<RXC)) )
   ;
   return UDR;
}

//-- pošli bajt ---------------------------
void uart_putc(unsigned char data ) 
{
   while ( !( UCSRA & (1<<UDRE)) )
   ;
   UDR = data;
}

//-- pošli string -------------------------
void uart_puts(char *s )
{
   while(*s != 0) 
   {uart_putc(*s); s++;}
}

//-----------------------------------------

char znaky[41];      // string 40 znaků
unsigned char i;

//=========================================
int main(void)
{
   UCSRB = (1<<RXEN)|(1<<TXEN);
   UBRRH = 0;
   UBRRL = 51;  // 9600 baud při 8 MHz

uart_puts("start\r\n");   

   while(1)
   {
      if(UCSRA & (1<<RXC))    // jestli přišel znak
      {                     
         for(i=0;i<40;i++)    // přijmi max 40 znaků
         { 
            znaky[i] =  uart_getc();
            if(znaky[i] == '*')        // přišel koncový znak
            {
               znaky[i] = 0;           // ukonči string nulou
               break;                  // a vystup ze smyčky for()
            }
         }
 
         uart_puts(znaky);             // pošli přijaté znaky
         uart_puts("\r\n");
      }
   }//while(1)
}//main()
//=========================================

Přílohy
uart.gif
(48.1 KiB) Staženo 52 x

Uživatelský avatar
epes
Příspěvky: 111
Registrován: 05 srp 2008, 02:00
Bydliště: Praha 5

#18 Příspěvek od epes »

Proč tady zapínáš přerušení RXC?

Měl bys používat funkce pro uart, jak je běžné.
Je také nutné nějak detekovat konec zprávy,
nejlepší je když zpráva má nějaký koncový znak.
Přerušení zapínám protože příjem zprávy chci realizovat mimo hlavní program.
Instrukce používám dle datašítu pro ATTINY4313. Nevím jaký je rozdíl mezi UART a USART.
Koncový znak, ač nerad, jsem jsem vyzkoušel již o víkendu (také hvězdičku), navíc jsem přidal časový test, protože nemůžu 100% zajistit, že v SMS zprávě ta hvězdička vždy bude.

Kód: Vybrat vše

 while ( !( UCSRA & (1<<UDRE)) )
   ;
   UDR = data; 


Přesně tuto konstrukci jsem nechtěl použít - 40x volat podprogram nebo přerušení kvůli jedné zprávě mně nepřipadalo jako nejlepší řešení. Ale jak je vidět je na rozdíl od této konstrukce funkční

Kód: Vybrat vše

  for(i=0;i<40;i++) 
{while ( !( UCSRA & (1<<UDRE)) )
  znak[i]=UDR;
}
Jinak vidím, že tobě příkaz break funguje. V mém případě příkazy continue a break fungují podivně a raději jsem je nahradil přikazem GOTO.

Uživatelský avatar
FHonza
Příspěvky: 1443
Registrován: 20 lis 2012, 01:00
Bydliště: Praha

#19 Příspěvek od FHonza »

40x volat podprogram nebo přerušení kvůli jedné zprávě mně nepřipadalo jako nejlepší řešení.
Naopak, od toho přerušení po přijmu znaku je.
Nevím jaký je rozdíl mezi UART a USART
USART - Universal Synchronous / Asynchronous Receiver and Transmitter
UART - Universal Asynchronous Receiver and Transmitter

V praxi se převážně používá asynchronní mód. Synchronní se mě vybavuje momentálně pouze jeden a to PS/2 klávesnice. Synchronní režim je víc odolnější proti chybám, nedochází ke ztrátě znaků, ale potřebuje minimálně o jeden vodič navíc (hodiny). V asynchronním režimu musí přijímač hodiny rekonstruovat, kvůli tomu je potřeba mnohem přesněji dodržet stejnou rychlost na obou stranách přijímač/vysílač.

Uživatelský avatar
epes
Příspěvky: 111
Registrován: 05 srp 2008, 02:00
Bydliště: Praha 5

#20 Příspěvek od epes »

Dík za vysvětlení rozdílu USART-UART, mne ale spíš zajímalo co jsi myslel větou
Měl bys používat funkce pro uart, jak je běžné.

Uživatelský avatar
AB1
Příspěvky: 312
Registrován: 23 lis 2009, 01:00

#21 Příspěvek od AB1 »

Měl bys používat funkce pro uart, jak je běžné.
Tím jsem myslel, že je obvyklejší používat funkce uart_getc(), uart_putc(), uart_puts()
(jsou v mém příkladu),
než vypisovat v programu pokaždé jejich kód.

Uživatelský avatar
epes
Příspěvky: 111
Registrován: 05 srp 2008, 02:00
Bydliště: Praha 5

#22 Příspěvek od epes »

Rozumím, problém je, že překladač, který používám tyto fce nezná, má sice jiné fce, ale ty jsou pěkně nenažrané a ATTINY zase neoplývá přebytkem paměti.
Rád bych tě požádal, jestli bys nemohl na svých strojích vyzkoušet tuto konstrukci

Kód: Vybrat vše

  for(i=0;i<40;i++)
{while ( !( UCSRA & (1<<UDRE)) )
  znak[i]=UDR; 
Díky

Uživatelský avatar
AB1
Příspěvky: 312
Registrován: 23 lis 2009, 01:00

#23 Příspěvek od AB1 »

problém je, že překladač, který používám tyto fce nezná,
Tyto funkce jsem napsal na začátek kódu, takže každý překladač se je rychle naučí.
Možná by to chtělo přečíst něco o funkcích v C.
má sice jiné fce, ale ty jsou pěkně nenažrané
Nejsou.
Schválně jsem nainstaloval MikroC-demo a použil vestavěné funkce.
Kód má 361 bajtů proti původním 349 bajtům.

Kód: Vybrat vše

//MikroC - Attiny2313 - 8 MHz

char znaky[41];      // string 40 znaků
unsigned char i;

//=========================================
main(void)
{
   UCSRB = (1<<RXEN)|(1<<TXEN);
   UBRRH = 0;
   UBRRL = 51;  // 9600 baud při 8 MHz
 
   UART1_Write_Text("start\r\n");

   while(1)
   {
      if (UART1_Data_Ready() == 1)   // jestli přišel znak
      {
         for(i=0;i<40;i++)           // přijmi max 40 znaků
         {
            znaky[i] = UART1_Read();
            if(znaky[i] == '*')      // přišel koncový znak
            {
               znaky[i] = 0;         // ukonči string nulou
               break;                // a vystup ze smyčky for()
            }
         }

         UART1_Write_Text(znaky);     // pošli přijaté znaky
         UART1_Write_Text("\r\n");    //new line
      }
   }//while(1)

return 0 ;
}//main()

Uživatelský avatar
Habesan
Příspěvky: 6924
Registrován: 12 led 2009, 01:00
Bydliště: Plzeňsko
Kontaktovat uživatele:

#24 Příspěvek od Habesan »

Nemohlo by to nějak souviset s vadným iotn4313.h viz.: t=62285 ???
Sháním hasičák s CO2 "sněhový", raději funkční.
(Nemusí mít platnou revizi.)
(Celkově budu raději, když se to obejde bez papírů.)

Uživatelský avatar
FHonza
Příspěvky: 1443
Registrován: 20 lis 2012, 01:00
Bydliště: Praha

#25 Příspěvek od FHonza »

Myslím že určitě ne, v tom druhém vlákně jde o chybu kdy kód nelze ani přeložit. Tady naopak dáváme příklady, které nefungují pouze v jediném případě.


Dej sem prosím celý svůj kód, takhle ani není úplně jasné, zda přijaté znaky čteš při přerušení nebo pollingem. A nechceš vyzkoušet AVR studio ? Je zadarmo, na internetu k němu nalezneš tisíce funkčních příkladů a knihoven.

Uživatelský avatar
AB1
Příspěvky: 312
Registrován: 23 lis 2009, 01:00

#26 Příspěvek od AB1 »

Rád bych tě požádal, jestli bys nemohl na svých strojích vyzkoušet tuto konstrukci

for(i=0;i<40;i++)
{while ( !( UCSRA & (1<<UDRE)) )
znak=UDR;

Vůbec nechápu co tím sleduješ.
Bit UDRE popisuje stav vysílacího bufferu.
Co to má společného s příjmem znaku?

Odpovědět

Zpět na „Programování PIC, ATMEL, EEPROM a dalších obvodů“