打印
[STM32U0]

【STM32U083测评】类似linux下的spidev_test开发与测试

[复制链接]
4847|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 xhackerustc 于 2024-5-19 13:28 编辑

这一贴测评SPI。根据官方datasheet,芯片有3个spi控制器,都支持spi master和spi slave,帧大小支持4bits - 16bits,详细可参见datasheet。本帖就以SPI1为对象测试。外设的测试一般都会接上对应设备,比如i2c slave等等,但SPI比较特别,可以用杜邦线把MISO和MSOI针脚连接起来,形成external loop,然后自发自收,这有点像linux下的spidev_test测试程序。根据笔者经验一般过了spidev_test,基本spi控制器没啥大问题了。

创建spidev_test工程
STM官方代码里有很多SPI样例,都在Projects/NUCLEO-U083RC/Examples/SPI/目录和Projects/NUCLEO-U083RC/Examples_LL/SPI/目录里,。笔者浏览以后挑了SPI_FullDuplex_ComPolling_Master为模板创建spidev_test工程。本来这个SPI_FullDuplex_ComPolling_Master需要两块板子,一块运行SPI_FullDuplex_ComPolling_Master,另一块运行SPI_FullDuplex_ComPolling_aSlave,咱们现在就改造它使用external loop方式。
cp -a Projects/NUCLEO-U083RC/Examples/SPI/SPI_FullDuplex_ComPolling_Master/ Projects/NUCLEO-U083RC/Examples/spidev_test/



串口printf打印
spidev_test测试结果是把收到的数据全打印出来,因为SPI_FullDuplex_ComPolling_Master传的是字符串,可以当字符串打印。所以现在还需要把Projects/NUCLEO-U083RC/Examples/UART/UART_Print的一些code拿过来。

第一个是stm32u0xx_hal_msp.c中的HAL_UART_MspInit()和HAL_UART_MspDeInit()函数,不过需要注意我们未使能HSI,所以需要把UART的时钟源改成ssysclk:
PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_SYSCLK;
第二拿过来的是MX_USART2_UART_Init函数以及PUTCHAR_PROTOTYPE

main函数中调用一次MX_USART2_UART_Init()后printf就可以用了

发起spi传输
照着SPI_FullDuplex_ComPolling_Master例子调用HAL_SPI_TransmitReceive()函数即可

接线datasheet里SPI1的MISO和MOSI针脚可选PB4与PB5,根据板子原理图这两根针脚接到了CN10的pin27和pin29, 用杜邦线连接它们即可

测试结果


完整main.c代码附上
#include <stdio.h>
#include <string.h>
#include "main.h"

SPI_HandleTypeDef hspi1;
UART_HandleTypeDef huart2;

/* Buffer used for transmission */
static uint8_t aTxBuffer[] = "****SPI - external loop communication based on Polling **** SPI Message ******** SPI Message ******** SPI Message ****";

static uint8_t aRxBuffer[BUFFERSIZE];

#if defined(__ICCARM__)
/* New definition from EWARM V9, compatible with EWARM8 */
int iar_fputc(int ch);
#define PUTCHAR_PROTOTYPE int iar_fputc(int ch)
#elif defined ( __CC_ARM ) || defined(__ARMCC_VERSION)
/* ARM Compiler 5/6*/
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#elif defined(__GNUC__)
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#endif
PUTCHAR_PROTOTYPE
{
  /* Place your implementation of fputc here */
  /* e.g. write a character to the USART2 and Loop until the end of transmission */
  HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, 0xFFFF);

  return ch;
}

static void MX_USART2_UART_Init(void)
{

  /* USER CODE BEGIN USART2_Init 0 */

  /* USER CODE END USART2_Init 0 */

  /* USER CODE BEGIN USART2_Init 1 */

  /* USER CODE END USART2_Init 1 */
  huart2.Instance = USART2;
  huart2.Init.BaudRate = 115200;
  huart2.Init.WordLength = UART_WORDLENGTH_8B;
  huart2.Init.StopBits = UART_STOPBITS_1;
  huart2.Init.Parity = UART_PARITY_NONE;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart2.Init.ClockPrescaler = UART_PRESCALER_DIV1;
  huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart2) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetTxFifoThreshold(&huart2, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetRxFifoThreshold(&huart2, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_DisableFifoMode(&huart2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART2_Init 2 */

  /* USER CODE END USART2_Init 2 */

}

void Error_Handler(void)
{
  while (1)
  {
    printf("error\n");
    HAL_Delay(1000);
  }
}

static void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
  RCC_OscInitStruct.MSIState = RCC_MSI_ON;
  RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_11;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * [url=home.php?mod=space&uid=247401]@brief[/url] SPI1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_SPI1_Init(void)
{
  hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_MASTER;
  hspi1.Init.Direction = SPI_DIRECTION_2LINES;
  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi1.Init.NSS = SPI_NSS_SOFT;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 7;
  hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
  hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {
    Error_Handler();
  }
}

int main(void)
{

  HAL_Init();

  SystemClock_Config();

  MX_USART2_UART_Init();
  MX_SPI1_Init();

  printf("** spi external loop test ** \n\r");
  printf("SysClockFreq:%ld\n", HAL_RCC_GetSysClockFreq());
  /* While the SPI in TransmitReceive process, user can transmit data through
     "aTxBuffer" buffer & receive data through "aRxBuffer" */
  /* Timeout is set to 5S */

  switch (HAL_SPI_TransmitReceive(&hspi1, (uint8_t *)aTxBuffer, (uint8_t *)aRxBuffer, BUFFERSIZE, 5000))
  {
    case HAL_OK:
      /* Communication is completed ___________________________________________ */
      /* Compare the sent and received buffers */
      printf("RX:\n%s\n", aRxBuffer);
      if (memcmp((uint8_t *)aTxBuffer, (uint8_t *)aRxBuffer, BUFFERSIZE))
      {
        /* Transfer error in transmission process */
        Error_Handler();
      }
      /* Turn LED4 on: Transfer in transmission/Reception process is correct */
      break;

    case HAL_TIMEOUT:
    /* An Error Occur ______________________________________________________ */
    case HAL_ERROR:
      /* Call Timeout Handler */
      Error_Handler();
      break;
    default:
      break;
  }

  for (;;)
        HAL_Delay(100000);
}





使用特权

评论回复
沙发
tpgf| | 2024-6-4 15:25 | 只看该作者
如何配置帧支持的数据位数呢?

使用特权

评论回复
板凳
八层楼| | 2024-6-4 16:05 | 只看该作者
spi通讯对波特率的容差是多少呢

使用特权

评论回复
地板
观海| | 2024-6-4 19:37 | 只看该作者
一个数据包的数据量能达到多少呢

使用特权

评论回复
5
晓伍| | 2024-6-4 20:09 | 只看该作者
spi的最大通讯速度能达到多少啊

使用特权

评论回复
6
磨砂| | 2024-6-4 20:41 | 只看该作者
是不是只有四线制的spi才有主从之分啊

使用特权

评论回复
7
木木guainv| | 2024-6-4 21:13 | 只看该作者
看题目这个到底是不是在linux系统下的操作呢

使用特权

评论回复
8
kepe| | 2024-7-31 00:09 | 只看该作者
形成external loop,然后自发自收,这有点像linux下的spidev_test测试程序

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

21

主题

68

帖子

0

粉丝