USART - atmega porovnání textového řetězce

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

Moderátor: Moderátoři

Zpráva
Autor
Uživatelský avatar
Nearduinista
Příspěvky: 23
Registrován: 08 kvě 2024, 00:00

USART - atmega porovnání textového řetězce

#1 Příspěvek od Nearduinista »

Zdravím už několik dní řeším proč tenhle konkrétní příklad nefunguje. Pokud pošlu zprávu “on” měla by svítit ledka. Když to zadám do přerušení, tak to funguje, ale v hlavním programu nic pokud to nějak nezaobalím.

Kód: Vybrat vše

#include <avr/io.h>
#include <stdio.h>
#include <stdlib.h> 
#include <avr/interrupt.h>
#include <string.h>

#define UART_BAUD_RATE  9600
#define UART_BAUD_REGISTERS  (((F_CPU / (UART_BAUD_RATE * 16UL))) - 1)

volatile char prijaty_znak=0;
char zprava[16];
 
ISR(USART_RX_vect)
{

static int i=0;
prijaty_znak = UDR;
 
 
 if((prijaty_znak != '\n') && (prijaty_znak!='\r'))
 {
  zprava[i]=prijaty_znak;
  i++;
 }
 else
 {
  zprava[i]='\0';
  i=0;
 }
}

int main(void){
   
   
   UBRRL = UART_BAUD_REGISTERS;;
   UCSRB = (1<<RXEN)|(1<<TXEN);
   UCSRC = (1<<URSEL)|(1<<UCSZ0) |(1<<UCSZ1);
   UCSRB |= (1 << RXCIE);
   
   DDRA =0xff;
   sei();
   
while(1){   
   
if(strcmp(zprava,"on")==0){PORTA |= (1<<PORTA0);}


 }
}
Uživatelský avatar
Cowley
Příspěvky: 3557
Registrován: 04 úno 2005, 00:00

#2 Příspěvek od Cowley »

Co toto ?
Uživatelský avatar
Dumitru
Příspěvky: 254
Registrován: 11 pro 2015, 00:00
Bydliště: Slovensko,Bratislava
Kontaktovat uživatele:

#3 Příspěvek od Dumitru »

Nearduinista píše:Zdravím už několik dní řeším proč tenhle konkrétní příklad nefunguje. Pokud pošlu zprávu “on” měla by svítit ledka. Když to zadám do přerušení, tak to funguje, ale v hlavním programu nic pokud to nějak nezaobalím.

Kód: Vybrat vše

#include <avr/io.h>
#include <stdio.h>
#include <stdlib.h> 
#include <avr/interrupt.h>
#include <string.h>

#define UART_BAUD_RATE  9600
#define UART_BAUD_REGISTERS  (((F_CPU / (UART_BAUD_RATE * 16UL))) - 1)

volatile char prijaty_znak=0;
char zprava[16];
 
ISR(USART_RX_vect)
{

static int i=0;
prijaty_znak = UDR;
 
 
 if((prijaty_znak != '\n') && (prijaty_znak!='\r'))
 {
  zprava[i]=prijaty_znak;
  i++;
 }
 else
 {
  zprava[i]='\0';
  i=0;
 }
}

int main(void){
   
   
   UBRRL = UART_BAUD_REGISTERS;;
   UCSRB = (1<<RXEN)|(1<<TXEN);
   UCSRC = (1<<URSEL)|(1<<UCSZ0) |(1<<UCSZ1);
   UCSRB |= (1 << RXCIE);
   
   DDRA =0xff;
   sei();
   
while(1){   
   
if(strcmp(zprava,"on")==0){PORTA |= (1<<PORTA0);}


 }
}


Aký reťazec posielaš ak taký "on\r\n" pripadne "on\n\r" tak ? ten poslední znak ty prepíše 'o' na '\0'. skús poslať len "on\r" pripadne "on\n"

Ak posielaš len "on" tak tam chyba ukončovači znak "\0" pre funkciu strcmp()

a dávaj pozor niektoré terminály ty môžu znaky "\r\n" vkladať automaticky
Uživatelský avatar
samec
Příspěvky: 6671
Registrován: 19 pro 2017, 00:00

#4 Příspěvek od samec »

char zprava[16]; musí byť volatile :wink:
Uživatelský avatar
Nearduinista
Příspěvky: 23
Registrován: 08 kvě 2024, 00:00

#5 Příspěvek od Nearduinista »

samec píše:char zprava[16]; musí byť volatile :wink:


Pokud použiji příkaz na porovnávání řetězců strcmp, tak když nechám volatile, překladač dá varování: passing argument 1 of ‘strncmp’ discards qualifiers from pointer target type. A nefunguje to stejně
Uživatelský avatar
Nearduinista
Příspěvky: 23
Registrován: 08 kvě 2024, 00:00

#6 Příspěvek od Nearduinista »

Dumitru píše:
Nearduinista píše:Zdravím už několik dní řeším proč tenhle konkrétní příklad nefunguje. Pokud pošlu zprávu “on” měla by svítit ledka. Když to zadám do přerušení, tak to funguje, ale v hlavním programu nic pokud to nějak nezaobalím.

Kód: Vybrat vše

#include <avr/io.h>
#include <stdio.h>
#include <stdlib.h> 
#include <avr/interrupt.h>
#include <string.h>

#define UART_BAUD_RATE  9600
#define UART_BAUD_REGISTERS  (((F_CPU / (UART_BAUD_RATE * 16UL))) - 1)

volatile char prijaty_znak=0;
char zprava[16];
 
ISR(USART_RX_vect)
{

static int i=0;
prijaty_znak = UDR;
 
 
 if((prijaty_znak != '\n') && (prijaty_znak!='\r'))
 {
  zprava[i]=prijaty_znak;
  i++;
 }
 else
 {
  zprava[i]='\0';
  i=0;
 }
}

int main(void){
   
   
   UBRRL = UART_BAUD_REGISTERS;;
   UCSRB = (1<<RXEN)|(1<<TXEN);
   UCSRC = (1<<URSEL)|(1<<UCSZ0) |(1<<UCSZ1);
   UCSRB |= (1 << RXCIE);
   
   DDRA =0xff;
   sei();
   
while(1){   
   
if(strcmp(zprava,"on")==0){PORTA |= (1<<PORTA0);}


 }
}


Aký reťazec posielaš ak taký "on\r\n" pripadne "on\n\r" tak ? ten poslední znak ty prepíše 'o' na '\0'. skús poslať len "on\r" pripadne "on\n"

Ak posielaš len "on" tak tam chyba ukončovači znak "\0" pre funkciu strcmp()

a dávaj pozor niektoré terminály ty môžu znaky "\r\n" vkladať automaticky


Například takhle už to funguje v pohodě ale proč? Tady defakto jen počkám až se zpráva nahraje celá . A potom vyhodnotím řetězec zda je stejný nebo není. To mě vrtá už několik dnů hlavou.

Kód: Vybrat vše

#include <avr/io.h>
#include <stdio.h>
#include <stdlib.h> 
#include <avr/interrupt.h>
#include <string.h>
 
#define UART_BAUD_RATE  9600
#define UART_BAUD_REGISTERS  (((F_CPU / (UART_BAUD_RATE * 16UL))) - 1)

volatile char prijaty_znak=0;
volatile int  prijato=0;
char zprava[16];


ISR(USART_RX_vect)
{
static int i=0;
prijaty_znak = UDR;

 if((prijaty_znak != '\n') && (prijaty_znak!='\r'))
 { 
  zprava[i]=prijaty_znak;
  i++;
 }
 else
 {
   zprava[i]='\0';
   prijato=1;
    i=0;
 }
}

int main(void)
{
    UBRRL = UART_BAUD_REGISTERS;
    UCSRB = (1<<RXEN)|(1<<TXEN);
    UCSRC = (1<<URSEL)|(1<<UCSZ0) |(1<<UCSZ1);     
    UCSRB |= (1 << RXCIE);    
 
    DDRD=0b00000010;
    DDRA =0xff;

   
    sei();
      
   while(1)
 {
    if(prijato==1)
   {
   if(strcmp(zprava,"on")==0)
            {
             PORTA |=(1<<PORTA1);         
         }
      prijato=0;
   }      
       
 }
}
Uživatelský avatar
samec
Příspěvky: 6671
Registrován: 19 pro 2017, 00:00

#7 Příspěvek od samec »

Ach jaj, strcmp. Používaš čarovné funkcie, tak máš čarovné výsledky.
Uživatelský avatar
Dumitru
Příspěvky: 254
Registrován: 11 pro 2015, 00:00
Bydliště: Slovensko,Bratislava
Kontaktovat uživatele:

#8 Příspěvek od Dumitru »

neviem koľko trvá kym sa funkcia strcmp vykoná ale v prvom prípade ju voláš dookola v maine a ako už som písal ak pošleš „on\r\n“ tak sa do bufra uloží zaprava[0] = „o“ a zaprava[1] = „n“ potom „\r“ zaprava[2] = „\0“ vynuluje i=0 a „\n“ do zprava[i=0] kde je uložene „o“ prepíše na „\0“ a ak strcmp tráva dlhšie ako prijatie jedného znaku tak potom to nesedí v druhom prípade spustíš strcmp len raz pravé vtedy keď sprava je korektná.
Naposledy upravil(a) Dumitru dne 08 kvě 2024, 21:40, celkem upraveno 1 x.
Uživatelský avatar
rnbw
Příspěvky: 37416
Registrován: 21 bře 2006, 00:00
Bydliště: Bratislava

#9 Příspěvek od rnbw »

V skompilovanom kod mozno ani ziadny strcmp nebude, pretoze kompilator usudi, ze dana podmienka sa nemoze nikdy splnit a pri optimalizacii ho odstrani.

Kód: Vybrat vše

$ cat test.c
#include <stdio.h>
#include <string.h>

char zprava[16];
int main() {
    while (1) {
        if (strcmp(zprava,"on") == 0)
            printf("AAAAAA\n");
    }
}
$ cc test.c -o test
$ strings test | grep strcmp
strcmp
strcmp@GLIBC_2.0
$ cc test.c -O2 -o test
$ strings test | grep strcmp
$
Uživatelský avatar
Nearduinista
Příspěvky: 23
Registrován: 08 kvě 2024, 00:00

#10 Příspěvek od Nearduinista »

Dumitru píše:neviem koľko trvá kym sa funkcia strcmp vykoná ale v prvom prípade ju voláš dookola v maine a ako už som písal ak pošleš „on\r\n“ tak sa do bufra uloží zaprava[0] = „o“ a zaprava[1] = „n“ potom „\r“ zaprava[2] = „\0“ vynuluje i=0 a „\n“ do zprava[i=0] kde je uložene „o“ prepíše na „\0“ a ak strcmp tráva dlhšie ako prijatie jedného znaku tak potom to nesedí v druhom prípade spustíš strcmp len raz pravé vtedy keď sprava je korektná.


Tož mě to taky napadlo, tak jsem se to pro zkoušku jal vyřešit takhle. A furt to nejede hm...



Kód: Vybrat vše

ISR(USART_RX_vect)
{
static int i=0;
prijaty_znak = UDR;

 if((prijaty_znak != '\n') && (prijaty_znak!='\r'))
 { 
  zprava[i]=prijaty_znak;
  i++;
 }
 else
 {
  if(i>0)
  {
   zprava[i]='\0';   
  }
    i=0;
 }
}
Uživatelský avatar
Dumitru
Příspěvky: 254
Registrován: 11 pro 2015, 00:00
Bydliště: Slovensko,Bratislava
Kontaktovat uživatele:

#11 Příspěvek od Dumitru »

Nearduinista píše:
Dumitru píše:neviem koľko trvá kym sa funkcia strcmp vykoná ale v prvom prípade ju voláš dookola v maine a ako už som písal ak pošleš „on\r\n“ tak sa do bufra uloží zaprava[0] = „o“ a zaprava[1] = „n“ potom „\r“ zaprava[2] = „\0“ vynuluje i=0 a „\n“ do zprava[i=0] kde je uložene „o“ prepíše na „\0“ a ak strcmp tráva dlhšie ako prijatie jedného znaku tak potom to nesedí v druhom prípade spustíš strcmp len raz pravé vtedy keď sprava je korektná.


Tož mě to taky napadlo, tak jsem se to pro zkoušku jal vyřešit takhle. A furt to nejede hm...



Kód: Vybrat vše

ISR(USART_RX_vect)
{
static int i=0;
prijaty_znak = UDR;

 if((prijaty_znak != '\n') && (prijaty_znak!='\r'))
 { 
  zprava[i]=prijaty_znak;
  i++;
 }
 else
 {
  if(i>0)
  {
   zprava[i]='\0';   
  }
    i=0;
 }
}


a sisi isty ze tam chodia znaky \r a \n inak sa ty tam nikdy nedostane \0


skus takto

Kód: Vybrat vše

volatile char zprava[16];
ISR(USART_RX_vect)
{
static int i=0;
prijaty_znak = UDR;

 if((prijaty_znak != '\n') && (prijaty_znak!='\r'))
 { 
  zprava[i]=prijaty_znak;
  i++;
 zprava[i] = '\0';
 }
 else
 {
  if(i>0)
  {
   zprava[i]='\0';   
  }
    i=0;
 }
}


a v maine

Kód: Vybrat vše


if (strcmp((char *)zprava,(char *)"on\0") == 0)
Uživatelský avatar
Nearduinista
Příspěvky: 23
Registrován: 08 kvě 2024, 00:00

#12 Příspěvek od Nearduinista »

Jistý už si nejsem ničím, každopádně pokračování zase zítra po práci už mám z toho bolehlav.
Uživatelský avatar
samec
Příspěvky: 6671
Registrován: 19 pro 2017, 00:00

#13 Příspěvek od samec »

tak nič
Uživatelský avatar
mhepp
Příspěvky: 121
Registrován: 16 srp 2017, 00:00

#14 Příspěvek od mhepp »

A není problém v té proměnné i?

Kód: Vybrat vše

...
volatile char zprava[16];
ISR(USART_RX_vect)
{
static int i=0;
...
}


Při každém volání ISR dojde k inicializaci proměnné i na 0, takže to vlastně neukládá nic... Z i bych udělal globální proměnnou:


Kód: Vybrat vše

...
volatile int prijato=0;
volatile char zprava[16];
volatile int i=0;

ISR(USART_RX_vect)
{
  prijaty_znak = UDR;

  //chybi osetreni delky vstupu - if (i>14) {...}

  if((prijaty_znak != '\n') && (prijaty_znak!='\r'))
  {
    zprava[i]=prijaty_znak;
    i++;
    zprava[i]=0;
  } else {
    i=0;
    prijato=1;
 }
}
Uživatelský avatar
Dumitru
Příspěvky: 254
Registrován: 11 pro 2015, 00:00
Bydliště: Slovensko,Bratislava
Kontaktovat uživatele:

#15 Příspěvek od Dumitru »

Odpovědět

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