WinAVR - Pytanie do znawcow C

May 14, 2010 5 Replies

Mam pytanie dlaczego zmienna Ki oraz Kp (s->Ki oraz s->Kp) wchodzaca w sklad struktury s_pid przyjmuje losowe warosci wewnatrz funkcji RegulatorNextStep; Przedstawiam ponizej zawartosc plikow zrodlowych



Dodam tylko ze problem rozwiazalem ale nie moge sobie wytlumaczyc tak dziwnego zachowania kompilatora. Rozwiazanie problemu polegalo na przeniesieniu tworzenia struktury (struct s_pid pid;) z wnetrza funkcji main() na zewnatrz jej (globalna).


******** plik main.c
********

#include "pid.h" ... main(1); { ... struct s_pid pid; // jezeli przeniose to strukture na zewnatrz funkcji main // to program wykonuje sie prawidlowo ... InitReg(&pid,40,1,0); ... while(1); { ... err=RegulatorNextStep(&pid,i_set,current); ... }// end while }// end main


*************************** plik pid.h
*
************************** #ifndef _PID_H_ #define _PID_H_

struct s_pid { signed int Kp; signed int Ki; signed int Kd; signed long sigma; signed int delta; };


void InitReg(struct s_pid *s, signed int Kp, signed int Ki, signed int Kd); signed int RegulatorNextStep(struct s_pid *s,signed int set,signed int mes); void RegulatorReset(struct s_pid *s);



#endif


***************************** plik pid.c
*
************************* #include "pid_flt.h" ... signed int RegulatorNextStep(struct s_pid *s,signed int set_value,signed int measure_value) { ...

p_term=(s->Kp) * error; i_term= (s->Ki * s->sigma)/8; ... lcd(s->Kp); // !!!!!! dla czego mam losowe wartosci??? lcd(s->Ki); ... return (signed int)out; }



void InitReg(struct s_pid *s, signed int Kp, signed int Ki, signed int Kd) { s->Kp=Kp; s->Ki=Ki; s->Kd=Kd; s->sigma=0; s->delta=0; }


******************************************************************************




__________ Informacja programu ESET NOD32 Antivirus, wersja bazy sygnatur wirusow 5103 (20100510) __________



Wiadomosc zostala sprawdzona przez program ESET NOD32 Antivirus.



formatting link
lub
formatting link


Szczerze mówiąc to napisanie czegoś takiego "main(1)" powinno zostać oprotestowane prez kompilator bo składnia main w C jest taka int main(int arg,char* argv[]) niemniej kompilatory są na ogół wyrozumiałe.

Natomiast

while(1); { }

to już ewidentny błąd. Dla kompilatora taki zapis oznacza, że program ma stać w pustej pętli i nie robić nic a instrukcje z bloku otoczonego klamrami w ogóle nie zostaną wykonane. Kompilator może wtedy potraktować strukturę s_pid jak nieużywaną i usunać ją.

Zapis powinien wyglądać tak:

while(1) // Bez średnika!!! { }

Wtedy procesor ma wykonywac w kółko instrukcje zawarte w bloku.

Jeśli miałbym się tutaj jeszcze czego przyczepić, to nie wiem jak kompilator reaguje na wyznaczanie adresu struktury w locie operatorem & Załóż dodatkową zmienną wskaźnikową typu struct s_pid* zainicjalizują ją adresem struktury pid i podaj do funkcji zamiast &pid. Możliwe, że coś źle działa operator & i podstawia do funkcji zły adres structury powodując przekłamania.

A tak w ogóle jaki to proc i kompilator?

roxy wrote:

Jeśli pytający napisał w temacie "WinAVR", to myślę, że chodzi o proca z rodziny AVR :)... kompilator - zapewne gcc, bo ten wchodzi w skład WinAVR ;)... Chyba, że pytasz dokładniej (jaka wersja, jaki konkretny układ), to niestety, nie wiadomo...

W dniu 2010-05-19 01:53 MrWebsky napisał(a):

BTW: Czasem niektóre kompilatory (nie wiem akurat tu o jaką wersję avr-gcc chodzi) narzekają przy takiej konstrukcji na stały warunek w pętli while. Dlatego w przenośnym kodzie dużo lepiej jest pisać:

for(;;)

zamiast

while(1)

Wiadomosc na grupe pisalem z glowy, to nie sa fragmenty listingu wiec wkradly sie bledy ktore zauwazyl kolwga MrWebsky. Ale powodem problemu bylo cos innego a mianowicie instrikcja sprintf_P. Dochodzi³o do niekontrolowanego nadpisywania ramu. Mialem cos takiego:

char str[8]; .. .. sprintf_P(str,SPTR("U=%dV "),x); lcd_write(str); ...

Przy wiekszej wartosci x dochodzi³o do pisania poza rozmiarem zadeklarowanej tablicy znakow str.

In the darkest hour on Sat, 22 May 2010 16:13:41 +0200, roxy snipped-for-privacy@o2.pl screamed:

Właśnie po to wymyślono snprintf.

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required