DS1867 Dual Pot (EEPROM)


The DS1867 Dual Pot is discussed in the context of the BASIC Stamp 2 and Microchip assembly elsewhere on this web site.


// DS1867.C  (CCS PCM, PIC16F84)
//
// DS1867 Dual Digital Potentiometer with EEPROM
//
// Illustrates how to set the two potentiometers and how to read
// them.
//
// Sets Stack bit to 0, Pot 1 to 80 (hex) and Pot 0 to 40H.
// Then reads pot settings and displays in hexadecimal on LCD on
// RA.0.
//
//	PIC16F84		      DS1867
//
//	RB2, term 8 ----------------> DQ, term 8
//	RB1, term 7 ----------------> CLK, term 6
//	RB0, term 6 ----------------> RST, term 5
//
//				  Terminal 9 connected to 8 through
//			          22K limiting resistor
//
// copyright, Peter H. Anderson, Baltimore, MD, Apr, '99

#case
#include <16f84.h>
#include <defs_f84.h>

#define DQ_PIN rb2
#define CLK_PIN rb1
#define RST_PIN rb0

#define DQ_DIR trisb2
#define CLK_DIR trisb1
#define RST_DIR trisb0

#define TxData 0	// RA.0 - interface to serial LCD

#define IN 1
#define OUT 0

void set_pot_values(int stack_bit, int setting_0, int setting_1);
void get_pot_values(int *p_stack, int *p_setting_0, int *p_setting_1);
void ds1867_out_8(int val);
int ds1867_in_8(void);

// delay routines
void delay_ms(long t);
void delay_10us(int t);

// LCD routines
void lcd_init(void);
void out_RAM_str(int *s);
void lcd_hex_byte(int val);
void lcd_dec_byte(int val, int digits);
int num_to_char(int val);
void lcd_char(int ch);
void lcd_new_line(void);


void main(void)
{
   int stack_bit, setting_0, setting_1;

   DQ_DIR = OUT;
   CLK_DIR = OUT;
   RST_DIR = OUT;

   stack_bit = 0;
   setting_0 = 0x80;
   setting_1 = 0x40;

   set_pot_values(stack_bit, setting_0, setting_1);

   get_pot_values(&stack_bit, &setting_0, &setting_1);
   // note passing by reference

   lcd_init();

   lcd_char(stack_bit + '0');	// display the stack bit
   lcd_new_line();
   lcd_hex_byte(setting_0);	// display setting of pot 0
   lcd_char(' ');
   lcd_hex_byte(setting_1);	// display setting of pot 1
   lcd_new_line();
}

void set_pot_values(int stack_bit, int setting_0, int setting_1)
{
   RST_PIN = 0;
   CLK_PIN = 0;
   RST_PIN = 1;	// bring RST high while CLK is low

   DQ_PIN = stack_bit & 0x01;
   CLK_PIN = 1;
   CLK_PIN = 0;

   ds1867_out_8(setting_1);
   ds1867_out_8(setting_0);

   RST_PIN = 0;
}

void get_pot_values(int *p_stack, int *p_setting_0, int *p_setting_1)
{
   DQ_DIR = IN;	// turn around DQ so as to read data
   RST_PIN = 0;
   CLK_PIN = 0;
   RST_PIN = 1;

   *p_stack = DQ_PIN;
   CLK_PIN = 1;
   CLK_PIN = 0;
   *p_setting_1 = ds1867_in_8();
   *p_setting_0 = ds1867_in_8();
   RST_PIN = 0;
   DQ_DIR = OUT; // this is simply housekeeping
}

void ds1867_out_8(int val)	// shift out, most sig bit first
{
   int n;
   for (n=0; n<8; n++)
   {
      DQ_PIN = (val>>7) & 0x01;	// most sig bit first
      CLK_PIN = 1;
      CLK_PIN = 0;
      val = val << 1;
   }
}

int ds1867_in_8(void)
{
   int n, val=0;

   for (n=0; n<8; n++)
   {
      val = (val << 1) | DQ_PIN;
      CLK_PIN = 1;	// post clock
      CLK_PIN = 0;
   }
   return(val);
}

// delay routines
void delay_10us(int t)
{
#asm
      BCF STATUS, RP0
DELAY_10US_1:
      CLRWDT
      NOP
      NOP
      NOP
      NOP
      NOP
      NOP
      DECFSZ t, F
      GOTO DELAY_10US_1
#endasm
}

void delay_ms(long t)	// delays t millisecs
{
   do
   {
     delay_10us(100);
   } while(--t);
}

// LCD routines
int num_to_char(int val)	// converts val to hex character
{
   int ch;
   if (val < 10)
   {
     ch=val+'0';
   }
   else
   {
     val=val-10;
     ch=val + 'A';
   }
   return(ch);
}

void lcd_char(int ch)	// serial output to PIC-n-LCD, 9600 baud
{
   int n, dly;
   		// start bit + 8 data bits

#asm
       BCF STATUS, RP0
       MOVLW 9
       MOVWF n
       BCF STATUS, C

LCD_CHAR_1:

       BTFSS STATUS, C
       BSF PORTA, TxData
       BTFSC STATUS, C
       BCF PORTA, TxData
       MOVLW 32
       MOVWF dly

LCD_CHAR_2:
       DECFSZ dly, F
       GOTO LCD_CHAR_2
       RRF ch, F
       DECFSZ n, F
       GOTO LCD_CHAR_1

       BCF PORTA, TxData
       CLRWDT
       MOVLW 96
       MOVWF dly

LCD_CHAR_3:
       DECFSZ dly, F
       GOTO LCD_CHAR_3
       CLRWDT
#endasm
}

// LCD routines

void lcd_init(void)	// sets TxData in idle state and resets PIC-n-LCD
{
#asm
        BCF STATUS, RP0
        BCF PORTA, TxData
        BSF STATUS, RP0
        BCF TRISA, TxData
        BCF STATUS, RP0
#endasm
   lcd_char(0x0c);
   delay_ms(250);
}

void lcd_new_line(void)	// outputs 0x0d, 0x0a
{
   lcd_char(0x0d);
   delay_ms(10);	// give the PIC-n-LCD time to perform the
   lcd_char(0x0a);	// new line function
   delay_ms(10);
}


void out_RAM_str(int *s)
{
   while(*s)
   {
      lcd_char(*s);
      ++s;
   }
}

void lcd_hex_byte(int val) // displays val in hex format
{
   int ch;
   ch = num_to_char((val>>4) & 0x0f);
   lcd_char(ch);
   ch = num_to_char(val&0x0f);
   lcd_char(ch);
}

void lcd_dec_byte(int val, int digits)
// displays byte in decimal as either 1, 2 or 3 digits
{
   int d;
   int ch;
   if (digits == 3)
   {
      d=val/100;
      ch=num_to_char(d);
      lcd_char(ch);
   }
   if (digits >1)	// take the two lowest digits
   {
       val=val%100;
       d=val/10;
       ch=num_to_char(d);
       lcd_char(ch);
   }
   if (digits == 1)	// take the least significant digit
   {
       val = val%100;
   }

   d=val % 10;
   ch=num_to_char(d);
   lcd_char(ch);
}