打印

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

[复制链接]
1831|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Vigilaanter|  楼主 | 2024-6-2 17:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本人使用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;//中断标志清零
}


使用特权

评论回复

相关帖子

沙发
是穹灵吖| | 2024-6-19 17:31 | 只看该作者

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

问题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)通讯模式。
最后,希望可以帮助到楼主。

使用特权

评论回复
板凳
嵌入式新手hhh| | 2024-6-21 15:02 | 只看该作者
大佬,求您的SPI代码,我不知道为什么数据写不进去,有偿求您的SPI代码~

使用特权

评论回复
地板
嵌入式新手hhh| | 2024-6-21 15:18 | 只看该作者
是穹灵吖 发表于 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; //中断禁止
   
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

1

帖子

1

粉丝