2010-03-18 15 views
2

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

配置是(书写的顺序定义):

  1. SPI_MR
    • MSTR = 1
    • PS = 0
    • PCSDEC = 0
    • PCS = 0111
    • DLYBCS = 0
  2. SPI_CSR[3]
    • CPOL = 0
    • NCPHA = 1
    • CSAAT = 0
    • BITS = 0000
    • SCBR = 20
    • DLYBS = 0
    • DLYBCT = 0
  3. SPI_CR
    • SPIEN = 1

后设置的结构中,所述代码验证该SPI被启用,通过检查SPIENS标志。

我执行字节的传输如下:

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. 
} 

问题:

  1. 是什么造成的SPI外设成为上写SPI_TDR禁用?
  2. 我是否应该取消注释SPI_Write()中读取SPI_RDR寄存器的行?
    手段,在下面的代码四号线:(第4行最初标记为注释的)

    void SPI_Write(AT91S_SPI *spi, unsigned int npcs, unsigned short data) 
    { 
        // Discard contents of RDR register 
        //volatile unsigned int discard = spi->SPI_RDR; 
        /* Send data */ 
        while ((spi->SPI_SR & AT91C_SPI_TXEMPTY) == 0); 
        spi->SPI_TDR = data | SPI_PCS(npcs); 
        while ((spi->SPI_SR & AT91C_SPI_TDRE) == 0); 
    } 
    
  3. 有什么问题上面的代码发送5个字节的数据?

请注意:

  • 的NPCS线民。 3是GPIO线(表示,在PIO模式下),不受SPI控制器控制。 我自己在代码中控制这条线,通过在需要时取消/断言ChipSelect#3(NPCS3)引脚。 我这样做的原因是因为在尝试让SPI控制器控制此引脚时出现了问题。
  • 我没有使用PDC/DMA控制器,更喜欢不使用它。
  • 我没有重置SPI外设两次,因为这个错误告诉我重置它两次,只有当我执行重置 - 我不这样做。引用勘误:

    如果执行软件复位(SWRST在SPI控制寄存器),该SPI可能无法正常工作 正确(时钟片选前启用。)
    问题的修复程序/解决方法
    需要将SPI控制寄存器字段SWRST(软件复位)写入两次,以便正确设置。

  • 我注意到,有时,如果我把一个延迟写入前到SPI_TDR寄存器(在SPI_Write()),那么代码完美的作品和通信成功。

相关链接:

初始化SPI并执行5个字节传输的示例非常感谢和帮助。

+0

你解决了这个Dor吗?我们很想知道你是否找到了根本原因。 – Bwooce 2011-02-13 09:12:44

+0

我不记得我是如何解决问题的。我认为我在处理器时钟的初始化过程中遇到了一个问题:init的步骤并不像数据表中所写的那样。 – Dor 2011-03-17 21:15:03

+0

值得注意的是,这段代码没有“传输五个字节的数据”。 – 2013-03-15 14:18:53

回答

1

您使用

while(i-- < dataSize) 

递减有符号整数i,不增加它和访问data[i]直到i溢出为正值。谁知道发生了什么,你正在访问什么内存或寄存器?如果您不需要保留负值,则使用无符号整数通常会更好。

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

另外,我强烈建议您使用PDC,如果你不同时进行数据交换,这不是我想的情况。