问答

汇集网友智慧,解决技术难题

21ic问答首页 - 求助各位大佬dspic33ev系列引脚映射SPI2存在问题

映射 ev dspic33 单片机 技术交流 嵌入式

求助各位大佬dspic33ev系列引脚映射SPI2存在问题

Vigilaanter2024-06-02
本人使用DSPIC33ev128与AD7606进行通信的过程中使用默认的SPI1可以正确读取7606总线数据,现在改用可映射的SPI2就出现以下问题。

问题1:片选信号在MISO的最后一个周期没有发完就拉高了,如下图所示
问题2:示波器看有输出信号但是SPI2BUF一直为空,单片机没有收到,while (!SPI2STATbits.SPIRBF)这个判别条件始终无法为通过。
问题3:单片机MOSI在发送两个字的数据,如0xff,示波器上显示输出只有一半,只有改为0xffff才显示完全
希望各位大佬不吝赐教,非常感谢代码如下:
void SPI2_Init(void)//主模式
{  
    TRISCbits.TRISC8 = 0;//设置为输出 SCK   
    TRISCbits.TRISC2 = 1;//设置为输入 MISO   
    TRISCbits.TRISC6 = 0;//设置输出 MOSI   
    RPOR7bits.RP56R = 0b001001;//配置RP35为SCK2引脚  RC8   
    RPINR22bits.SDI2R = 0b0110010;//配置RPI34为MISO引脚  RB2   
    RPOR6bits.RP54R = 0b001000;//配置RP54为MOSI引脚  RC
    IFS2bits.SPI2IF = 0; //清中断
    IEC2bits.SPI2IE = 0; //中断禁止
    SPI2CON1bits.SPRE=0b001;
    SPI2CON1bits.PPRE=0b01;
    SPI2CON1bits.DISSCK = 0; //使能内部 SPI 时钟
    SPI2CON1bits.DISSDO = 0; //SDOx引脚由模块控制
    SPI2CON1bits.MODE16 = 1; //通信为字节宽 (16位)                                                                                                
    SPI2CON1bits.SMP = 0; //输入数据在数据输出时间末端采样
    SPI2CON1bits.CKE = 0; //串行输出数据在时钟从工作状态转变为空闲状态时变化
    SPI2CON1bits.CKP = 1; //空闲状态时钟信号为高电平;
    SPI2CON1bits.SSEN = 0;//模块不使用SS引脚
    SPI2CON1bits.MSTEN = 1; //主控模式
    SPI2CON2bits.SPIBEN = 0; //传统模式
    SPI2STATbits.SPIEN = 1; //使能模块并将SCKx、SDOx、SDIx和SSx配置为串口引脚
    SPI2BUF = 0x0000; //写0
    IFS2bits.SPI2IF = 0; //清中断
    IEC2bits.SPI2IE = 1; //使能中断
}
unsigned int SPI2_ReadByte(unsigned int TxData)
{
    SPI2BUF = TxData;

//    while (!SPI2STATbits.SPIRBF);
    while(SPI2STATbits.SPITBF);
    return SPI2BUF;
}
void AD7606_ReadData(void)
{  
    unsigned int i;
    AD_CS_L;
    for(i=0;i<8;i++)  
    {        
        DB_data[i]  = SPI2_ReadByte(dummy);
    }   
    AD_CS_H;
}
void __attribute__((__interrupt__, auto_psv)) _SPI2Interrupt(void)
{
    IFS2bits.SPI2IF = 0;//中断标志清零
}


回答 +关注 1
1950人浏览 3人回答问题 分享 举报
3 个回答
  • 是穹灵吖 发表于 2024-6-19 17:31
    问题1:参考技术手册第18章 串行外设接口(SPI)中的18.3,在SPIx主模式中看到当数据从SPIxTXB传输到SPIxSR ...

    大佬,我怕配置的SPI初始化,不知道为什么CS波形一直是错的,导致MOSI和SCK的波形一模一样,然后ID号读不出来,能麻烦您帮我看看吗?
    代码如下:
    #define SPI_W25Q40_CS   LATBbits.LATB0
    unsigned char SPI1_ReadWriteByte(unsigned char TxData)
    {
        SPI1BUF = TxData;
        while (!SPI1STATbits.SPIRBF);        //发送一个byte
        return SPI1BUF;
    }
    uchar Manufacturer_ID, Memory_Type, Capacity;
    void vFlashInit(void)
    {
             
            SPI_W25Q40_CS=0;
            SPI1_ReadWriteByte(Read_Identification);
            Manufacturer_ID = SPI1_ReadWriteByte(NOP);
            Memory_Type = SPI1_ReadWriteByte(NOP);
            Capacity =SPI1_ReadWriteByte(NOP);
            SPI_W25Q40_CS=1;
    }
    void SPI1_Init(void)//主模式
    {  
       
       
        //SPI1STATbits.SPISIDL = 0;    // don't stop in idle mode       1
        //SPI1STATbits.SPIROV = 0;     //CLear Receive overflow flag bit   2

        TRISCbits.TRISC3 = 0;//设置输出  SCK
        TRISAbits.TRISA9 = 1;//设置为输入//主接收
        TRISAbits.TRISA4 = 0;//设置为输出//主输出
       
        TRISBbits.TRISB0 = 0;//CS引脚为输出 SC 引脚用于选择特定的设备
       
        IFS0bits.SPI1IF = 0; // Clear the Interrupt flag
        IEC0bits.SPI1IE = 0; // Disable the interrupt
        SPI1CON1bits.PPRE = 0b01;   // Primary Prescaler = 4:1
        SPI1CON1bits.SPRE = 0b100;   // Secondary Prescaler = 4:1

        SPI1CON1bits.DISSCK = 0; //使能内部 SPI 时钟
        SPI1CON1bits.DISSDO = 0; //SDOx引脚由模块控制//SDO引脚用于将数据从主设备发送到从设备。如果您需要使用SPI的数据输出功能,就需要将DISSDO设置为0               
        SPI1CON1bits.MODE16 = 0; //通信为字节宽 (8位1字节)  1每次传输的数据长度为 16 位(2 字节)
        SPI1CON1bits.SMP = 0; //输入数据在数据输出时间中间采样  0在时钟信号的中间采样数据 1SMP数据采样发生在SPI时钟信号的最后一个边沿。这通常用于高频率SPI通信
        SPI1CON1bits.CKE = 0; //串行输出数据在时钟从工作状态转变为空闲状态时变化 。它们决定数据何时被采样和发送
        SPI1CON1bits.CKP = 1; //空闲状态时钟信号为低电平;工作状态为高电平
        SPI1CON1bits.SSEN = 0;//模块不使用SS引脚 需要通过软件手动控制从选择设备引脚。具体方法是将该引脚设置为输出,并在进行通信前将其拉低,在通信完成时后将其拉高。
        SPI1CON1bits.MSTEN = 1; //主控模式
        SPI1CON2bits.SPIBEN = 0; //传统模式
       
        SPI1STATbits.SPIEN = 1; //使能模块并将SCKx、SDOx、SDIx和SSx配置为串口引脚
       
        SPI1BUF = 0;
       
        SPI_W25Q40_CS=1;
        IFS0bits.SPI1IF = 0; //清中断
        IEC0bits.SPI1IE = 1; //中断禁止
       
    }
  • 大佬,求您的SPI代码,我不知道为什么数据写不进去,有偿求您的SPI代码~
  • 问题1:参考技术手册第18章 串行外设接口(SPI)中的18.3,在SPIx主模式中看到当数据从SPIxTXB传输到SPIxSR时,SPIxSTATbits.SPITBF就清零了。标志位清除DB_data  = SPI2_ReadByte(dummy)结束,跳出了for循环。所以就产生了问题1所述的现象。问题2:dsPIC33E系列的有些引脚默认是模拟模式,参考数据手册第11章 I/O端口,在用作数字模式时需要先将引脚配置为数字模式。
            ANSELx寄存器在上电初始状态是0XFFFF;
            例如:ANSELCbits.ANSC6  = 0;  // 设置RC6为数字模式
    问题3:看到你配置的时候 SPI2CON1bits.MODE16 = 1; //通信为字节宽 (16位)。这个设置时,SPIxBUF为16位模式,赋值0XFF时,二进制0B11111111为8位,在SPIxBUF中只有低8位,前面补0,所以看到波形只有一半。
            可以参考:SPI1CON1bits.MODE16  = 0;   // 采用字节宽(8bits)通讯,这样就采用8位数据模式发送了。
            SPI1CON1bits.MODE16  = 1;时为字宽(16bits)通讯模式。
    最后,希望可以帮助到楼主。

您需要登录后才可以回复 登录 | 注册