21ic问答首页 - 求助各位大佬dspic33ev系列引脚映射SPI2存在问题
求助各位大佬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:片选信号在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;//中断标志清零
}
赞0
大佬,我怕配置的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; //中断禁止
}
评论
2024-06-21
赞0
评论
2024-06-21
赞0
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)通讯模式。
最后,希望可以帮助到楼主。
评论
2024-06-19
您需要登录后才可以回复 登录 | 注册