Sida 1 av 3

Att jämföra sträng på rätt sätt?

Postat: 28 juni 2017, 15:18:36
av newbadboy
Har ett program där jag skickar ordet "Post" från en uart TX till en uart RX. I mottagar delen försöker jag kolla varje cell med if satser men jag förstår att detta inte är helt säkert att göra då jag alltid behöver sända en hel del ggr innan alla if satser går genom och jag får ut textet "du har ny post" på displayen. Och ibland missar den trigga helt faktiskt.

Rätt ofta får jag även konstiga tecken och hängningar oxå.

Signalen in på RX pinnen till Ic´n är verifierad med logikanalysator och det kommer inget skräp alls utan bara ordet "post" så hådvarumässigt är det ok!

Kod: Markera allt

if(uart_rd[0]=='P'){
               if(uart_rd[1]=='o')
                 if(uart_rd[2]=='s')
                   if(uart_rd[3]=='t'){
                                       delay_ms(100);
                                       BACKLIGHT=1;
                                       LCD_Cmd(_LCD_CLEAR);
                                       Lcd_out(1,1,"Du har ny post!");
                                       LOADSWITCH=1;
                                       BUZZER=1;
                                       delay_ms(200);
                                       BUZZER=0;
                                       delay_ms(200);
                                       BUZZER=1;
                                       delay_ms(200);
                                       BUZZER=0;
                                       delay_ms(200);

                                       while(SETRST==0){
                                            BACKLIGHT=1;
                                            }
                                      }


                }

Re: Att jämföra sträng på rätt sätt?

Postat: 28 juni 2017, 16:08:23
av johano
Vad är det för plattform & kompilator?
Kan du visa koden som läser in uart_rd?

Om uart_rd verkligen innehåller "Post" så kommer din kod fungera. Så det är alltså inte kontrollen som strular
utan att uart_rd inte innehåller det du tror att den gör.

/j

Re: Att jämföra sträng på rätt sätt?

Postat: 28 juni 2017, 16:09:15
av Synesthesia
Är buffringen som den skall? Det är möjligen inte så att serie-data kommer in via interrupt och du läser av i main?

Re: Att jämföra sträng på rätt sätt?

Postat: 28 juni 2017, 17:35:41
av sodjan
Det skulle kanske vara effektivare (mindre kod och bättre prestanda)
genom att använda någon av de strängfunktioner som brukar finnas i C.
(Ja, jag vet att det rent formellt inte ligger i C i sig, utan i biblioteken...)

Sen är det ju frågan *när* koden ovan körs? Vad är det som triggar det?
Skickas det enbart "Post" eller skickas det även CR och/eller LF?

Det syns inte i den visade koden, men någonstans måste du ju även sätta
pekaren till bufferten till början igen för att ta emot nästa packet.

Det vanliga är nog att man fyller på en buffert (skulle kunna vara uart_rd)
och när en speciell avslutare ("terminator") kommer in, så analyserar man
vad som finns i bufferten. Eventuellt kopierar man först bufferten snabbt till
en ny area så att huvudbufferten direkt är tillgänglig för att ta emot nästa
packet under tiden som man analyserar och agerar på föregående paket.

Re: Att jämföra sträng på rätt sätt?

Postat: 28 juni 2017, 18:09:41
av newbadboy
johano skrev:Vad är det för plattform & kompilator?
Kan du visa koden som läser in uart_rd?

Om uart_rd verkligen innehåller "Post" så kommer din kod fungera. Så det är alltså inte kontrollen som strular
utan att uart_rd inte innehåller det du tror att den gör.

/j
Kompilatorn mikroC.

Med plattform menar du HW eller sw

Fullständig kod se nedan

Re: Att jämföra sträng på rätt sätt?

Postat: 28 juni 2017, 18:10:31
av newbadboy
Synesthesia skrev:Är buffringen som den skall? Det är möjligen inte så att serie-data kommer in via interrupt och du läser av i main?

Ojoj, vet inte vad som menas med buffringen i detta fall. Sorry för min okunskap

Re: Att jämföra sträng på rätt sätt?

Postat: 28 juni 2017, 18:13:25
av newbadboy
sodjan skrev:Det skulle kanske vara effektivare (mindre kod och bättre prestanda)
genom att använda någon av de strängfunktioner som brukar finnas i C.
(Ja, jag vet att det rent formellt inte ligger i C i sig, utan i biblioteken...)

Sen är det ju frågan *när* koden ovan körs? Vad är det som triggar det?
Skickas det enbart "Post" eller skickas det även CR och/eller LF?

Det syns inte i den visade koden, men någonstans måste du ju även sätta
pekaren till bufferten till början igen för att ta emot nästa packet.

Det vanliga är nog att man fyller på en buffert (skulle kunna vara uart_rd)
och när en speciell avslutare ("terminator") kommer in, så analyserar man
vad som finns i bufferten. Eventuellt kopierar man först bufferten snabbt till
en ny area så att huvudbufferten direkt är tillgänglig för att ta emot nästa
packet under tiden som man analyserar och agerar på föregående paket.
Som uart överföring använder jag tx/rx 433MHz modulerna från Swech och det är alltså pinnen som är rx kopplad till PICen som jag verifierat rena datasignaler!
Kod nedan.

Kod: Markera allt

char uart_rd[20];
int i;

// Defining IO name
#define LOADSWITCH PORTA.F3
#define BUZZER PORTA.F4
#define SETRST PORTB.F3
#define BACKLIGHT PORTA.F2

//LCD module connection
sbit LCD_RS at RB4_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D4 at RA6_bit;
sbit LCD_D5 at RA7_bit;
sbit LCD_D6 at RA0_bit;
sbit LCD_D7 at RA1_bit;

sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISA6_bit;
sbit LCD_D5_Direction at TRISA7_bit;
sbit LCD_D6_Direction at TRISA0_bit;
sbit LCD_D7_Direction at TRISA1_bit;
//End LCD module connection


void Init_Main(){
APFCON0=0b00000000;
OSCCON=0b01101000;      //4Mhz
C1ON_bit=0;
SRLEN_bit=0;


TRISA=0b00000000;
TRISB=0b00001010;
ANSELA=0b00000000;
ANSELB=0b00000000;
ADCON0=0b00000000;
ADCON1=0b00000000;

UART1_Init(9600);

LOADSWITCH=0;
BUZZER=1;
BACKLIGHT=1;
LCD_Init();
LCD_Cmd(_LCD_CURSOR_OFF);
LCD_Cmd(_LCD_CLEAR);
Lcd_out(1,1,"HusDiag R1.0");
Lcd_out(2,1,"Karoly.S 2017");
BUZZER=0;
for(i=0; i<20; i++){
    delay_ms(100);
    }
LCD_Cmd(_LCD_CLEAR);
Lcd_out(1,1,"Sensorer OK");
Lcd_out(2,1,"inget larm");
BACKLIGHT=0;

}

void LightUp(){
    BACKLIGHT=1;
    BUZZER=1;
    delay_ms(100);
    BUZZER=0;
    delay_ms(2000);
    BACKLIGHT=0;
    }

void Recieve(){
 if(UART1_Data_Ready()==1){

       UART1_Read_Text(uart_rd,"\n",255);

       if(uart_rd[0]=='D'){
         if(uart_rd[1]=='r')
            if(uart_rd[2]=='a')
               if(uart_rd[3]=='n')
                  if(uart_rd[4]=='a')
                     if(uart_rd[5]=='g')
                        if(uart_rd[6]=='e'){
                                       LCD_Cmd(_LCD_CLEAR);
                                       Lcd_out(1,1,"Dränering full");
                                       Lcd_out(2,1,"pumpa ut vatten!");
                                       LOADSWITCH=1;
                                       }
                        }
                                       
        else if(uart_rd[0]=='P'){
               if(uart_rd[1]=='o')
                 if(uart_rd[2]=='s')
                   if(uart_rd[3]=='t'){
                                       delay_ms(100);
                                       BACKLIGHT=1;
                                       LCD_Cmd(_LCD_CLEAR);
                                       Lcd_out(1,1,"Du har ny post!");
                                       LOADSWITCH=1;
                                       BUZZER=1;
                                       delay_ms(200);
                                       BUZZER=0;
                                       delay_ms(200);
                                       BUZZER=1;
                                       delay_ms(200);
                                       BUZZER=0;
                                       delay_ms(200);

                                       while(SETRST==0){
                                            BACKLIGHT=1;
                                            }

                                        }

                }

    LCD_Cmd(_LCD_CLEAR);
    Lcd_out(1,1,"Sensorer OK");
    Lcd_out(2,1,"inget larm");
    BACKLIGHT=0;
    LOADSWITCH=0;


    }
 }




void main() {
   Init_Main();
   while (1){
        if(SETRST==1)
           LightUp();
        
        Recieve();
        }
   }

det som också gör mig lite mörkrädd är varifrån kommer alla hittepå tecken jag får ut i displayen. Display texten är ju satt på ett par rader och är alltså inte "dynamisk".

Re: Att jämföra sträng på rätt sätt?

Postat: 28 juni 2017, 18:13:47
av Jan Almqvist
Att ta emot och tolka sådant som kommer på seriekanal är mycket svårare än man kan tro. I mitt tycke är t.ex. delay_ms() och liknande totalt bannlyst och man måste ha en riktig hantering av timeout så att telegrammottagaren kan hitta rätt igen när det kommer skräp eller bara delar av meddelanden.

Re: Att jämföra sträng på rätt sätt?

Postat: 28 juni 2017, 18:28:35
av sodjan
Ah, OK. Jag har inte kollat dokumentationen, men jag antar att
"UART1_Read_Text(uart_rd,"\n",255);" läser upp till 255 tecken
eller till nästa LF. Sedan kollar du vad som har kommit in. Är väl
i princip OK, antar jag. Koden är alltså "fast" i UART1_Read_Text()
funktionen under hela mottagandet.

Det är ju viktigt att du skickar en "\n" efter varje kommando, annars
händer inget fören det har kommit 255 tecken och då kollas det första
kommandot i bufferten. Sedan behövs det 255 nya tecken innan nästa
koll sker. O.s.v...

"\n" motsvarar LF ("Line Feed") och det skickar du kanske aldrig. Om du
trycker "ENTER" så är det en CR ("Carriage Return"" som skickas och då
skulle det kunna fungera om du byter "\n" till "\r" (vilket betyder just CR)...

Jag är lite tveksam till om UART1_Data_Ready() behöver kollas, sannolikt
gör UART1_Read_Text() något motsvarande internt. Men jag tror inte
heller att det är just det som är problemet.

Prova att bara byta "\n" till "\r"...

Re: Att jämföra sträng på rätt sätt?

Postat: 28 juni 2017, 18:30:57
av sodjan
> I mitt tycke är t.ex. delay_ms() och liknande totalt bannlyst...

Ja, rent generellt och principiellt. :-)

I just detta fall så sker nog hela mottagandet i en och samma funktion,
så delay funktionerna körs inte under den tiden.

Re: Att jämföra sträng på rätt sätt?

Postat: 28 juni 2017, 18:41:17
av newbadboy
Jag håller med ang delays. Dock har jag ju medvetet inte använt den alls där uart läsning och sådant görs

edit: sodjan hann före

Re: Att jämföra sträng på rätt sätt?

Postat: 28 juni 2017, 18:42:28
av newbadboy
http://elektronikforumet.com/forum/view ... 46&t=87690


länken ovan hittar ni schema etc

Det är föressten pic16F1847 som använts med 4 Mhz intern oscilltor

Re: Att jämföra sträng på rätt sätt?

Postat: 28 juni 2017, 18:52:58
av newbadboy
sodjan skrev:Ah, OK. Jag har inte kollat dokumentationen, men jag antar att
"UART1_Read_Text(uart_rd,"\n",255);" läser upp till 255 tecken
eller till nästa LF. Sedan kollar du vad som har kommit in. Är väl
i princip OK, antar jag. Koden är alltså "fast" i UART1_Read_Text()
funktionen under hela mottagandet.

Det är ju viktigt att du skickar en "\n" efter varje kommando, annars
händer inget fören det har kommit 255 tecken och då kollas det första
kommandot i bufferten. Sedan behövs det 255 nya tecken innan nästa
koll sker. O.s.v...

"\n" motsvarar LF ("Line Feed") och det skickar du kanske aldrig. Om du
trycker "ENTER" så är det en CR ("Carriage Return"" som skickas och då
skulle det kunna fungera om du byter "\n" till "\r" (vilket betyder just CR)...

Jag är lite tveksam till om UART1_Data_Ready() behöver kollas, sannolikt
gör UART1_Read_Text() något motsvarande internt. Men jag tror inte
heller att det är just det som är problemet.

Prova att bara byta "\n" till "\r"...
Nixpix. Skickar varken \n eller \r. Ska prova och återkomma.

Re: Att jämföra sträng på rätt sätt?

Postat: 28 juni 2017, 19:16:01
av newbadboy
Med \n så funkar det oftare men oftast verkar det inte gå genom alla if satser. Men inga konstiga tecken i displayen

Med \r så fick jag inte en enda lyckad triggning däremot en massa skumma tecken och sådant

Re: Att jämföra sträng på rätt sätt?

Postat: 28 juni 2017, 20:33:58
av svanted
char uart_rd[20];
//
UART1_Read_Text(uart_rd,"\n",255);

borde inte 20 vara 255 eller mer?

iom att du har "\n" som delimiter måste du skicka "\n" på slutet.