参考までに以下は前回のブログでのMCP23S17の初期設定のコード(コンパイラはBASCOM-AVR)です。MCP23S17と関係のある個所のみで、他の設定と処理は省略。
BASCOMを使われている方はそれほど多くないと思いますが、コピーされたい方はお使いください。CPUはATmega328PB、クロック16MHzで動作検証済みです。ソフトSPIの場合、命令語にSPI0やSPI1の様にチャンネル番号は付かないのでご注意を。ソフトSPIですからポートは変更しても問題無いはずです。変更されるときはポートの入出力設定の変更をお忘れ無く。回路図(一部抜粋)は一番下にPDFで置いてあります。
(一部訂正)config spiにおいて、Mode=0が抜けていたので追記。また、IOCONAとIOCONBは共通なのでIOCONAにのみ初期設定。(B側にあったオープンドレイン設定はA側での設定にしIOCONBの設定はコメント化。)
'SPI initialize
Config Spi = Soft , Clock = Portc.1 , Dout = Porte.3 , Din = Pinc.0 , Ss = None , Mode = 0
Dim Port_data As Byte 'output data for spi
Dim S_data(5) As Byte 'write data for spiout
'for MCP23S17 --------------
Dim Mcp23s17_write As Byte 'device opcode(write)
Dim Mcp23s17_read As Byte 'device opcode(read)
Dim Iodira_adrs As Byte
Dim Iodirb_adrs As Byte
Dim Ipola_adrs As Byte
Dim Ipolb_adrs As Byte
Dim Gpintena_adrs As Byte
Dim Gpintenb_adrs As Byte
Dim Defvala_adrs As Byte
Dim Defvalb_adrs As Byte
Dim Intcona_adrs As Byte
Dim Intconb_adrs As Byte
Dim Iocona_adrs As Byte
Dim Ioconb_adrs As Byte
Dim Gppua_adrs As Byte
Dim Gppub_adrs As Byte
Dim Intfa_adrs As Byte
Dim Intfb_adrs As Byte
Dim Intcapa_adrs As Byte
Dim Intcapb_adrs As Byte
Dim Gpioa_adrs As Byte
Dim Gpiob_adrs As Byte
Dim Olata_adrs As Byte
Dim Olatb_adrs As Byte
'---------------------------
Set Porte.2 'MCP23S17 /CS to high
'ポートの入出力設定
Config Portc.0 = Input 'MISO1
Config Portc.1 = Output 'SCK1
Config Porte.2 = Output 'MCP23S17 /CS Hard-SPIなら設定不要
Config Porte.3 = Output 'MOSI1
Spiinit
'初期化のためのアドレスとデータの定義
Mcp23s17_write = &H40
Mcp23s17_read = &H41
Iodira_adrs = &H00
Iodirb_adrs = &H01
Ipola_adrs = &H02
Ipolb_adrs = &H03
Gpintena_adrs = &H04
Gpintenb_adrs = &H05
Defvala_adrs = &H06
Defvalb_adrs = &H07
Intcona_adrs = &H08
Intconb_adrs = &H09
Iocona_adrs = &H0A
Ioconb_adrs = &H0B
Gppua_adrs = &H0C
Gppub_adrs = &H0D
Intfa_adrs = &H0E
Intfb_adrs = &H0F
Intcapa_adrs = &H10
Intcapb_adrs = &H11
Gpioa_adrs = &H12
Gpiob_adrs = &H13
Olata_adrs = &H14
Olatb_adrs = &H15
'以下は処理用のサブルーチン
Mcp_initial:
'Mcp23S17 -----------------------------------------------------------------------------------
'set IOCONA
S_data(1) = Mcp23s17_write 'set opcode
S_data(2) = Iocona_adrs 'set reg-adrs
S_data(3) = &B00100100 'set data BANK=0 アドレス連続 シーケンシャル動作無効 オープンドレイン出力
Gosub Spiwr_sub
'set IOCONB
'S_data(1) = Mcp23s17_write 'set opcode
'S_data(2) = Ioconb_adrs 'set reg-adrs
'S_data(3) = &B00100100 'set data BANK=0 アドレス連続 シーケンシャル動作無効 オープンドレイン出力
'Gosub Spiwr_sub
'set IODIRA(全て出力)
S_data(1) = Mcp23s17_write 'set opcode
S_data(2) = Iodira_adrs 'set reg-adrs
S_data(3) = &B00000000 'set data
Gosub Spiwr_sub
'set IODIRB(全て入力)
S_data(1) = Mcp23s17_write 'set opcode
S_data(2) = Iodirb_adrs 'set reg-adrs
S_data(3) = &B11111111 'set data
Gosub Spiwr_sub
'set GPPUA(プルアップ無し)
'S_data(1) = Mcp23s17_write 'set opcode
'S_data(2) = Gppua_adrs 'set reg-adrs
'S_data(3) = &B00000000 'set data
'Gosub Spiwr_sub
'Set Gppub(プルアップ無し)
S_data(1) = Mcp23s17_write 'set opcode
S_data(2) = Gppub_adrs 'set reg-adrs
S_data(3) = &B00000000 'set data
Gosub Spiwr_sub
'set GPINTENA
'S_data(1) = Mcp23s17_write 'set opcode
'S_data(2) = Gpintena_adrs 'set reg-adrs
'S_data(3) = &B00000000 'set data 状態変化割り込み無効
Gosub Spiwr_sub
'set DEFVALA
'S_data(1) = Mcp23s17_write 'set opcode
'S_data(2) = Defvala_adrs 'set reg-adrs
'S_data(3) = &B00000000 'set data
'Gosub Spiwr_sub
'set DEFVALB(プルアップなので全て1)
S_data(1) = Mcp23s17_write 'set opcode
S_data(2) = Defvalb_adrs 'set reg-adrs
S_data(3) = &B11111111 'set data fault状態と反対の論理に設定(=全て1)
Gosub Spiwr_sub
'set INTCONA
'S_data(1) = Mcp23s17_write 'set opcode
'S_data(2) = Intcona_adrs 'set reg-adrs
'S_data(3) = &B00000000 'set data
'Gosub Spiwr_sub
'set INTCONB (全て入力)
S_data(1) = Mcp23s17_write 'set opcode
S_data(2) = Intconb_adrs 'set reg-adrs
S_data(3) = &B11111111 'set data 全てのビットでDEFBALBレジスタと比較
Gosub Spiwr_sub
'set GPINTENB(状態変化割り込み有効)
S_data(1) = Mcp23s17_write 'set opcode
S_data(2) = Gpintenb_adrs 'set reg-adrs
S_data(3) = &B11111111 'set data 状態変化割り込み有効
Gosub Spiwr_sub
Port_data = 0 'DATA output
Gosub Spiout_sub 'GPA 出力全てLow
Waitus 10
Return
Spiwr_sub:
Reset Porte.2 'CS-low
Waitus 1
Spiout S_data(1) , 3 '3byte write
Waitus 5
Set Porte.2 'CS-high
Return
Spird_sub:
Reset Porte.2 'CS-low
Waitus 1
Spiin S_data(1) , 3 '3byte write
Waitus 5
Set Porte.2 'CS-high
Return
Spiout_sub: 'MCP23S17-0(Lower)
S_data(1) = Mcp23s17_write 'set adrs (&H40)
S_data(2) = Olata_adrs 'set olata adrs (&H12)
S_data(3) = Port_data 'set byte data
Gosub Spiwr_sub
Return
CPUとMCP23S17の接続(全体回路図からの一部抜粋)はこちら。リセットは4.3VのリセットICをCPUとエキスパンダに使っています。どちらにもパワーオンリセット機能がありますが、共通にしないと起動のタイミングが揃わない可能性があるためにリセットICを使った方が確実です。