0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PIC32MX370F512F 64pin (4) SPI通信

Last updated at Posted at 2024-10-23

PIC32MX370F512T SPI通信

IMG_5023.JPG

MCP23S17 SPI16bits IOエキスパンダーとSPI通信させます。

PIC32MXのSPI2モジュールで駆動。

SPI2 SCK: 4番ピン RG6(固定)
SPI2 SDI:51番ピン RD3(PPS割り付け)
SPI2 SDO:45番ピン RD11(PPS割り付け)
SPI2 CS:11番ピン RB5(define定義)

pin割り付け表.png

SPIのボーレート設定レジスタの値

SPI速度計算.png

Section 23. Serial Peripheral Interface (SPI) DS61106G-page 23-29
PIC32MX_SPIデータシートBRG計算.png

BRG値表計算.png

BRGレジスタの値を1にしました。よって速度は、Fpb=80Mhzなので、Fsck=20Mhzで通信します。

BRG設定
SPI2BRG=1;//Fsck=20Mhz Fpb=80Mhz

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;
}

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?