如何修复STM32F3上SPI的芯片选择时序?
How to fix Chip Select Timing for SPI on STM32F3?
我正在使用需要全双工SPI的STM32F303RE进行项目,并且正在使用STM提供的HAL库。虽然所有线路都在SCK,MOSI和MISO方面工作,但我注意到芯片选择线的低电平比必要的要长得多,并且似乎在20kHz左右触发,而不是2MHz SPI。这是一个问题,因为我在CS线路上使用的从属服务器,并且在多次SPI调用期间数据损坏。如何确定时间?
我目前正在使用手动 GPIO,它只是在 SPI 调用之前和之后设置低/高。从在线阅读来看,CS引脚似乎是很多人的问题来源,因为也可以选择使用硬件NSS信号,尽管人们建议不要这样做,因为它无法正常工作。
// Set SS pin low to activate
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);
// Read Temp
if(HAL_SPI_TransmitReceive(&hspi2, (uint8_t*)&master_buffer_tx[4], (uint8_t*)&master_buffer_rx[4], 1, 1000)!=HAL_OK){
Error_Handler();
}
// Check finished
while(HAL_SPI_GetState(&hspi2) != HAL_SPI_STATE_READY){
}
// Set SS pin high to deactivate
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET);
HAL_Delay(10);
我预计 CS 在 SCK 之前和之后大约半个周期会走低。 这些是我可能的想法:"检查完成"行是否导致了问题?可能是我的时钟设置吗?我使用的 GPIO 引脚是否应该与 NSS 的位置相同?我应该使用硬件 NSS 吗?我是否需要使用中断和 DMA?
抱歉,如果这些看起来很幼稚,因为我仍在努力了解微控制器。谢谢!
CS 和 SCK 时序
我想我可以解释CS激活和SPI传输之间的延迟: 如果您查看内部HAL_SPI_TransmitReceive()
您会发现它实际上需要大量操作来设置和启动实际的SPI传输。根据您的时钟配置,这很容易需要几微秒(另请参阅此问题)。
我对 SPI 传输后的延迟有点困惑,直到 CS 被取消断言。与传输准备相比,HAL 代码完成传输所需的操作要少得多。"检查完成"代码不需要很多循环,因为它实际上只检查软件标志(甚至不检查硬件寄存器)。但是,调用不是必需的,因为HAL_SPI_TransmitReceive()
是一个阻塞函数,仅在SPI传输完成后返回。
关于您的问题,我想建议使用硬件NSS功能。但仔细想想,一旦启用 SPI 单元,就会断言 CS。ST HAL 似乎不会在每次传输后禁用 SPI 单元 - 因此这不会按预期工作。
我认为您需要进一步分析在实际 SPI 传输和 CS 取消断言之间 HAL 内部发生了什么。这看起来不像是正常行为。没有必要使用中断或 DMA 来改进 CS 行为。这些功能从 CPU 加载,但需要更复杂的代码,这可能不会改善 CS 延迟。
- 如何使用默认参数等选择模板专业化
- 如何(从固定列表中)选择一个数字序列,该序列将与目标数字相加
- 选择要调用的构造函数
- C++选择排序算法中的逻辑错误
- QTreeView幻灯片多选后无法使用单击选择
- 无法获取菜单选择以运行函数.C++
- Qt C++静态thread_local QNetworkAccessManager是线程应用程序的好选择吗
- 在C++中,如何通过几种类型从元组中选择多个元素
- 讨论 - 创建矩阵时的数组与向量的向量 - 什么是最实用的选择
- 对可变参数使用声明.如何选择正确的功能
- 选择选举获胜者的程序
- 如何选择在 csv 文件中输出的位置
- 根据用户回答声明"Players"。用户选择玩家数量。播放器是结构体
- 程序在尝试猜测它选择的随机数时进入无限循环?
- 选择和修改嵌套向量中的条目的最佳实践
- 在PostgreSQL中根据它们的ID选择大量行的最快方法是什么?
- 表达式 SFINAE:如何根据类型是否包含具有一个或多个参数的函数来选择模板版本
- 在运行时选择父类的实现
- 数数并选择 sqlite 中的前三名
- 如何修复STM32F3上SPI的芯片选择时序?