Stránka 2 z 2

Napsal: 14 led 2014, 09:04
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.

Napsal: 14 led 2014, 13:11
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()
//=========================================


Napsal: 14 led 2014, 19:39
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.

Napsal: 14 led 2014, 20:40
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č.

Napsal: 15 led 2014, 08:12
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é.

Napsal: 15 led 2014, 08:44
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.

Napsal: 15 led 2014, 09:06
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

Napsal: 15 led 2014, 12:49
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()

Napsal: 15 led 2014, 12:53
od Habesan
Nemohlo by to nějak souviset s vadným iotn4313.h viz.: t=62285 ???

Napsal: 15 led 2014, 13:00
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.

Napsal: 15 led 2014, 13:38
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[i]=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?