/***********************************************************************/ /* */ /* Merici program pro zarizeni DRAK5 fy PaPouch. */ /* Napsal Marek Drapal (c) 2003. Volne siritelne pod licenci GNU GPL. */ /* */ /***********************************************************************/ #define PORT "/dev/ttyS1" /* V linuxu je ttyS1 druhy seriovy port */ #define BAUD_RATE_1 B115200 /* Rychl. portu B115200 (115.2 kBd) */ #define S_O_BUFFER 255 /* Velikost bufferu pro cteni z draka */ #define POCET_B_KON_MER 50 /* Delka odpovedi pri kont. mereni (4 vstupy) */ #define POCET_CYKLU_MERENI 5000 /* Pocet mer. cyklu (*4=pocet mereni) */ #include /* Definice standardnich vstupne/vyst. fci */ #include /* Definice stringovych fci */ #include /* Definice standardnich UNIXovych fci */ #include /* Definice souborovych operaci */ #include /* Definice chybovych hlasek a fci */ #include /* Definice POSIXovych terminal. nastaveni */ /* Definice struktury merici instrukce */ struct merici_instrukce { unsigned char *dotaz; int delka_dotazu; unsigned char *odpoved; int delka_odpovedi; }; /* Definice nekterych zakladnich instrukci. * Pozor na spravne nastaveni delek dotazu * a odpovedi - jinak dojde k preteceni bufferu !*/ /* Nastaveni mericiho rozsahu na -2.5 az 2.5 V */ struct merici_instrukce nastav_rozsah_plus_minus_2_5 = { "\x2a\x61\x00\x09\x01\x02\x10\x00\x00\x00\x00\x58\x0d", 13, "\x2a\x61\x00\x05\x01\x02\x01\x6b\x0d", 9 }; /* Nastaveni mericiho rozsahu na -0.625 az 0.625 V */ struct merici_instrukce nastav_rozsah_plus_minus_0_625 = { "\x2a\x61\x00\x09\x01\x02\x10\x02\x02\x02\x02\x50\x0d", 13, "\x2a\x61\x00\x05\x01\x02\x01\x6b\x0d", 9 }; /* Nastaveni mericiho rozsahu na 0 az 2.5 V */ struct merici_instrukce nastav_rozsah_0_az_2_5 = { "\x2a\x61\x00\x09\x01\x02\x10\x03\x03\x03\x03\x4c\x0d", 13, "\x2a\x61\x00\x05\x01\x02\x01\x6b\x0d", 9 }; /* Nastaveni mericiho rozsahu na 0 az 0.625 V */ struct merici_instrukce nastav_rozsah_0_az_0_625 = { "\x2a\x61\x00\x09\x01\x02\x10\x05\x05\x05\x05\x44\x0d", 13, "\x2a\x61\x00\x05\x01\x02\x01\x6b\x0d", 9 }; /* Rychle kontinualni mereni vsech 4 vstupu 1000x za sekundu */ struct merici_instrukce kontinualni_mereni_4_vstupu_1000x_sec = { "\x2a\x61\x00\x07\x01\x02\x52\x0f\x01\x08\x0d", 11, "\x2a\x61\x00\x05\x01\x02\x01\x6b\x0d", 9 }; /* Reset pristroje */ struct merici_instrukce reset_pristroje = { "\x2a\x61\x00\x05\x01\x02\xe3\x89\x0d", 9, "\x2a\x61\x00\x05\x01\x02\x01\x6b\x0d", 9 }; /* Funkce otevre PORT standartnimi POSIX instrukcemi */ int /* Vystup filedesc. souboru ci -1 pri chybe */ open_port (void) { int fd; /* File deskriptor souboru (tj. portu) */ /* Otevre PORT pro cteni a zapis, vyradi terminal. preruseni a DCD */ fd = open (PORT, O_RDWR | O_NOCTTY | O_NDELAY); if (fd == -1) { perror ("open_port: Nelze otevrit:"); /* Nepodarilo se otevrit */ perror (PORT); /* PORT definovany port */ } else fcntl (fd, F_SETFL, 0); /* Nast. read do neblok. rezimu */ return (fd); } /* Funkce posle instrukci typu struct merici_instrukce na otevreny a * inicializovany port int fd a precte odpoved, kterou porovna s odpovedi * vzorovou vraci 0 pri uspechu a tato zaporna cisla pri chybach: * -1 - nepodarilo se poslat vsechna data na port * -2 - prijata odpoved nesouhlasi se vzorovou */ int posli_instrukci (struct merici_instrukce m_instrukce, int fd) { unsigned char prijimana_data[S_O_BUFFER + 2]; /* Buffer na cteni z portu */ int i, j = 0; /* Pomocne promenne */ /* Paranoia */ prijimana_data[S_O_BUFFER + 1] = '\0'; /* Vypis instrukce mereni */ printf ("\nPosilam:"); for (i = 0; i < m_instrukce.delka_dotazu; i++) { printf (" %02x", m_instrukce.dotaz[i]); } /* Zapis merici instrukce na port */ if (write (fd, m_instrukce.dotaz, m_instrukce.delka_dotazu) < m_instrukce.delka_dotazu) { perror ("posli_instrukci: nedari se poslat vsechny byty do souboru"); return (-1); /* Konec posli_instrukci */ } /* Cteni odpovedi na merici instrukci */ while ((j != m_instrukce.delka_odpovedi) && (j < S_O_BUFFER)) { /* Cteme vzdy maximum z bufferu, vzdy na aktualni pozici */ i = read (fd, prijimana_data + j, m_instrukce.delka_odpovedi - j); j += i; /* Pocet nactenych bajtu */ } /* Paranoia */ prijimana_data[m_instrukce.delka_odpovedi + 1] = '\0'; /* Vypis odpovedi na merici instrukci */ printf ("\nOdpoved:"); for (i = 0; i < m_instrukce.delka_odpovedi; i++) { printf (" %02x", prijimana_data[i]); } printf ("\n"); /* TODO, zatim porovna jen nez narazi na \0. Kontrolni soucty se * nekontroluji, ale to nevadi, protoze drak * dava u nekterych instukci spatne kontrolni soucty */ /* Porovnani odpovedi prijate s odpovedi vzorovou */ if (strcmp (prijimana_data, m_instrukce.odpoved) != 0) { perror ("posli_instrukci: prijata odpoved nesouhalsi se vzorovou"); return (-2); /* Konec posli_instrukci */ } else { return (0); /* Vse probehlo O.K. */ } } /* Funkce, ktera dostane adresu funkce bud prepocti_i_zaporne, nebo * prepocti_jen_kladne, podle toho, zda se meri jen kladne hodnoty, nebo i * zaporne */ int (*prepocti) (unsigned char prijimana_data[], int delka_prijimanych_dat, float rozsah_abs_h, unsigned char kontrolni_cislo); /* Prepocte a vytiskne prijata data v prijimana_data[] se znamou delkou dat v * delka_prijimanych_dat na +/- rozsah specifikovany v rozsah_abs_h a kontroluje * kontrolni_cislo. * Vraci 0 pri uspechu a -1 pri chybe */ int prepocti_i_zaporne (unsigned char prijimana_data[], int delka_prijimanych_dat, float rozsah_abs_h, unsigned char kontrolni_cislo) { int i, j; int vstup; char nekonzistence_dat = 'n'; if (strncmp (prijimana_data, "\x2a\x61", 2) == 0) { if (prijimana_data[7] == kontrolni_cislo) { for (i = 8; i < (delka_prijimanych_dat - 2) && i < POCET_B_KON_MER; i += 8) { for (j = 0; (j < 8) && ((j + i) < POCET_B_KON_MER); j += 2) { vstup = (int) (prijimana_data[j + i]); vstup <<= 8; vstup |= (int) (prijimana_data[j + i + 1]); printf ("%f\t", (((float) vstup) - 32768.0) * rozsah_abs_h / 32768.0); } printf ("\n"); } nekonzistence_dat = 'n'; } else { nekonzistence_dat = 'a'; } } else { nekonzistence_dat = 'a'; } if (nekonzistence_dat == 'a') { perror ("prepocti_jen_kladne: nekonzistence dat"); return (-1); } return (0); } /* Prepocte a vytiskne prijata data v prijimana_data[] se znamou delkou dat v * delka_prijimanych_dat na + rozsah specifikovany v rozsah_abs_h a kontroluje * kontrolni_cislo. * Vraci 0 pri uspechu a -1 pri chybe */ int prepocti_jen_kladne (unsigned char prijimana_data[], int delka_prijimanych_dat, float rozsah_abs_h, unsigned char kontrolni_cislo) { int i, j; int vstup; char nekonzistence_dat = 'n'; if (strncmp (prijimana_data, "\x2a\x61", 2) == 0) { if (prijimana_data[7] == kontrolni_cislo) { for (i = 8; i < (delka_prijimanych_dat - 2) && i < POCET_B_KON_MER; i += 8) { for (j = 0; (j < 8) && ((j + i) < POCET_B_KON_MER); j += 2) { vstup = (int) (prijimana_data[j + i]); vstup <<= 8; vstup |= (int) (prijimana_data[j + i + 1]); printf ("%f\t", ((float) vstup) * rozsah_abs_h / 65535.0); } printf ("\n"); } nekonzistence_dat = 'n'; } else { nekonzistence_dat = 'a'; } } else { nekonzistence_dat = 'a'; } if (nekonzistence_dat == 'a') { perror ("prepocti_jen_kladne: nekonzistence dat"); return (-1); } return (0); } /* Funkce na kontinualni mereni */ int kontin_drak (char rozsah, float rozsah_abs_h, int fd) { unsigned char prijimana_data[S_O_BUFFER + 2]; int delka_prijimanych_dat; int i, j; unsigned char kontrolni_cislo = 0; unsigned int k; /* Paranoia */ prijimana_data[S_O_BUFFER + 1] = '\0'; /* Pro mene nez 4 vstupy neni kod zatim nenapsan, navahej to dopsat!! * Pridej paramet p_vstupu do kontin_drak... */ if (POCET_B_KON_MER != 50) { perror ("kontin_drak: kod neni optimalizovan na jiny pocet mer. bajtu"); return (-1); } /* Mereny rozsah obsahuje i zaporna cisla */ if (rozsah == '-') { prepocti = &prepocti_i_zaporne; } /* Mereny rozsah obsahuje jen kladna cisla */ else if (rozsah == '+') { prepocti = &prepocti_jen_kladne; } /* Spatne definovane znamenko rozsahu */ else { perror ("kontin_drak: rozsah_i_zaporny neni ani '-' ani '+'"); return (-2); /* Konec kontin_drak */ } posli_instrukci (kontinualni_mereni_4_vstupu_1000x_sec, fd); /* Nacteme 4-nasobny pocet hodnot nez POCET_CYKLU_MERENI */ for (k = 0; k < POCET_CYKLU_MERENI; k++) { delka_prijimanych_dat = POCET_B_KON_MER; j = 0; while (j != delka_prijimanych_dat) { i = read (fd, prijimana_data + j, delka_prijimanych_dat - j); j += i; } /* Paranoia */ prijimana_data[delka_prijimanych_dat + 1] = '\0'; prepocti (prijimana_data, delka_prijimanych_dat, rozsah_abs_h, kontrolni_cislo); if (kontrolni_cislo == 255) kontrolni_cislo = 0; else kontrolni_cislo++; } posli_instrukci (reset_pristroje, fd); return (0); } /* Funkce nastavi seriovy port. Rychlost BAUD_RATE_1 a dalsi */ int nastav_port (int fd) /* Vstup fd, vraci 0 pri OK */ { struct termios options; /* Systemova struktura terminalu */ tcgetattr (fd, &options); /* Nacteni aktualniho stavu */ cfsetispeed (&options, BAUD_RATE_1); /* Vstupni rychlost portu */ cfsetospeed (&options, BAUD_RATE_1); /* Vystupni rychlost portu */ cfmakeraw (&options); /* Nastav vstup na ciste binarni */ tcsetattr (fd, TCSAFLUSH, &options); /* Zapsani struktury */ return (0); } /* Reset pristroje softwarovou instrukci, ne vzdy funkcni */ int drak_reset (int fd) { posli_instrukci (reset_pristroje, fd); sleep (2); return (0); } /* Inicializace a spusteni kontinualniho mereni */ int main (void) { int fd; sleep (0); fd = open_port (); nastav_port (fd); drak_reset (fd); posli_instrukci (nastav_rozsah_plus_minus_0_625, fd); kontin_drak ('-', .625, fd); close (fd); return (0); }