Tips på kodsnutt för att ta emot en sträng

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
thepirateboy
EF Sponsor
Inlägg: 2109
Blev medlem: 27 augusti 2005, 20:57:58
Ort: Borlänge

Tips på kodsnutt för att ta emot en sträng

Inlägg av thepirateboy »

Har någon nåt tips på en kodsnutt för att lagra en sträng med data som tas emot från uarten. Tex om jag skickar "hejsan" från ett terminalprogram från en PC vill jag lagra denna i en array i uC'n. Jag använder Atmega 128 och avr-gcc och har enablat interupt (ISR(USART0_RX_vect)). Att ta emot tecken fungerar bra men kommer inte riktigt på hur jag ska lagra en hel sträng.
Användarvisningsbild
björn
EF Sponsor
Inlägg: 2570
Blev medlem: 29 mars 2004, 23:09:55

Inlägg av björn »

Kan väl göra en teckenarray som du lägger dom mottagna tecknen i?
thepirateboy
EF Sponsor
Inlägg: 2109
Blev medlem: 27 augusti 2005, 20:57:58
Ort: Borlänge

Inlägg av thepirateboy »

Ja jag har gjort det men jag antar att jag måste polla nån flagga för att att kunna ta emot ett tecken i taget och lägga in i arrayen.
Användarvisningsbild
björn
EF Sponsor
Inlägg: 2570
Blev medlem: 29 mars 2004, 23:09:55

Inlägg av björn »

Nej, i interrupten (för visst körde du interruptstyrt?) får du tecknet i UDR, så du lägger bara det som finns i UDR på "nästa lediga plats" i din array.

EDIT: lade till en liten kodsnutt som bör funka, se Atmels appnote avr306 för mera kod.

Kod: Markera allt

#pragma interrupt_handler twi_isr:18
void twi_isr(void)
{
 unsigned char data;
	 unsigned char tmphead;
 	 
 	 data = UDR;
 	 	 
	/* calculate buffer index */
	tmphead = ( UART_RxHead + 1 ) & UART_RX_BUFFER_MASK;
	UART_RxHead = tmphead; /* store new index */
	if ( tmphead == UART_RxTail )
		{
		/* ERROR! Receive buffer overflow */
		}
		
	UART_RxBuf[tmphead] = data; /* store received data in buffer */	
	
 	
}
EDIT2: observera att min interruptrutin är för iccavr, du får byta ut till gcc's namn på usartinterrupten.
thepirateboy
EF Sponsor
Inlägg: 2109
Blev medlem: 27 augusti 2005, 20:57:58
Ort: Borlänge

Inlägg av thepirateboy »

Tack nu funkar det. Min tanke var om det gick att stanna i interruptet tills alla tecken var mottagna men det kanske inte går/är dumt? Vill lagra strängen i en tvådimensionell array (sSMS) så jag vill även öka index med ett när en sträng är mottagen, men det går väl att lösa på nåt annat vis.

Koden:

ISR(USART0_RX_vect)
{
sTemp[counter] = UDR0;
counter++;

strcpy(sSMS[0],sTemp);
numberOfSMS = 1;
}
Användarvisningsbild
björn
EF Sponsor
Inlägg: 2570
Blev medlem: 29 mars 2004, 23:09:55

Inlägg av björn »

Nej, jag tror bara usartbufferten kan hålla 8 bitar så du måste te ett tecken i taget.
Bra att jag kunde hjälpa iallafall :)
Användarvisningsbild
cykze
EF Sponsor
Inlägg: 1539
Blev medlem: 8 april 2004, 10:40:28
Ort: Uppsala

Inlägg av cykze »

Är du medveten om att strcpy(sSMS[0],sTemp) kräver att sTemp är nullterminerad? Dessutom verkar det lite onödigt att kopiera över hela strängen efter varje inläst tecken.
thepirateboy
EF Sponsor
Inlägg: 2109
Blev medlem: 27 augusti 2005, 20:57:58
Ort: Borlänge

Inlägg av thepirateboy »

Att den måste vara nullterminerad visste jag inte men det låter ju logiskt nu när du säger det. Att den kopieras varje gång är jag medveten om, ville bara kolla om det funka. Om man nu vill kopiera och öka index när en sträng är mottagen, något tips på hur man kan göra. Jag kommer bara skicka en sträng då och då. Ska man sätta en "flagga" i interuptet som man kollar av då och då i huvudprogrammet eller hur göra?
Användarvisningsbild
Icecap
Inlägg: 26686
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

Kod: Markera allt

typedef unsigned char byte;

#pragma interrupt_handler twi_isr:18
void twi_isr(void)
  {
  byte Data;
  static byte Index = 0;
  Data = UDR; // Read incoming char
  if(Index >= UART_RxTail)
    { // Trying to fill in too muck, flag for error
    /* ERROR! Receive buffer overflow */
    }
  else
    { // All is well, put in buffer
    UART_RxBuf[Index++] = data; // store received data in buffer
    UART_RxBuf[Index]     = 0; // Terminate string
    }
  } 
Denna gör att du måste antingen ha en kod för "ny sträng" eller flytta ut 'Index' (skip då 'static') och nolla den vid behov. Jag hoppas att din error-rutin är begränsat till att sätta en flagga bara.
Användarvisningsbild
cykze
EF Sponsor
Inlägg: 1539
Blev medlem: 8 april 2004, 10:40:28
Ort: Uppsala

Inlägg av cykze »

Det här borde väl göra vad du vill.

Kod: Markera allt

ISR(USART0_RX_vect)
{
    static uint8_t counter = 0;

    if (counter >= sizeof(sTemp))
    {
        // Bufferten full
    }
    else
    {
        sTemp[counter] = UDR0;

        if (sTemp[counter] == '\0')
        {
            strcpy(sSMS[numberOfSMS++], sTemp);
            counter = 0;
        }
        else
            counter++;
    }
}
edit: Koden förutsätter att texten som skickas via UART:en är nullterminerad. Startvärdet för numberOfSMS bör vara 0.
Senast redigerad av cykze 31 maj 2006, 21:39:18, redigerad totalt 2 gånger.
thepirateboy
EF Sponsor
Inlägg: 2109
Blev medlem: 27 augusti 2005, 20:57:58
Ort: Borlänge

Inlägg av thepirateboy »

Nice, ska prova detta imorrn. :)
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

> Min tanke var om det gick att stanna i interruptet tills alla tecken var mottagna...

Generellt (oavsett om det är AVR, PIC eller något annan processor) är det
en dålig ide, om det inte är väldigt snabb kommunikation (alltså inget
som en UART klarar av).

En ISR ska inte göra mer än vad som absolut *måste* göras just i ISR'en...
Skriv svar