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

[复制链接]
5411|7
 楼主| xhackerustc 发表于 2024-5-19 13:20 | 显示全部楼层 |阅读模式
本帖最后由 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方式。
  1. 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:
  1. 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, 用杜邦线连接它们即可

测试结果
2.jpg

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

  4. SPI_HandleTypeDef hspi1;
  5. UART_HandleTypeDef huart2;

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

  8. static uint8_t aRxBuffer[BUFFERSIZE];

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

  24.   return ch;
  25. }

  26. static void MX_USART2_UART_Init(void)
  27. {

  28.   /* USER CODE BEGIN USART2_Init 0 */

  29.   /* USER CODE END USART2_Init 0 */

  30.   /* USER CODE BEGIN USART2_Init 1 */

  31.   /* USER CODE END USART2_Init 1 */
  32.   huart2.Instance = USART2;
  33.   huart2.Init.BaudRate = 115200;
  34.   huart2.Init.WordLength = UART_WORDLENGTH_8B;
  35.   huart2.Init.StopBits = UART_STOPBITS_1;
  36.   huart2.Init.Parity = UART_PARITY_NONE;
  37.   huart2.Init.Mode = UART_MODE_TX_RX;
  38.   huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  39.   huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  40.   huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  41.   huart2.Init.ClockPrescaler = UART_PRESCALER_DIV1;
  42.   huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  43.   if (HAL_UART_Init(&huart2) != HAL_OK)
  44.   {
  45.     Error_Handler();
  46.   }
  47.   if (HAL_UARTEx_SetTxFifoThreshold(&huart2, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
  48.   {
  49.     Error_Handler();
  50.   }
  51.   if (HAL_UARTEx_SetRxFifoThreshold(&huart2, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
  52.   {
  53.     Error_Handler();
  54.   }
  55.   if (HAL_UARTEx_DisableFifoMode(&huart2) != HAL_OK)
  56.   {
  57.     Error_Handler();
  58.   }
  59.   /* USER CODE BEGIN USART2_Init 2 */

  60.   /* USER CODE END USART2_Init 2 */

  61. }

  62. void Error_Handler(void)
  63. {
  64.   while (1)
  65.   {
  66.     printf("error\n");
  67.     HAL_Delay(1000);
  68.   }
  69. }

  70. static void SystemClock_Config(void)
  71. {
  72.   RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  73.   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  74.   /** Configure the main internal regulator output voltage
  75.   */
  76.   HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);

  77.   /** Initializes the RCC Oscillators according to the specified parameters
  78.   * in the RCC_OscInitTypeDef structure.
  79.   */
  80.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
  81.   RCC_OscInitStruct.MSIState = RCC_MSI_ON;
  82.   RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
  83.   RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_11;
  84.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  85.   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  86.   {
  87.     Error_Handler();
  88.   }

  89.   /** Initializes the CPU, AHB and APB buses clocks
  90.   */
  91.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
  92.                               |RCC_CLOCKTYPE_PCLK1;
  93.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
  94.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  95.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

  96.   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
  97.   {
  98.     Error_Handler();
  99.   }
  100. }

  101. /**
  102.   * [url=home.php?mod=space&uid=247401]@brief[/url] SPI1 Initialization Function
  103.   * @param None
  104.   * @retval None
  105.   */
  106. static void MX_SPI1_Init(void)
  107. {
  108.   hspi1.Instance = SPI1;
  109.   hspi1.Init.Mode = SPI_MODE_MASTER;
  110.   hspi1.Init.Direction = SPI_DIRECTION_2LINES;
  111.   hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  112.   hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
  113.   hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  114.   hspi1.Init.NSS = SPI_NSS_SOFT;
  115.   hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
  116.   hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  117.   hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  118.   hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  119.   hspi1.Init.CRCPolynomial = 7;
  120.   hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
  121.   hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
  122.   if (HAL_SPI_Init(&hspi1) != HAL_OK)
  123.   {
  124.     Error_Handler();
  125.   }
  126. }

  127. int main(void)
  128. {

  129.   HAL_Init();

  130.   SystemClock_Config();

  131.   MX_USART2_UART_Init();
  132.   MX_SPI1_Init();

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

  138.   switch (HAL_SPI_TransmitReceive(&hspi1, (uint8_t *)aTxBuffer, (uint8_t *)aRxBuffer, BUFFERSIZE, 5000))
  139.   {
  140.     case HAL_OK:
  141.       /* Communication is completed ___________________________________________ */
  142.       /* Compare the sent and received buffers */
  143.       printf("RX:\n%s\n", aRxBuffer);
  144.       if (memcmp((uint8_t *)aTxBuffer, (uint8_t *)aRxBuffer, BUFFERSIZE))
  145.       {
  146.         /* Transfer error in transmission process */
  147.         Error_Handler();
  148.       }
  149.       /* Turn LED4 on: Transfer in transmission/Reception process is correct */
  150.       break;

  151.     case HAL_TIMEOUT:
  152.     /* An Error Occur ______________________________________________________ */
  153.     case HAL_ERROR:
  154.       /* Call Timeout Handler */
  155.       Error_Handler();
  156.       break;
  157.     default:
  158.       break;
  159.   }

  160.   for (;;)
  161.         HAL_Delay(100000);
  162. }





tpgf 发表于 2024-6-4 15:25 | 显示全部楼层
如何配置帧支持的数据位数呢?
八层楼 发表于 2024-6-4 16:05 | 显示全部楼层
spi通讯对波特率的容差是多少呢
观海 发表于 2024-6-4 19:37 | 显示全部楼层
一个数据包的数据量能达到多少呢
晓伍 发表于 2024-6-4 20:09 | 显示全部楼层
spi的最大通讯速度能达到多少啊
磨砂 发表于 2024-6-4 20:41 | 显示全部楼层
是不是只有四线制的spi才有主从之分啊
木木guainv 发表于 2024-6-4 21:13 | 显示全部楼层
看题目这个到底是不是在linux系统下的操作呢
kepe 发表于 2024-7-31 00:09 | 显示全部楼层
形成external loop,然后自发自收,这有点像linux下的spidev_test测试程序
您需要登录后才可以回帖 登录 | 注册

本版积分规则

42

主题

166

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部