PIC32MX370F512T SPI通信
MCP23S17 SPI16bits IOエキスパンダーとSPI通信させます。
SPI2 コード
PIC32_SPI2.h
#ifndef DSSSP2_H
#define DSSSP2_H
#ifdef __cplusplus
extern "C" {
#endif
#include <xc.h>
#include <cp0defs.h>
#include <sys/attribs.h>
#include <stdio.h>
#include <stdbool.h>
#include "peripheral.h"
#define Low 0
#define High 1
#define SPI2_CS LATBbits.LATB5
typedef struct{
uint8_t val;
bool error;
}_SPI_RD;
extern _SPI_RD SPI_RD;
extern void Spi2Init(void);
extern void SPI2_Start(void);
extern uint8_t SPI2_Write(unsigned char _data);
extern bool SPI2_Write3byte(unsigned char _data0,unsigned char _data1,unsigned char _data2);
extern _SPI_RD SPI2_Read(void);
extern void SPI2_Stop(void);
/*-----------------------------------*/
//MCP23S08 I/O expander
/*-----------------------------------*/
#define MCP23S08_Device1Add 0x40
#define MCP23S08_Device2Add 0x42
#define MCP23S_R 1
#define MCP23S_W 0
typedef enum
{
IODIR=0x00,
IPOL,
GPINTEN,
DEFVAL,
INTCN,
IOCON,
GPPU,
mINTF,
INTCAP,
GPIO,
OLAT=0x0A
}_reg;
extern unsigned char reg_value[10];
extern bool MCP23S_Init(uint8_t _device_add);
extern bool MCP23S_SendOPcode(uint8_t _device_add, uint8_t _reg_add, uint8_t RW);
extern bool MCP23S_WriteReg(uint8_t _device_add,uint8_t _reg_add, uint8_t _data);
extern bool MCP23S_b2Write(uint8_t _device_add, uint8_t _data1, uint8_t _data2);
extern uint8_t MCP23S_b1ReadReg(uint8_t _device_add, uint8_t _reg_add);
#ifdef __cplusplus
}
#endif
#endif /* SSP1_H */
PIC32_SPI2.c
#include "PIC32_SPI2.h"
_SPI_RD SPI_RD;
//3pin mode
void Spi2Init(void)
{
//1.using Interrupt
IFS1bits.SPI2EIF=0;
IEC1bits.SPI2EIE=0;
//2.Master Mode
SPI2CONbits.DISSDI=0;
SPI2CONbits.DISSDO=0;
SPI2CONbits.MODE16=0;
SPI2CONbits.SMP=1;
SPI2CONbits.CKE=1;
SPI2CONbits.CKP=0;
SPI2CONbits.MSTEN=1;//master mode
//3.SPI baudrate
//SPI2BRG=255;
SPI2BRG=1;//20Mhz Fpb=80Mhz
SPI2STATbits.SPIROV=0;
SPI2CON2=0x0000;
SPI2CONbits.ENHBUF=0;//FIFObusser no use:0
//5.Port pin
//SDO2 RD11
RPD11Rbits.RPD11R = 0b0110;
//SDI2 RD3
SDI2R = 0b0000;//RPD3
TRISD|=0x0008; //RD3
//4.SPI enable
SPI2CONbits.ON=1;//1:Enable SPI
}
void SPI2_Start(void)
{
SPI2_CS=Low;
}
uint8_t SPI2_Write(unsigned char _data)
{
int i;
unsigned char buf;
i=0;
buf=SPI2BUF;
for(i=0x7FFF; i; i--)
{
if(!SPI2STATbits.SPITBF)
{
break;
}
}
SPI2BUF=_data;
for(i=0x7FFF; i; i--)
{
if(!SPI2STATbits.SPITBF)
{
break;
}
}
for(i=0x7FFF; i; i--)
{
if(!SPI2STATbits.SPIBUSY)
{
return true;
}
}
return false;
}
bool SPI2_Write3byte(unsigned char _data0,unsigned char _data1,unsigned char _data2)
{
int i,j;
unsigned char buf;
for(j=0; j<3; j++)
{
buf=SPI2BUF;
for(i=0x7FFF; i; i--)
{
if(!SPI2STATbits.SPITBF)
{
break;
}
}
if(j==0)
SPI2BUF=_data0;
if(j==1)
SPI2BUF=_data1;
if(j==2)
SPI2BUF=_data2;
for(i=0x7FFF; i; i--)
{
if(!SPI2STATbits.SPITBF)
{
break;
}
}
for(i=0x7FFF; i; i--)
{
if(IFS1bits.SPI1EIF)
{
IFS1bits.SPI1EIF=0;
break;
}
}
}
return true;
}
_SPI_RD SPI2_Read(void)
{
signed int i;
SPI_RD.error=true;
SPI_RD.val=0xFC;
for(i=0x7FFF; i; i--)
{
if(SPI2STATbits.SPIRBF)
{
SPI_RD.val=SPI2BUF;
SPI_RD.error=false;
break;
}
}
return SPI_RD;
}
void SPI2_Stop(void)
{
unsigned char buf;
buf=SPI2BUF;
SPI2_CS=High;
__delay_us(10);
}
/*-----------------------------------*/
//MCP23S08 I/O expander
/*-----------------------------------*/
_reg MCP23S08reg;
unsigned char reg_value[10]={0x00,0x00,0x00,0x00,0x18,
0xFF,0x00,0x00,0x00,0x00};
_SPI_RD SPI_RD;
bool MCP23S_Init(uint8_t _device_add)
{
bool ret;
ret=MCP23S_WriteReg(_device_add,IODIR,0x00);
if(!ret) return 0xB1;
__delay_ms(1);
ret=MCP23S_WriteReg(_device_add,IOCON,0x38);
if(!ret) return 0xB2;
return true;
}
bool MCP23S_SendOPcode(uint8_t _device_add, uint8_t _reg_add, uint8_t RW)
{
bool ret=false;
ret=SPI2_Write(_device_add|RW);
if(!ret)
{
return false;
}
ret=SPI2_Write(_reg_add);
if(!ret)
{
return false;
}
return ret;
}
bool MCP23S_WriteReg(uint8_t _device_add,uint8_t _reg_add, uint8_t _data)
{
bool ret=false;
SPI2_Start();
ret=MCP23S_SendOPcode(_device_add, _reg_add, MCP23S_W);
if(ret!=true)
return 0xF1;
ret=SPI2_Write(_data);
if(ret!=true)
return 0xF2;
SPI2_Stop();
return ret;
}
bool MCP23S_b2Write(uint8_t _device_add, uint8_t _data1, uint8_t _data2)
{
bool ret=false;
SPI2_Start();
ret=SPI2_Write(_device_add|MCP23S_W);
if(ret!=true)
return 0xF1;
ret=SPI2_Write(_data1);
if(ret!=true)
return 0xF2;
ret=SPI2_Write(_data2);
if(ret!=true)
return 0xF3;
SPI2_Stop();
return ret;
}
uint8_t MCP23S_b1ReadReg(uint8_t _device_add, uint8_t _reg_add)
{
bool ret;
_SPI_RD rdRet;
SPI2_Start();
ret=SPI2_Write(_device_add|MCP23S_R);
if(!ret)
{
return false;
}
ret=SPI2_Write(_reg_add);
if(!ret)
{
return false;
}
SPI2_Write(0xFF);
rdRet=SPI2_Read();
SPI2_Stop();
if(rdRet.error)
{
return rdRet.val=0xFE;
}
return rdRet.val;
}
ds_MCP23S17.h
#ifndef DS_MCP23S17_H
#define DS_MCP23S17_H
#include <xc.h>
#include "PIC32_SPI2.h"
#define MCP23S17_deviceAdd1 0x4E
#define MCP23S17_deviceAdd2 0x46
extern void MCP23S17Init(uint8_t _deviceAdd);
extern void MCP23Sdebug(uint8_t _deviceAdd);
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* DS_MCP23S17_H */
ds_MCP23S17.c
#include "PIC32_SPI2.h"
void MCP23S17Init(uint8_t _deviceAdd)
{
uint8_t ret,regVal[6];
ret=MCP23S_WriteReg(_deviceAdd, 0x0A, 0xA8);
regVal[0]=MCP23S_b1ReadReg(_deviceAdd,0x05);
//printf("0x05=%02x ",regVal);
regVal[1]=MCP23S_b1ReadReg(_deviceAdd,0x15);
// printf("0x0A=%02x ",regVal);
__delay_ms(1);
ret=MCP23S_b2Write(_deviceAdd,0x00,0x00);//IOCON.bank=1 HAEN=1
ret=MCP23S_b2Write(_deviceAdd,0x0A,0x00);
ret=MCP23S_b2Write(_deviceAdd,0x10,0x00);
ret=MCP23S_b2Write(_deviceAdd,0x1A,0x00);
regVal[0]=MCP23S_b1ReadReg(_deviceAdd,0x00);
regVal[1]=MCP23S_b1ReadReg(_deviceAdd,0x0A);
regVal[2]=MCP23S_b1ReadReg(_deviceAdd,0x10);
regVal[3]=MCP23S_b1ReadReg(_deviceAdd,0x1A);
regVal[4]=MCP23S_b1ReadReg(_deviceAdd,0x05);
}
void MCP23Sdebug(uint8_t _deviceAdd)
{
while(1)
{
MCP23S_b2Write(_deviceAdd,0x0A,0x55);
MCP23S_b2Write(_deviceAdd,0x0A,0x55);
MCP23S_b2Write(_deviceAdd,0x1A,0x55);
MCP23S_b2Write(_deviceAdd,0x1A,0x55);
__delay_ms(500);
MCP23S_b2Write(_deviceAdd,0x0A,0xAA);
MCP23S_b2Write(_deviceAdd,0x0A,0xAA);
MCP23S_b2Write(_deviceAdd,0x1A,0xAA);
MCP23S_b2Write(_deviceAdd,0x1A,0xAA);
__delay_ms(500);
}
}
main関数内の、Timer1割り込み処理(フラグ処理)で、IOエキスパンダーのLEDを点滅させています。
main.c
// PIC32MX370F512H Configuration Bit Settings
// 'C' source line config statements
// DEVCFG3
#pragma config USERID = 0xFFFF // Enter Hexadecimal value (Enter Hexadecimal value)
#pragma config FSRSSEL = PRIORITY_7 // Shadow Register Set Priority Select (SRS Priority 7)
#pragma config PMDL1WAY = OFF // Peripheral Module Disable Configuration (Allow multiple reconfigurations)
#pragma config IOL1WAY = OFF // Peripheral Pin Select Configuration (Allow multiple reconfigurations)
// DEVCFG2
#pragma config FPLLIDIV = DIV_2 // PLL Input Divider (2x Divider)
#pragma config FPLLMUL = MUL_20 // PLL Multiplier (20x Multiplier)
#pragma config FPLLODIV = DIV_2 // System PLL Output Clock Divider (PLL Divide by 1)
// DEVCFG1
#pragma config FNOSC = FRCPLL // Oscillator Selection Bits (Fast RC Osc with PLL)
#pragma config FSOSCEN = OFF // Secondary Oscillator Enable (Disabled)
#pragma config IESO = OFF // Internal/External Switch Over (Disabled)
#pragma config POSCMOD = OFF // Primary Oscillator Configuration (Primary osc disabled)
#pragma config OSCIOFNC = OFF // CLKO Output Signal Active on the OSCO Pin (Disabled)
#pragma config FPBDIV = DIV_1 // Peripheral Clock Divisor (Pb_Clk is Sys_Clk/1)
#pragma config FCKSM = CSECMD // Clock Switching and Monitor Selection (Clock Switch Enable, FSCM Disabled)
#pragma config WDTPS = PS1048576 // Watchdog Timer Postscaler (1:1048576)
#pragma config WINDIS = OFF // Watchdog Timer Window Enable (Watchdog Timer is in Non-Window Mode)
#pragma config FWDTEN = OFF // Watchdog Timer Enable (WDT Disabled (SWDTEN Bit Controls))
#pragma config FWDTWINSZ = WINSZ_25 // Watchdog Timer Window Size (Window Size is 25%)
// DEVCFG0
#pragma config DEBUG = OFF // Background Debugger Enable (Debugger is Disabled)
#pragma config JTAGEN = OFF // JTAG Enable (JTAG Disabled)
#pragma config ICESEL = ICS_PGx2 // ICE/ICD Comm Channel Select (Communicate on PGEC2/PGED2)
#pragma config PWP = OFF // Program Flash Write Protect (Disable)
#pragma config BWP = OFF // Boot Flash Write Protect bit (Protection Disabled)
#pragma config CP = OFF // Code Protect (Protection Disabled)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#include <xc.h>
#include <stdio.h>
#include <cp0defs.h>
#include <sys/attribs.h>
#include "peripheral.h"
#include "PIC32_I2C1driver.h"
#include "I2C_LCD.h"
#include "PIC32_SPI2.h"
#include "ds_MCP23S17.h"
void portInit(void)
{
TRISB=0x0000;
TRISC=0x0000;
TRISD=0x0000;
TRISE=0x0000;
TRISF=0x0000;
TRISG=0x0000;
ANSELB=0x0000;
ANSELC=0x0000;
ANSELD=0x0000;
ANSELE=0x0000;
ANSELF=0x0000;
ANSELG=0x0000;
PORTB=0x0000;
PORTC=0x0000;
PORTD=0x0000;
PORTE=0x0000;
PORTF=0x0000;
PORTG=0x0000;
}
void main(void)
{
uint8_t val,length;
uint8_t txt[10];
unsigned int counter=0x0000;
uint32_t address;
unsigned int tmp_CP0_Status; // Temporary register for CP0 reg storing
//oscillator init---------------------------------
SYSKEY = 0x0; // ensure OSCCON is locked
SYSKEY = 0xAA996655; // Write Key1 to SYSKEY
SYSKEY = 0x556699AA; // Write Key2 to SYSKEY
//PLL Output Divisor bits
OSCCONbits.PLLODIV=0b000; //000 = PLL output divided by 1
//PeripheralBusClock diviser.
OSCCONbits.PBDIV=0b00; //SYSCLK divided by1
SYSKEY = 0x0; // ensure OSCCON is locked
//port init---------------------------------------
portInit();
//peripheral initializing-------------------------
timer1Init();
I2C1_Init();
LCD_Init(LcdDeviceAdd);
I2C1BRG=0x003D;//600khz Fp=80Mhz
LCD_Printf(LcdDeviceAdd,"PIC32MX",7,0x80);
usartInit();
__delay_ms(10);//これを入れないとazが出力されない。
putchar('a');putchar('z');
Spi2Init();
MCP23S17Init(MCP23S17_deviceAdd1);
//MCP23Sdebug(MCP23S17_deviceAdd1);
//interrupt initializing-------------------------
printf("\nPIC32MX370F512HT\n");
//割り込み関連
address=_CP0_GET_EBASE();//例外ベクタアドレス
printf("EBASE=%lx\n",address);
INTCONbits.MVEC=1;
tmp_CP0_Status=_CP0_GET_STATUS();
tmp_CP0_Status|=0x00000001;//CP0.STATUS.IE=1で割り込み許可
_CP0_SET_STATUS(tmp_CP0_Status);
// __builtin_enable_interrupts();
while(1)
{
if(rxU1.completed)
{
rxU1.completed=false;
printf("%s\r",rxU1.buf);
rxU1.length=0;
IEC1bits.U1RXIE=1;
}
if(tm1.fg)
{
tm1.fg=false;
LATBbits.LATB0=~LATBbits.LATB0;
I2C1_b1Write(0x4A,val);
MCP23S_b2Write(MCP23S17_deviceAdd1,0x0A,val);
MCP23S_b2Write(MCP23S17_deviceAdd1,0x0A,val);
MCP23S_b2Write(MCP23S17_deviceAdd1,0x1A,val);
MCP23S_b2Write(MCP23S17_deviceAdd1,0x1A,val);
if(val==0x55)
val=0xAA;
else
val=0x55;
length=sprintf(txt,"%8ld",counter++);
LCD_Printf(LcdDeviceAdd,txt,length,0xC0);
IEC0bits.T1IE=1;
}
}
return;
}