Full Version : 3 Channel 8 Bit EEPROM DAC on 8 Pin AVR
avr >>PROJECTS (AVR) >>3 Channel 8 Bit EEPROM DAC on 8 Pin AVR


AVR_Admin- 04-28-2006
3 Channel, 8 bit EEPROM DAC with DS interface


•Low power
•EEPROM memory for autonomous operation, 16 bytes available for general purpose use.
•Low cost
This device provides three channels of 8 bit pulse-width modulation. Output pulse duty cycle ranges from 0 to 255/256 in 255 steps. DACs may be loaded by the DS interface. DAC values may also be copied into the on-chip EERPOM and then automatically be loaded into the DACs when power is applies, making it useful for automatic set up of circuits that do not contain microcontrollers. This replaces more expensive EEPROM DACs and EEPROM pots in many applications, owing to its use of a small area high volume integrated circuit microcontroller. Additionally, one page of 16 bytes of on-chip EEPROM storage is accessible via the DS interface.


Pinouts of the DAC. Avoid long parallel traces or flat ribbon cable runs with the PWM0 and Attention line signals in parallel in such a way that the PWM0 signal couples heavily into the Attention line as this signal could make the interface hang up .


When programming the chip it is recommended elect internal oscillator and set the brownout detector to the high voltage consistent with your application.


Hardware considerations


With the values for the RC (resistor-capacitor) filters given on the schematic above, the worst case ripple will be about 1/2 lsb at 5V. Lower power supply voltages casue the ATtiny12's osciallator frequency to dorp, thus to maintain 1/2 lsb ripple, it would be necessary to increase the resistors or the capcaitors in the output filter.

If during reset initialization, the EEPROM checksum is found to be correct, the DAC values stored in EEPROM will be loaded into the DACs. As such, the DS interface pins can be permanently tied to ground if the situation calls for it. Similarly, if the reset input is not used, the 100k resistor may be omitted and pin 1 tied directly to VCC. If the reset input is tied directly to VCC check the final assembly language code carefully to make sure that DDRB bit 5 is never set as an output and PB5 is never driven low because port B bit 5 is an alternative function of pin 1.

This DS slave device does not have any internal pull-ups. This chip uses the same PWM generation method as the 8 channel 8 bit DAC. See this page for details of operation.

It should be noted that the VCC of the PWM DAC needs to be close to the VCC of the host. Check the device's respective data sheets for details.


The DS DAC is composed of a DS interface followed by an Incoming Data Register and an Instruction Interpreter. The instruction interpreter moves to and from the register file and the EEPROM and controls the DAC control. Instructions provide for reading from and writing the register set and the EEPROM.

Using the DS interface, DAC values are written to registers 0, 1, and 2 to control DAC 0, 1, and 2, respectively. The DAC control blocks creates a bit-reversed image for use by the PWM routines and places them in registers 4,5, and 6. A command allows the register set and a checksum to be written to a dedicated section of the EEPROM. As part of the rest initialization routine, the EEPROM data are checked against the checksum and if the checksum is valid, registers 0,1, and 2 will be loaded from the EEPROM and DAC operation commenced using the stored data.

Sixteen bytes of on-chip EEPROM are accessible directly and useable at the discretion of the programmer. The EEPROM is written every time an instruction to write to the EEPROM (instruction $4X) is interpreted -since the manufacturer only guarantees the EEPROM to work for a limited number of erase-write cycles (100,000 at the time of this writing), routines that frequently write to the EEPROM should be avoided. Note that when the EEPROM is written, the stored checksum becomes invalid and the automatic loading of the DAC values after reset will not work again until the command to write a new checksum to the EEPROM (command $70) is interpreted.

REGISTER FUNCTION0........................Store DAC0 input value here1........................Store DAC1 input value here2........................Store DAC2 input value here3........................Not used. May be used for a fourth channel in the future.4........................DAC0 working storage (bit-reversed pattern of register 0)5........................DAC1 working storage (bit-reversed pattern of register 1)6........................DAC2 working storage (bit-reversed pattern of register 2)7........................Not used. May be used for a fourth channel in the future.8........................Not used by DAC and is available for use9........................Not used by DAC and is available for useA........................Not used by DAC and is available for useB........................Not used by DAC and is available for useC........................Not used by DAC and is available for useD........................Not used by DAC and is available for useE........................Used by DAC for internal purposes. Best not to modify this oneF........................Used by DAC for internal purposes. Best not to modify this one


Instruction Set

$1R store data in register set

$2R read data from register set

$4A store to EEPROM at address

$5A read data from EEPROM at address

$60 write PWM data registers to and checksum EEPROM

$70 write EEPROM checksum to EEPROM

$80 read revision level of firmware

$90 write EEPROM data to PWM registers

The use of R and A above indicate register numbers and EEPROM addresses, respectively. F or example, command $1C would write the contents of the Incoming Data Register to register $C in the register set and command $2C would read the contents of that register back to the host. Similarly commands $48 and $58 would write and read EEPROM location 8 in devices that have EEPROM.

Detailed Description of Instruction Set

$1R store data in register set

Store data in one of the 16 registers $0..$F. For example, register 2 may be written with the data previously sent to the Incoming Data Register. by writing the command $12.
|
$2R read data from register set

Read data from register indicated. For example to read the value of the data in register 2, write the command $22.


$4A store to EEPROM at address

Store data in one of the 16 EEPROM locations, $0..$F. For example EEPROM location 2 may be written with the data previously sent to the Incoming Data Register by writing the command $42. Writing to the EEPROM with this command will void any previously stored checksum and a write checksum to EEPROM command (command $70) must be executed before DAC values stored in EEPROM will be automatically used during reset initialization.

This command writes directly to the EEPROM and the limited number of erase-write cycles needs to be paid attention to. See the manufacturer's data sheet for more information.


$5A read data from EEPROM at address

Read data from EEPROM at address indicated. For example to read the value of the data in at EEPROM address 2, write the command $52.


$60 write PWM data registers and checksum to EEPROM

Writes registers 0, 1, and 2 along with a checksum to the EEPROM.


$70 write EEPROM checksum to EEPROM


Calculated EEPROM checksum and writes it to the EEPROM.


$80 read revision level of firmware

Causes the DS DAC to send two data bytes. The first byte is the version of the DAC and the second byte is the minor revision level.


$90 write EEPROM data to PWM registers

This command is useful for restoring previously stored values after modification. For example, a default DAC value can be stored using the write PWM data registers and checksum to the EEPROM command (command $60), and the DAC values then replaced. Unless the write PWM data registers and checksum to EEPROM command (command $60) is issued after the modification, using the write EEPROM to PWM data registers (this command, command $90) will restore the default DAC values, as will resetting the chip.

Link to Site: http://cappels.org/dproj/DSDACpage/dsdac.htm


AVR_Admin- 04-28-2006
CODE

.include "tn12def.inc"
 
;Note: Storage of input values in r3 thorugh r18 are not important to the DAC function.
 
;serial version major and minor revision leves.
.equ  version =  $0 ;0 sstarting August 20, 2002
 
.equ revision= $1;seems completely funcitonal settle time set to $02
 
;I/O pin descriptions
.equ dataline= 0;B0 Data line
.equ attline = 1;B1 Attention line
 
.equ pwm0out = 2;B2 pwm0 output
.equ pwm0or  = 4;value to set channel 0
 
.equ pwm1out = 3;B3 pwm1 output
.equ pwm1or  = 8;value to set channel 1
 
.equ pwm2out = 4;B4 pwm2 output
.equ pwm2or  = $10;value to set channel 2
 
;Note: Pin one of Attiny12 is used as reset input
 
.equ checksum =$0F
.equ initialddrb = $3C; Inital value for DDRB (pin 1 default open)
 
;parameters
.equ setltime    =$40;How long to wait for data and I/O lines to settle
 
.def sregtemp=  r1 ;temporary storage of status register during interrupt time
.def datareg =  r2 ;data register
 
 
;Note: user 4,5,6, and 7 as well as pwmvalue 4,5,6, and 7 are not used in ATtiny12.
;////start user accessible regisers:
.def pwm0 =  r3 ;pwm value for pwm channel 0 (user register 0)
.def pwm1 =  r4 ;user 1
.def pwm2 =  r5 ;user 2
.def user3 =  r6 ;user 3
.def  pwmvalue0= r7 ;duty cycle user register 4
.def  pwmvalue1 = r8 ;duty cycle user register 5
.def  pwmvalue2 = r9 ;duty cycle user register 6
.def  pwmvalue3 = r10 ;duty cycle user register 7
.def  spare1   = r11
.def  spare2   =r12
.def spare3    =r13
.def spare4    =r14
.def spare5    =r15
.def  spare6   =r16
.def eeprompointer    =r17
.def spare18   =r18 ;Scratch register
;/////end of user accessible registers
 
 
 
.def ticks  = r19 ; interrupt number modulus 8
.def bout = r20 ; interrupt only temporary buffer for output port b
 
.def temp  = r21 ;scratch
.def tempi   = r22 ;scratch for use during interrupt  
.def rxtxbyte= r23 ;byte to be sent -can be lower register
.def delayc = r24 ;counter used for timing delay
.def bitcount= r25 ;counter for number of bits transfered
.def tempcounter= r26 ;variable used to reverse order of bits
.def pwmvalue  = r27 ;variable used to reverse order of bits  
.def oldticks = r28 ;variable used to decide when to make a pulse
.def index = r29 ;used to index registers  
;note that r30 and r31 used as Z register
 
 
.ORG $0000
rjmp reset
reti   ;External interrupt handler - not used
reti   ;Pin change interrupt -not used
rjmp tovflo  ;timer overflow interrupt handler
 
reset:
ldi  temp,$00  ;Aero as initial value for pwm channels
mov pwmvalue0,temp
mov pwmvalue1,temp
mov pwmvalue2,temp
mov pwmvalue3,temp
 
ldi temp,initialddrb;load data direction value for PORTB
out  DDRB,temp ;no pullups on B0 and B1 ***
out PORTB,temp  
ldi temp,$80
out ACSR,temp ;Turn off comparitor (save a little power).
ldi temp,$01
out TCCR0,temp ;Set timer prescaler to clock/1
 
ldi temp,0  ;preload timer counter
out TCNT0,temp
ldi temp,$02 ;enable timer overflow interrupts
out TIMSK,temp
 
clr pwm0  
clr  pwmvalue0
clr pwm1
clr  pwmvalue1  
clr pwm2  
clr  pwmvalue2
 
sei   ;enable interrupts in general
rjmp checkandloadeeprom
 
 
sendrevisoin:
ldi rxtxbyte,version
rcall sendbyte
ldi rxtxbyte,revision
rcall sendbyte
rjmp main
 
CopyEEPROMtopwmvalues:

ldi eeprompointer,$00
clr ZH
ldi ZL,3 ;Point to highest register to be transferred

wratzC: sbic eecr,eewe;Wait for EEPROM write to not be busy
rjmp wratzC
 
wyloop:
 
out eear,eeprompointer  ;move to EEPROM address register
sbi eecr,eere ;Trigger the read
in temp,eedr ;Get the data into temp
st Z,temp  ;Get data to register
 
inc eeprompointer
inc ZL
cpi ZL,$0F
brne wyloop
 
rjmp main

 
checkandloadeeprom:
 
clr temp  ;Uses ZL,ZH,temp. Locatoin [checksum] is not used in the calculation.
clr ZH  ;checksum kept here  
ldi ZL,checksum-1 ;pointer

wratzD: sbic eecr,eewe;Wait for EEPROM write to not be busy
rjmp wratzD
 

moretosum2:
 

out eear,ZL  ;move to EEPROM address register
sbi eecr,eere ;Trigger the read
in temp,eedr ;Get the data into temp
add ZH,temp
dec ZL
cpi ZL,$FF
brne moretosum2

ldi temp,checksum
out eear,temp ;move to EEPROM address register
sbi eecr,eere ;Trigger the read
in temp,eedr ;Get the data into temp
 
cp ZH,temp
breq CopyEEPROMtopwmvalues
rjmp main



main:
 
rjmp ReceiveByte
recrtn:
brcc CarryIsClear ;if carry is not set, it is data, so place in datareg.

;  //////Interpret DataShake input as an instruction//////
 
   ;If carry is not set, interpret as an instruction.
   ;make lower nybble register pointer just in case its needed
mov ZL,rxtxbyte ;move pointer into ZL register
andi ZL,$0F  ;mask off upper nybble
ldi ZH,$00

andi rxtxbyte,$F0 ;mask off lower nybble in rxtxbyte
   ;and interpret the command
cpi rxtxbyte,$10 ;test for store instruction
breq storereg
 
cpi rxtxbyte,$20 ;test for read instruction
breq readreg  ;finished fetching and interpreting. go for another byte


cpi rxtxbyte,$40 ;test for command to write to EEPROM (only lower 16 bytes accessible)
breq WriteEEPROM

cpi rxtxbyte,$50 ;test for command to read to EEPROM (only lower 16 bytes accessible)
breq ReadEEPROM

cpi rxtxbyte,$60 ;test for command to copy  registers to EEPROM
breq CopypwmvaluesToEEPROM

cpi rxtxbyte,$70 ;test for command to write EEPROM checksum in [checksum]-1
breq Seteepromchecsum

cpi rxtxbyte,$80 ;test for command to write revision to host
breq sendrevisoin
 
cpi rxtxbyte,$90 ;test for command to copy  EEPROM to registers
breq CopyEEPROMtopwmvalues
 
 

storereg:   ;STORE INCOMING BYTE INTO DATAREG
clr ZH ;  
ldi index,03  ;
add ZL,index  ;point to registers 3 thrugh 18
st Z,datareg  
 
mov pwmvalue,datareg;REverse the bit order and store in pwmvalue registers
rcall reversepwmvalue ;for the interrupt pwm routine to use.
ldi index,$04
add ZL,index
st Z,pwmvalue

rjmp main
 
readreg:
clr  ZH
ldi temp,03  ;
add ZL,temp  ;point to registers 3 thrugh 18
ld rxtxbyte,Z ;READ BYTE FROM REGISTER
clc   ;clear the carry becuase data is being sent
rcall SendByte
rjmp main



CarryIsClear:   ;If carry is clear, its data -store in data register
mov datareg,rxtxbyte
rjmp  main


 
 
;/////EEPROM WRITE, READ, AND CHECKSUM ROUTINES.
;ENTER WITH ZL POINTING TO EEPROM ADDRESS, WRITE DATA IN datareg, READ ROUTINE CALLS SENDBYTE.
;CHECKSUM STORED IN EEPROM LOCATOIN [checksum] Checksum is from EEPROM location 0 to [checkusm]-1
;WRITE ROUTINE TURNS OF INTERRUPTS WHILE EEPROM IS BURNT -MAY CAUSE GLITCH IN PWM OUTPUT

WriteEEPROM:   ;Write contents of datareg into EEPROM register pointed to by ZL
wrat: sbic eecr,eewe ;Wait for EEPROM write to not be busy
rjmp wrat
out eear,ZL    
out eedr,datareg ;Set up the  write data
cli   ;Inhibit interrupts while triggering EPROM write
sbi eecr,eemwe
sbi eecr,eewe ;Trigger the write
sei   ;re-enable interrupts now that EEPROM write has been triggered
rjmp main


ReadEEPROM:   ;Read contents of EEPROM register pointed to by ZL to datareg
 
wratzE: sbic eecr,eewe;Wait for EEPROM write to not be busy
rjmp wratzE
 
out eear,ZL  ;move to EEPROM address register
sbi eecr,eere ;Trigger the read
in rxtxbyte,eedr ;Get the data into temp
rcall SendByte
rjmp main  ;This rjmp instruction is being kept incase this routine is relocated
 
 
Seteepromchecsum:  ;Calculate EERPOM checksum and store in location [checksum].
clr temp  ;Uses ZL,ZH,temp. Locatoin [checksum] is not used in the calculation.
clr ZH  ;checksum kept here  
ldi ZL,checksum-1 ;pointer
 
wratzB: sbic eecr,eewe ;Wait for EEPROM write to not be busy
rjmp wratzB
 
moretosum:
out eear,ZL  ;move to EEPROM address register
sbi eecr,eere ;Trigger the read
in temp,eedr ;Get the data into temp
add ZH,temp
dec ZL
cpi ZL,$FF
brne moretosum
   ;Store checksum stored in ZH into EEPROM location [checksum]
wrat1: sbic eecr,eewe ;Wait for EEPROM write to not be busy
rjmp wrat1

ldi ZL,checksum
out eear,ZL    
out eedr,ZH  ;Set up the write data
cli   ;Inhibit interrupts while triggering EPROM write
sbi eecr,eemwe
sbi eecr,eewe ;Trigger the write
sei   ;re-enable interrupts now that EEPROM write has been triggered
rjmp main  

;//////END OF GENERIC EEPROM ROUTINES/////  
 


CopypwmvaluesToEEPROM:

ldi eeprompointer,$00
clr ZH
ldi ZL,3 ;Point to highest register to be transferred
wzloop:
ld temp,Z ;Get data pointed to by ZL
 
wratzA: sbic eecr,eewe ;Wait for EEPROM write to not be busy
rjmp wratzA
out eear,eeprompointer    
out eedr,temp ;Set up the  write data
cli   ;Inhibit interrupts while triggering EPROM write
sbi eecr,eemwe
sbi eecr,eewe ;Trigger the write
sei;re-enable interrupts now that EEPROM write has been triggered
 
inc eeprompointer
inc ZL
cpi ZL,$0F
brne wzloop
 
rjmp Seteepromchecsum

 
;//////////SEND A BYTE
; Send carry bit as first bit, then send rxtxbyte bit-by-bit. rxtxbyte destroyed.
 
SendByte:
 
ldi bitcount,$09
 
S1:

sbis PINB,attline ;Wait for Attention line to go high =--SEND A BIT
rjmp S1

 
   ;Put data on data line
cbi DDRB,dataline
brcs R1
cbi PORTB,dataline
sbi DDRB,dataline
R1:
cbi PORTB,attline ;Set Attention line low
sbi DDRB, attline
 
rcall shortdelay  ;Wait a short time so other chip can see Attnetion line is low
cbi DDRB,attline ;Release Attention line for a peak
rcall shortdelay ;Short delay to allow settling of lines
sbic PINB,attline  ;If Attention line isn't low, go back and put it low again, else continue
rjmp R1

brcs szero  ;Invert data line
cbi DDRB,dataline
rjmp R3
szero: cbi PORTB,dataline
sbi DDRB,dataline
R3:

sbis PINB,attline ;Wait for Attention line to go high
rjmp R3

cbi DDRB,dataline ;Let data line float
   ;-finished sending a bit
rol rxtxbyte ;Shift rxtxbyte through carry
dec bitcount
brne S1  ;Continue until all bits sent
ret
 
 
ReceiveByte:
ldi bitcount,$09
 
W3A:;    ;Get a bit from the input into the carry
 
 
W3:
sbic PINB,attline ;Wait for Attention line to go low
rjmp w3
cbi PORTB,attline ;ACK by pulling attention line low
sbi DDRB, attline
clc   ;Latch dataline into carry bit
sbis PINB,dataline
rjmp NotaOne
sec

W1:       ;Wait for data line to go low
sbic PINB,dataline
rjmp W1
rjmp RelesaseAttLineAndGo  
NotaOne:  
W2:    ;Wait for data line to go high
sbis PINB,dataline
rjmp W2
RelesaseAttLineAndGo:  ;Release attention line
cbi DDRB, attline  
   ;DONE RECEIVING BIT
rol rxtxbyte ;Shift rxtxbyte through carry
dec bitcount
brne W3A  ;Continue until all bits received
rjmp recrtn
 

shortdelay:
ldi delayc,setltime  
D1: dec delayc
brne D1
ret
 
 
 

;REVERSE BIT ORDER OR PWMVALUE. Midifies pwmvalue, uses temp
reversepwmvalue:  ; reverse bit order in pwmvale.
ldi  temp,$08 ; 8 times through loop because there are 8 bits
mov tempcounter,temp
rotateagain:
rol pwmvalue  
ror temp
dec tempcounter
 
brne rotateagain
mov pwmvalue,temp
ret
 
 
 
;///////////////TIMER OVERFLOW SERVICE//////////////////
 
tovflo:  
 
in sregtemp,SREG ;save the status register contents

ldi tempi,$E; **** set 32 clocks until next interrupt
out  TCNT0,tempi
 
in tempi,portb;preserve two lower bits of portb
andi tempi,$03
andi bout,$FC
or bout,tempi
 
out portb,bout;transfer portb buffer to port b
andi bout,$03 ;preset all PWM bits to zero
 
mov oldticks,ticks;copy interrupt counter to temp
inc ticks ;increment interrupt timer
eor oldticks,ticks;do X-OR and AND to find bits that changed to 1 (result in temp)
and oldticks,ticks;do AND to find bits that just changes to a 1

 
; OUTPUT PWM COMB WAVEFORM TO PORTB BIT 0
mov tempi,oldticks
and tempi,pwmvalue0;AND to find if ones in data correspond to this interrupt count change
breq dontset0 ; if ones present, set lsb in portb  buffer
ori bout,pwm0or
dontset0:
 
 
 
; OUTPUT PWM COMB WAVEFORM TO PORTB BIT 1
mov tempi,oldticks
and tempi,pwmvalue1;AND to find if ones in data correspond to this interrupt count change
breq dontset1 ; if ones present, set lsb in portb  buffer
ori bout,pwm1or
dontset1:

 

; OUTPUT PWM COMB WAVEFORM TO PORTB BIT 2
mov tempi,oldticks
and tempi,pwmvalue2;AND to find if ones in data correspond to this interrupt count change
breq dontset2 ; if ones present, set lsb in portb  buffer
ori bout,pwm2or
 
dontset2:
 
 
out SREG,sregtemp ;restore the status register contents
reti
 
;end of assembly souce listing


AVR_Admin- 04-28-2006
About the DS protocol

The DS protocol was designed to provide firmware-based bidirectional host-to-slave inter processor communications for situations in which no hardware solution is available and the host and/or the slave in incapable of tending the interface in real time. The only specialized hardware required is two bidirectional I/O ports on each chip (alternatively two input ports and two output ports that can be put into an high impedance state may be used).

Link to Site: http://cappels.org/dproj/dspage/ds.htm

Forumer™ is Voted #1 Free Forum Hosting provider
Build your own community today with the largest message board hosting company.