通信相手は、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 件のコメント:
コメントを投稿