我的AT91SAM7X512的SPI外设在我写入SPI_TDR
的X时间(X变化)被禁用。
结果,处理器挂起while循环,检查TDRE
中的SPI_SR
标志。此while循环位于函数SPI_Write()
中,该函数属于ATMEL提供的软件包/库。
问题是随意发生的 - 有时候一切正常,有时它会在重复尝试时失败(尝试将相同的二进制文件下载到MCU并运行程序)。
配置(按写入顺序定义):
SPI_MR
:
MSTR
= 1 PS
= 0 PCSDEC
= 0 PCS
= 0111 DLYBCS
= 0 SPI_CSR[3]
:
CPOL
= 0 NCPHA
= 1 CSAAT
= 0 BITS
= 0000 SCBR
= 20 DLYBS
= 0 DLYBCT
= 0 SPI_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.
}
问题:
SPI_TDR
?我应该取消注释SPI_Write()
注册SPI_RDR
的{{1}}行吗?
意味着,以下代码中的第4行:(第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个字节的数据?
请注意:
我没有重置SPI外设两次,因为勘误表示只有在我执行复位时才重置两次 - 我不这样做。引用勘误表:
如果执行了软件复位(SPI控制寄存器中的SWRST),SPI可能无法工作 正确(在芯片选择之前启用时钟。)
问题解决/解决方法
SPI控制寄存器字段SWRST(软件复位)需要写入两次才能完成 直接设置。
我注意到有时是,如果我在写入SPI_TDR
寄存器(SPI_Write()
)之前放一个延迟,那么代码就可以完美地运行了沟通成功。
有用的链接:
初始化SPI并执行5个字节的传输的示例非常受欢迎且非常有用。
答案 0 :(得分:1)
您使用
while(i-- < dataSize)
递减有符号整数i
,不递增它并访问data[i]
,直到i
溢出为正值。谁知道会发生什么,你正在访问什么内存或注册?如果您不需要保留负值,则使用无符号整数通常会更好。
此外,您已经在检查TXEMPTY
,这意味着数据被移动到移位寄存器并发送出去。因此,您也不需要检查TDRE
,这意味着数据被移动到移位寄存器但可能不会被发送出去。
此外,如果您不同时交换数据,我强烈建议您使用PDC,我认为情况并非如此。