AT91SAM7X512的SPI外设在我写入SPI_TDR
的X时间(X变化)被禁用。 因此,处理器在while循环中挂起,该循环检查SPI_SR
中的TDRE
标志。此while循环位于属于ATMEL提供的软件包/库的函数SPI_Write()
中。 这个问题是任意发生的 - 有时候一切正常,有时它会在重复尝试时失败(试图=将相同的二进制文件下载到MCU并运行程序)。AT91SAM7X512的SPI外设在写入SPI_TDR时被禁止
配置是(书写的顺序定义):
SPI_MR
:MSTR
= 1PS
= 0PCSDEC
= 0PCS
= 0111DLYBCS
= 0
SPI_CSR[3]
:CPOL
= 0NCPHA
= 1CSAAT
= 0BITS
= 0000SCBR
= 20DLYBS
= 0DLYBCT
= 0
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.
}
问题:
- 是什么造成的SPI外设成为上写
SPI_TDR
禁用? 我是否应该取消注释
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); }
有什么问题上面的代码发送5个字节的数据?
请注意:
- 的NPCS线民。 3是GPIO线(表示,在PIO模式下),不受SPI控制器控制。 我自己在代码中控制这条线,通过在需要时取消/断言ChipSelect#3(NPCS3)引脚。 我这样做的原因是因为在尝试让SPI控制器控制此引脚时出现了问题。
- 我没有使用PDC/DMA控制器,更喜欢不使用它。
我没有重置SPI外设两次,因为这个错误告诉我重置它两次,只有当我执行重置 - 我不这样做。引用勘误:
如果执行软件复位(SWRST在SPI控制寄存器),该SPI可能无法正常工作 正确(时钟片选前启用。)
问题的修复程序/解决方法
需要将SPI控制寄存器字段SWRST(软件复位)写入两次,以便正确设置。我注意到,有时,如果我把一个延迟写入前到
SPI_TDR
寄存器(在SPI_Write()
),那么代码完美的作品和通信成功。
相关链接:
- AT91SAM7X Series Preliminary.pdf
- ATMEL software package/library
- spi.c from Atmel's library
- spi.h from Atmel's library
初始化SPI并执行5个字节传输的示例非常感谢和帮助。
你解决了这个Dor吗?我们很想知道你是否找到了根本原因。 – Bwooce 2011-02-13 09:12:44
我不记得我是如何解决问题的。我认为我在处理器时钟的初始化过程中遇到了一个问题:init的步骤并不像数据表中所写的那样。 – Dor 2011-03-17 21:15:03
值得注意的是,这段代码没有“传输五个字节的数据”。 – 2013-03-15 14:18:53