Embedded AT91SAM7X512';s SPI外围设备在写入SPI_TDR时被禁用

Embedded AT91SAM7X512';s SPI外围设备在写入SPI_TDR时被禁用,embedded,arm,spi,atmel,Embedded,Arm,Spi,Atmel,我的AT91SAM7X512的SPI外设在我写入SPI\u TDR的X时间(X变化)被禁用。 因此,处理器挂起while循环,该循环检查SPI\u SR中的TDRE标志。该while循环位于函数SPI_Write()中,该函数属于ATMEL提供的软件包/库。 这个问题是任意发生的——有时一切正常,有时重复尝试就会失败(attemp=将相同的二进制文件下载到MCU并运行程序) 配置(按编写顺序定义): const short int dataSize = 5; // Filling array w

我的AT91SAM7X512的SPI外设在我写入
SPI\u TDR
的X时间(X变化)被禁用。 因此,处理器挂起while循环,该循环检查
SPI\u SR
中的
TDRE
标志。该while循环位于函数
SPI_Write()
中,该函数属于ATMEL提供的软件包/库。 这个问题是任意发生的——有时一切正常,有时重复尝试就会失败(attemp=将相同的二进制文件下载到MCU并运行程序)

配置(按编写顺序定义):

const short int dataSize = 5;
// Filling array with random data
unsigned char data[dataSize] = {0xA5, 0x34, 0x12, 0x00, 0xFF};
short int i = 0;
volatile unsigned short dummyRead;

SetCS3();   // NPCS3 == PIOA15
while(i-- < dataSize) {
    mySPI_Write(data[i]);
    while((AT91C_BASE_SPI0->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
    dummyRead = SPI_Read(); // SPI_Read() from Atmel's library
}
ClearCS3();
/**********************************/
void mySPI_Write(unsigned char data) {
    while ((AT91C_BASE_SPI0->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
    AT91C_BASE_SPI0->SPI_TDR = data;
    while ((AT91C_BASE_SPI0->SPI_SR & AT91C_SPI_TDRE) == 0); // <-- This is where
    // the processor hangs, because that the SPI peripheral is disabled
    // (SPIENS equals 0), which makes TDRE equal to 0 forever.
}
  • SPI\u MR
    • MSTR
      =1
    • PS
      =0
    • PCSDEC
      =0
    • PCS
      =0111
    • DLYBCS
      =0
  • SPI\u CSR[3]
    • CPOL
      =0
    • NCPHA
      =1
    • CSAAT
      =0
    • =0000
    • SCBR
      =20
    • DLYBS
      =0
    • DLYBCT
      =0
  • SPI\u CR
    • SPIEN
      =1
  • 设置配置后,代码通过检查
    SPIENS
    标志来验证SPI是否已启用

    我执行如下字节传输:

    const short int dataSize = 5;
    // Filling array with random data
    unsigned char data[dataSize] = {0xA5, 0x34, 0x12, 0x00, 0xFF};
    short int i = 0;
    volatile unsigned short dummyRead;
    
    SetCS3();   // NPCS3 == PIOA15
    while(i-- < dataSize) {
        mySPI_Write(data[i]);
        while((AT91C_BASE_SPI0->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
        dummyRead = SPI_Read(); // SPI_Read() from Atmel's library
    }
    ClearCS3();
    /**********************************/
    void mySPI_Write(unsigned char data) {
        while ((AT91C_BASE_SPI0->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
        AT91C_BASE_SPI0->SPI_TDR = data;
        while ((AT91C_BASE_SPI0->SPI_SR & AT91C_SPI_TDRE) == 0); // <-- This is where
        // the processor hangs, because that the SPI peripheral is disabled
        // (SPIENS equals 0), which makes TDRE equal to 0 forever.
    }
    
  • 上面传输5字节数据的代码是否有问题

  • 请注意:

    const short int dataSize = 5;
    // Filling array with random data
    unsigned char data[dataSize] = {0xA5, 0x34, 0x12, 0x00, 0xFF};
    short int i = 0;
    volatile unsigned short dummyRead;
    
    SetCS3();   // NPCS3 == PIOA15
    while(i-- < dataSize) {
        mySPI_Write(data[i]);
        while((AT91C_BASE_SPI0->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
        dummyRead = SPI_Read(); // SPI_Read() from Atmel's library
    }
    ClearCS3();
    /**********************************/
    void mySPI_Write(unsigned char data) {
        while ((AT91C_BASE_SPI0->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
        AT91C_BASE_SPI0->SPI_TDR = data;
        while ((AT91C_BASE_SPI0->SPI_SR & AT91C_SPI_TDRE) == 0); // <-- This is where
        // the processor hangs, because that the SPI peripheral is disabled
        // (SPIENS equals 0), which makes TDRE equal to 0 forever.
    }
    
    • NPCS线路编号3是一条GPIO线路(即,在PIO模式下),不受SPI控制器控制。 我在代码中自己控制这一行,在需要时取消/断言ChipSelect#3(NPCS3)引脚。 我这样做的原因是,在尝试让SPI控制器控制该引脚时出现了问题
    • 我没有使用PDC/DMA控制器,更喜欢不使用它
    • 我没有两次重置SPI外围设备,因为勘误表告诉我只有在执行重置时才重置它两次-我没有这样做。引用勘误表:

      如果执行软件复位(SPI控制寄存器中的SWRST),SPI可能无法工作 正确(时钟在芯片选择之前启用。)
      问题修复/解决方法
      SPI控制寄存器字段SWRST(软件复位)需要写入两次才能进行校正- 直线设置

    • 我注意到,有时,如果我在写入
      SPI\u TDR
      寄存器(在
      SPI\u write()
      中)之前加上一个延迟,那么代码工作正常,通信成功

    有用的链接:

    const short int dataSize = 5;
    // Filling array with random data
    unsigned char data[dataSize] = {0xA5, 0x34, 0x12, 0x00, 0xFF};
    short int i = 0;
    volatile unsigned short dummyRead;
    
    SetCS3();   // NPCS3 == PIOA15
    while(i-- < dataSize) {
        mySPI_Write(data[i]);
        while((AT91C_BASE_SPI0->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
        dummyRead = SPI_Read(); // SPI_Read() from Atmel's library
    }
    ClearCS3();
    /**********************************/
    void mySPI_Write(unsigned char data) {
        while ((AT91C_BASE_SPI0->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
        AT91C_BASE_SPI0->SPI_TDR = data;
        while ((AT91C_BASE_SPI0->SPI_SR & AT91C_SPI_TDRE) == 0); // <-- This is where
        // the processor hangs, because that the SPI peripheral is disabled
        // (SPIENS equals 0), which makes TDRE equal to 0 forever.
    }
    
    初始化SPI并执行5字节传输的示例非常值得赞赏和帮助。

    您可以使用

    while(i-- < dataSize)
    
    while(i--
    递减有符号整数
    i
    ,不递增并访问
    数据[i]
    ,直到
    i
    溢出为正值。谁知道会发生什么,您正在访问什么内存或寄存器?如果不需要保留负值,则使用无符号整数通常更好

    另外,您已经在检查
    TXEMPTY
    ,这意味着数据被移动到移位寄存器并发送出去。因此,您也不需要检查
    TDRE
    ,这意味着数据被移动到移位寄存器,但可能不会被发送出去


    另外,如果您不同时交换数据,我强烈建议您使用PDC,我认为情况并非如此。

    您是否解决了此Dor?我们很想知道你是否找到了根本原因。我不记得我是如何解决这个问题的。我认为我在处理器时钟的初始化过程中遇到了一个问题:init的步骤没有如数据表中所述。值得注意的是,这段代码没有“传输五个字节的数据”。