c - STM32主/从SPI通信使用HAL_SPI_TransmitReceive()
问题描述
我正在尝试使用 HAL_SPI_TransmitReceive() 测试 SPI 主机,因为我将与 SPI 从机进行通信。SPI 从设备尚不可用。我有两个正在使用的 STM32F4 NUCLEO。一个将是主设备,一个假装是从设备。我已将它们连接在一起并使用以下代码:
Master_main.c
SPI_HandleTypeDef hspi2;
static void MX_SPI2_Init(void);
uint8_t spi_tx_data[9];
uint8_t spi_rx_data[9];
int main(void)
{
MX_SPI2_Init();
spi_tx_data[0] = 0;
spi_tx_data[1] = 0;
spi_tx_data[2] = 0;
spi_tx_data[3] = 0;
spi_tx_data[4] = 0;
spi_tx_data[5] = 0;
spi_tx_data[6] = 0;
spi_tx_data[7] = 0;
spi_tx_data[8] = 1;
while (1)
{
static HAL_StatusTypeDef spi_error = HAL_OK;
static uint32_t PreviousTicks_GreenLight = 0U;
uint32_t CurrentTicks_GreenLight = HAL_GetTick();
if((CurrentTicks_GreenLight - PreviousTicks_GreenLight) >= 500u)
{
HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin);
PreviousTicks_GreenLight = CurrentTicks_GreenLight;
}
static uint8_t runonce = 0;
if (HAL_GPIO_ReadPin(USER_Btn_GPIO_Port, USER_Btn_Pin) != 0) {
if (runonce != 1){
HAL_GPIO_WritePin(GPIO_ADR1_GPIO_Port, GPIO_ADR1_Pin, 0);
HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
spi_error = HAL_SPI_TransmitReceive(&hspi2,spi_tx_data, spi_rx_data,18,0x01);
HAL_Delay(1);
HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
HAL_GPIO_WritePin(GPIO_ADR1_GPIO_Port, GPIO_ADR1_Pin, 1);
runonce = 1;
}
} else {
runonce = 0;
}
static uint32_t PreviousTicks_RedLight = 0U;
uint32_t CurrentTicks_RedLight = HAL_GetTick();
if((CurrentTicks_RedLight - PreviousTicks_RedLight) >= 500u)
{
if ( spi_error == HAL_TIMEOUT || spi_error == HAL_ERROR){
HAL_GPIO_TogglePin(LD3_GPIO_Port, LD3_Pin);
} else {
if ( spi_rx_data[8] == 2){
HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
}
}
PreviousTicks_RedLight = CurrentTicks_RedLight;
}
}
}
static void MX_SPI2_Init(void)
{
hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_MASTER;
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi2.Init.NSS = SPI_NSS_SOFT;
hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi2.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi2) != HAL_OK)
{
Error_Handler();
}
}
slave_main.c
uint8_t spi_tx_data[9];
uint8_t spi_rx_data[9];
uint8_t rx_cmplt = 0;
void HAL_SPI_RxCpltCallback (SPI_HandleTypeDef *hspi) {
static uint8_t rx_counter = 0;
if ( rx_counter == 8 ){
rx_cmplt = 1;
} else {
rx_counter++;
}
HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
}
int main(void)
{
MX_SPI2_Init();
spi_tx_data[0] = 0;
spi_tx_data[1] = 0;
spi_tx_data[2] = 0;
spi_tx_data[3] = 0;
spi_tx_data[4] = 0;
spi_tx_data[5] = 0;
spi_tx_data[6] = 0;
spi_tx_data[7] = 0;
spi_tx_data[8] = 2;
while (1)
{
static HAL_StatusTypeDef spi_error = HAL_OK;
static uint32_t PreviousTicks_GreenLight = 0U;
uint32_t CurrentTicks_GreenLight = HAL_GetTick();
if((CurrentTicks_GreenLight - PreviousTicks_GreenLight) >= 1000u)
{
HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin);
PreviousTicks_GreenLight = CurrentTicks_GreenLight;
}
static uint8_t runonce = 0;
if (HAL_GPIO_ReadPin(GPIO_ADR1_GPIO_Port, GPIO_ADR1_Pin) != 1) {
if (runonce != 1){
HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
//spi_error = HAL_SPI_TransmitReceive_IT(&hspi2, spi_tx_data, spi_rx_data, 18);
spi_error = HAL_SPI_TransmitReceive(&hspi2,spi_tx_data, spi_rx_data,18,0x01);
HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
runonce = 1;
}
} else {
runonce = 0;
}
static uint32_t PreviousTicks_RedLight = 0U;
uint32_t CurrentTicks_RedLight = HAL_GetTick();
if((CurrentTicks_RedLight - PreviousTicks_RedLight) >= 500u)
{
if ( rx_cmplt == 1 ){
if (spi_rx_data[8] == 1){
HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, 1);
} else {
HAL_GPIO_WritePin(LD3_GPIO_Port, LD3_Pin, 1);
}
} else {
if ( spi_error == HAL_TIMEOUT || spi_error == HAL_ERROR){
HAL_GPIO_TogglePin(LD3_GPIO_Port, LD3_Pin);
if (spi_error == HAL_TIMEOUT){
HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
}
}
}
PreviousTicks_RedLight = CurrentTicks_RedLight;
}
}
}
static void MX_SPI2_Init(void)
{
hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_SLAVE;
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi2.Init.NSS = SPI_NSS_SOFT;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi2.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi2) != HAL_OK)
{
Error_Handler();
}
}
为了简单起见,我去掉了各种 MCU 初始化。我之前曾尝试使用 IT 版本的 TransmitRecieve,但没有成功传输。如果我多次使用主设备上的 USER 按钮,它确实会激活从设备上的相应灯,但不会在主设备上激活。
解决方案
我怀疑我有某种接线问题。我在混合物中添加了一个面包板并插入了一些 LED,不知何故,在将所有东西连接起来后,主从都正常工作。我确实更改了代码以使用 SPI 的一些 STM 示例,但那是在面包板之前。
从站.c
static uint8_t runonce = 0;
if (HAL_GPIO_ReadPin(GPIO_ADR1_GPIO_Port, GPIO_ADR1_Pin) != 1) {
if (runonce != 1){
switch(HAL_SPI_TransmitReceive(&hspi2, spi_tx_data, spi_rx_data, 9, 5000))
{
case HAL_OK:
/* Communication is completed_____________________________________________*/
/* Compare the sent and received buffers */
if(spi_rx_data[8] == 1)
{
HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin);
}
break;
case HAL_TIMEOUT:
/* A Timeout occurred_____________________________________________________*/
/* Call Timeout Handler */
HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
break;
/* An Error occurred______________________________________________________*/
case HAL_ERROR:
/* Call Timeout Handler */
HAL_GPIO_TogglePin(LD3_GPIO_Port, LD3_Pin);
break;
default:
break;
}
runonce = 1;
}
} else {
runonce = 0;
}
大师.c
static uint8_t runonce = 0;
if (HAL_GPIO_ReadPin(USER_Btn_GPIO_Port, USER_Btn_Pin) != 0) {
if (runonce != 1){
HAL_GPIO_WritePin(GPIO_ADR1_GPIO_Port, GPIO_ADR1_Pin, 0);
HAL_Delay(0x01);
switch(HAL_SPI_TransmitReceive(&hspi2, spi_tx_data, spi_rx_data, 9, 5000))
{
case HAL_OK:
/* Communication is completed_____________________________________________*/
/* Compare the sent and received buffers */
if(spi_rx_data[8] == 2)
{
HAL_GPIO_WritePin(LD1_GPIO_Port, LD1_Pin, 1);
}
break;
case HAL_TIMEOUT:
/* A Timeout occurred_____________________________________________________*/
/* Call Timeout Handler */
HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, 1);
break;
/* An Error occurred______________________________________________________*/
case HAL_ERROR:
/* Call Timeout Handler */
HAL_GPIO_WritePin(LD3_GPIO_Port, LD3_Pin, 1);
break;
default:
break;
}
//HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
HAL_GPIO_WritePin(GPIO_ADR1_GPIO_Port, GPIO_ADR1_Pin, 1);
runonce = 1;
}
} else {
runonce = 0;
}
推荐阅读
- php - 在 Codeigniter 中生成 JSON 查询结果
- c++ - 为什么字符串类型会导致c++程序无法运行?
- php - cpanel如何创建账户?
- google-apps-script - 是否可以使用 Google 表单触发 iMacros 脚本?
- python - Cython 如何从另一个包导入
- jupyter-notebook - 使用带有选项 manual=True 的 ipywidget interactive()
- sql - SQL Server 中的 CASE 表达式
- javascript - Chrome 扩展:如何将来自多个窗口的标签 URL 存储到数组中
- wordpress - 当我尝试获取产品名称 $product->get_name() 时出现内部服务器错误
- html - 如何根据图像在外部缩放 css 形状