Чтение данных через интерфейс SPI в микроконтроллере PIC24E - PullRequest
0 голосов
/ 26 апреля 2020

Я пытаюсь прочитать данные через интерфейс SPI в микроконтроллере PIC24E , который работает с использованием внешней тактовой частоты 32 МГц и скорости передачи данных SPI 4 МГц. Я могу настроить порт SPI2 в стандартном режиме работы для автоматической отправки тактовых импульсов, когда сигнал выбора микросхемы в AD C становится низким и данные записываются в SPI2BUF. Наблюдая за сигналом контакта SDO через осциллограф, я могу определить, что правильные данные записываются в AD C. При обратном чтении я пытаюсь вернуть записанные данные из AD C, выбрав AD C и записав SPI2BUF в рабочий регистр WREG0. Наблюдая за сигналом контакта SDI, я вижу, что вернулись и правильные данные. Однако значение SPI2BUF, наблюдаемое через отладчик, равно 0. Я проверил сигналы CKE и CKP для порта SPI2, и все они также в порядке. Я хотел бы знать, пропустил ли я что-то, или я что-то упускаю. Ниже приведен код, с которым я работаю.

// FGS
#pragma config GWRP = OFF               // General Segment Write-Protect bit (General Segment may be written)
#pragma config GSS = OFF                // General Segment Code-Protect bit (General Segment Code protect is disabled)
#pragma config GSSK = OFF               // General Segment Key bits (General Segment Write Protection and Code Protection is 

Disabled)

// FOSCSEL
#pragma config FNOSC = PRI              // Initial Oscillator Source Selection bits (Internal Fast RC (FRC))
#pragma config IESO = ON                // Two-speed Oscillator Start-up Enable bit (Start up device with FRC, then switch to 

user-selected oscillator source)

// FOSC
#pragma config POSCMD = EC            // Primary Oscillator Mode Select bits (Primary Oscillator disabled)
#pragma config OSCIOFNC = OFF           // OSC2 Pin Function bit (OSC2 is clock output)
#pragma config IOL1WAY = OFF            // Peripheral pin select configuration (Allow multiple reconfigurations)
#pragma config FCKSM = CSECMD           // Clock Switching Mode bits (Clock switching is enabled,Fail-safe Clock Monitor is 

disabled)

// FWDT
#pragma config WDTPOST = PS32768        // Watchdog Timer Postscaler bits (1:32,768)
#pragma config WDTPRE = PR128           // Watchdog Timer Prescaler bit (1:128)
#pragma config PLLKEN = ON              // PLL Lock Wait Enable bit (Clock switch to PLL source will wait until the PLL lock 

signal is valid.)
#pragma config WINDIS = OFF             // Watchdog Timer Window Enable bit (Watchdog Timer in Non-Window mode)
#pragma config FWDTEN = OFF             // Watchdog Timer Enable bit (Watchdog timer enabled/disabled by user software)

// FPOR
#pragma config FPWRT = PWR1             // Power-on Reset Timer Value Select bits (Disabled)
#pragma config BOREN = ON               // Brown-out Reset (BOR) Detection Enable bit (BOR is enabled)
#pragma config ALTI2C1 = OFF            // Alternate I2C pins for I2C1 (SDA1/SCK1 pins are selected as the I/O pins for I2C1)
#pragma config ALTI2C2 = OFF            // Alternate I2C pins for I2C2 (SDA2/SCK2 pins are selected as the I/O pins for I2C2)

// FICD
#pragma config ICS = PGD3               // ICD Communication Channel Select bits (Communicate on PGEC3 and PGED3)
#pragma config RSTPRI = PF              // Reset Target Vector Select bit (Device will obtain reset instruction from Primary 

flash)
#pragma config JTAGEN = OFF             // JTAG Enable bit (JTAG is disabled)

// FAS
#pragma config AWRP = OFF               // Auxiliary Segment Write-protect bit (Aux Flash may be written)
#pragma config APL = OFF                // Auxiliary Segment Code-protect bit (Aux Flash Code protect is disabled)
#pragma config APLK = OFF               // Auxiliary Segment Key bits (Aux Flash Write Protection and Code Protection is 

Disabled)

#include <xc.h>
#include <p24EP512GU814.h>
#include "address.h"
//#include "pcm.h"

#define _XTAL_FREQ 32000000
#define FP 16000000
#define BAUDRATE 2000000
#define BRGVAL ((FP/BAUDRATE)/4)-1
#define DELAY_1mS asm volatile ("REPEAT, #16000"); Nop();  //1 mS delay
#define DELAY_7cyc asm volatile ("REPEAT, #7"); Nop();  //7 cycle delay
#define DELAY_8cyc asm volatile ("REPEAT, #8"); Nop();  //8 cycle delay
#define DELAY_5cyc asm volatile ("REPEAT, #5"); Nop();  //8 cycle delay
#define DELAY_20cyc asm volatile ("REPEAT, #20"); Nop();  //20 cycle delay
#define DELAY_10cyc asm volatile ("REPEAT, #10"); Nop();  //10 cycle delay
#define DELAY_4cyc asm volatile ("REPEAT, #4"); Nop();  //4 cycle delay
//Interrupt variables
unsigned int int1_flag = 0;
unsigned int int2_flag = 0;
unsigned int start_flag = 0;
unsigned long int start_counter = 0;
unsigned int i = 0;

unsigned int data1;
unsigned int * data; 
unsigned int * pcm_data;


void SPI2_functions_init(void) 
{
    INTCON2bits.GIE=0;
    TRISGbits.TRISG6=0; //SCLK
    TRISGbits.TRISG7=1; //DOUT
    TRISGbits.TRISG8=0; //DIN
    //Bits to be enabled
    TRISJbits.TRISJ4=0; //0 output 1 input, For SS_N
    TRISGbits.TRISG15=1;    //DRDY
    TRISJbits.TRISJ12=0;    //ADCMode bits
    TRISJbits.TRISJ14=0;    //ADDR1
    TRISJbits.TRISJ15=0;    //ADDR2
    TRISKbits.TRISK0=0; //ADDR3
    TRISKbits.TRISK1=0; //ADDR4
    IFS2bits.SPI2IF = 0; // clear interrupt flag
    IEC2bits.SPI2IE = 0; // disable interrupt
    //SPI interface 2
    IFS2bits.SPI2IF=0;//Flag is cleared for SPI2 interrupt 
    IEC2bits.SPI2IE=1;//Interrupt is cleared for SPI2 interrupt
    //SPI2STAT = 0x2000; //Status and control register
    //SPI2CON1 = 0x033E; //Control register for  clock pre-scaler, Master/Slave mode, Word/Byte communication, clock polarity 

and clock/data pin operation
    //SPI2CON2 = 0x0000; //Control register for Enable or disable of Enhanced buffer and framed SPI operation, specifies 

frame synchronization pulse direction, polarity and edge selection
    SPI2BUF = 0x00; //SPI data transmit / receive buffer
    SPI1STATbits.SPIROV = 0;    //Clear the Overflow Status Bit
    SPI1STATbits.SPISIDL = 1;   //0 = Continue module operation in Idle mode

    SPI2CON1bits.DISSCK = 0;    //1 = Internal SPI clock is disabled, pin functions as I/O
    SPI2CON1bits.DISSDO = 0;    //1 = SDO1 pin is not used by module; pin functions as I/O
    SPI2CON1bits.MODE16 = 0;    //0 = Communication is byte-wide (8 bits)
    SPI2CON1bits.SMP = 0;       //1 = Input data sampled at end of data output time / 0 = At Middle (Master) & 0=(Slave)
    SPI2CON1bits.CKE = 1;       //1 = Serial output data changes on transition from active clock state to Idle clock state
    SPI2CON1bits.SSEN = 0;      //1 = SSx pin used for Slave mode
    SPI2CON1bits.CKP = 0;       //1 = Idle state for clock is a high level; active state is a low level
    SPI2CON1bits.MSTEN = 1;     //1 = Master mode & 0 = Slave mode
    SPI2CON1bits.SPRE = 0b111;  //Secondary Prescale bits (Master mode)
                                //111 = Secondary prescale 1:1
                                //110 = Secondary prescale 2:1
                                //???
                                //000 = Secondary prescale 8:1
    SPI2CON1bits.PPRE = 0b10;   //Primary Prescale bits (Master mode)
                                //11 = Primary prescale 1:1
                                //10 = Primary prescale 4:1
                                //01 = Primary prescale 16:1
                                //00 = Primary prescale 64:1

    SPI2CON2bits.FRMEN = 0;     //1 = Framed SPIx support enabled (SSx pin used as frame sync pulse input/output)
    SPI2CON2bits.SPIFSD = 0;    //1 = Framed sync pulse input (slave) & 0 = Frame sync pulse output (master)
    SPI2CON2bits.FRMPOL = 0;    //1 = Framed sync pulse is active-high & 0 = Frame sync pulse is active-low
    SPI2CON2bits.FRMDLY = 0;    //1 = Framed sync pulse coincides with first bit clock & 0 = Frame sync puls
    //PORTJbits.RJ4=1;    //Chip select as high 
    //PORTJbits.RJ12=1;   //Mode bit as high
    //Testing
    TRISDbits.TRISD13=0;    //RD13 to test whether the received data is acknowledged or not
}

void POR_ADC1_init(void)    //Reset Pulse of 1ms duration to SCL ADC 1. The required POR is 4Fcy
{
    TRISEbits.TRISE5=0;
    _RE5=1;
    DELAY_1mS;  //For stabilization   
    _RE5=0;
    DELAY_1mS;  //For 1ms POR 
    _RE5=1;
    DELAY_1mS;  //For stabilization 
}


int main(void) 
{
    POR_ADC1_init();
    SPI2_functions_init();

    //SPI2 enable
    SPI2STATbits.SPIEN=1;
    _RJ4=1;
    __asm__ volatile("SPI_write_check:");
    __asm__ volatile("BCLR PORTJ,#12"); //ADC mode bit
    __asm__ volatile("REPEAT,#2"); Nop();
    __asm__ volatile("Spi_go:");
    data1=0x03;
    __asm__ volatile("BCLR PORTJ,#14"); //ADDR1 bit
    __asm__ volatile("BCLR PORTJ,#15"); //ADDR2 bit
    __asm__ volatile("BCLR PORTK,#0");  //ADDR3 bit
    __asm__ volatile("BCLR PORTK,#1");  //ADDR4 bit
    __asm__ volatile("REPEAT,#5"); Nop();
    __asm__ volatile("Spi_valid:");
    _RJ4=0; //Chip select
    __asm__ volatile("REPEAT,#2"); Nop();
    SPI2BUF=0x57;//0x53 moved to SPI2BUF
    __asm__ volatile("call SPI_tx");
    __asm__ volatile("REPEAT,#2"); Nop();
    _RJ4=1;
    __asm__ volatile("REPEAT,#20"); Nop();
    _RJ4=0;
    __asm__ volatile("REPEAT,#2"); Nop();
    SPI2BUF=0x21;
    __asm__ volatile("call SPI_tx");
    __asm__ volatile("REPEAT,#2"); Nop();
    _RJ4=1;
    __asm__ volatile("REPEAT,#20"); Nop();


    __asm__ volatile("SPI_read_check:");
    __asm__ volatile("Spi_read_go:");
    __asm__ volatile("BCLR PORTJ,#4"); //Chip select
    __asm__ volatile("REPEAT,#2"); Nop();
    SPI2BUF=0x47;   //0x47 moved to SPI2BUF
    __asm__ volatile("call SPI_tx");
    __asm__ volatile("REPEAT,#2"); Nop();
    __asm__ volatile("BSET PORTJ,#4");  //Chip select
    __asm__ volatile("REPEAT,#20"); Nop();
    __asm__ volatile("BCLR PORTJ,#4"); //Chip select
    SPI2BUF=0x00;   //0x00 moved to SPI2BUF
    __asm__ volatile("call SPI_rx");
    __asm__ volatile("REPEAT,#2"); Nop();
    __asm__ volatile("BSET PORTJ,#4");  //Chip select
    data1=WREG0;
    __asm__ volatile("REPEAT,#20"); Nop();

    //Testing 
    __asm__ volatile("goto Spi_go");

    __asm__ volatile("SPI_tx:");
    __asm__ volatile("BTSS IFS2,#1");
    __asm__ volatile("GOTO SPI_tx");
    __asm__ volatile("MOV SPI2BUF,W0");
    __asm__ volatile("BCLR IFS2,#1");
    __asm__ volatile("return");

     __asm__ volatile("SPI_rx:");
    __asm__ volatile("BTSS IFS2,#1");
    __asm__ volatile("GOTO SPI_rx");
    __asm__ volatile("MOV SPI2BUF,W0");
    __asm__ volatile("BCLR IFS2,#1");
    __asm__ volatile("return");   

    //The normal operations starts here
    return 0;
}











...