Ryan7777
- 29th May 2015, 17:12
Hello all!
I am using a couple of MCP23S17's with a PIC18F2320 in order to communicate with a circuit that converts a 24 bit parallel output from the MCP23S17's to a fiber optic signal.
The fiber signal requires timing that the PIC just cannot do, unfortunately, so a bunch of standard logic does the fast stuff, and the PIC handles feeding values in parallel via the port expanders (MCP23S17's)
I'm using some code that I borrowed from here: http://www.picbasic.co.uk/forum/content.php?r=471-MCP23S17-Three-different-approaches-ShiftIn-ShiftOut-MSSP-PBP-MSSP-ASM
The first variation to be exact. I've modified it to work with my circuit, as it includes two MCP23S17's, one of them only using 8 bits and the other using all 16 bits
The MCP23S17 that handles 8 bit's of the full 24 bit packet is easy to deal with because the data is pretty much static and each of the 8 bits is handled as an individual, so no problem there.
The problem is that the other 16 bits need to be handled as a singular WORD for a 16 bit numerical value. It's nice and easy doing math on an integer, etc.
The way the code example works is that it sends everything to the MCP23S17 MSB first. My value has to be transmitted LSB first!
So to the code %1000000000000000 looks like "32768" but if I send that, my circuit thinks it's "1"!!!
So how do I go about reversing the bit order just before I send it on its way to the MCP23S17?
I already have the PCB made, so I can't simply change my bit order by wiring or I would just do that. Trust me, I already have a "blue wire" or two "fixing" a bug or two, one you'll notice with PORTA.4, so I just shared a line with the other chip select, since the MCP's are hardware addressed anyway.
The following is test code, far from complete and fraught with other issues to work through.
' --------------------CHIP FUSES-------------------------------
@ __CONFIG _CONFIG1H, _HS_OSC_1H & _FSCM_OFF_1H & _IESO_OFF_1H
@ __CONFIG _CONFIG2L, _PWRT_OFF_2L & _BOR_OFF_2L
@ __CONFIG _CONFIG2H, _WDT_OFF_2H & _WDTPS_1_2H
@ __CONFIG _CONFIG4L, _STVR_OFF_4L & _LVP_OFF_4L & _DEBUG_OFF_4L
@ __CONFIG _CONFIG3H, _CCP2MX_OFF_3H & _PBAD_DIG_3H & _MCLRE_ON_3H
DEFINE OSC 40
INTCON = 0
ADCON1.0 = 1 ' Turn off analog inputs
ADCON1.1 = 1
ADCON1.2 = 1
ADCON1.3 = 1
ADCON0.0 = 0 ' Turn off analog converter
CMCON.0 = 1
CMCON.1 = 1
CMCON.2 = 1
' --------------------Ports---------------------------------------
'76543210 '76543210
TRISA = %00000000: PORTA = %00000000
TRISB = %00000011: PORTB = %00000000
TRISC = %00000000: PORTC = %00000000
' ALIAS & MODIFIERS
' ================================================== ==============
nCSA VAR PORTA.3
nCSB var PORTA.4 '- BAD - OPEN COLLECTOR! DO NOT USE
nRST VAR PORTA.2
SCLK VAR PORTA.1
SDO VAR PORTA.0
xmit Var PORTA.5
UPbtn VAR PORTB.0
DWNbtn VAR PORTB.1
' VARIABLES & COSTANTS
' ================================================== ==============
MCP23A CON $42 'Register address to MCP23S17 Config
MCP23B CON $40 'Register address to MCP23S17 PortA(1)
IOCON CON $0A 'Register address to MCP23S17 Config
IODIRA CON $00 'Register address to MCP23S17 PortA(1)
IODIRB CON $01 'Register address to MCP23S17 PortB(2)
GPIOA CON $12 'Register address to MCP23S17 GPIOA(1)
GPIOB CON $13 'Register address to MCP23S17 GPIOB(2)
OLATA CON $14 'Register address to MCP23S17 LATA(1)
OLATB CON $15 'Register address to MCP23S17 LATB(2)
DataOut var BYTE
Voltage VAR WORD 'Variable for manipulating Voltage as full 16 bit word
VoltageFst VAR Voltage.BYTE0 'Variable for Voltage Byte 0 to Send to MCP23S17A-A
VoltageSec VAR Voltage.BYTE1 'Variable for Voltage Byte 1 to Send to MCP23S17A-B
Param Var BYTE 'Variable for Parameters Byte to Send to MCP23S17B-A
RD VAR Param.0 'Varible to set read bit on IP Board - 0 = Read
WR VAR Param.1 'Varible to set write bit on IP Board - 1 = Write
O4 VAR Param.2 'Varible unused 4
RY VAR Param.3 'Varible to set Relay bit on IP Board - 1 = Relay Pulled
O3 VAR Param.4 'Varible unused 3
O2 VAR Param.5 'Varible unused 2
CH1 VAR Param.6 'Varible bit 0 of ADC channel select
CH0 VAR Param.7 'Varible bit 1 of ADC channel select
AuxPort Var BYTE 'Variable for Aux Port Byte to Send to the MCP23S17B-B
UPbtnvar Var BYTE 'Variable for UP Button
DWNbtnvar VAR BYTE 'Variable for DOWN Button
MCPReg VAR BYTE 'Variable for the Register to Send to the MCP23S17
MCPWRT var BYTE 'Command o write in MCP23S17 Address $00
MCPRED var BYTE 'Command o read from MCP23S17 Address $00
' INIT
' ================================================== ==============
UPbtnvar = 0
DWNbtnvar = 0
ncsa = 1
'ncsb = 1
nRST = 0 'Reset the port expanders
PAUSE 1
nRST = 1
MCPReg = IOCON 'Configures MCP23S17-A
DataOut = $28
nCSA = 0 'Enable MCP23S17-A
SHIFTOUT SDO, SCLK, 1, [MCP23A,MCPReg,DataOut]
nCSA = 1 'Disable MCP23S17-A
MCPReg = IODIRA 'Configures PortA(1) All Output
DataOut = $00
nCSA = 0 'Enable MCP23S17-A
SHIFTOUT SDO, SCLK, 1, [MCP23A,MCPReg,DataOut]
nCSA = 1 'Disable MCP23S17-A
MCPReg = IODIRB 'Configures PortB(2) All Output
DataOut = $00
nCSA = 0 'Enable MCP23S17-A
SHIFTOUT SDO, SCLK, 1, [MCP23A,MCPReg,DataOut]
nCSA = 1 'Disable MCP23S17-A
MCPReg = IOCON 'Configures the MCP23S17
DataOut = $28
nCSA = 0 'Enable MCP23S17-B
SHIFTOUT SDO, SCLK, 1, [MCP23B,MCPReg,DataOut]
nCSA = 1 'Disable the MCP23S17
MCPReg = IODIRA 'Configures PortA(1) All Output
DataOut = $00
nCSA = 0 'Enable MCP23S17-B
SHIFTOUT SDO, SCLK, 1, [MCP23B,MCPReg,DataOut]
nCSA = 1 'Disable the MCP23S17
MCPReg = IODIRB 'Configures PortB(2) All Output
DataOut = $00
nCSA = 0 'Enable MCP23S17-B
SHIFTOUT SDO, SCLK, 1, [MCP23B,MCPReg,DataOut]
nCSA = 1 'Disable the MCP23S17
AuxPort = %00000000
GOSUB SEND_AuxPort
' _
' |CH|--|RY|-|W|R
Param = %00001010 ' 00 00 1 0 1 0
GOSUB SEND_Param
Voltage = 0
GOSUB SEND_Voltage
' MAIN LOOP
' ================================================== =============
MAIN:
BUTTON DWNbtn,1,255,255,DWNbtnvar,1,BtnDwn
BUTTON UPbtn,1,255,255,UPbtnvar,1,BtnUp
GOSUB Transmit
GOTO MAIN
' SUB - ROTINES
' ================================================== ==============
BtnUp:
IF Voltage >= 65535 THEN
gOTO MAIN
ENDIF
Voltage = (Voltage + 1)
GOSUB SEND_Voltage
'pause 50
GOTO MAIN
BtnDwn:
IF Voltage = 0 THEN
GOTO MAIN
ENDIF
Voltage = (Voltage - 1)
GOSUB SEND_Voltage
'pause 50
GOTO MAIN
Transmit:
xmit = 1
PAUSEUS 1
xmit = 0
pause 50
RETURN
SEND_Voltage:
Voltage = Voltage REV 16
nCSA = 0 'Enable MCP23S17-A
SHIFTOUT SDO, SCLK, 1, [MCP23A,OLATA,VoltageFst]
nCSA = 1 'Disable the MCP23S17
pause 1
nCSA = 0 'Enable MCP23S17-A
SHIFTOUT SDO, SCLK, 1, [MCP23A,OLATB,VoltageSec]
nCSA = 1 'Disable the MCP23S17
RETURN
SEND_Param:
nCSA = 0 'Enable MCP23S17-B
SHIFTOUT SDO, SCLK, 1, [MCP23B,OLATA,Param]
nCSA = 1 'Disable the MCP23S17
RETURN
SEND_AuxPort:
nCSA = 0 'Enable MCP23S17-B
SHIFTOUT SDO, SCLK, 1, [MCP23B,OLATB,Auxport]
nCSA = 1 'Disable the MCP23S17
RETURN
goto main
END
I am using a couple of MCP23S17's with a PIC18F2320 in order to communicate with a circuit that converts a 24 bit parallel output from the MCP23S17's to a fiber optic signal.
The fiber signal requires timing that the PIC just cannot do, unfortunately, so a bunch of standard logic does the fast stuff, and the PIC handles feeding values in parallel via the port expanders (MCP23S17's)
I'm using some code that I borrowed from here: http://www.picbasic.co.uk/forum/content.php?r=471-MCP23S17-Three-different-approaches-ShiftIn-ShiftOut-MSSP-PBP-MSSP-ASM
The first variation to be exact. I've modified it to work with my circuit, as it includes two MCP23S17's, one of them only using 8 bits and the other using all 16 bits
The MCP23S17 that handles 8 bit's of the full 24 bit packet is easy to deal with because the data is pretty much static and each of the 8 bits is handled as an individual, so no problem there.
The problem is that the other 16 bits need to be handled as a singular WORD for a 16 bit numerical value. It's nice and easy doing math on an integer, etc.
The way the code example works is that it sends everything to the MCP23S17 MSB first. My value has to be transmitted LSB first!
So to the code %1000000000000000 looks like "32768" but if I send that, my circuit thinks it's "1"!!!
So how do I go about reversing the bit order just before I send it on its way to the MCP23S17?
I already have the PCB made, so I can't simply change my bit order by wiring or I would just do that. Trust me, I already have a "blue wire" or two "fixing" a bug or two, one you'll notice with PORTA.4, so I just shared a line with the other chip select, since the MCP's are hardware addressed anyway.
The following is test code, far from complete and fraught with other issues to work through.
' --------------------CHIP FUSES-------------------------------
@ __CONFIG _CONFIG1H, _HS_OSC_1H & _FSCM_OFF_1H & _IESO_OFF_1H
@ __CONFIG _CONFIG2L, _PWRT_OFF_2L & _BOR_OFF_2L
@ __CONFIG _CONFIG2H, _WDT_OFF_2H & _WDTPS_1_2H
@ __CONFIG _CONFIG4L, _STVR_OFF_4L & _LVP_OFF_4L & _DEBUG_OFF_4L
@ __CONFIG _CONFIG3H, _CCP2MX_OFF_3H & _PBAD_DIG_3H & _MCLRE_ON_3H
DEFINE OSC 40
INTCON = 0
ADCON1.0 = 1 ' Turn off analog inputs
ADCON1.1 = 1
ADCON1.2 = 1
ADCON1.3 = 1
ADCON0.0 = 0 ' Turn off analog converter
CMCON.0 = 1
CMCON.1 = 1
CMCON.2 = 1
' --------------------Ports---------------------------------------
'76543210 '76543210
TRISA = %00000000: PORTA = %00000000
TRISB = %00000011: PORTB = %00000000
TRISC = %00000000: PORTC = %00000000
' ALIAS & MODIFIERS
' ================================================== ==============
nCSA VAR PORTA.3
nCSB var PORTA.4 '- BAD - OPEN COLLECTOR! DO NOT USE
nRST VAR PORTA.2
SCLK VAR PORTA.1
SDO VAR PORTA.0
xmit Var PORTA.5
UPbtn VAR PORTB.0
DWNbtn VAR PORTB.1
' VARIABLES & COSTANTS
' ================================================== ==============
MCP23A CON $42 'Register address to MCP23S17 Config
MCP23B CON $40 'Register address to MCP23S17 PortA(1)
IOCON CON $0A 'Register address to MCP23S17 Config
IODIRA CON $00 'Register address to MCP23S17 PortA(1)
IODIRB CON $01 'Register address to MCP23S17 PortB(2)
GPIOA CON $12 'Register address to MCP23S17 GPIOA(1)
GPIOB CON $13 'Register address to MCP23S17 GPIOB(2)
OLATA CON $14 'Register address to MCP23S17 LATA(1)
OLATB CON $15 'Register address to MCP23S17 LATB(2)
DataOut var BYTE
Voltage VAR WORD 'Variable for manipulating Voltage as full 16 bit word
VoltageFst VAR Voltage.BYTE0 'Variable for Voltage Byte 0 to Send to MCP23S17A-A
VoltageSec VAR Voltage.BYTE1 'Variable for Voltage Byte 1 to Send to MCP23S17A-B
Param Var BYTE 'Variable for Parameters Byte to Send to MCP23S17B-A
RD VAR Param.0 'Varible to set read bit on IP Board - 0 = Read
WR VAR Param.1 'Varible to set write bit on IP Board - 1 = Write
O4 VAR Param.2 'Varible unused 4
RY VAR Param.3 'Varible to set Relay bit on IP Board - 1 = Relay Pulled
O3 VAR Param.4 'Varible unused 3
O2 VAR Param.5 'Varible unused 2
CH1 VAR Param.6 'Varible bit 0 of ADC channel select
CH0 VAR Param.7 'Varible bit 1 of ADC channel select
AuxPort Var BYTE 'Variable for Aux Port Byte to Send to the MCP23S17B-B
UPbtnvar Var BYTE 'Variable for UP Button
DWNbtnvar VAR BYTE 'Variable for DOWN Button
MCPReg VAR BYTE 'Variable for the Register to Send to the MCP23S17
MCPWRT var BYTE 'Command o write in MCP23S17 Address $00
MCPRED var BYTE 'Command o read from MCP23S17 Address $00
' INIT
' ================================================== ==============
UPbtnvar = 0
DWNbtnvar = 0
ncsa = 1
'ncsb = 1
nRST = 0 'Reset the port expanders
PAUSE 1
nRST = 1
MCPReg = IOCON 'Configures MCP23S17-A
DataOut = $28
nCSA = 0 'Enable MCP23S17-A
SHIFTOUT SDO, SCLK, 1, [MCP23A,MCPReg,DataOut]
nCSA = 1 'Disable MCP23S17-A
MCPReg = IODIRA 'Configures PortA(1) All Output
DataOut = $00
nCSA = 0 'Enable MCP23S17-A
SHIFTOUT SDO, SCLK, 1, [MCP23A,MCPReg,DataOut]
nCSA = 1 'Disable MCP23S17-A
MCPReg = IODIRB 'Configures PortB(2) All Output
DataOut = $00
nCSA = 0 'Enable MCP23S17-A
SHIFTOUT SDO, SCLK, 1, [MCP23A,MCPReg,DataOut]
nCSA = 1 'Disable MCP23S17-A
MCPReg = IOCON 'Configures the MCP23S17
DataOut = $28
nCSA = 0 'Enable MCP23S17-B
SHIFTOUT SDO, SCLK, 1, [MCP23B,MCPReg,DataOut]
nCSA = 1 'Disable the MCP23S17
MCPReg = IODIRA 'Configures PortA(1) All Output
DataOut = $00
nCSA = 0 'Enable MCP23S17-B
SHIFTOUT SDO, SCLK, 1, [MCP23B,MCPReg,DataOut]
nCSA = 1 'Disable the MCP23S17
MCPReg = IODIRB 'Configures PortB(2) All Output
DataOut = $00
nCSA = 0 'Enable MCP23S17-B
SHIFTOUT SDO, SCLK, 1, [MCP23B,MCPReg,DataOut]
nCSA = 1 'Disable the MCP23S17
AuxPort = %00000000
GOSUB SEND_AuxPort
' _
' |CH|--|RY|-|W|R
Param = %00001010 ' 00 00 1 0 1 0
GOSUB SEND_Param
Voltage = 0
GOSUB SEND_Voltage
' MAIN LOOP
' ================================================== =============
MAIN:
BUTTON DWNbtn,1,255,255,DWNbtnvar,1,BtnDwn
BUTTON UPbtn,1,255,255,UPbtnvar,1,BtnUp
GOSUB Transmit
GOTO MAIN
' SUB - ROTINES
' ================================================== ==============
BtnUp:
IF Voltage >= 65535 THEN
gOTO MAIN
ENDIF
Voltage = (Voltage + 1)
GOSUB SEND_Voltage
'pause 50
GOTO MAIN
BtnDwn:
IF Voltage = 0 THEN
GOTO MAIN
ENDIF
Voltage = (Voltage - 1)
GOSUB SEND_Voltage
'pause 50
GOTO MAIN
Transmit:
xmit = 1
PAUSEUS 1
xmit = 0
pause 50
RETURN
SEND_Voltage:
Voltage = Voltage REV 16
nCSA = 0 'Enable MCP23S17-A
SHIFTOUT SDO, SCLK, 1, [MCP23A,OLATA,VoltageFst]
nCSA = 1 'Disable the MCP23S17
pause 1
nCSA = 0 'Enable MCP23S17-A
SHIFTOUT SDO, SCLK, 1, [MCP23A,OLATB,VoltageSec]
nCSA = 1 'Disable the MCP23S17
RETURN
SEND_Param:
nCSA = 0 'Enable MCP23S17-B
SHIFTOUT SDO, SCLK, 1, [MCP23B,OLATA,Param]
nCSA = 1 'Disable the MCP23S17
RETURN
SEND_AuxPort:
nCSA = 0 'Enable MCP23S17-B
SHIFTOUT SDO, SCLK, 1, [MCP23B,OLATB,Auxport]
nCSA = 1 'Disable the MCP23S17
RETURN
goto main
END