Я пытаюсь прочитать данные через интерфейс 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;
}