This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
您好!
我正在尝试 将 TCAN4550EVM 连接到我的 STM32F407VET6板、但我在第一步中遇到困难。 我甚至无法正确读取器件 ID。 我从地址'h000 &'h0004得到的是随机值。
我能够使用 USART 和 COM 功能 并 读取 MCU 板上闪存的器件 ID、因此 MCU 本身不会损坏。
我正在使用的编译器是 Keil V5 Lite。 网站上的代码示例似乎用于 其他编译器和 MCU、因此我无法直接使用。 我将代码简化为与 SPI 相关的代码、希望有人可以检查出任何问题。 我在 MCU 应用方面的经验非常有限。 可能是简单的错误。
我将 SPI 频率设置为10MHz (APB 时钟为80MHz)、CPHA=0、CPOL=0。 仅连接6根导线:VBAT 和 GND 至12V 电源、SCLK 至 PA5、SDI 至 PA7、SDO 至 PA6、NCS 至 PA4。
void SPISendByte(unsigned char tmpData) { while((SPI1->SR&2)==0); //wait for TXE SPI1->DR = tmpData; } unsigned char SPIGetByte() { while((SPI1->SR&2)==0); //wait for TXE while(SPI1->SR&(1<<7)); //wait for !BSY SPI1->DR = 0; //send dummy data while(!(SPI1->SR&1)); //wait for RXNE return SPI1->DR; } void TCANReadBytes(unsigned short address, unsigned char *tmpC, unsigned short len1) { GPIOA->BSRRH |= GPIO_Pin_4; //set to 0, enable SPISendByte(0x41); //read SPISendByte(address>>8); //MSB SPISendByte(address&0xFF); //LSB SPISendByte(len1); //len1*32bit while((SPI1->SR&2)==0); //wait for TXE while(SPI1->SR&(1<<7)); //wait for !BSY SPI1->DR; //read the last dummy byte for (unsigned short idx1=0; idx1<len1*4; ++idx1) tmpC[idx1] = SPIGetByte(); GPIOA->BSRRL |= GPIO_Pin_4; //set to 1, disable } int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); USART1_Init(115200); //SPI settings RCC->AHB1ENR |= RCC_AHB1Periph_GPIOA; GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; //nCS GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIOA->BSRRL |= GPIO_Pin_4; //set to 1, disable NCS GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1); GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1); GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1); RCC->APB2ENR |= (1<<12); //enable SPI1 clock SPI1->CR1 |= 0 << 0; //CPHA = 0 SPI1->CR1 |= 0 << 1; //CPOL = 0 SPI1->CR1 |= 1 << 2; //master mode SPI1->CR1 |= 2 << 3; //baudrate = fPCLK /8 SPI1->CR1 |= 0 << 7; //MSB first SPI1->CR1 |= 1 << 9; //software slave management SPI1->CR1 |= 1 << 8; //software slave internal SPI1->CR1 |= 0 << 10; //RXonly =0, full-duplex SPI1->CR1 |= 0 << 11; //frame format: 8 bit data SPI1->CR1 |= 1 << 6; //enable external unsigned char tmpC[5]; tmpC[4] = 10; for(int idx1=0;idx1<8;idx1=idx1+4) { tmpC[0] = 0; tmpC[1] = 0; tmpC[2] = 0; tmpC[3] = 0; TCANReadBytes(idx1, tmpC, 1); USART1SendChar((char*)tmpC, 5); //send the response to PC via COM port } while (1) { } }
响应将
[ 2023年07月20日10:43:10.502]#接收十六进制>
00 00 00 00 0A C0 7F F2 40 0A
[ 2023年07月20日10:43:12.824]#接收十六进制>
FF EA 00 0A 02 00 00 0A
[ 2023年07月20日10:43:15.247]#接收十六进制>
FF FF 92 00 0A 02 00 00 0A
[ 2023年07月20日10:43:17.708]#接收十六进制>
FF F5 40 0A 02 00 00 0A
[ 2023年07月20日10:43:20.001]#接收十六进制>
FF FF 92 00 0A 00 00 00 0A
[ 2023年07月20日10:43:23.255]#接收十六进制>
00 00 00 00 0A 00 00 52 0A
[ 2023年07月20日10:43:25.510]#接收十六进制>
FF FF 89 00 0A 00 01 39 05 0A
[ 2023年07月20日10:43:27.581]#接收十六进制>
00 00 00 00 0A 00 00 00 0A
[ 2023年07月20日10:43:29.656]#接收十六进制>
00 00 00 00 0A 00 00 00 0A
[ 2023年07月20日10:43:31.665]#接收十六进制>
00 00 00 00 0A 00 00 00 0A
[ 2023年07月20日10:43:33.786]#接收十六进制>
00 00 00 00 0A 00 00 00 0A
[ 2023年07月20日10:43:35.888]#接收十六进制>
00 00 00 00 0A 00 00 00 0A
[ 2023年07月20日10:43:38.188]#接收十六进制>
7F FF FF 0A C4 80 00 00 0A
[ 2023年07月20日10:43:40.176]# RECV HEXE>
FF FF 92 00 0A 00 01 39 05 0A
我尝试在 MCU 启动期间读取 TCAN ID、并使用 MCU 板的复位按钮对其进行了测试。
您好 Reko:
TCAN4550演示代码是使用 Code Composer Studio 和 MSP430FR6989 MCU 开发的。 但是、大多数代码是 ANSI-C、可按原样移植到任何应用中。 必须修改固件 GPIO 引脚控制和 SPI 驱动程序以匹配应用的 MCU、例如 本例中的 STM32F407VET6。
您是否能够使用示波器或逻辑分析仪监控 SPI 信号? 如果是、它们应该与数据表中显示需要遵循的字节序列的 SPI 读取和写入数字相匹配。 请注意、单个寄存器读取/写入事务有两个数据字、NCS 引脚在整个64位期间必须保持低电平。 它无法在32位字之间转换为高电平、这是调试 SPI 驱动器代码时的常见观察结果。
请注意、数据表图显示了双倍寄存器写入或读取、该值在第一个(标头)字中设置"长度"字节、这将指示需要写入或读取2个(数据)字。 对于单次寄存器读取、您要将长度字节设置为0x01、然后仅在单个32位数据字期间保持 nCS 引脚处于低电平状态。
您能否共享所有 SPI 信号的示波器或逻辑分析仪图、以及或同时传输的 MOSI 和 MISO 数据以供查看? 仅仅看到收到的响应不能让我知道实际 SPI 信号是多少、其中包括发送到 TCAN4550的 MOSI 数据。 如果 MOSI 数据格式不正确、TCAN4550将不会返回有效数据。
此致、
乔纳森
感谢您的建议。 逻辑分析仪是一款非常有用的工具。 我从同事那里借用了一个、发现我的 nCS 引脚异常。 我将 nCS 更改为另一个引脚、并建立了基本通信。
但我也发现了其他2个问题。
1. 上电大约5分钟后、TCAN 返回全零、而不是正确的 ID。 nINT 和 nWKRQ 的 LED 熄灭、INH 亮起。 其他功能也可能已停止。
除了 SPI 线之外、我还将 TCAN 的5V 连接到 MCU 板5V、并将 VIO 连接到 MCU 3.3V。 MCU 板可通过 PC 上的5V 引脚或 USB 电缆供电。 按下复位按钮可使其恢复正常、其中 nINT 和 nWKRQ 打开、 INH 关闭。 我发现此问题与 TCAN4550EVM 类似:连接 MCU 时遇到问题-接口论坛-接口- TI E2E 支持论坛、但我尚未配置 TCAN、并且未连接 CAN 电缆。
如果 TCAN 在未连接 MCU 的情况下上电、则 INH、GPO2、nINT、GPIO1的 LED 会亮起、并且 nWKRQ 会在上电5分钟后熄灭。 在该状态下、复位按钮不起作用。 电路板必须由电源复位。
这种 行为是否正常? 我在手册中没有找到状态更改逻辑、所有功能模式都不符合上述 LED 状态。
2.您的代码样本在读取 SPI 数据时使用"wait_for_idle"。 我复制了这个逻辑、并将其转换为"while (SPI1->SR&(1<<7));"(我在这里学到了:controllerstech.com/spi-using-registers-in-stm32/)。 但逻辑分析仪显示、该线路在一段时间内暂停 SPI 时钟。
据我所知、ST 和 TI 的 MCU 都是基于 ARM 的、因此它们的行为方式应该类似。 因此我想 "wait_for_idle" 不等于"while (SPI1->SR&(1<<7));"。 我找到了"#define WAIT_FOR_IDLE while ((HWREG16 (SPI_HW_ADDR + OFS_UCBxSTATW)& UCBUSY))"、但我找不到 UCBUSY 的值。 您认为我应该如何解释"wait_for_idle"? 虽然我不使用 code composer、但我想您能理解这两种编译器。
您好 Reko:
您的第一个问题的答案是器件由于睡眠唤醒错误(SWE)计时器超时而进入睡眠模式、这是器件的失效防护功能之一。 如需更多信息、请参阅数据表的8.4.5失效防护特性部分。 上电后、您将有4分钟的时间来清除 PWRON 标志(0x0820[20])或配置器件、并通过写入工作模式和引脚配置寄存器(0x0800[7:6])中的 MODE_SEL 字段来进入正常模式。 如果在4分钟 SWE 计时器到期之前未发生上述任一情况、则器件将进入睡眠模式并需要唤醒事件。
在第二个问题中、这实际上只是用来检查 MSP430 MCU 是否仍在积极处理 SPI 传输的一行代码。 UCBUSY 是一个信号、表示器件正在发送或接收。
因为 SPI 协议是基于边沿的、所以在 SPI 时钟突发之间可以暂停、例如在每8或16位之间暂停。 只要出现时钟信号、就会捕获数据。 大多数 MCU 将在总体数据的较小的8位或16位部分上运行、在 SPI 时钟波形中通常会看到这些短暂的停顿。
此致、
乔纳森