通信相手は、microchip社のMCP23S17(IOエクスパンダ)。試したのはマイコンからの送信のみ。受信は後日。
SPI2を使うための手順は、以下。
- GPIOのクロックを有効化
- GPIOの初期化
- SPI2のクロックを有効化
- SPI2の初期化
- SPI2が割当てられている端子をGPIO→AF使用に設定
- SPI2を有効化
main.cのほかに、mcp23s17.cとmcp23s17.hを作ってリンクする。
ソースコードは以下。
main.c
メインモジュール#include "stm32f4xx.h" #include "mcp23s17.h" /* time : 約1uSec,1000000=1sec */ void delay(uint32_t time){ uint32_t t; volatile uint8_t i; for(i=0;i<24;i++){ t = time; while(t--); } } // void spi2_init(void){ // structure to initialize GPIO GPIO_InitTypeDef GPIO_InitStructure; // GPIOB , SPI2 のクロックを有効化 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; // PB13(SCK),PB14(MISO),PB15(MOSI) GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_Init(GPIOB,&GPIO_InitStructure); //GPIOBのPIN13-15をオルタネィテブファンクションのSPI2に割り当て GPIO_PinAFConfig(GPIOB , GPIO_PinSource13 , GPIO_AF_SPI2); GPIO_PinAFConfig(GPIOB , GPIO_PinSource14 , GPIO_AF_SPI2); GPIO_PinAFConfig(GPIOB , GPIO_PinSource15 , GPIO_AF_SPI2); // PB12 はSPI2のCSとして使用 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; // PB12(NSS) GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_Init(GPIOB,&GPIO_InitStructure); // SPI2 設定 SPI_InitTypeDef SPI_InitStructure; SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_Init(SPI2 , &SPI_InitStructure); SPI_Cmd(SPI2,ENABLE); } int main(void) { /* structure to initialize GPIO */ GPIO_InitTypeDef GPIO_InitStructure; SystemInit(); // -------------------------------------------------- // Port A 設定(SW入力) ここから // SW on = 1 , off = 0 // supply the clock to AHB1(GPIOD) RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //GPIO pin configuration GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_Init(GPIOA,&GPIO_InitStructure); // Port A 設定(SW入力) ここから // -------------------------------------------------- // -------------------------------------------------- // Port D 設定(LED出力) ここから // PD12(LED4) , PD13(LED3) , PD14(LED5) , PD15(LED6) // GPIOD->BSRRL(点灯) , GPIOD->BSRRH(消灯) // supply the clock to AHB1(GPIOD) RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,ENABLE); //GPIO pin configuration GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOD,&GPIO_InitStructure); // Port D 設定(LED出力) ここまで // -------------------------------------------------- spi2_init(); while(1){ if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)){ //ボタンが押されて1になっていたら以下を実行 GPIO_SetBits(GPIOD,GPIO_Pin_13); // 点灯 while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)); // ボタンを放したら以下を実行 mcp23s17_init(SPI2); mcp23s17_wr(SPI2,MCP23S17_IODIRA,0x00); mcp23s17_wr(SPI2,MCP23S17_GPIOA,0x01); delay(1000000); mcp23s17_wr(SPI2,MCP23S17_GPIOA,0x02); delay(1000000); mcp23s17_wr(SPI2,MCP23S17_GPIOA,0x04); delay(1000000); mcp23s17_wr(SPI2,MCP23S17_GPIOA,0x08); delay(1000000); mcp23s17_wr(SPI2,MCP23S17_GPIOA,0x04); delay(1000000); mcp23s17_wr(SPI2,MCP23S17_GPIOA,0x02); delay(1000000); mcp23s17_wr(SPI2,MCP23S17_GPIOA,0x01); delay(1000000); }else{ GPIO_ResetBits(GPIOD,GPIO_Pin_13); // 消灯 } } return 0; }
mcp23s17.c
MCP23S17にアクセスするためのモジュールとか。#include "stm32f4xx.h" #include "mcp23s17.h" /* MCP23S17 初期化 BANK = 0 MIRROR = 0 SEQOP = 1 (disable) DISSLW = 0 HAEN = 0 ODR = 0 INTPOL = 0 */ void mcp23s17_init(SPI_TypeDef *SPIx){ MCP23S17_CS_ON(); while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET); // 送信バッファが空 SPI_I2S_SendData(SPIx,MCP23S17_WR); while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET); // 送信バッファが空 SPI_I2S_SendData(SPIx,MCP23S17_IOCONA); while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET); // 送信バッファが空 SPI_I2S_SendData(SPIx,0x20); while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_BSY) == SET); // 送信完了待ち MCP23S17_CS_OFF(); MCP23S17_CS_ON(); while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET); // 送信バッファが空 SPI_I2S_SendData(SPIx,MCP23S17_WR); while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET); // 送信バッファが空 SPI_I2S_SendData(SPIx,MCP23S17_IOCONB); while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET); // 送信バッファが空 SPI_I2S_SendData(SPIx,0x20); while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_BSY) == SET); // 送信完了待ち MCP23S17_CS_OFF(); } /* MCP23S17 ライト */ void mcp23s17_wr(SPI_TypeDef *SPIx , uint8_t reg , uint8_t data){ MCP23S17_CS_ON(); while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET); // 送信バッファが空 SPI_I2S_SendData(SPIx,MCP23S17_WR); while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET); // 送信バッファが空 SPI_I2S_SendData(SPIx,reg); while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET); // 送信バッファが空 SPI_I2S_SendData(SPIx,data); while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_BSY) == SET); // 送信完了待ち MCP23S17_CS_OFF(); }
mcp23s17.h
MCP23S17にアクセスするための定義とか。#ifndef _H_MCP23S17_ #define _H_MCP23S17_ /* MCP23S17 register map */ #define MCP23S17_IODIRA 0x00 #define MCP23S17_IODIRB 0x01 #define MCP23S17_IPOLA 0x02 #define MCP23S17_IPOLB 0x03 #define MCP23S17_GPINTENA 0x04 #define MCP23S17_GPINTENB 0x05 #define MCP23S17_DEFVALA 0x06 #define MCP23S17_DEFVALB 0x07 #define MCP23S17_INTCONA 0x08 #define MCP23S17_INTCONB 0x09 #define MCP23S17_IOCONA 0x0A #define MCP23S17_IOCONB 0x0B #define MCP23S17_GPPUA 0x0C #define MCP23S17_GPPUB 0x0D #define MCP23S17_INTFA 0x0E #define MCP23S17_INTFB 0x0F #define MCP23S17_INTCAPA 0x10 #define MCP23S17_INTCAPB 0x11 #define MCP23S17_GPIOA 0x12 #define MCP23S17_GPIOB 0x13 #define MCP23S17_OLATA 0x14 #define MCP23S17_OLATB 0x15 #define MCP23S17_CS_ON() GPIO_ResetBits(GPIOB,GPIO_Pin_12) #define MCP23S17_CS_OFF() GPIO_SetBits(GPIOB,GPIO_Pin_12) #define MCP23S17_WR 0x40 #define MCP23S17_RD 0x41 void mcp23s17_init(SPI_TypeDef *SPIx); void mcp23s17_wr(SPI_TypeDef *SPIx , uint8_t reg , uint8_t data); #endif
0 件のコメント:
コメントを投稿