I'm trying to use a 16F877 to control an MCP4131 digital pot and have run into difficulties (having no access to a scope doesnt help much either). I'm still a bit confused by everything to do with SPI despite doing a fair bit of googling and reading up.
OK, so just to confirm firstly have I connected this up correctly, I have connected:
Pin 1 CS to RA5(CS), Pin 2 SCK to RC3(SCK), Pin3 SDI/SDO to RC5(SDO)
So from what I think I understand so far I have to hold RA5 LOW while using SPItransfer to send data then change it back to High?
Also as far as I can tell I have to send a channel number then the value, so can i accomplish this using 2 consecutive SPItransfer commands, something like:
;Chip Settings
#chip 16F877,20
#config OSC=XT
;Variables
Dim DigiPot As byte
SPIMode MasterFast
Dir PORTA.5 Out
Start:
DigiPot = 0
Wait 5 s
DigiPot = 64
Wait 5 s
DigiPot = 128
Wait 5 s
Goto Start
'''Send data to Digipot
Sub SPIsend
Set PORTA.5 Off
SPITransfer 2,
SPITransfer DigiPot,
Set PORTA.5 Off
Exit Sub
End Sub
I found this code for a Picaxe, which is what I tried to base my code above from
SYMBOL CS = C.5 ; chip select pin is tied high
SYMBOL channel = b0 ; range 0 to 3
SYMBOL setting = b1 ; range 0 to 255
SYMBOL index = b2
channel = %00000010 ; need to get the channel into top 2 bits of byte for MSB_First
setting = %00000000
hspisetup spimode00, spifast
Send_data:
low CS ; enable chip select
hspiout (channel, setting) ;
high CS ; disable chip select
return
I've trimmed the stuff out where they are setting the value of setting variable, but does it look like my program will produce the same result on the SPI side of things?
Thanks
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
still experimenting to see what I changed to sort it but this worked ok:
;Chip Settings
#chip 16F877,20
;Variables
Dim DigiPot As byte
Dir PORTB.5 Out
Dir PORTC.5 Out
Dir PORTC.3 Out
Dir PORTA.5 Out
SPIMode Master
Set PORTA.5 On
DigiPot = 0
start:
Set PORTB.5 On
Do Until DigiPot = 255
SPIsetpot
DigiPot = DigiPot+1
Wait 100 ms
Loop
Wait 5 s
Set PORTB.5 Off
Do Until DigiPot = 0
SPIsetpot
DigiPot = DigiPot-1
Wait 100 ms
Loop
Wait 5 s
Goto start
Sub SPIsetpot
Set PORTA.5 Off
Wait 10 ms
SPITransfer 00000010,
SPITransfer DigiPot,
Wait 10 ms
Set PORTA.5 On
Exit Sub
End Sub
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hmm spoke too soon I think, I tried directly setting values of 0 and 255 and it doesnt seem to work unless I actually ramp the value up/down. Any ideas?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Also spoke too soon about it working, it was working when I tested it out, tried powering the circuit back up and no matter what I seem to do it now doesnt seem to do anything, i've tried adding a delay in the main program loop and one before and after RA5 getting pulled high/low so I can see it with a test meter, I've finally bit the bullet and ordered a secondhand 30mhz scope from fleabay as a) I really could use one and b) this problem is driving me nuts
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
the code for SPITransfer uses some improper syntax:
SPITransfer 00000010,
For binary numbers, it should be
SPITransfer b'00000010', 0
Is it necessary to write a '1' to the error code register? No delays should be required. If the code still refuses to work, you can try a simple software routine say with the increment, decrement commands? MOSI, and SCK needs to be initialized to '0':
sub SPI_Xfer(xfer)
For clocks = 1 to 8
If xfer.7 = 1 Then
MOSI = 1
Else
MOSI = 0
End if
Rotate xfer Left Simple
SCK = 1
If MISO = 1 Then
xfer.0 = 1
Else
xfer.0 = 0
End If
SCK = 0
Next
end sub
A scope is a really nice tool to have :-).
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thanks for the reply Kent, Can I just double check with you my understanding of the commands required to control the pot, If i understand the datasheet corectly (page 46 - memory map and supported commands) I have to send a 16-bit command to volatile wiper 1 as 2 8 bit commands consisting of '000000nn' and 'nnnnnnnn' where 'n' is the data to be written to the pot wiper, and as i understand it the last two bits of the first byte will always be 0 anyway and the last byte ill hold my value in binary from 0-255. I find getting my head around this kind of thing really difficult so all advice it greatly appreciated.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Basically correct; That would be write to wiper0 b'000000nn", or wiper1 b'000100nn' as the first byte. the MCP4131 is a 7 bit device so per data sheet 0-128 decimal for the said 129 steps of the second byte. Make sure Master SDO goes to slave (MCP4131) SDI.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I have only tried writing 0's to it so far, I had hooked up the pot across 5v-0V to measure the voltage output, it was happily sitting a 0v so that proves thats working, tomorrow I will try and get it to write a few more values to determine if that works. On the 4131 shares a single pin for SDI/SDO however I dont intend to read values back from it so should it be ok just to repeatedly send the 1st byte as 0's and the second with the required value and not worry about recieving anything back or checking the error bit as in the circuit I'm using this for (variable PSU) I'll be masuring the controlled voltage on RA0 via a potential divider and if I've got the gist of it, if an error occurs it waits for slave select to go back to high then low and will resume correct operation?
Cheers
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Cool that you got it working, as the POR value is 0x40. I think it was the SPIWrite binary number syntax that was the problem, just that the compiler/assembler didn't complain. Good luck.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi guys,
I'm trying to use a 16F877 to control an MCP4131 digital pot and have run into difficulties (having no access to a scope doesnt help much either). I'm still a bit confused by everything to do with SPI despite doing a fair bit of googling and reading up.
Datasheet for digital pot http://ww1.microchip.com/downloads/en/DeviceDoc/22060b.pdf
OK, so just to confirm firstly have I connected this up correctly, I have connected:
Pin 1 CS to RA5(CS), Pin 2 SCK to RC3(SCK), Pin3 SDI/SDO to RC5(SDO)
So from what I think I understand so far I have to hold RA5 LOW while using SPItransfer to send data then change it back to High?
Also as far as I can tell I have to send a channel number then the value, so can i accomplish this using 2 consecutive SPItransfer commands, something like:
I found this code for a Picaxe, which is what I tried to base my code above from
I've trimmed the stuff out where they are setting the value of setting variable, but does it look like my program will produce the same result on the SPI side of things?
Thanks
Resolved now.
still experimenting to see what I changed to sort it but this worked ok:
Hmm spoke too soon I think, I tried directly setting values of 0 and 255 and it doesnt seem to work unless I actually ramp the value up/down. Any ideas?
Also spoke too soon about it working, it was working when I tested it out, tried powering the circuit back up and no matter what I seem to do it now doesnt seem to do anything, i've tried adding a delay in the main program loop and one before and after RA5 getting pulled high/low so I can see it with a test meter, I've finally bit the bullet and ordered a secondhand 30mhz scope from fleabay as a) I really could use one and b) this problem is driving me nuts
the code for SPITransfer uses some improper syntax:
For binary numbers, it should be
Is it necessary to write a '1' to the error code register? No delays should be required. If the code still refuses to work, you can try a simple software routine say with the increment, decrement commands? MOSI, and SCK needs to be initialized to '0':
A scope is a really nice tool to have :-).
Thanks for the reply Kent, Can I just double check with you my understanding of the commands required to control the pot, If i understand the datasheet corectly (page 46 - memory map and supported commands) I have to send a 16-bit command to volatile wiper 1 as 2 8 bit commands consisting of '000000nn' and 'nnnnnnnn' where 'n' is the data to be written to the pot wiper, and as i understand it the last two bits of the first byte will always be 0 anyway and the last byte ill hold my value in binary from 0-255. I find getting my head around this kind of thing really difficult so all advice it greatly appreciated.
Basically correct; That would be write to wiper0 b'000000nn", or wiper1 b'000100nn' as the first byte. the MCP4131 is a 7 bit device so per data sheet 0-128 decimal for the said 129 steps of the second byte. Make sure Master SDO goes to slave (MCP4131) SDI.
Thanks Kent :)
I have only tried writing 0's to it so far, I had hooked up the pot across 5v-0V to measure the voltage output, it was happily sitting a 0v so that proves thats working, tomorrow I will try and get it to write a few more values to determine if that works. On the 4131 shares a single pin for SDI/SDO however I dont intend to read values back from it so should it be ok just to repeatedly send the 1st byte as 0's and the second with the required value and not worry about recieving anything back or checking the error bit as in the circuit I'm using this for (variable PSU) I'll be masuring the controlled voltage on RA0 via a potential divider and if I've got the gist of it, if an error occurs it waits for slave select to go back to high then low and will resume correct operation?
Cheers
Cool that you got it working, as the POR value is 0x40. I think it was the SPIWrite binary number syntax that was the problem, just that the compiler/assembler didn't complain. Good luck.
Really appreciated the help, thanks Kent your advice was spot-on :)