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);
}