让SPI在PIC24上运行有问题

问题描述 投票:0回答:1

我正试图配置PIC24FJ512GA610使用SPI与ADC模块接口。 因此,我将其配置为两线模式(只有SCK和SDI,CS由端口控制)。 下面是我用来配置SPI的相关代码。 一个头文件包含了大部分定义。

// SPI3 is used to read from 22-bit ADC tied to RTDs

// SPI3CON1L
#define SPI3EN      0<<15   // SPI Enable Pin
// unimplemented 
#define SPI3SIDL    0<<13   // Stop when CPU is in idle mode
#define SPI3DSSDO   1<<12   // Disable SDO (no data sent to ADC module)
#define SPI3MODE1   0<<11   // Data mode: (0,0) transmits 8-bits 
#define SPI3MODE0   0<<10   //  
#define SPI3SMP     1<<9    // Sampling phase: samples at the end of output data time
#define SPI3CKE     0<<8    // Transmits on transition from idle to active
#define SPI3SSEN    0<<7    // only used in slave mode
#define SPI3CKP     0<<6    // clock idle state is low, active state is high
#define SPI3MSTEN   1<<5    // Master mode enabled
#define SPI3DISSDI  0<<4    // Disable SDI (no data received the board))
#define SPI3DISSCK  0<<3 
#define SPI3MCLKEN  1<<2 
#define SPI3SPIFE   0<<1 
#define SPI3ENHBUF  0<<0 

#define SPI3CON1L_MASK (SPI3EN | SPI3SIDL | SPI3DSSDO | SPI3MODE1 | SPI3MODE0 | SPI3SMP |\
                        SPI3CKE | SPI3SSEN | SPI3CKP | SPI3MSTEN | SPI3DISSDI | SPI3DISSCK | SPI3MCLKEN |\
                        SPI3SPIFE | SPI3ENHBUF )

// SPI3CON1H
#define AUDEN3      0<<15   // Audio codec enable
#define SPI3SGNEXT  0<<14   // Sign Extend Enable
#define IGNROV3     0<<13   // Ignore Receive Overflow
#define IGNTUR3     0<<12   // Ignore Transmit Underrun
#define AUDMONO3    0<<11   // Audio data format
#define URDTEN3     0<<10   // Transmit underrun data enable
#define AUDMOD31    0<<9    // Audio protocol mode select
#define AUDMOD30    0<<8    // 
#define FRMEN3      1<<7    // Framed SPI support
#define FRMSYNC3    0<<6    // Frame sync pulse direction control
#define FRMPOL3     0<<5    // Frame sync/slave select polarity bit
#define MSSEN3      0<<4    // Master mode slave select enable
#define FRMSYPW3    0<<3    // Frame sync pulse width bit
#define FRMCNT32    0<<2    // Frame sync pulse counter bits
#define FRMCNT31    0<<1    // 
#define FRMCNT30    0<<0    // 

#define SPI3CON1H_MASK (AUDEN3 | SPI3SGNEXT | IGNROV3 | IGNTUR3 | AUDMONO3 | URDTEN3 | AUDMOD31 |\
                        AUDMOD30 | FRMEN3 | FRMSYNC3 | FRMPOL3 | MSSEN3 | FRMSYPW3 | FRMCNT32 |\
                        FRMCNT31 | FRMCNT30 )

配置SPI的函数在其他地方找到。

void SPI3Init(void)
// SPI 3 is the thermocouple interface chip or
// the external adc interface for the cryostat
// **************************************
{
#if PROCESSOR == __PIC24FJ512GA610__

    //  Used for SPI communication to read RTDs through ADC
    IEC3bits.SPI3RXIE = 0;          // disable all SPI3 interrupts
    IEC5bits.SPI3TXIE = 0;
    IEC5bits.SPI3IE = 0;
    SPI3BUFL = 0;                   // clear buffer
    SPI3BUFH = 0;

    OSCCONbits.IOLOCK = 0;
    RPINR28bits.SDI3R = 30;         // assign SPI3 SDI to pin 52 (RP30)
//    RPINR28bits.SCK3R = 15;         // assign SPI3 SCK to pin 53 (RP15) 
    RPOR7bits.RP15R = 24;           // Set SCK pin to SPI3 SCK OUT (function 24)
    RPOR8bits.RP16R = 23;           // Map SDO to N/C pin 51 (function 23)
    OSCCONbits.IOLOCK = 1;

    SPI3CON1Lbits.SPIEN = 0;        // disable the port

    SPI3IMSKH = 0;       // disable all interrupts
    SPI3CON1L = 0;       // disable SPI 
    SPI3CON1H = 0;       // turn off AUDEN & FRMEN
    SPI3BRGL = 832;     // 3=16mhz / (2* (3+1)) = 2mhz,  7=16/2(7+1) = 1mhz, 832 -> 9600  )

    SPI3CON1L = SPI3CON1L_MASK;  // Write config masks
    SPI3CON1H = SPI3CON1H_MASK;
    SPI3CON2L = 7;               // 8 bit data

    SPI3STATLbits.SPIROV = 0;   // clear any overflow status
    SPI3CON1Lbits.SPIEN = 1;        // enable the port

    SPI3BUFL = 0;
    ADC_CS_HIGH;
    ADC_CS_LOW;
    ADC_CS_HIGH;
#endif

return;
}

实际上读取ADC会调用这个函数三次(每8位分辨率调用一次)

unsigned char Read_SPI3()
{
    unsigned char ioByte = 0;
    if(SPI3STATLbits.SPIROV)
        SPI3STATLbits.SPIROV = 0;  // clear overflow

    SPI3BUFL = ioByte;      // CLK out data on falling edge  
    while(!SPI3STATLbits.SPIRBF)
    ;     

    ioByte = SPI3BUFL;      // CLK in data on rising edge
    return ioByte;
}

我这一两天一直在看我的代码,在网上梳理了一下,想不通我到底做错了什么。 在SCK线上放一个范围,说明串行时钟没有运行。 我已经确认配置位被成功写入。 谁能告诉我可能出了什么问题?

c pic spi microchip
1个回答
1
投票

一些想法。

  • 你对DISSDI的设置是启用SDI(评论说是禁用)。
  • 没有给出TRIS寄存器的设置,但SDI的引脚必须为1,SCLK的引脚必须设置为0。
  • 通过设置MCKLEN,您的时钟源是REFO--假设它的配置是正确的?(例如:ROEN=1)

1
投票

有了这个

RPOR7bits.RP15R = 24; 

你把SCLK引脚映射到了RF8上。但你必须把这个引脚切换到输出。

TRISFbits.TRISF8 = 0;  

而你必须把这个引脚切换到数字式的

ANSELFbits.ANSELF8 = 0;

SDO引脚也是如此。

正如 @Dan 已经提到的,你需要一个PPS的解锁序列。请参考第163页的 数据表


0
投票

您用来解锁引脚选择器的语句。

    OSCCONbits.IOLOCK = 0;

并不是Microchip所要求的

因为 OSCCON 寄存器中的所有可写位都是 "受保护 "的,必须使用内置的编译器扩展命令来更改这些位。

解锁 PPS 的命令如下。

    __builtin_write_OSCCONL(OSCCON & _OSCCON_IOLOCK_MASK);

锁定PPS的命令是这样的:

    __builtin_write_OSCCONL(OSCCON | _OSCCON_IOLOCK_MASK);

根据你对配置字的设置 PPS可能被配置成无法解锁的状态 一旦被锁定,PPS就需要上电复位才能解锁

© www.soinside.com 2019 - 2024. All rights reserved.