// Program STOPKY pro mereni casu prujezdu mezi cidlama pro souteze solarnich robotu
//
// (c) miho 2004
//
// Historie
//
// 1.00 Uvodni verze
#define VER "1.00"
// Definice zakladnich parametru
//
#include <16F84.h> // procesor
#use delay(clock=4000000) // krystal
#use rs232(baud=9600, xmit=PIN_B4) // seriovka a jeji parametry
#fuses XT,PUT,NOWDT,NOPROTECT // prepinace
// Definice pro pripojeni LCD displeje
//
#define LCD_RS PIN_A2 // Signal RS
#define LCD_E PIN_A3 // Signal E
#define LCD_D0 PIN_A4 // Data
#define LCD_D1 PIN_B1
#define LCD_D2 PIN_B2
#define LCD_D3 PIN_B3
#include <LCD.C>
// Definice pro pripojeni vstupu (cidel)
//
#define BUTTON_START PIN_B7 // Tlacitko START
#define BUTTON_STOP PIN_B6 // Tlacitko STOP
#define BUTTON_TEST PIN_B5 // Tlacitko TEST pro prechod do testovaciho rezimu
// Defince pro pripojeni vystupu pro pipak
//
#define BEEP_PORT_P PIN_A0 // Piezo pipak pozitivni
#define BEEP_PORT_N PIN_A1 // Piezo pipak negativni
// Definice globalnich promennych
//
unsigned int Beep; // citac pulperiod pro pipnuti
short int Beep_state; // stav pipaku (0 nebo 1)
unsigned int State_run; // 0 .. klid
// 1 .. bezi mereni casu
// 2 .. cas zmereny
// Obsluha vstupu cidel
//
// Cas se meri od signalu na tlacitku START po signal na tlacitku STOP
// Signaly na tlacitkach vyvolaji preruseni a dojde k preklopeni stavu v promenne State_run
//
#int_RB
RB_isr()
{
if(State_run)
{
if(~input(BUTTON_STOP))
{
State_run=2; // Domereno
Beep=100;
disable_interrupts(INT_RB); // Zakaz vstup tlacitek aby byl cas na zpracovani
}
}
else
{
if(~input(BUTTON_START))
{
State_run=1;
Beep=100;
}
}
}
// Obsluha preruseni od casovace
//
unsigned int32 Time; // citac casu (perioda 256us)
#int_RTCC
RTCC_isr()
{
if(State_run==1) Time++; // zvetsi citac
if(Time==(3600000000>>8)) Time=0; // Osetreni preteceni po 1 hodine
if(Beep) // pokud se ma pipnout pipni
{ // Beep je pocet pulperiod
Beep--;
output_bit(BEEP_PORT_P,Beep_state);
Beep_state=~Beep_state;
output_bit(BEEP_PORT_N,Beep_state);
}
}
// Obsluha vystupu a jeho presmerovani na LCD a RS232
//
int PutCharMode;
#define LCD 1
#define RS232 2
void PutChar(char c)
{
if(PutCharMode & LCD) LCD_Putc(c);
if(PutCHarMode & RS232) putc(c);
}
// Vypis casu - dlouhy program ale jen na jedinem miste
//
void DisplayCas()
{
int32 xTime;
// Tisk vysledku v ms
// printf(PutChar,"Cas:%8lums\n\r",(Time<<8)/1000);
// Tisk vysledku v s
xTime=(Time<<8)/1000;
printf(PutChar,"Cas:%4lu.%03lus\n\r",xTime/1000,xTime%1000);
}
// Testovaci rezim
//
void TestMode()
{
int T;
// Otestuj tlascitko TEST
if(input(BUTTON_TEST)) return;
// Vypis na displej
printf(LCD_Putc,"\fTest Mode\n");
for(;1;)
{
T=0;
if(~input(BUTTON_START)) T+=1;
if(~input(BUTTON_STOP)) T+=2;
printf(LCD_putc,"\n%d",T);
if(T)
{
if(T==3) T=4;
output_bit(BEEP_PORT_P,0);
output_bit(BEEP_PORT_N,1);
delay_ms(T);
output_bit(BEEP_PORT_P,1);
output_bit(BEEP_PORT_N,0);
delay_ms(T);
}
}
}
// Hlavni program
//
void main()
{
// Inicializace LCD displeje
lcd_init();
PutCharMode=LCD|RS232;
printf(PutChar,"\n\rStopky v."VER"\r\n(c) miho 2004\n\r");
delay_ms(100);
// Inicializace stavovych promennych
State_run=0; // stopky stoji
// Inicializace vstupu (preruseni od zmeny stavu)
input(BUTTON_START); // precti RB aby se inicializoval registr zmen RB
port_b_pullups(TRUE); // zapni pull up odpory
// Testovaci mod
TestMode();
// Inicializace casovace pod prerusenim
setup_counters(RTCC_INTERNAL,WDT_18MS); // Perioda je 256 instrukcnich taktu
// Hlavni smycka porad dokola
for(;1;)
{
// Nuluj citace
Time=0; // nulovy cas
Beep=0; // nepipej
State_run=0;
// Povoleni preruseni
enable_interrupts(INT_RTCC); // povol preruseni od casovace
enable_interrupts(INT_RB); // povol preruseni od zmeny portu RB
enable_interrupts(global); // povol preruseni
// Cekej az se zacne merit
for(;State_run==0;)
{
}
// Prubezne vypisuj cas
PutCharMode=LCD; // vystup jen na LCD
for(;State_run==1;)
{
DisplayCas();
}
// Vypis vysledny cas - na LCD hned
DisplayCas();
// Vypis vysledny cas - na RS232 az po pipnuti
delay_ms(100); // ted se pod prerusenim pipa
PutCharMode=RS232;
disable_interrupts(global); // zakaz preruseni (aby fungovalo casovani seriovky)
DisplayCas();
enable_interrupts(global); // opet povol preruseni
}
}