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
mtajovsky
Příspěvky: 3728
Registrován: 19 zář 2007, 00:00
Bydliště: Praha

#16 Příspěvek od mtajovsky »

mhepp píše:A není problém v té proměnné i?

Není, i je statická a proto si uchovává svou hodnotu i mezi jednotlivými spuštěními interruptové rutiny.

V principu je špatně, pokud se něco v main() porovnává a zároveň na pozadí v přerušení se s těmito daty manipuluje. Proměnná prijato je v pořádku, nemá cenu provnávat dokola nehotová data. Ale jak testování prijato tak strcmp() by se mělo provádět s vypnutým přerušením od UART. A po otestování zprávy na ON se nastaví prijato na 0 a terpve pak se povolí přerušení. V operačních systémech máme k dispozici kritické sekce nebo mutexy, tady si musíme vystačit s vypínáním/zapínámí přerušení.
Uživatelský avatar
mhepp
Příspěvky: 121
Registrován: 16 srp 2017, 00:00

#17 Příspěvek od mhepp »

OK... Z céčka jsem už trochu vypadl. Očividně si to musím oživit.
Uživatelský avatar
Nearduinista
Příspěvky: 23
Registrován: 08 kvě 2024, 00:00

#18 Příspěvek od Nearduinista »

Dumitru píše:
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)


Ne prostě to fungovat nebude, tohle vypadalo nadějně, ale furt stejný. Přidával jsem si tam echo zpátky a co jsem odeslal to jsem dostal.
Zajímavý když dám před to zpoždění nejmíň 40ms, tak funguje.

Kód: Vybrat vše

   

while(1)
 {
 _delay_ms(40);

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

#19 Příspěvek od Nearduinista »

mtajovsky píše:
mhepp píše:A není problém v té proměnné i?

Není, i je statická a proto si uchovává svou hodnotu i mezi jednotlivými spuštěními interruptové rutiny.

V principu je špatně, pokud se něco v main() porovnává a zároveň na pozadí v přerušení se s těmito daty manipuluje. Proměnná prijato je v pořádku, nemá cenu provnávat dokola nehotová data. Ale jak testování prijato tak strcmp() by se mělo provádět s vypnutým přerušením od UART. A po otestování zprávy na ON se nastaví prijato na 0 a terpve pak se povolí přerušení. V operačních systémech máme k dispozici kritické sekce nebo mutexy, tady si musíme vystačit s vypínáním/zapínámí přerušení.


Takže použít něco jako ATOMIC_BLOCK??
Uživatelský avatar
asdf
Příspěvky: 707
Registrován: 06 říj 2022, 00:00
Kontaktovat uživatele:

#20 Příspěvek od asdf »

A nemůže to být tak, že ta fce strcmp() na začátku provede strlen(), aby věděla, jak je to dlouhé, a na tom se zasekne, protože nemůže najít nikde nulu? Takže bych jen tak na zkoušku dal do main před ten while něco jako:

Kód: Vybrat vše

zprava[15] = 0;
Uživatelský avatar
Nearduinista
Příspěvky: 23
Registrován: 08 kvě 2024, 00:00

#21 Příspěvek od Nearduinista »

asdf píše:A nemůže to být tak, že ta fce strcmp() na začátku provede strlen(), aby věděla, jak je to dlouhé, a na tom se zasekne, protože nemůže najít nikde nulu? Takže bych jen tak na zkoušku dal do main před ten while něco jako:

Kód: Vybrat vše

zprava[15] = 0;


Tohleto záhadně funguje, ale proč když to moc smysl nedává, spíš už mi připadá, že se přerušení s hlavním programem nedokáže synchronizovat dostatečně rychle a tím, že před to dám nějakou část kódu tak tím dám čas aby se příkaz strcmp dokázal vyhodnotit, nic moc už mě nenapadá.

Kód: Vybrat vše

   while(1)
 {
zprava[15]='\0';

if (strcmp(zprava,"on") == 0) 
            {
             PORTA |=(1<<PORTA1);         
         }
     else  PORTA &=~(1<<PORTA1);
 }
}
Uživatelský avatar
Dumitru
Příspěvky: 254
Registrován: 11 pro 2015, 00:00
Bydliště: Slovensko,Bratislava
Kontaktovat uživatele:

#22 Příspěvek od Dumitru »

Bohužiaľ odpoveď už sme dostali

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


a mal pravdu dneska som napísal presne ten kod čo sme mali naposledy pod Atmegu168 a tiež to nefungovalo

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;
 }
}


Kód: Vybrat vše

if (strcmp((char *)zprava,(char *)"on\0") == 0)


potom som zistil že if compilator zahadzuje a tak som vypnul optimizacie

Kód: Vybrat vše

#pragma GCC optimize ("Og") // vypnutie optimizacii 
#include <avr/io.h>
#include <stdio.h>
#include <stdlib.h>
#include <avr/interrupt.h>
#include <string.h>


a potom to fungovalo korektne


ako náhle sa v nekonečnom cykle nachádza aj akýkoľvek iný kód potom compilator ten if nezahodí a preto ty to funguje keď tam čokoľvek dopíšeš iné


Je to zaujímavý prípad :) - :roll:


Každopádne ale takto kontrolovať nie je správne , skús si napísať detekciu že prišli ukončovacie znaky \r\n a až potom kontroluj pomocou strcmp poprípade aj vynuluj už skontrolovane dáta, a tak tiež kontroluj aby ty premenná zprava nepretiekla.
Uživatelský avatar
Nearduinista
Příspěvky: 23
Registrován: 08 kvě 2024, 00:00

#23 Příspěvek od Nearduinista »

Tak jsem to šel zkusit a nic, říkám si to je v prd... Ale zjistil jsem ,že při překladu mi to vyhodilu hlášku :c:50: warning: ignoring #pragma GCC optimize
Takže jsem otevřel makefile a našel jsem tam tohle

Kód: Vybrat vše

# Optimization level, can be [0, 1, 2, 3, s]. 
#     0 = turn off optimization. s = optimize for size.
#     (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
OPT = s


To jsem tedy přepsal na nulu a hle už to funguje. Je tedy potom otázka jestli optimalizovat nabo ne a k čemu to vlastně slouží? Když to může udělat problém.
Na tohle bych v životě sám nepřišel, že to je překladem, takže to je pro mě novinka. Moc děkuji za spolupráci.

Určitě je to takhle nesmysl, si jen hraju abych zjistil co a jak funguje nebo ne. Právě tohle jsem řešil asi týden. Protože logicky by to jako fungovat mělo. Samozřejmě je to k ničemu program, ale hodně mě to naučilo.

Jinak jsem ten příjem o něco vylepšil, ještě tam dodělat nějaký to přetečení a bude to asi ok.

Kód: Vybrat vše

ISR(USART_RX_vect)
{
char prijaty_znak;
static uint8_t i=0;

prijaty_znak = UDR;
UDR=prijaty_znak;

 if(prijato==0)
 {
   if((prijaty_znak != '\n') && (prijaty_znak!='\r'))
   {
   zprava[i]=prijaty_znak;
   i++;
   }
   else
   {
   zprava[i]='\0';   
   i=0;
   prijato=1;
   }
 }
}
Naposledy upravil(a) Nearduinista dne 10 kvě 2024, 19:29, celkem upraveno 1 x.
Uživatelský avatar
rnbw
Příspěvky: 37414
Registrován: 21 bře 2006, 00:00
Bydliště: Bratislava

#24 Příspěvek od rnbw »

Optimalizovat ano, ale neprogramovat ako prasa.
Uživatelský avatar
samec
Příspěvky: 6670
Registrován: 19 pro 2017, 00:00

#25 Příspěvek od samec »

Nearduinista píše:Právě tohle jsem řešil asi týden.
Vyhoď prvých 5 či 6, či koľko ich tam teraz máš riadkov (tie s #...) a začni programovať. Skôr sa tak dopracuješ k funkčnému výsledku.
Odpovědět

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