// HFV - High Frequency Voltmeter - Firmware
// (c)miho 2002
//
// Historie:
//
// 0.00 Uvodni verze
#define VERSION "0.00"
// Zakladni nastaveni prekladace
//
#include <16F876.h>
#device ADC=10
#use delay(clock=4000000)
#fuses XT,NOWDT,NOBROWNOUT,NOLVP
#case
// Matematicka knihovna
//
#include "MATHA.C"
// Knihovna pro LCD display
//
#define LCD_RS PIN_B2 // rizeni registru LCD displeje
#define LCD_E PIN_B1 // enable LCD displeje
#define LCD_DATA_LSB PIN_C2 // pripojeni LSB bitu datoveho portu LCD displeje (celkem 4 bity vzestupne za sebou)
#include "LCD.C"
// Knihovna pro obsluhu tlacitek
//
#include "KBD_B4.C"
// Knihovna pro pristup do pameti EEPROM
//
#include <EEPROM.C>
// Casova smycka pro zakladni cyklus obsluhy
//
// Predpoklada pripojeni krystalu 32768Hz na TIMER1, slouzi pro definovani delky intervalu
// spanku.
//
#define IPS 64 // pocet preruseni za sekundu od casovace 1
#define TIMERXTAL 32768 // frekvence krystalu casovace 1
BOOLEAN Timer1; // semafor nastavovany pri vstupu do preruseni od casovace 1
long int TimerCounter; // pomocna promenna pro odmerovani spozdeni
#int_timer1
void IntTimer1()
{
Timer1=TRUE; // bylo peruseni od timeru 1
if (TimerCounter>0) TimerCounter--; // zmensi pomocny citac
set_timer1(-TIMERXTAL/IPS); // znovu natahni Timer 1
if (kbd_timer!=0 && kbd_state==0) // kbd_k4.c
{ // kbd_k4.c
kbd_timer--; // kbd_k4.c
} // kbd_k4.c
}
// Kalibracni konstanty (nactene z EEPROM)
//
long int VREF;
float K1, K2;
#define EE_SUMA 0 // int8 kontrolni suma
#define EE_VREF 1 // int16 napeti reference v mV
#define EE_K1 3 // float kalibracni konstanta K1
#define EE_K2 7 // float kalibracni konstanta K2
#define EE_MEMORY 11 // int16 zde zacinaji pametove bunky
#define VREF_LOW 2000 // spodni mez platneho VREF
#define VREF_HIGH 6000 // horni mez platneho VREF
#define VREF_DEFAULT 3735 // defaultni hodnota napeti reference
#define VREF_STEP 5 // krok pro nastavovani hodnoty VREF pri kalibraci
// Mereni napeti baterie
//
#define HFV_ENABLE PIN_A5 // zapinani detekcni sondy
float Read_Vdd()
{
long int Vdd;
setup_adc(ADC_CLOCK_INTERNAL); // zapni prevodnik
setup_adc_ports(RA0_RA1_RA3_ANALOG); // reference je Vdd
set_adc_channel(3); // nastav mereni RA3 - reference
delay_us(20); // pockej na ustaleni
Vdd=read_adc(); // precti hodnotu
setup_adc(ADC_OFF); // vypni prevodnik
return ((float)VREF*1.023)/Vdd; // prepocti hodnotu na volty
}
// Mereni napeti na vystupu sondy (napeti umerne logaritmu amplitudy signalu)
// Pozor mereni se musi provadet pravidelne a dosatatecne casto (asi 50x za sekundu)
// aby se v pauzach nevybily kondenzatory
//
#DEFINE MULT_FACTOR 10
signed long int read_hfv()
{
int i; // pocitadlo opakovani mereni
signed long int Hfv; // vysledek
Hfv=0; // nuluj stradac
for (i=MULT_FACTOR;i!=0;i--) // oapkovani
{
output_high(HFV_ENABLE); // zapni sondu
delay_us(400); // pockej na jeji aktivaci
setup_adc(ADC_CLOCK_INTERNAL); // nastav prevodnik
setup_adc_ports(RA0_RA1_ANALOG_RA3_REF);
set_adc_channel(0); // vyber kanal
delay_us(20); // pockej na ustaleni
Hfv+=read_adc(); // precti hodnotu
output_low(HFV_ENABLE); // odpoj sondu
setup_adc(ADC_OFF); // vypni prevodnik
sleep(); // prodleva
}
return Hfv;
}
// Spocitej kontrolni soucet EEPROM, casti s kalibracnimi konstantami
//
int Suma()
{
unsigned int Adr;
int Sum;
Sum=0;
for (Adr=0; Adr<EE_MEMORY; Adr++)
{
Sum += read_eeprom(Adr);
}
return Sum;
}
#define KLEVEL_HIGH_MAX 20
#define KLEVEL_HIGH_MIN -50
#define KLEVEL_HIGH_START 0
#define KLEVEL_LOW_MAX -30
#define KLEVEL_LOW_MIN -90
#define KLEVEL_LOW_START -60
#define KLEVEL_STEP 10
// Proved kalibraci
//
void Callibrate(BOOLEAN Requested)
{
char c;
signed int L1,L2;
signed int16 A1,A2;
printf(lcd_putc,"\f\nESC \20 \21 OK");
// kalibrace VREF
//
do
{
printf(lcd_putc,"\rCAL Vref: %4ldmV",VREF);
c=kbd_waitc();
if (c==KBD_K1)
{
reset_cpu();
}
if (c==KBD_K2)
{
if (VREF<=VREF_HIGH-VREF_STEP) VREF += VREF_STEP;
}
if (c==KBD_K3)
{
if (VREF>=VREF_LOW+VREF_STEP) VREF -= VREF_STEP;
}
}
while (c!=KBD_K4);
EE_WR(EE_VREF, VREF);
if (!Requested)
{
write_eeprom(EE_SUMA,read_eeprom(EE_SUMA)-Suma()); // dopocti kontrolni soucet a uloz ho
}
// Kalibrace High urovne
//
L1=KLEVEL_HIGH_START;
do
{
printf(lcd_putc,"\rCAL High: %3ddBV",L1);
c=kbd_waitc();
if (c==KBD_K1)
{
reset_cpu();
}
if (c==KBD_K2)
{
if (L1<=KLEVEL_HIGH_MAX-KLEVEL_STEP) L1 += KLEVEL_STEP;
}
if (c==KBD_K3)
{
if (L1>=KLEVEL_HIGH_MIN+KLEVEL_STEP) L1 -= KLEVEL_STEP;
}
}
while (c!=KBD_K4);
for (c=10;c>0;c--) A1 = read_hfv();
// Kalibrace Low urovne
//
L2=L1-60;
do
{
printf(lcd_putc,"\rCAL Low: %3ddBV",L2);
c=kbd_waitc();
if (c==KBD_K1)
{
reset_cpu();
}
if (c==KBD_K2)
{
if (L2<=L1-2*KLEVEL_STEP) L2 += KLEVEL_STEP;
}
if (c==KBD_K3)
{
if (L2>=KLEVEL_LOW_MIN+KLEVEL_STEP) L2 -= KLEVEL_STEP;
}
}
while (c!=KBD_K4);
for (c=10;c>0;c--) A2 = read_hfv();
// Vypocti kalibracni konstanty a uloz je do EEPROM
//
K1 = (float)(L2-L1) / (float)(A2-A1); // vypocti K1 (strmost)
K2 = ((float)L1*A2 - (float)L2*A1) / (float)(A2-A1); // vypocti K2 (posunuti)
EE_WR(EE_K1, K1); // uloz K1 do EEPROM
EE_WR(EE_K2, K2); // uloz K2 do EEPROM
write_eeprom(EE_SUMA,read_eeprom(EE_SUMA)-Suma()); // dopocti kontrolni soucet a uloz ho
//printf(lcd_putc,"\fL1 %d L2 %d\nA1 %ld A2 %ld",L1,L2,A1,A2);
//kbd_waitc();
//printf(lcd_putc,"\fK1 %f\nK2 %f",K1,K2);
//kbd_waitc();
}
#include "knob.c"
#define WARNINGVOLTAGE 4.75 // hranice pro varovani vybite baterie
void main()
{
int c;
int i;
int Mode;
// Inicializace nevyuzitych pinu
//
//output_low(PIN_A0); // zde je analogovy vstup
// output_low(PIN_A1); // zde je otocny knoflik
// output_low(PIN_A2); // zde je otocny knoflik
//output_low(PIN_A3); // zde je napetova refence
output_low(PIN_A4);
output_low(PIN_A5); // zde je rizeni
// output_low(PIN_B0); // zde je RTS#
//output_low(PIN_B1); // LCD_E
//output_low(PIN_B2); // LCD_RS
// output_low(PIN_B3); // zde je CTS#
//output_low(PIN_B4); // tlaciko 1
//output_low(PIN_B5); // tlaciko 2
//output_low(PIN_B6); // tlaciko 3
//output_low(PIN_B7); // tlaciko 4
//output_low(PIN_C0); // xtal 32768Hz
//output_low(PIN_C1); // xtal 32768Hz
//output_low(PIN_C2); // LCD D4 (LSB)
//output_low(PIN_C3); // LCD D5
//output_low(PIN_C4); // LCD D6
//output_low(PIN_C5); // LCD D7
output_low(PIN_C6); // RS232 TX
output_low(PIN_C7); // RS232 RX
// Zakladni vypis
//
lcd_init();
printf(lcd_putc,"\fHF Vmeter " VERSION);
delay_ms(100); // cas pro ustaleni napajeni
lcd_define_char(0,LCD_CHAR_UP LCD_CHAR_DOWN); // Znaky sipka nahoru a sipka dolu od pozice 0
// Inicializace zakladni casovaci smycky casovane pomoci preruseni od casovace 1
//
Timer1=FALSE; // inicializuj pocitadla
TimerCounter=0;
setup_timer_1(T1_EXTERNAL | T1_CLK_OUT | T1_DIV_BY_1); // nastav TIMER1 jako 32768Hz oscilator
set_timer1(-TIMERXTAL/IPS); // definuj casovy interval tak, aby bylo IPS opakovani za sekundu
enable_interrupts(INT_TIMER1); // povol preruseni
enable_interrupts(GLOBAL); // povol globalni preruseni
// Inicializace obsluhy klavesnice
//
kbd_init(); // inicializuj klavesnici
knob();
// Nacteni kalibracnich hodnod z EEPROM
//
EE_RD(EE_VREF, VREF);
EE_RD(EE_K1, K1);
EE_RD(EE_K2, K2);
if (VREF<VREF_LOW || VREF>VREF_HIGH)
{
VREF = VREF_DEFAULT;
}
// Kontrola kontrolniho souctu EEPROM
//
if (Suma()) // spocitej kontrolni soucet EEPROM (jen kalibracni konstanty)
{
printf(lcd_putc,"\nERR: Bad EEPROM"); // chyba EEPROM
kbd_waitc(); // uzivatel potvrdi
Callibrate(TRUE); // spust kalibraci s priznakem vnucene kalibrace
}
// Mereni napajeciho napeti
//
{
BOOLEAN Wait;
float Vdd;
TimerCounter=3*IPS; // timeout 3 sekundy
Wait=FALSE; // Priznak, ze se ma cekat na klavesu
do
{
Vdd=Read_Vdd(); // precti hodnotu
if (Vdd>=WARNINGVOLTAGE) // otestuj zda je dostatecne napajeni
{
printf(lcd_putc,"\nVdd: %1.2fV",Read_Vdd()); // je O.K.
}
else
{
printf(lcd_putc,"\fBattery Low\nVdd: %1.2fV",Read_Vdd()); // baterie je slaba
Wait=TRUE; // a budeme cekat na reakci uzivatele
}
sleep(); // usni
if (!Wait && kbd_getc()) Wait=TRUE; // pokud nebyla podminka wait a byla klavesa budeme cekat
if (Wait && kbd_getc()) break; // pokud jiz cekame cekani ukoncime pri stisku klavesy
}
while (TimerCounter || Wait); // mer dokud neni zmacknuta klavesa nebo dokud nevyprsi timeout
}
// Hlavni smycka zpracovani
//
#define MODE_MIN 0
#define MODE_MAX 2
Mode=MODE_MIN;
for (;;)
{
printf(lcd_putc,"\f\nMW \20MODE\21 CFG"); // smaz displej a definuj stavovou radku
do
{
float RES;
long int HFV;
HFV = read_hfv();
RES = K1*HFV+K2;
if (Mode==0) printf(lcd_putc,"\rLEVEL: %3.1f dB",RES); // mer a zobrazuj dBV
if (Mode==1) printf(lcd_putc,"\rLEVEL: %03.3e V",expdb(RES)); // mer a zobrazuj V
if (Mode==2) printf(lcd_putc,"\rLEVEL: %ld RAW",HFV); // mer a zobrazuj primo vystup prevodniku
}
while (!kbd_key); // dokud uzivatel neco nezmackne
i=kbd_getc();
if (i==KBD_K1) {};
if (i==KBD_K2) { if (Mode<MODE_MAX) Mode++; };
if (i==KBD_K3) { if (Mode>MODE_MIN) Mode--; };
if (i==KBD_K4) { };
}
}
//Callibrate(FALSE);
//Spravny postup co nejkratsi smycky (vede na instrukci DECFSZ)
//
// i=12;
// do
// lcd_putc(i);
// while (--i);
//#ifdef SHRT
//#rom 0x2100={0x36, 0x97, 0x0E, 0x78, 0x78, 0x2E, 0x04, 0x85, 0xD3, 0x76, 0x35}
//#endif
// If you need to use any pin on any port use:
// *(pin_to_use/8|0x80) &= ~(1<<(pin_to_use&7)); // **
// *(pin_to_use/8) |= (1<<(pin_to_use&7));
// In all cases pin_to_use is the normal PIN_A0... defines.
|