找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4323|回复: 1
收起左侧

STM32L0简易多总线测试仪制作

[复制链接]
ID:127084 发表于 2016-6-17 17:28 | 显示全部楼层 |阅读模式
本版本是初级版本,编程与2016年5月1日下午。在HMC5983上做了初步测试,单仍然不能确保是否完全正确。但是因为答应沐紫五一更新,所以就敢在晚上提交了代码。
下面是硬件连接:
1 串口使用UART1(PA9-Tx,PA10-Rx),SPI使用SPI1(PB3-SCK,PB4-MISO,PB5-MOSI,PA15-NSS).
具体的Nucleo板子的连接可参考L073的图纸,这里简单列举一下连接:
CN10的27/29/31和CN7的17作为SPI口使用。CN7的18提供5V,12和16提供3.3V,20/22提供接地电源。


PS:
就像我帖子里所说,这里通过串口来调试SPI设备的接口。因为只是测试,所以还没有写上位机界面,而且如果要写上位机界面,串口不会提供这么多信息的。串口的接受到时候也会改成中断方式。
另外代码逻辑可能有不严谨的地方,请高手指正。谢谢!


常常遇到人们在调试一台新的I2C设备或者SPI设备的时候,没有方便的设备可用来验证身边的硬件是好是坏。也遇到过人们对于自己拿到的CAN或者RS485等设备不知道这些设备的状态或者数据格式。这些日常的问题催发了需求。当然有人已经做了类似的工作,但是价格和封闭性是一个弊端。现在想做一款这样的小产品,代码和电路图都公开。测试期间可以利用L073的平台来实现,等成熟时在做原理图,美化上位机等。

大致的功能:
        I2C从设备,SPI从设备的读取。
        CAN总线命令解析,可以选择时候短帧或者长帧
        TTL、232/485解析(主要是收发器不一样)
上位机准备用QT或者C#编写。

好吧就这么多。

||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
分割线|||2016.04.27
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
沐紫姐姐留言了,收到板子有一段时间了。可是只是做了几个简单的测试,总线检测仪的项目一直没有正式开始。
好吧,是时候说明一下这款总线检测仪的详细情况。
PS:本来想加入CAN检测的功能,可是详细看了一下这个系列,发现的确不支持CAN总线。不过不要紧,如果这个项目在L0上实现,可以移植到别的上面。毕竟STM32的代码移植性很高。

第一阶段,打算分别测试和编写各种类型总线,包括I2C,SPI,UART(IrDA、LIN、Modubus)。另外添加几个ADC采集的引脚,和PWM的输出引脚。方便测试。打算两周完成。
第二阶段,基于RTOS编写调度和接口程序用于与上位机通讯。起初想用现成的串口工具,然后用QT编写一个界面用于测试。打算三周。
第三阶段,做板子,并优化界面。打算三周。
详细一点的现成调度相关的东西,稍后在写。五一期间,先贡献I2C和SPI读取的实验。然后慢慢添加Modubus之类的,毕竟手边这种工具不多。
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
分割线|||2016.5.01 SPI总线测试(测试设备HMC5983)
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
撑着五一测试了一下SPI接口,写了一个通过UART测试SPI的简单程序,这只属于最初步的工作。
下面先代码先放上。
L073_SPI.rar (6.67 MB, 下载次数: 19)
本版本是初级版本,编程与2016年5月1日下午。在HMC5983上做了初步测试,单仍然不能确保是否完全正确。但是因为答应沐紫五一更新,所以就赶在晚上提交了代码。
下面是硬件连接:
1 串口使用UART1(PA9-Tx,PA10-Rx),SPI使用SPI1(PB3-SCK,PB4-MISO,PB5-MOSI,PA15-NSS).
具体的Nucleo板子的连接可参考L073的图纸,这里简单列举一下连接:
CN10的27/29/31和CN7的17作为SPI口使用。CN7的18提供5V,12和16提供3.3V,20/22提供接地电源。

PS:
就像我帖子里所说,这里通过串口来调试SPI设备的接口。因为只是测试,所以还没有写上位机界面,而且如果要写上位机界面,串口不会提供这么多信息的。串口的接受到时候也会改成中断方式。
另外代码逻辑可能有不严谨的地方,请高手指正。谢谢!

顺便附上调试的照片:
230302kcj9b2m6vlrgy9gh.jpg 230311dsmjjipjmm6mz074.jpg
这是昨天拍的,在公司里做变得时,顺便赔了一下接口,可是没来得及编程。
230645inmv288g8rtmn42s.jpg
这是今天在家里测试的。
命令提示能够在串口中看到,大致就是三个字节长度的命令。
具体的要发送的东西,要看相关芯片手册。这里就不具体讲了。可以留在之后有时间再说。
231108w29928qg1nwe2xqx.png

|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
分割线|||2016.5.? I2C总线测试(测试设备MC8607)
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
其实这个已经在F401上测试过,有代码,可是暂时还没有整理和移植到F073,看看明天有时间吗。因为明天要组装一个书柜。我这过得真是劳动节。

  1. /**
  2.   ******************************************************************************
  3.   * File Name          : main.c
  4.   * Description        : Main program body
  5.   ******************************************************************************
  6.   *
  7.   * COPYRIGHT(c) 2016 STMicroelectronics
  8.   *
  9.   * Redistribution and use in source and binary forms, with or without modification,
  10.   * are permitted provided that the following conditions are met:
  11.   *   1. Redistributions of source code must retain the above copyright notice,
  12.   *      this list of conditions and the following disclaimer.
  13.   *   2. Redistributions in binary form must reproduce the above copyright notice,
  14.   *      this list of conditions and the following disclaimer in the documentation
  15.   *      and/or other materials provided with the distribution.
  16.   *   3. Neither the name of STMicroelectronics nor the names of its contributors
  17.   *      may be used to endorse or promote products derived from this software
  18.   *      without specific prior written permission.
  19.   *
  20.   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  21.   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22.   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  23.   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  24.   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  25.   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  26.   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  27.   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  28.   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29.   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30.   *
  31.   ******************************************************************************
  32.   */
  33. /* Includes ------------------------------------------------------------------*/
  34. #include "stm32l0xx_hal.h"
  35. #include "spi.h"
  36. #include "usart.h"
  37. #include "gpio.h"

  38. /* USER CODE BEGIN Includes */

  39. /* USER CODE END Includes */

  40. /* Private variables ---------------------------------------------------------*/

  41. /* USER CODE BEGIN PV */
  42. /* Private variables ---------------------------------------------------------*/
  43. #define SPI_PIPE_LEN 20
  44. //#define UART_PIPE_LEN 20
  45. uint8_t AR_SPI_TX[SPI_PIPE_LEN] = {0};
  46. uint8_t AR_SPI_RX[SPI_PIPE_LEN] = {0};
  47. //uint8_t AR_UART_TX[SPI_PIPE_LEN] = {0};
  48. //uint8_t AR_UART_RX[SPI_PIPE_LEN] = {0};
  49. uint32_t baudRateList[5] = {(uint32_t)SPI_BAUDRATEPRESCALER_32,(uint32_t)SPI_BAUDRATEPRESCALER_64,(uint32_t)SPI_BAUDRATEPRESCALER_128,(uint32_t)SPI_BAUDRATEPRESCALER_16,(uint32_t)SPI_BAUDRATEPRESCALER_8};


  50. /* USER CODE END PV */

  51. /* Private function prototypes -----------------------------------------------*/
  52. void SystemClock_Config(void);
  53. void Error_Handle(HAL_StatusTypeDef _state);
  54. void spiTask0(uint8_t len);
  55. void spiTask1(uint8_t cmd, uint8_t len);
  56. void spiTask2(uint8_t len);
  57. void spiTask3(uint8_t _CPOL, uint8_t _CPHA);
  58. void spiTask4(uint8_t _firstBit,uint8_t _baudrate);
  59. /* USER CODE BEGIN PFP */
  60. /* Private function prototypes -----------------------------------------------*/

  61. /* USER CODE END PFP */

  62. /* USER CODE BEGIN 0 */

  63. /* USER CODE END 0 */

  64. int main(void)
  65. {

  66.   /* USER CODE BEGIN 1 */
  67.         uint32_t counter = 0;
  68.         uint8_t spiCmd[3] = {0};
  69.         HAL_StatusTypeDef state;
  70.   /* USER CODE END 1 */
  71.         
  72.   /* MCU Configuration----------------------------------------------------------*/

  73.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  74.   HAL_Init();

  75.   /* Configure the system clock */
  76.   SystemClock_Config();

  77.   /* Initialize all configured peripherals */
  78.   MX_GPIO_Init();
  79.   MX_SPI1_Init();
  80.   MX_USART1_UART_Init();

  81.   /* USER CODE BEGIN 2 */
  82.         printf("instruction is like this CMD0 CMD1 CMD2. CMD0 is direction, CMD1 is what you want to input, CMD2 is length ");
  83.         printf("CMD0 is direction:0-just get data, 1-send a command and get data,2-send lots of data ");
  84.         printf("when CMD0 is 2, CMD2 means how long what you will send ");
  85.         printf("when CMD0 is 3, you can config spi. CMD1 means CPOL(0-LOW,1-HIGH,other no change),CMD2 means CPHA(0:1st edge, 1:2ns edge,other- no change) ");
  86.         printf("when CMD0 is 4, you can config spi. CMD1 means First bit select(0-MSB,1-LSB,other-no change).CMD2 Baud rate(0-1Mbps,1-500Kbps,2-250Kbps,3-2Mbps,4-4Mbps,other-nochange) ");
  87.         printf("When CMD0 is 5, give some tips again.");
  88.         printf("You can't give a too long parameter for CMD2. It should be not bigger than %d",(uint8_t)SPI_PIPE_LEN);
  89.   /* USER CODE END 2 */

  90.   /* Infinite loop */
  91.   /* USER CODE BEGIN WHILE */
  92.   while (1)
  93.   {
  94.   /* USER CODE END WHILE */

  95.   /* USER CODE BEGIN 3 */
  96.                 printf("counter is %d ",counter++);
  97. //                HAL_GPIO_TogglePin(LD2_GPIO_Port,LD2_Pin);
  98. //                HAL_Delay(500);
  99.                 HAL_GPIO_WritePin(LD2_GPIO_Port,LD2_Pin,GPIO_PIN_SET);
  100.                 printf("Please give me a instruction for SPI ");
  101.                 state = HAL_UART_Receive(&huart1,spiCmd,3,0xffffffff);
  102.                 if( state != HAL_OK){
  103.                         printf("UART is ");
  104.                         Error_Handle(state);
  105.                 }
  106.                 else{
  107.                         HAL_GPIO_WritePin(LD2_GPIO_Port,LD2_Pin,GPIO_PIN_RESET);
  108.                         switch(spiCmd[0]){
  109.                                 case 0: printf("you want to get %d data from spi device",spiCmd[2]);spiTask0(spiCmd[2]);break;
  110.                                 case 1: printf("you want to send command:0x%X to spi device",spiCmd[1]);spiTask1(spiCmd[1],spiCmd[2]);break;
  111.                                 case 2: printf("you want to input %d byte data",spiCmd[2]);spiTask2(spiCmd[2]);break;
  112.                                 case 3: printf("you want to config CPOL and CPHA.");break;
  113.                                 case 4: printf("you want to config First bit and Baudrate.");break;
  114.                                 default: printf("what you have input is wrong");break;
  115.                         }
  116.                 }

  117.   }
  118.   /* USER CODE END 3 */

  119. }

  120. /** System Clock Configuration
  121. */
  122. void SystemClock_Config(void)
  123. {

  124.   RCC_OscInitTypeDef RCC_OscInitStruct;
  125.   RCC_ClkInitTypeDef RCC_ClkInitStruct;
  126.   RCC_PeriphCLKInitTypeDef PeriphClkInit;

  127.   __HAL_RCC_PWR_CLK_ENABLE();

  128.   __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  129.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  130.   RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS;
  131.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  132.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  133.   RCC_OscInitStruct.PLL.PLLMUL = RCC_PLLMUL_8;
  134.   RCC_OscInitStruct.PLL.PLLDIV = RCC_PLLDIV_2;
  135.   HAL_RCC_OscConfig(&RCC_OscInitStruct);

  136.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
  137.                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  138.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  139.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  140.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  141.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
  142.   HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1);

  143.   PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;
  144.   PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
  145.   HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);

  146.   HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

  147.   HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  148.   /* SysTick_IRQn interrupt configuration */
  149.   HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
  150. }

  151. /* USER CODE BEGIN 4 */
  152. void Error_Handle(HAL_StatusTypeDef _state){
  153.         switch(_state){
  154.                 case HAL_ERROR: printf("error");break;
  155.                 case HAL_TIMEOUT: printf("timeout");break;
  156.                 case HAL_BUSY: printf("busy");break;
  157.                 default: printf(" in unknow error");break;
  158.         }
  159. }

  160. void spiTask0(uint8_t len){
  161.         HAL_StatusTypeDef st = HAL_SPI_Receive(&hspi1,AR_SPI_RX,len,1000);
  162.         if(st != HAL_OK){
  163.                 printf("SPI receive task is ");
  164.                 Error_Handle(st);
  165.                 return;
  166.         }
  167.         else{
  168.                 printf("so what you want to get is:");
  169.                 for(uint8_t cir=0;cir<len;cir++){
  170.                         if(cir%3 == 0) printf("    ");
  171.                         printf("0x%X  ",AR_SPI_RX[cir]);
  172.                 }
  173.         }
  174. }
  175. void spiTask1(uint8_t cmd, uint8_t len){
  176.         uint8_t send = cmd;
  177.         if(len == 0) len = 1;
  178.         else if(len > SPI_PIPE_LEN){
  179.                 len = SPI_PIPE_LEN;               
  180.         }
  181.         HAL_StatusTypeDef st = HAL_SPI_TransmitReceive(&hspi1,&send,AR_SPI_RX,len,1000);
  182.         if(st != HAL_OK){
  183.                 printf("SPI transmit task is ");
  184.                 Error_Handle(st);
  185.                 return;
  186.         }
  187.         else{
  188.                 printf("Device have succeed to receive your command ");
  189.                 printf(" and device give you some data:");
  190.                 for(uint8_t cir=0;cir<len;cir++){
  191.                         if(cir%3 == 0) printf("    ");
  192.                         printf("0x%X  ",AR_SPI_RX[cir]);
  193.                 }
  194.                 printf("");
  195.         }
  196. }
  197. void spiTask2(uint8_t len){
  198.         if(len == 0) len = 1;
  199.         else if(len > SPI_PIPE_LEN){
  200.                 len = SPI_PIPE_LEN;               
  201.         }
  202.         HAL_StatusTypeDef state = HAL_UART_Receive(&huart1,AR_SPI_TX,len,0xffff);
  203.         if( state != HAL_OK){
  204.                 printf("UART is ");
  205.                 Error_Handle(state);
  206.                 return;
  207.         }
  208.         else{
  209.                 printf("what you want to get from spi deceive is:");
  210.                 for(uint8_t cir2 = 0;cir2<len;cir2++){
  211.                         if(cir2%3 == 0) printf("    ");
  212.                         printf("0x%X  ",AR_SPI_TX[cir2]);
  213.                 }
  214.                 printf("");
  215.         }

  216. }

  217. void spiTask3(uint8_t _CPOL, uint8_t _CPHA){
  218.         if( (_CPOL < 2) || (_CPHA < 2) ){
  219.                 if(_CPOL == 0){
  220.                         hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
  221.                         printf("CPOL will set to LOW and ");
  222.                 }
  223.                 else if(_CPOL == 1){
  224.                         hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH;
  225.                         printf("CPOL will set to HIGH and ");
  226.                 }
  227.                 if(_CPHA == 0){
  228.                         hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  229.                         printf("CPHA will set to 1st Edge ");
  230.                 }
  231.                 else if(_CPHA == 1){
  232.                         hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;
  233.                         printf("CPHA will set to 2nd Edge ");
  234.                 }
  235.                 HAL_SPI_Init(&hspi1);
  236.         }
  237. }
  238. void spiTask4(uint8_t _firstBit,uint8_t _baudrate){
  239.         uint16_t myBaudRate[5] ={1000,500,250,2000,4000};
  240.         if( (_firstBit < 2) || (_baudrate < 5) ){
  241.                 if(_firstBit == 0){
  242.                         hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  243.                         printf("First bit will set to MSB and ");
  244.                 }
  245.                 else if(_firstBit == 1){
  246.                         hspi1.Init.FirstBit = SPI_FIRSTBIT_LSB;
  247.                         printf("First bit will set to LSB and ");
  248.                 }
  249.                 if(_baudrate <= 4){
  250.                         hspi1.Init.BaudRatePrescaler = baudRateList[_baudrate];
  251.                         printf("BaudRate will set to %dKbps",myBaudRate[_baudrate]);
  252.                 }               
  253.                 HAL_SPI_Init(&hspi1);
  254.         }
  255. }

  256. /* USER CODE END 4 */

  257. #ifdef USE_FULL_ASSERT

  258. /**
  259.    * @brief Reports the name of the source file and the source line number
  260.    * where the assert_param error has occurred.
  261.    * @param file: pointer to the source file name
  262.    * @param line: assert_param error line source number
  263.    * @retval None
  264.    */
  265. void assert_failed(uint8_t* file, uint32_t line)
  266. {
  267.   /* USER CODE BEGIN 6 */
  268.   /* User can add his own implementation to report the file name and line number,
  269.     ex: printf("Wrong parameters value: file %s on line %d", file, line) */
  270.   /* USER CODE END 6 */

  271. }

  272. #endif

  273. /**
  274.   * @}
  275.   */

  276. /**
  277.   * @}
  278. */

  279. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
复制代码



</len;cir2++){
</len;cir++){
</len;cir++){
回复

使用道具 举报

ID:59609 发表于 2019-12-25 13:52 | 显示全部楼层
确实不错 很严谨
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表