Stránka 2 z 2
Napsal: 09 kvě 2024, 13:52
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í.
Napsal: 09 kvě 2024, 14:00
od mhepp
OK... Z céčka jsem už trochu vypadl. Očividně si to musím oživit.
Napsal: 09 kvě 2024, 14:58
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);
}
}
Napsal: 09 kvě 2024, 15:08
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??
Napsal: 09 kvě 2024, 16:15
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:
Napsal: 09 kvě 2024, 17:00
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:
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);
}
}
Napsal: 09 kvě 2024, 23:03
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

-
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.
Napsal: 10 kvě 2024, 16:19
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;
}
}
}
Napsal: 10 kvě 2024, 16:35
od rnbw
Optimalizovat ano, ale neprogramovat ako prasa.
Napsal: 10 kvě 2024, 21:14
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.