Stránka 1 z 2

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

Napsal: 08 kvě 2024, 19:18
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);}


 }
}

Napsal: 08 kvě 2024, 19:32
od Cowley
Co toto ?

Napsal: 08 kvě 2024, 20:30
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

Napsal: 08 kvě 2024, 20:50
od samec
char zprava[16]; musí byť volatile :wink:

Napsal: 08 kvě 2024, 20:58
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ě

Napsal: 08 kvě 2024, 21:16
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;
   }      
       
 }
}

Napsal: 08 kvě 2024, 21:25
od samec
Ach jaj, strcmp. Používaš čarovné funkcie, tak máš čarovné výsledky.

Napsal: 08 kvě 2024, 21:36
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á.

Napsal: 08 kvě 2024, 21:37
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
$

Napsal: 08 kvě 2024, 21:58
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;
 }
}

Napsal: 08 kvě 2024, 22:24
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)

Napsal: 08 kvě 2024, 22:37
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.

Napsal: 08 kvě 2024, 23:40
od samec
tak nič

Napsal: 09 kvě 2024, 13:02
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;
 }
}

Napsal: 09 kvě 2024, 13:42
od Dumitru