打印
[其他ST产品]

【STM32G4评测+使用串口驱动voc温湿度传感器svm40】

[复制链接]
700|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
dql2015|  楼主 | 2021-3-24 19:36 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
手头正好有一个VOC传感器&温湿度传感器模块svm40,可以输出空气质量相关的参数:VOC指数、温度、湿度。后面打算用它进行一个综合demo的设计,将传感器数据推送到物联网平台云端。svm40使用串口接口,这里配置stm32g491的串口中断方式接收,使用stm32cubemx工具只需要简单的点几下鼠标,用户体验very nice。






在main.c中添加自己的代码,首先初始化传感器,然后进行数据的读取。
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * [url=home.php?mod=space&uid=288409]@file[/url]           : main.c
  * [url=home.php?mod=space&uid=247401]@brief[/url]          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>© Copyright (c) 2021 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usart.h"
#include "tim.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "ringBuffer.h"
#include "svm40_port.h"
#include <stdbool.h>
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

#define MY_DEBUG
#ifdef MY_DEBUG
#define MY_LOG printf
#else
#define MY_LOG
#endif
                        

uint8_t aRxBufferSvm40=0;
uint8_t tx_buff[64]={0};
uint8_t rx_buff[64]={0};
static uint8_t rbBuf[128];
int len;
rb_t rb_svm40;
int idle_mode=0;
int ready=0;
float v_f;
float h_f;
float t_f;

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

void HAL_UART_RxCpltCallback(UART_HandleTypeDef*UartHandle)  
{  
    if(UartHandle->Instance == USART1)
    {
        if(rbWrite(&rb_svm40, &aRxBufferSvm40, 1) != 1)
        {
            printf("ERR: Failed to rbWrite\n");
        }
        HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBufferSvm40, 1);
    }               
}  

#define sw16(x) \
    ((short)( \
        (((short)(x) & (short)0x00ffU) << 8 ) | \
        (((short)(x) & (short)0xff00U) >> 8 ) ))

void SerialSend(uint8_t* ptr,uint32_t len)
{
    if(HAL_OK!=HAL_UART_Transmit(&huart1, ptr,len, HAL_MAX_DELAY))
    {
        MY_LOG("Serial Send Error!\n");
    }
}

int ProcRecvProtocol(uint8_t* ptr,uint32_t len,uint8_t cmd, uint8_t state)
{
    if (state & 0x80)
    {
        MY_LOG("device error flag\n");
        MY_LOG("execution error code=0x%02x\n", state & 0x7F);
    }
    else
        {
        switch (cmd)
        {
            case _cmd_t_svm40_get_version:
                {
                uint8_t firmware_major_version;
                uint8_t firmware_minor_version;
                uint8_t firmware_debug_state;
                uint8_t hardware_major_version;
                uint8_t hardware_minor_version;
                uint8_t protocol_major_version;
                uint8_t protocol_minor_version;

                int ret3 = f_unpack_svm40_get_version_res_frame(rx_buff, 1024, &firmware_major_version,
                                                                &firmware_minor_version, &firmware_debug_state,
                                                                &hardware_major_version, &hardware_minor_version,
                                                                &protocol_major_version, &protocol_minor_version);
                printf("firmware version:V%d.%d\n",firmware_major_version,firmware_minor_version);
                                                                printf("firmware_debug_state:%d\n",firmware_debug_state);
                                                                printf("hardware version:V%d.%d\n",hardware_major_version,hardware_minor_version);
                                                                printf("protocol version:V%d.%d\n",protocol_major_version,protocol_minor_version);
            }
            case _cmd_t_svm40_start_measurement:
            {
                MY_LOG("_cmd_t_svm40_start_measurement\n");
                ready=1;
            }
                break;
            case _cmd_t_svm40_device_reset:
            {
                MY_LOG("_cmd_t_svm40_device_reset\n");
                idle_mode=1;
            }
                break;
            case _cmd_t_svm40_get_signals:
            {
                MY_LOG("_cmd_t_svm40_get_signals\n");
                uint16_t voc_index=0,humidity=0,temperature=0;
                int ret=f_unpack_svm40_get_signals_res_frame(rx_buff,64,&voc_index,&humidity,&temperature);
                if(ret>0)
                {
                    int16_t v=sw16(voc_index);
                    int16_t h=sw16(humidity);
                    int16_t t=sw16(temperature);
                    v_f=v/10.0;
                    h_f=h/100.0;
                    t_f=t/200.0;
                    printf("voc_index:%0.1f humidity:%0.2f temperature:%0.2f\r\n",v_f,h_f,t_f);
                }
            }
                break;
        }
    }

}

int ProcRecvData(uint8_t* ptr,uint32_t len)
{
    for (int i = 0; i < len; ++i) {
        if(ptr[i]==0x7D && ptr[i+1]==0x33)
        {
            MY_LOG("detect Byte-Stuffing!\n");
            ptr[i]=0x13;
            for(int j=i+1;j<len;j++)
            {
                ptr[j]=ptr[j+1];
            }
            len=len-1;
            break;
        }
        else if(ptr[i]==0x7D && ptr[i+1]==0x31)
        {
            MY_LOG("detect Byte-Stuffing!\n");
            ptr[i]=0x11;
            for(int j=i+1;j<len;j++)
            {
                ptr[j]=ptr[j+1];
            }
            len=len-1;
            break;
        }
        else if(ptr[i]==0x7D && ptr[i+1]==0x5D)
        {
            MY_LOG("detect Byte-Stuffing!\n");
            ptr[i]=0x7D;
            for(int j=i+1;j<len;j++)
            {
                ptr[j]=ptr[j+1];
            }
            len=len-1;
            break;
        }
        else if(ptr[i]==0x7D && ptr[i+1]==0x5E)
        {
            MY_LOG("detect Byte-Stuffing!\n");
            ptr[i]=0x7E;
            for(int j=i+1;j<len;j++)
            {
                ptr[j]=ptr[j+1];
            }
            len=len-1;
            break;
        }
    }

    int cret,ret = -1;
    uint32_t shift;
    uint8_t cmd, state;;
    for(shift = 0;shift < len;++shift)
    {
        cret = f_check(ptr + shift,len - shift,&cmd, &state);
        if(cret > 0)
        {
            ret = cret + shift;
            ProcRecvProtocol(ptr + shift,cret,cmd,state);
        }
    }
    return ret;
}


/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

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

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_LPUART1_UART_Init();
  MX_USART1_UART_Init();
  MX_UART4_Init();
  MX_TIM6_Init();
  /* USER CODE BEGIN 2 */
       
        printf("nucleo-stm32g491 test,by 21ic dql2015!2021-03-24\r\n");
       
        HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBufferSvm40, 1);

        rb_svm40.rbCapacity = 512;
        rb_svm40.rbBuff = rbBuf;
        if(0 == rbCreate(&rb_svm40))
        {
                        MY_LOG("rbCreate Success\n");
        }
        else
        {
                        MY_LOG("rbCreate Faild\n");
        }
       
        HAL_Delay(100);
       
        len = f_pack_svm40_get_version_frame(tx_buff, 64);
        MY_LOG("Serial Send To SVM40 <svm40_get_version> [len:%d]", len);
        if (len > 0)
        {
                for (int i = 0; i < len; ++i)
                {
                                MY_LOG("0x%02X ", tx_buff[i]);
                }
                MY_LOG("\n");
                SerialSend(tx_buff, len);
        }

        len=f_pack_svm40_device_reset_frame(tx_buff,64);
        MY_LOG("Serial Send To SVM40 <cmd:svm40_device_reset> [len:%d]", len);
        if (len > 0)
                {
                        for (int i = 0; i < len; ++i)
                        {
                                        MY_LOG("0x%02X ", tx_buff[i]);
                        }
                        MY_LOG("\n");
                        SerialSend(tx_buff, len);
        }
               
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
               
                        int ret=rbCanRead(&rb_svm40);
      if(ret>=7)
      {
          if(ret==rbRead(&rb_svm40, (uint8_t*)rx_buff, ret))
          {
              MY_LOG("Serial Receive From SVM40[len:%d]", ret);
              for (int i = 0; i < ret; ++i)
              {
                  MY_LOG("%02X ", rx_buff[i]);
              }
              MY_LOG("\n");
              ProcRecvData(rx_buff,ret);
          }
      }

      if(idle_mode) {
          idle_mode=0;
          len=f_pack_svm40_start_measurement_frame(tx_buff,64);
          MY_LOG("Serial Send To SVM40 <cmd:svm40_start_measurement> [len:%d]", len);
          if (len > 0) {
              for (int i = 0; i < len; ++i) {
                  MY_LOG("0x%02X ", tx_buff[i]);
              }
              MY_LOG("\n");
              SerialSend(tx_buff, len);
          }
      }
      if(ready)
      {
          static uint32_t lastTimer = 0;

          if((HAL_GetTick()-lastTimer ) > 1000)
          {
              len=f_pack_svm40_get_signals_frame(tx_buff,64);
              MY_LOG("Serial Send To SVM40 <cmd:svm40_get_signals> [len:%d]", len);
              if (len > 0) {
                  for (int i = 0; i < len; ++i) {
                      MY_LOG("0x%02X ", tx_buff[i]);
                  }
                  MY_LOG("\n");
                  SerialSend(tx_buff, len);
              }

              lastTimer = HAL_GetTick();
          }
      }
      HAL_Delay(50);
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  /** Configure the main internal regulator output voltage
  */
  HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST);
  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV6;
  RCC_OscInitStruct.PLL.PLLN = 85;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
  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_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the peripherals clocks
  */
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1|RCC_PERIPHCLK_UART4
                              |RCC_PERIPHCLK_LPUART1;
  PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
  PeriphClkInit.Uart4ClockSelection = RCC_UART4CLKSOURCE_PCLK1;
  PeriphClkInit.Lpuart1ClockSelection = RCC_LPUART1CLKSOURCE_PCLK1;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/





测试工程源码:
nucleo_stm32g491_svm40.rar (7.47 MB)

使用特权

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

本版积分规则

101

主题

372

帖子

7

粉丝