MCP4921 / MCP4922 SPI interfacing 18x

Janne

Senior Member
I though I'd post the little piece of code i write for bit-bang interfacing of this DAC chip with picaxe 18x.
In the manual and in the code examples folder, that comes with the PE, there seems to be a small error in the provided shiftout routines. I'm referring to this part:

Code:
shiftout_MSBFirst:
    for counter = 1 to bits            ' number of bits
        mask = var_out & MSBValue     ' mask MSB 
        [COLOR="Red"]low sdata[/COLOR]             ' data low
        if mask = MSBValue then skipMSB      
        [COLOR="Red"]high sdata[/COLOR]            ' data high
skipMSB:
        pulsout sclk,1             ' pulse clock for 10us 
        var_out = var_out * 2         ' shift variable left for MSB 
    next counter
    return
The low and high statements seem to have been reversed, in the way it's printed in the manual and in the sample it makes no sense, and i had to swap them to make it work.

Anyways, here is the small test program i came up with, i hope anyone getting started with this IC might find it useful. All it really does is increasing the dummy variable, and then sending it via SPI to the IC, running in continous loop.

Code:
#rem

18.2.2010
An example code how to bit-bang interface to the MCP4921 / 4922 12-bit DAC IC, with picaxe 18x.
"value" is the value transmitted to dac output, and in this test it is increased by 2 on each program run cycle.
ldac pin is tied down, so the outputs are latched immediately in this test after completing the SPI transfer. 
indicator led is connected to output 0

#endrem
#picaxe 18x
#no_data
'#no_table

'----------------------------------------------
'SYMBOLS
symbol sclk = 1		' clock (output pin)
symbol sdata = 2		' data (output pin for shiftout)
symbol led = 0		' mandatory indicator led
symbol cs = 3		' chip select

symbol counter = b1	' variable used during loop
symbol mask = w2 		' bit masking variable
symbol var_out = w1	' data variable used during shiftout
symbol value = w3		' test value to be transmitted to the DAC

symbol bits = 16		' number of bits
symbol MSBvalue = 32768	' MSBvalue (=128 for 8 bits, 512 for 10 bits, 2048 for 12 bits)


'----------------------------------------------

init:

high cs 	'put the chip select to idle
pause 100
setfreq m8

do
 
if value > 4095 then 
value = 0
endif

toggle led

'bit 15; 1= write to DACb 0= write to DACa
'bit 14; 1= enable input buffer 0 = input buffer is disabled
'bit 13; 1= outputgain at 1x 0 = 2x output gain 
'bit 12; 1= outputs enabled 0 = outputs are floating (high impedance)
'bits 11-0 Transferred data, MSb first.

var_out = value | %0011000000000000	'mask the 4 control bits --> writing to DACa, input buffer disabled, output at 1x gain, outputs enabled.
var_out = var_out & %0011111111111111
'sertxd (#var_out)

'*****spi transfer
low cs 	'low chip select
gosub shiftout_MSBFirst
high cs	'cs back to idle, latches data to output

value = value + 2		'increase dummy variable

loop



' ========================================================================
' ***** Shiftout MSB first *****
' Shift out the data MSB first from variable var_out 
' Using clock output pin sclk
' Using data output pin sdata 

' Note the number 128 (used twice) is the mask byte for MSB of 8 bits
' If using 10 bits use 512, 12 bits use 2048 etc

shiftout_MSBFirst:
	for counter = 1 to bits			' number of bits
		mask = var_out & MSBValue 	' mask MSB 
		high sdata 			' data high		WARNING - IF YOU COPY THIS PART FROM THE EXAMPLE's folder CODE, REMEMBER THAT.
						'			THE HIGH AND LOW STATEMENTS HERE ARE REVERSED.
		if mask = MSBValue then skipMSB  	
		low sdata			' data low
skipMSB:
		pulsout sclk,1 			' pulse clock for 10us 
		var_out = var_out * 2 		' shift variable left for MSB 
	next counter
	return
' ========================================================================
 
Last edited:

westaust55

Moderator
Thanks Janne.

Thank may come in useful.

I have a virtually identical MCP4822-E/P 12-Bit DAC with Internal Vref and SPI Interface in a DIP package format (courtesy of a friend) to play with when I get a chance. (So many projects :D . . . so little time :rolleyes:)

with respect ot the correct Low . . . High pin setting,
in the manual 2 (V5.1 thru to V6.9) page 193, the examples are:
mask = var_out & MSBValue ‘ mask MSB
low sdata ‘ data low
if mask = 0 then skipMSB
high sdata ‘ data high
skipMSB: pulsout sclk,1​
which is correct.

The difference is that with the example you reference/use
the mask is being compared with MSBValue instead of 0.


Agree however that the shiftin_out.bas code in the PR Samples folder is incorrect as you advise.
 
Last edited:

Janne

Senior Member
I just had another look into the manual, and indeed the code in the manual should work ok. My bad, I just looked at the order of the high / low statements there, and not into the actual code(After figuring out what was wrong in the example provided with PE). So those copying the code example from the manual should be ok.

edit: I also tested the DAC in my actual board with picaxe 40x1. HSPI also worked perfectly, at least with; spimode00, spislow, high byte sent first. Higher speed setting should also be ok, according to datasheet, but untested.
 
Last edited:
Top