⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 v_ref_2.c

📁 Low End Microchip PICs C函数
💻 C
字号:
// V_REF_2.C - PIC14000
//
//
// copyright, Peter H Anderson, Elmore, VT, June, '02

#case

#device PIC14000 *=16

#include <defs_14.h>
#include <delay.h>
#include <ser_14.h>

#define MAKE_LONG(h, l)  (((unsigned long) (h)) << 8) | (l)

#define TRUE !0
#define FALSE 0

#define TxData 2	// PORTC, Bit 2
#define INV

#define CERDIP2

#define AN1_IN 0x10
#define BG_IN 0x40
#define REFHI_IN 0x50
#define REFLO_IN 0x60
#define TEMP_IN 0x70
#define REFA 0x80
#define REFB 0x90

#define CURRENT28 0xb0

float set_vref(byte channel, float vref_val);
byte increment_vref_setting(byte x);
byte decrement_vref_setting(byte x);

float ad_meas(byte channel, byte current_source);

void display_calibration(void);

unsigned long ad_integrate(byte channel, byte current_source);
void read_calibration_float(unsigned long adr, float *p_float);

byte ad_int_occ, adov_int_occ, default_int_occ;	// global variables for interrupt

void main(void)
{
   float v;
   ser_init();
   display_calibration();

   while(1)
   {
      ser_char(0x0c);
      v = set_vref(REFA, 0.535);
      printf(ser_char, "REFA = %f", v);
      ser_new_line();
      v = set_vref(REFB, 0.40);
      printf(ser_char, "REFB = %f", v);
      ser_new_line();
      delay_ms(5000);
   }
}


float set_vref(byte channel, float vref_val)
{

	byte x, too_high, too_low, too_high_prev, too_low_prev;
   float v;

   cmoff = 0;


	if (vref_val > 0.55)
	{
		x = ((byte) ((vref_val - 0.55)/0.05) + 0x0a) * 8;
	}
	else if (vref_val < 0.45)
	{
		x = ((byte) ((0.45 - vref_val) / 0.05) + 0x0a) * 8 + 0x80;
	}

	else if (vref_val >=0.5)
	{
		x = ((byte) ((vref_val - 0.5) / 0.005)) * 8;
	}

	else
	{
		x = ((byte) ((0.5 - vref_val) / 0.005)) * 8 + 0x80;
	}


	if (channel == REFA)
	{
      cmaoe = 1;
		PREFA = x;
	}

	else
	{
      cmboe = 1;
		PREFB = x;
	}

	// do a measurement. if too small ++PREF, if too large --

	too_high_prev = FALSE;
	too_low_prev = FALSE;

	while(1)
	{

	   v = ad_meas(channel, CURRENT28);

	   if (v > vref_val)
	   {
		   x = decrement_vref_setting(x);
	   	   too_high = TRUE;
		   too_low = FALSE;
	   }
	   else
	   {
		   x = increment_vref_setting(x);
		   too_high = FALSE;
		   too_low = TRUE;
	   }

	   if ( ((too_high) && (too_low_prev)) || ((too_low) && (too_high_prev)) )
	   {
		   return(v);
	   }

	   else
	   {
		   too_high_prev = too_high;
		   too_low_prev = too_low;
	   }

      printf(ser_char, "%2x", x);
      ser_new_line();
      delay_ms(1000);

	   	if (channel == REFA)
	   	{
	   		PREFA = x;
	   	}

	   	else
	   	{
	   		PREFB = x;
	    }
   }
}

byte increment_vref_setting(byte x)
{
   byte y;

   y = x & 0x07;
   ++y;
   y = y & 0x07;
   x = (x & 0xf8) | y;

   if (y)			// if least sig three bits non zero
   {
	   return(x);
   }
   else				// if zero, then kick up the coarse adjustment
   {
      if (x == 0x80)
      {
         x = 0x00;
      }

      else if ((x & 0x80) == 0)
      {
         x = x + 8;
      }

      else
      {
         x = x - 8;
      }

      return(x);
   }
}

byte decrement_vref_setting(byte x)
{
   byte y;

   y = x & 0x07;	// strip off low three bits
   --y;				// decrement
   y = y & 0x07;
   x = (x & 0xf8) | y;
   if (y != 0x07)
   {

	   return(x);
   }

   else
   {

      if (x == 0x00)
      {
         x = 0x80;
      }

      else if ((x & 0x80) == 0)
      {
         x = x - 8;
      }

      else
      {
         x = x + 8;
      }
      return(x);
   }
}

float ad_meas(byte channel, byte current_source)
{
    unsigned long Nin, Nbg, Nrefhi, Nreflo;
    float Noffset, Vin, Kref, Kbg;

    read_calibration_float(0x0fc0, &Kref);
    read_calibration_float(0x0fc4,&Kbg);

    Nin = ad_integrate(channel, CURRENT28);
    Nbg = ad_integrate(BG_IN, CURRENT28);
    Nrefhi = ad_integrate(REFHI_IN, CURRENT28);
    Nreflo = ad_integrate(REFLO_IN, CURRENT28);

    Noffset = (float) Nreflo - Kref * (float) (Nrefhi - Nreflo);
    Vin = ((float) Nin - Noffset) / ( (float) Nbg - Noffset) * Kbg;
    return(Vin);
}

unsigned long ad_integrate(byte channel, byte current_source)
{
	unsigned long ret_val;

	refoff = 0;  adoff = 0; 	// turn on band gap reference and turn on A/D

    ADCON0 = (ADCON0 & 0x0f) | (channel);
    ADCON1 = (ADCON1 & 0x0f) | (current_source);

    pcfg3 = 0; pcfg2 = 0;	// portd configured as analog
    pcfg1 = 0; pcfg0 = 0;	// porta configured as analog

    amuxoe = 0;	// no output on AN0
    adzero = 0;
	adrst = 1;	// discharge the integrating cap - 200 us delay required
    delay_ms(1);

    ADTMRH = 0x00;
    ADTMRL = 0x00;

    ad_int_occ = FALSE;
    adov_int_occ = FALSE;
    default_int_occ = FALSE;

    ovfif = 0;  adcif = 0;	// kill any pending interrupts
    ovfie = 1; adcie = 1; peie = 1; gie = 1;

    adrst = 0;

    while(1)
    {
		if (ad_int_occ)
		{
			while(gie)
			{
				gie = 0;
			}
			adcif = 0;
			ret_val = MAKE_LONG(ADCAPH, ADCAPL);
			break;
		}

		if (adov_int_occ)
		{
			while(gie)
			{
				gie = 0;
			}
			ovfif = 0;
			ret_val = 0xffff;
			break;
		}

      if (default_int_occ)
      {
			while(gie)
			{
				gie = 0;
			}
			ret_val = 0x0000;
			break;
		}
	}
   peie = 0;  ovfie = 0;  adcie = 0;	// clean up
   adrst = 1;	// discharge
   return(ret_val);
}

void display_calibration(void)
{

    float Kref, Kbg, Vtherm, Ktc;

    lcd_cursor_pos(0, 0);
    printf(ser_char, "Calibration");

    lcd_cursor_pos(1, 0);	// fetch and display the calibration constants
    read_calibration_float(0x0fc0, &Kref);
    printf(ser_char, "%3.4f", Kref);

    lcd_cursor_pos(1, 10);
    read_calibration_float(0x0fc4,&Kbg);
    printf(ser_char, "%3.4f", Kbg);

    lcd_cursor_pos(2, 0);
    read_calibration_float(0x0fc8, &Vtherm);
    printf(ser_char, "%3.4f", Vtherm);

    lcd_cursor_pos(2, 10);
    read_calibration_float(0x0fcc, &Ktc);
    printf(ser_char, "%3.4f", Ktc);

    delay_ms(5000);
}

void read_calibration_float(unsigned long adr, float *p_float)
{
#ifdef CERDIP1
   const byte cal[16] = {0x7c, 0x00, 0x94, 0x5a, 0x7f, 0x18, 0x14, 0xa8,
                         0x7f, 0x0d, 0xf7, 0x55, 0x76, 0x68, 0xa6, 0xe4};

#endif

#ifdef CERDIP2
   const byte cal[16] = {0x7c, 0x01, 0xd4, 0x76, 0x7f, 0x1a, 0xd7, 0xae,
                         0x7f, 0x04, 0xf0, 0x3d, 0x76, 0x69, 0x0e, 0x5b};
#endif

#ifdef CERDIP3
   const byte cal[16] = {0x7c, 0x02, 0x17, 0xa5, 0x7f, 0x17, 0x52, 0xf6,
                         0x7f, 0x08, 0xc8, 0x42, 0x76, 0x77, 0xe6, 0x50};
#endif

   byte n, array[4];
#ifndef PRODUCTION

   for (n=0; n<4; n++)
   {
      array[n] = cal[adr - 0xfc0 + n];
   }
#else // Production

   for (n=0; n<4; n++)
   {
      array[n] = read_calibration(adr- 0xfc0 + n);	// fetch each byte in turn into a byte array
   }
#endif
   *p_float =  *((float *) array);	// copy the array to a float
}

#int_ad
ad_int_handler(void)
{
	ad_int_occ = TRUE;
}

#int_adof
adof_int_handler(void)
{
	adov_int_occ  = TRUE;
}

#int_default
default_int_handler(void)
{
   default_int_occ = TRUE;
}

#include <delay.c>
#include <ser_14.c>


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -