搜索
bottom↓
回复: 8

dsPIC33E单片机的SPI通信问题

[复制链接]

出0入0汤圆

发表于 2013-11-6 16:11:03 | 显示全部楼层 |阅读模式
本帖最后由 Lu.Shi 于 2013-11-6 16:24 编辑

我自己使用dsPIC33E单片机往25LC256里面读写数据,但是感觉SPI2BUF写不进去数据。
具体的代码如下:

SPI.c函数:

static void Spi_vSpi2SetPin(void)
{
    /*Chose SPI2: so SDI2 - RG7, SDO2 - RG8*/
    TRISGbits.TRISG7 = 1; /*RG7 - input*/
    TRISGbits.TRISG8 = 0;  /*RG8 - output*/

    /*use RD12 for CS signal*/
    TRISDbits.TRISD12 = 0;  /*RD12 - output*/
    return;
}

static void Spi_vSpi2Write(unsigned char Data)
{
     SPI2BUF = Data & 0xff;
    while(SPI2STATbits.SPITBF);
    Data = SPI2BUF; /*avoiding overflow when reading*/
    return;
}

static unsigned char Spi_u8Spi2Read(void)
{
    unsigned char Data=0;
    SPI2STATbits.SPIROV = 0;
    while(!SPI2STATbits.SPIRBF);/* Check for Receive buffer full status bit of status register*/
    if (SPI2STATbits.SPIRBF)
    {
        SPI2STATbits.SPIROV = 0;
        Data = SPI2BUF;
    }
    return(Data);
}

void Spi_vSpi2Initial(void)
{
    Spi_vSpi2SetPin();
    /*intial SPI2STAT SFR*/
    SPI2STATbits.SPIEN = 0; /*bits 15:disable SPI*/
    SPI2STATbits.SPISIDL = 0; /*bit 13:still work in free mode*/
    SPI2STATbits.SPIBEC = 0;/*bit 10-8:it will work in ESPI*/
    SPI2STATbits.SRMPT = 0;/*bit 7:it will work in ESPI*/
    SPI2STATbits.SPIROV = 0;/*bit 6:ont receive Ooerflow*/
    SPI2STATbits.SRXMPT = 0;/*bits 5:it will work in ESPI*/
    SPI2STATbits.SISEL = 0;/*bit 4-2:it will work in ESPI*/
    SPI2STATbits.SPITBF = 0; /*bit 1:auto set or clear by hardware*/
    SPI2STATbits.SPIRBF = 0;/*bit 0:auto set or clear by hardware*/

    /*initial SPI2CON1 SFR*/
    SPI2CON1bits.DISSCK = 0;/*bit 12: use internal SPI clock*/
    SPI2CON1bits.DISSDO = 0;/*bit 11:SDO2 control by SPI*/
    SPI2CON1bits.MODE16 = 0;/*bit 10:communication by 8 bits*/
    SPI2CON1bits.SMP = 0;/*bit 9:input data during data output*/
    SPI2CON1bits.CKE = 1;/*bit 8:change data when mode from work to free*/
    SPI2CON1bits.SSEN = 0;/*bit 7:SSx control by SPI*/
    SPI2CON1bits.CKP = 0;/*bit 6:work - high level;free - low level*/
    SPI2CON1bits.MSTEN = 1;/*bit 5:enable Master mode*/

    /*Fsck = Fcy/(SPRE * PPRE), Fsck = 30MHz/(3*4) = 2.5MHz*/
    SPI2CON1bits.SPRE = 5;/*bit 4-2:Auxiliary preassigned frequency 3:1*/
    SPI2CON1bits.PPRE = 2;/*bit 1-0:preassigned frequency 4:1*/

    /*initial SPI2CON2 SFR*/
    SPI2CON2bits.FRMEN = 0;/*bit 15:disable SPIx frame mode*/
    SPI2CON2bits.SPIFSD = 0;/*bit 14:Frame synchronization pulse output*/
    SPI2CON2bits.FRMPOL = 0;/*bit 13:Frame synchronization pulse low level*/
    SPI2CON2bits.FRMDLY = 0;/*bit 1:use the same clock */
    SPI2CON2bits.FRMEN = 0;/*bit 0:use standed mode*/
   
    /*set input and output pins*/
    RPOR14bits.RP120R = 8;
    RPOR13bits.RP118R = 9;                /*SCK2 to G6*/

    SPI2STATbits.SPIEN = 1; /*bits 15:enable SPI*/
}

void Spi_vSpi2WriteEnable(void)
{
    LATDbits.LATD12 = 0;
    Spi_vSpi2Write(SPI_WRITE_EN_COMMAND);
    LATDbits.LATD12 = 1;
    return;
}

void Spi_vSpi2WriteCheck(void)
{
    unsigned char Status;
    do
    {
        LATDbits.LATD12 = 0;                        
        Spi_vSpi2Write(SPI_READ_SR_COMMAND);         /*Read STATUS Register command*/
        Status = Spi_u8Spi2Read();              /*Read STATUS Register*/
        LATDbits.LATD12 = 1;                    
    } while (Status & 0x01);
}

void Spi_vSpi2WriteStatusReg(unsigned char StatusData)
{
    LATDbits.LATD12 = 0;
    Spi_vSpi2Write(SPI_WRITE_SR_COMMAND);
    Spi_vSpi2Write(StatusData);
    LATDbits.LATD12 = 1;
    return;
}

void Spi_vSpi2WriteByte(unsigned char AddressH,unsigned char AddressL,unsigned char Data)
{
    Spi_vSpi2WriteCheck();
    LATDbits.LATD12 = 0;
    /*send BTTE WRITE SEQUENCE command*/
    Spi_vSpi2Write(SPI_WRITE_COMMAND);

    /*write address:16 bits*/
    Spi_vSpi2Write(AddressH);/*send AddressH*/
    Spi_vSpi2Write(AddressL);/*send AddressL*/

    /*write data*/
    Spi_vSpi2Write(Data);
    LATDbits.LATD12 = 1;
    Spi_vSpi2WriteCheck();
    return;
}

unsigned char Spi_u8Spi2ReadSequence(unsigned char AddressH,unsigned char AddressL)
{
    static unsigned char Data;
    LATDbits.LATD12 = 0;
   
    /*send write READ SEQUENCE command*/
    Spi_vSpi2Write(SPI_READ_COMMAND);
   
    /*write READ DATA address*/
    Spi_vSpi2Write(AddressH);/*send AddressH*/
    Spi_vSpi2Write(AddressL);/*send AddressL*/

    /*read data*/
    Data = Spi_u8Spi2Read();
    LATDbits.LATD12 = 1;
    return(Data);
}

Main.c函数:
void InitPorts(void)
{

    TRISA = 0x0000;
    LATA = 0x00FF;   /*LED is all ON*/
}

void delay(void)
{
    unsigned int i,j;
    for(i=0;i<3000;i++)
    {
        for(j=0;j<3000;j++)
        ;
    }
}

int main(void)
{

    PLLFBD = 0x003A;
    CLKDIV = 0x0040;

    InitPorts();
    delay();
    delay();
    Spi_vSpi2Initial();
   
    while(1)
    {
        Spi_vSpi2WriteEnable();
        Spi_vSpi2WriteByte(0x01,0x03,0x01);
        LATA = Spi_u8Spi2ReadSequence(0x01,0x03);
        delay();
        delay();
    }

}

然后把程序烧板子里面会出现LED先全亮一会(初始化全亮然后有delay延时),然后全灭,说明通过SPI读到的数据为0,但是往相同地址写数据了,只有可能是没写进去,然后我连着板子在线调试了,程序会停在 Spi_vSpi2Write()函数的while循环,但是按照datasheet的说明while判断没有问题,那就是数据写不进SPI2BUF,但是为什么会写不进去呢??
希望各位牛人给点建议和意见,在此表示非常感谢!!!!

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

发表于 2013-11-6 16:15:39 | 显示全部楼层
mark
            

出0入0汤圆

 楼主| 发表于 2013-11-7 14:42:57 | 显示全部楼层
没有人遇到这个问题吗?期待有经验的人指导指导,谢谢。。。。

出20入12汤圆

发表于 2013-11-7 16:04:27 | 显示全部楼层
static void Spi_vSpi2Write(unsigned char Data)
{
     SPI2BUF = Data & 0xff;
    while(SPI2STATbits.SPITBF);
    Data = SPI2BUF; /*avoiding overflow when reading*/
    return;
}
问题可能处在:片选抬高太快。
SPIxBUF后边还有8 级深FIFO发送缓冲区,移位寄存器。只有移位寄存器空才表示数据真正在总线上发送完成。

出0入0汤圆

 楼主| 发表于 2013-11-11 17:11:54 | 显示全部楼层
gaolf_2012 发表于 2013-11-7 16:04
static void Spi_vSpi2Write(unsigned char Data)
{
     SPI2BUF = Data & 0xff;

你好!很高兴能给我回复。就是你的意思是LATDbits.LATD12片选调高后,稍微有个短延时吗?然后SPI2BUF缓冲移位数据的时候使用内部的SPI时钟,所以只用在这个函数里面数据给了SPI2BUF后只等待发送完成标志位的呀。

出20入12汤圆

发表于 2013-11-6 16:11:04 | 显示全部楼层
简单的说,发送数据时,给SPIxBUF赋值后,经过while(SPI2STATbits.SPITBF)等待,还不够,还要等数据从移位寄存器移出到SDO口线上,在这些动作完成后,片选才可以置高。

出0入0汤圆

 楼主| 发表于 2013-11-12 08:56:41 | 显示全部楼层
gaolf_2012 发表于 2013-11-12 07:37
简单的说,发送数据时,给SPIxBUF赋值后,经过while(SPI2STATbits.SPITBF)等待,还不够,还要等数据从移位 ...

谢谢你的建议,但是我试验了一下,这个方法好像行不通,然后想了一下,我觉得机器周期是1/30M,然后SPI的频率是2.5M,两者是12倍的关系,所以应该是数据可以传输完的呀。

出20入12汤圆

发表于 2013-11-12 10:15:34 | 显示全部楼层
如果SPI总线上没有别的设备,那么为避免不必要的麻烦HOLD脚请上拉,另外SPI频率先别调得太高,1M就可以,等试验成功再往高调。惭愧我一般都是io模拟时序。

出0入0汤圆

 楼主| 发表于 2013-11-18 13:24:46 | 显示全部楼层
gaolf_2012 发表于 2013-11-12 10:15
如果SPI总线上没有别的设备,那么为避免不必要的麻烦HOLD脚请上拉,另外SPI频率先别调得太高,1M就可以,等 ...

谢谢你的建议,最近都没有时间忙这个事,非常感谢。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-6-3 07:23

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表