// SWR/Wattmeter Project Using C // The programmer is a PICSTART Plus, and the microcontroller is a PIC16F72. // This program was created and uploaded into the microcontroller with MPLAB v8.10 and HI-TECH C PRO v9.60PL3 (free version) for the PIC-10-12-16 MCU Family v9.60PL3. // The OS is Windows XP. HI-TECH C PRO v9.60PL3 does not work with Windows 98. // The wattmeter display parameters: // LED A/D range VF2 range Approx. Power Power Output Range LED color // D11 8-10 .32-.45V .28W .20-.40W blue/green // D12 11-15 .45-.63V .56W .40-.79W blue/green // D13 16-22 .63-.89V 1.1W .79-1.6W blue/green // D14 23-31 .89-1.3V 2.2W 1.6-3.2W blue/green // D15 32-44 1.3-1.8V 4.5W 3.2-6.3W blue/green // D16 45-63 1.8-2.5V 8.9W 6.3-13W blue/green // D17 64-89 2.5-3.5V 18W 13-25W blue/green // D18 90-127 3.5-5.0V 35W 25-50W blue/green // D19 128-179 5.0-7.1V 71W 50-100W yellow // D20 180-255 7.1-10V >100W 100-200W red // The SWR meter display parameters: // LED Reflection ratio range Approx. SWR SWR range LED color // D1 0 to 1/9 1.1 1.00 to 1.25 blue/green // D2 1/9 to 2/9 1.4 1.25 to 1.57 blue/green // D3 2/9 to 1/3 1.8 1.57 to 2.0 blue/green // D4 1/3 to 4/9 2.3 2.0 to 2.6 yellow // D5 4/9 to 5/9 3 2.6 to 3.5 yellow // D6 5/9 to 2/3 4 3.5 to 5 yellow // D7 2/3 to 7/9 6 5 to 8 red // D8 7/9 to 8/9 11 8 to 17 red // D9 8/9 to 1 35 >17 red // D10 >1 infinity infinity red // All of the LEDs in the SWR meter and wattmeter displays remain dark when transmitted power is under 200mW. // Port A pin 4 is different from all of the other pins, because it is an open port pin. // I couldn't find a way to control the corresponding LED D5 through the PORT value, // so I am using the TRIS value to control the impedance. Note also that this pin is // connected to 5V instead of ground through the series resistor and LED. // This program uses 3EBh/800h (1003/2048, 49.0%) words of program space. // This program uses Bh/80h (11/128, 8.6%) bytes of data space. // The files stdlib.h and pic.h need to be included in the list of header files shown in the workspace window. // These files are in the C:\Program Files\HI-TECH Software\PICC\PRO\9.60\include directory. #define __16F72 #include #include __CONFIG (XT&WDTDIS&PWRTDIS&BORDIS&UNPROTECT); // Set the configuration bits: // XT=crystal oscillator, WDTDIS=Watchdog Timer disabled, PWRTDIS=Power Up Timer disabled, BORDIS=Brown Out Detector disabled, UNPROTECT=code is unprotected // Go to Configure->Configuration Bits to confirm configuration bits. // The crystal is a 3.579545 MHz crystal resonator. unsigned char fwd, refl, ninths, count, prod_1, prod_256; void start(void) { RP1=0; RP0=1; // Select Register Bank 01. TRISA=0b00000011; // Set pins RA5, RA4, RA3, and RA2 as outputs and pins AN1 and AN0 as inputs. TRISB=0b00000000; // Set RB7-RB0 pins as outputs. TRISC=0b00000000; // Set RC7-RC0 pins as outputs. ADCON1=0b00000100; // RA0 and RA1 are analog. // Because RA3 is an output, the digital output will be converted to an analog value. RP0=0; // Select Register Bank 00. GIE=0; // Disable Global Interrupt } void delay_10_usec (void) { count=0; while (count<143) { // One instruction takes up 1/4 of a clock cycle (69.8 nsec given a 3.57945 MHz crystal resonator). 143 instructions take 10 usec. count++; } } void delay_1_msec (void) { count=0; while (count<100) { delay_10_usec(); // 100 delays of 10 usec each. count++; } void get_fwd(void) // Get the analog input representing forward voltage and store the result in the function fwd. { RP1=0; RP0=1; // Select Register Bank 1. ADCON1=0b00000100; // V_REV=V_DD; RA0, RA1, and RA3 are analog; RA2 and RA5 are digital RP1=0; RP0=0; // Select Register Bank 0. ADCON0=0b10000001; // A/D conversion clock rate of FOSC/32, Channel 0 (RA0), A/D conversion not in progress, A/D converter module operating // Bits 5-3: select channel // Bit 2 (A/D conversion status bit, ADGO): 0=A/D conversion not in progress, 1=A/D conversion in progress // Bit 0 (A/D on bit, ADON): 0=A/D converter module not operating, 1=A/D converter module operating delay_10_usec; // Let the A/D converter module continue operating for 20 usec. ADGO=1; // Start the A/D conversion process while (ADGO==1) // Continue to keep the A/D converter active until the A/D conversion process completes. {} fwd=ADRES; // fwd=the result of the A/D conversion=V_F_2*255/10V RP1=0; RP0=1; // Select Register Bank 1 ADCON1=0b00000111; // V_REF=V_DD; RA0, RA1, RA2, RA3, and RA5 are digital RP1=0; RP0=0; // Select Register Bank 0. // Place break point here and provide value for fwd in watch window. } void clear_displays (void) { RA5=0; RC0=0; RC1=0; RC2=0; RC3=0; RB0=0; RC7=0; RC6=0; RC5=0; RC4=0; // Turn off LEDs D11-D20, respectively. RB7=0; RB6=0; RA2=0; RA3=0; // Turn off LEDs D1-D4, respectively. RP1=0; RP0=1; // Select Register Bank 1. TRISA4=1; // Port A pin 4 is now an input pin. This means high impedance, low current, and a dark LED D5. RP1=0; RP0=0; // Select Register Bank 0. RB5=0; RB4=0; RB3=0; RB2=0; RB1=0; // Turn off LEDs D6-D10, respectively. } void displaywatt(void) { if (fwd>=180) {RC4=1;} else if (fwd>=128) {RC5=1;} else if (fwd>=90) {RC6=1;} else if (fwd>=64) {RC7=1;} else if (fwd>=45) {RB0=1;} else if (fwd>=32) {RC3=1;} else if (fwd>=23) {RC2=1;} else if (fwd>=16) {RC1=1;} else if (fwd>=11) {RC0=1;} else {RA5=1;} } void get_refl(void) { RP1=0; RP0=1; // Select Register Bank 1. ADCON1=0b00000100; // RA0 and RA1 are analog. RP1=0; RP0=0; // Select Register Bank 0. ADCON0=0b10001001; // A/D conversion clock rate of FOSC/32, Channel 1 (RA1), A/D conversion not in progress, A/D converter module operating // Bits 5-3: select channel // Bit 2 (A/D conversion status bit, ADGO): 0=A/D conversion not in progress, 1=A/D conversion in progress // Bit 0 (A/D on bit, ADON): 0=A/D converter module not operating, 1=A/D converter module operating delay_10_usec; // Let the A/D converter module continue operating for 20 usec. ADGO=1; // Start the A/D conversion process while (ADGO==1) // Continue to keep the A/D converter active until the A/D conversion process completes. {} refl=ADRES; // refl=the result of the A/D conversion=V_R_2*255/10V RP1=0; RP0=1; // Select Register Bank 1 ADCON1=0b00000111; // RA2, RA3, RA4, and RA5 are digital. RP1=0; RP0=0; // Select Register Bank 0. // Place break point here and provide value for refl in watch window. } void get_refl_ratio(void) { // We already know that refl/fwd<1 at this point. // Now we only need to determine how many full units of 1/9 there are in this ratio. // refl/fwd=ninths/9, 9*refl=ninths*fwd, 9*refl-ninths*fwd=0 // ninths is maximum unsigned char for which 9*refl-ninths*fwd>=0 // prod=256*prod_256+prod_1 stores the result of the addition and subtraction operations in the process. prod_1=0; prod_256=0; count=0; ninths=0; while (count<9) { // Increment prod by refl. If prod_l+refl>255, then increment prod_256 by 1. if (prod_1>255-refl) {prod_256++;} prod_1=prod_1+refl; count++; } // Now prod=9*refl. Time to keep subtracting fwd from prod until prod0 | prod_1>=fwd) // This means prod>=fwd. The while loop is repeated until prod=8) // All LEDs remain dark unless transmitted power is >=200mW { displaywatt(); get_refl(); if (refl>=fwd) // refl/fwd>=1, SWR is infinite { RB1=1; // Light LED D10 } else // refl/fwd<1, SWR is finite { get_refl_ratio(); // We now have a value for ninths. This value (0-8) determines which SWR meter LED lights up. displayswr(); // This only applies for LEDs D1-D9. The case involving LED D10 is already covered. } } delay_1_msec; } }