pic16f688 voltmeter

Status
Not open for further replies.

mr farhan

New Member
hi anyone...

i want to use pic16f688 to make voltmeter. I found this coding The firmware is written and compiled with mikroC compiler. The code is here.

/*
Digital Voltmeter based on PIC16F688
Rajendra Bhatt, Oct 12, 2010
*/

// LCD module connections
sbit LCD_RS at RC4_bit;
sbit LCD_EN at RC5_bit;
sbit LCD_D4 at RC0_bit;
sbit LCD_D5 at RC1_bit;
sbit LCD_D6 at RC2_bit;
sbit LCD_D7 at RC3_bit;
sbit LCD_RS_Direction at TRISC4_bit;
sbit LCD_EN_Direction at TRISC5_bit;
sbit LCD_D4_Direction at TRISC0_bit;
sbit LCD_D5_Direction at TRISC1_bit;
sbit LCD_D6_Direction at TRISC2_bit;
sbit LCD_D7_Direction at TRISC3_bit;
// End LCD module connections

char Message1[] = "DVM Project";
unsigned int ADC_Value, DisplayVolt;
char *volt = "00.0";

void main() {
ANSEL = 0b00000100; // RA2/AN2 is analog input
ADCON0 = 0b00001000; // Analog channel select @ AN2
ADCON1 = 0x00;
CMCON0 = 0x07 ; // Disbale comparators
TRISC = 0b00000000; // PORTC All Outputs
TRISA = 0b00001100; // PORTA All Outputs, Except RA3 and RA2
Lcd_Init(); // Initialize LCD
Lcd_Cmd(_LCD_CLEAR); // CLEAR display
Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off
Lcd_Out(1,1,Message1);
Lcd_Chr(2,10,'V');

do {

ADC_Value = ADC_Read(2);
DisplayVolt = ADC_Value * 2;
volt[0] = DisplayVolt/1000 + 48;
volt[1] = (DisplayVolt/100)%10 + 48;
volt[3] = (DisplayVolt/10)%10 + 48;
Lcd_Out(2,5,volt);
delay_ms(100);
} while(1);

}

How to use this coding to PIC C compiler? Anyone please help me.
 
Good day, mr farhan and rajbex

I would also like to know how the above code would change when using in PIC C Compiler please.
If anyone here found out recently, please let me know...
 
I love Mr. Bhatt's blog but I've always thought it was ironic to host a blog with projects for hobbyists that used a rather expensive C compiler (lol).

Have you Gentlemen considered simply re-writing the program in your favorite version of C? It's a relatively simple program. If it helps, here's my (untested) interpretation of Mr. Bhatt's program using the free/lite version of BoostC (no hidden libraries required).

Good luck & best wishes. Regards, Mike

Code:
  /******************************************************************
   *                                                                *
   *  Project: Raj Voltmeter                                        *
   *   Source: Raj_Voltmeter.c                                      *
   *   Author: Mike McLaren, K8LH                                   *
   *     Date: 03-Aug-12                                            *
   *  Revised: 03-Aug-12                                            *
   *                                                                *
   *  16F688 + HD44780 2x16 LCD Voltmeter Experiment based on a     *
   *  project from Rajendra Bhatt's 'Embedded-Lab.com' blog.        *
   *                                                                *
   *                                                                *
   *      IDE: MPLAB 8.84 (tabs = 4)                                *
   *     Lang: Sourceboost BoostC v7.05, Lite/Free version          *
   *                                                                *
   ******************************************************************/

   #include <system.h>

   #pragma DATA _CONFIG, _WDT_OFF & _INTOSCIO

   #pragma CLOCK_FREQ 8000000   // 8-MHz INTOSC

  /******************************************************************
   *  function prototypes                                           *
   ******************************************************************/
  /******************************************************************
   *  variables                                                     *
   ******************************************************************/

   char *volt = "00.0 V";       //
   int input;                   // adc voltage reading

  /******************************************************************
   *  defines                                                       *
   ******************************************************************/

   #define line1 0x80           // lcd ddram address for line 1
   #define line2 0xC0           // lcd ddram address for line 2

   #define lcd_d4 portc.0       // RC0
   #define lcd_d5 portc.1       // RC1
   #define lcd_d6 portc.2       // RC2
   #define lcd_d7 portc.3       // RC3
   #define lcd_rs portc.4       // RC4
   #define lcd_e portc.5        // RC5

  /******************************************************************
   *  low level drivers & functions                                 *
   ******************************************************************/

   void PutNyb(char work)       // write nibble
   { lcd_d4 = work.4;           //
     lcd_d5 = work.5;           //
     lcd_d6 = work.6;           //
     lcd_d7 = work.7;           //
     lcd_e = 1; lcd_e = 0;      // strobe 'E' pin
     delay_us(160);             //
   }                            //

   void PutLCD(char work)       // write byte (two nibbles)
   { PutNyb(work);              // write hi nibble
     asm swapf  _work,F         // swap nibbles
     PutNyb(work);              // write lo nibble
   }                            //

   void PutCMD(char pdata)      // lcd command (RS=0)
   { lcd_rs = 0; PutLCD(pdata); //
   }                            //

   void PutDAT(char pdata)      // lcd data (RS=1)
   { lcd_rs = 1; PutLCD(pdata); //
   }                            //

   void PutDAT(char* pdata)     // lcd data (RS=1) strings
   { char temp; char ndx = 0;   //
     while(temp = pdata[ndx])   //
       PutDAT(temp);            //
   }                            //

  /*                                                                *
   *  HD44780 "initialize by instruction" procedure for 4-bit mode  *
   *                                                                */
   void lcdinit()               //
   { delay_ms(100);             //
     lcd_rs = 0;                // RS=0 (command)
     PutNyb(0x30); delay_ms(4); // step 1 (required 4-ms delay)
     PutNyb(0x30);              // step 2 (built-in 160-us delay)
     PutNyb(0x30);              // step 3 (built-in 160-us delay)
     PutNyb(0x20);              // step 4 (built-in 160-us delay)
  /*                                                                *
   *  now in 4-bit interface mode and can write full 8-bit bytes    *
   *                                                                */
     PutCMD(0x28);              // 4-bit, 2-lines, 5x7 font
     PutCMD(0x0C);              // display on, currsor & blink off
     PutCMD(0x06);              // cursor inc, shift off
     PutCMD(0x01);              // clear display
     delay_ms(2);               // required delay
   }                            //

   int getadc(char channel)     // 
   { int result;                //
     adcon0.CHS0 = channel.0;   //
     adcon0.CHS1 = channel.1;   //
     adcon0.CHS2 = channel.2;   //
     adcon0.ADON = 1;           // turn ADC on
     delay_us(20);              //
     adcon0.GO_DONE = 1;        //
     while(adcon0.GO_DONE);     //
     adcon0.ADON = 0;           // turn ADC off
     result = adresh << 8;      //
     result |= adresl;          //
     return result;             // 0..1023
   }

  /******************************************************************
   *  main init                                                     *
   ******************************************************************/

   void main()                  //
   { 
     ansel = 0b00000100;        // RA2/AN2 analog, others digital
     adcon0 = 0b10000000;       // right justified adc result
     adcon1 = 0b01010000;       // Fosc/16 conversion clock
     cmcon0 = 0x07;             // disable comparators
     osccon = 0b01110000;       // INTOSC = 8-MHz
     while(osccon.HTS == 0);    // wait until osc stable
     trisa = 0b00001100;        // RA2(AN2) & RA3(MCLR) inputs
     trisc = 0b00000000;        // portc all outputs

     lcdinit();                 // init LCD in 4-bit interface mode
     PutDAT("DVM Project");     // 

  /******************************************************************
   *  main loop                                                     *
   ******************************************************************/

     do                         //
     { input = getadc(2);       // get adc reading, 0..1023
       input *= 2;              // scale to volts * 100
       input += 5;              // rounding (to 1/10th volt)

      /*                                                            *
       *  format the output and display on LCD                      *
       *                                                            */
       volt[0] = (input/1000) | '0';    // 'tens' digit
       volt[1] = (input/100)%10 | '0';  // 'ones' digit
       volt[3] = (input/10)%10 | '0';   // 'tenths' digit

       PutCMD(line2+5);         // line 2 tab 6
       PutDAT(volt);            // update LCD
       delay_ms(500);           // 500 msec update intervals
     } while(1);                // loop forever
   }                            //
 
Last edited:
Couldn't resist... Here's Hi-tech C version ( Hi-tech doesn't do bits... Unless you create a structure )
Code:
/******************************************************************
   *                                                                *
   *  Project: Raj Voltmeter                                        *
   *   Source: Raj_Voltmeter.c                                      *
   *      IDE: MPLAB 8.83 				                            *
   *     Lang: Hi-tech C, Lite/Free version        					*
   *                                                                *
   ******************************************************************/
 
   #include <htc.h>
 
   __CONFIG( WDTE_OFF & FOSC_INTOSCIO );
 
   #define _XTAL_FREQ 8000000   // 8-MHz INTOSC
 
  /******************************************************************
   *  function prototypes                                           *
   ******************************************************************/
  /******************************************************************
   *  variables                                                     *
   ******************************************************************/
 
   char volt[] = "00.0 V";      //
   int input;                   // adc voltage reading
 
  /******************************************************************
   *  defines                                                       *
   ******************************************************************/
 
   #define line1 0x80           // lcd ddram address for line 1
   #define line2 0xC0           // lcd ddram address for line 2
 
   #define lcd_rs RC4       // RC4
   #define lcd_e RC5        // RC5
 
  /******************************************************************
   *  low level drivers & functions                                 *
   ******************************************************************/
 
	void PutNyb(char work)       // write nibble
	{ 
	PORTC &= 0xf0;
	PORTC |= (work & 0xf);		//
	lcd_e = 1; 
	lcd_e = 0;					// strobe 'E' pin
	__delay_us(160);			//
	}							//
 
   void PutLCD(char work)       // write byte (two nibbles)
	{ 
	PutNyb((work >> 4) & 0xf);			// write hi nibble
    PutNyb(work & 0xf);				// write lo nibble
	}	
 
	void PutCMD(char pdata)		// lcd command (RS=0)
	{ 
	lcd_rs = 0; 
	PutLCD(pdata);				//
	}	
 
	void PutDAT(char pdata)      // lcd data (RS=1)
	{ 
	lcd_rs = 1; 
	PutLCD(pdata);				//
	}	
 
	void PutDATS(char* pdata)  // lcd data (RS=1) strings
	{ 
	while(*pdata != 0)			//
		PutDAT(*pdata++);		//
	} 	

	void PutDATRS(const char* pdata)  // lcd data (RS=1) strings
	{
	while(*pdata != 0)			//
		PutDAT(*pdata++);		//
	} 

  /*                                                                *
   *  HD44780 "initialize by instruction" procedure for 4-bit mode  *
   *                                                                */
	void lcdinit()               //
	{ 
	__delay_ms(100);             //
	lcd_rs = 0;                // RS=0 (command)
	PutNyb(0x2); 
	__delay_ms(4);				// step 1 (required 4-ms delay)
	PutNyb(0x2);				// step 2 (built-in 160-us delay)
	PutNyb(0x2);				// step 3 (built-in 160-us delay)
	/*                                                                *
	*  now in 4-bit interface mode and can write full 8-bit bytes    *
	*                                                                */
	PutCMD(0x28);				// 4-bit, 2-lines, 5x7 font
	PutCMD(0x0C);				// display on, currsor & blink off
	PutCMD(0x06);				// cursor inc, shift off
	PutCMD(0x01);				// clear display
	__delay_ms(2);				// required delay
	} 
 
	unsigned int getadc(char channel)	// 
	{ 
	unsigned int result;	
	ADCON0 = 0x80; 				// Right justified
	ADCON0 += channel<<2;		//
	ADON = 1;					// turn ADC on
	__delay_us(20);				//
	GO_DONE = 1;				//
	while(GO_DONE);				//
	ADON = 0;					// turn ADC off
	result = ADRESH << 8;		//
	result |= ADRESL;			//
	return result;				// 0..1023
	}
 
  /******************************************************************
   *  main init                                                     *
   ******************************************************************/
 
   void main()                  //
   { 
     ANSEL = 0b00000100;        // RA2/AN2 analog, others digital
     ADCON1 = 0b01010000;       // Fosc/16 conversion clock
     CMCON0 = 0x07;             // disable comparators
     OSCCON = 0b01110000;       // INTOSC = 8-MHz
     while(HTS == 0);    		// wait until osc stable
     TRISA = 0b00001100;        // RA2(AN2) & RA3(MCLR) inputs
     TRISC = 0b00000000;        // portc all outputs
 
     lcdinit();                 // init LCD in 4-bit interface mode
     PutDATRS("DVM Project");     // 
 
  /******************************************************************
   *  main loop                                                     *
   ******************************************************************/
 
     do                         //
     { input = getadc(2);       // get adc reading, 0..1023
       input *= 2;              // scale to volts * 100
       input += 5;              // rounding (to 1/10th volt)
 
      /*                                                            *
       *  format the output and display on LCD                      *
       *                                                            */
       volt[0] = (input/1000) | '0';    // 'tens' digit
       volt[1] = (input/100)%10 | '0';  // 'ones' digit
       volt[3] = (input/10)%10 | '0';   // 'tenths' digit
 
       PutCMD(line2+5);         // line 2 tab 6
       PutDATS(volt);            // update LCD
       __delay_ms(500);           // 500 msec update intervals
     } while(1);                // loop forever
   }                            //
 
Sure
Code:
HI-TECH C Compiler for PIC10/12/16 MCUs (Lite Mode)  V9.83
Copyright (C) 2011 Microchip Technology Inc.
(1273) Omniscient Code Generation not available in Lite mode (warning)

Memory Summary:
    Program space        used   2A7h (   679) of  1000h words   ( 16.6%)
    Data space           used    1Eh (    30) of   100h bytes   ( 11.7%)
    EEPROM space         used     0h (     0) of   100h bytes   (  0.0%)
    Configuration bits   used     1h (     1) of     1h word    (100.0%)
    ID Location space    used     0h (     0) of     4h bytes   (  0.0%)


Running this compiler in PRO mode, with Omniscient Code Generation enabled,
produces code which is typically 40% smaller than in Lite mode.
The HI-TECH C PRO compiler output for this code could be 264 words smaller.
See http://microchip.htsoft.com/portal/pic_pro for more information.

Also... ISIS doesn't like a 4 bit being intialised with 0x33... I use 0x22 and it works.... Just in case someone asked....
 
Last edited:
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…