MCP23S17の初期設定(with ATmega328PB)

 参考までに以下は前回のブログでの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を使った方が確実です。