PDA

View Full Version : help using SHIFTOUT to control SPI digital potentiometer



keithv
- 14th May 2015, 20:40
I'm trying to use the MCP4231-104 7bit digital potentiometer to make an LED get dimmer and brighter. That's not my ultimate goal with the digipot, but I'm just trying to make it do something basic before moving on. I'm using the PIC16F676 for the MCU. CS is connected to PORTC.0, SDO is connected to PORTC.1, and SCK is connected to PORTC.2

Main:

PORTC.0 = 0
SHIFTOUT PORTC.1, PORTC.2, 1, [0\7]
PORTC.0 = 1
PAUSE 100

PORTC.0 = 0
SHIFTOUT PORTC.1, PORTC.2, 1, [64\7]
PORTC.0 = 1
PAUSE 100

PORTC.0 = 0
SHIFTOUT PORTC.1, PORTC.2, 1, [128\7]
PORTC.0 = 1
PAUSE 100

PORTC.0 = 0
SHIFTOUT PORTC.1, PORTC.2, 1, [64\7]
PORTC.0 = 1
PAUSE 100

goto main
end

This isn't doing anything. I've also tried enter the shiftout bits as binary, but I get the error msg "Malformed Binary Integer".

mark_s
- 14th May 2015, 23:07
I believe you need to send a command byte before your data. I have never used this chip,
but have used a MCP42010. The digi-pot needs to know if you are reading or writing to it. Look at page 47 data sheet it is showing a 16bit command/data format.
It would probably be easy to send two bytes in a row while the CS line is low. First byte would be your
command byte and second your 8bit variable. Even if its only seven bits you need to send a zero to pad the 8th bit etc



PORTC.0 = 0
SHIFTOUT PORTC.1, PORTC.2, 1, [constant\8]
SHIFTOUT PORTC.1, PORTC.2, 1, [variable\8]
PORTC.0 = 1

PAUSE 100



Here is an example sending two bytes, no need for bits
http://www.picbasic.co.uk/forum/showthread.php?t=3982&highlight=MCP42010

or like this


PORTC.0 = 0
SHIFTOUT PORTC.1, PORTC.2, 1, [constant,variable]

PORTC.0 = 1

PAUSE 100

keithv
- 15th May 2015, 00:28
Thank you so much, Mark! That did the trick!

mark_s
- 15th May 2015, 00:37
Great!

What did you use for your control byte? In case someone else wants to use that chip in the future.

keithv
- 15th May 2015, 18:29
I just used mister e's code essentially verbatim. My IC, the MCP4231-xxx is a dual digital potentiometer. At first I thought the two pots were ganged, but turns out, you can actually control them separately by changing the address in the command byte. So I added a second "WriteOnPot" constant.



'
' Hardware configuration
' ======================
TRISC=0

'
' Hardware connection
' ===================
CS VAR PORTC.0
CLK VAR PORTC.1
SI VAR PORTC.2

'
' Variables definition
' ===================
Wiper var byte

'
' Constants definition
' ====================
MSBFIRST CON 1
WriteOnPot0 con 000001
WriteOnPot1 con 010001

'
' Software/Hardware initialisation
' ================================
cs = 1 ' disable MCP
PAUSE 100 ' safe settle time

Start:
for wiper = 0 to 255
cs=0 ' enable
shiftout si,clk, MSBFIRST,[WriteOnPot0, WIPER] ' Write to MCP first address
shiftout si,clk, MSBFIRST,[WriteOnPot1, WIPER] ' Write to MCP second address
cs = 1 ' Disable
pause 10
next
goto start


"WriteOnPot0 con 000001" Is the part of the command byte that tells it to WRITE on the first wiper address. I added "WriteOnPot1 con 010001" which allows you to write to the 2nd wiper address. So it's the first two bits that make up the wiper address. I'm not really sure in what situation you would want to use any of the functions other than write, but it's the last 4 bits that tell it to read, write, increment, or decrement. And then you just tell it where you want to wiper at with a decimal number between 0 - 255. This chip can use 7 or 8 bit resolution. If you wanted to use 7 bit, the WIPER variable would need to be a dec num between 0 - 127 and the syntax would need to be [WriteOnPot0, Wiper\7]. Once again, I'm not sure where the advantage of this would be over just keeping it 8 bit. I'm pointing these things out because it made figuring out how to use the chip more confusing than it needed to be....at least for me. The example above proves that you can SHIFTOUT to both addresses simultaneously...or at least within a few uS apart in the same CS enable/disable. The example below proves that you can operate both addresses independently of one another.



Start:
for wiper = 0 to 255
cs=0 ' enable
shiftout si,clk, MSBFIRST,[WriteOnPot0, WIPER] ' Write to MCP first address
cs = 1 ' Disable
pause 10
next

for wiper = 0 to 255
cs=0 ' enable
shiftout si,clk, MSBFIRST,[WriteOnPot1, WIPER] ' Write to MCP second address
cs = 1 ' Disable
pause 10
next
goto start

mark_s
- 15th May 2015, 21:19
The increment and decrement interest me. I wonder if you can set the wiper to say 64 and then just send a increment/decrement command to count up/down? That would make a push button volume control without software counters. Thanks for posting your findings

keithv
- 15th May 2015, 23:23
With regards to the increment/decrement, I was wondering about that too. Maybe you could use some sort of rotary encoder? I was thinking it was more likely to use a pulseout statement. MC probably threw that in there for the old school programmers who were more familiar with that style of digital pot.

UPDATE: I've discovered that these are not either 8 or 7 bit resolution. There are one of the other. MCP4x3x is the 7 bit. MCP4x5x is the 8 bit. So for 7 bit, after the address/mode command byte, you would enter 0 - 127 for the wiper position. You do not need to add the /7 to tell it is in 7 bit.