7118|10

1239

帖子

68

TA的资源

纯净的硅(中级)

楼主
 

【测评SGP40】+自己动手丰衣足食-驱动编写&踩坑记录 [复制链接]

 

拿到板子迫不及待的去官方网站寻找开发资料,官方提供了嵌入式、Arduino、Python驱动代码:

 

 

 

原计划使用Arduino uno开发板的I2C接口驱动,安装手册连线,烧写最简单的测试程序,结果一直不对。。。

后来仔细看了开发手册,使用I2C居然要外接上拉电阻,板子上没有集成。。。。哎,手头也没有合适的电阻了。

 

于是只好看看其它的接口,还好板子支持串口,但是回头找了一圈,官方居然没有提供任何平台的串口驱动。。。。

于是发扬自己动手丰衣足食的精神,svm40串口驱动使用了自家开发的SHDLC协议,比较简单。。。基本就是数据帧的封装。

一共有13个串口命令。

进行简单测试,只需要实现几个必须的就可以了,我这里基于stm32f410rb实现了获取版本号、复位、获取数据三个命令。

stm32串口2用于打印调试,串口1备用,串口6连接svm40,配置成115200波特率、8位数据、无校验、1位停止位、无流控,开启中断接收。

接下来就是按照手册进行数据帧的封装了。三个基本命令描述如下:

 

 

驱动头文件:svm40_port.h

#pragma once
#ifndef ___PORT_HPP__
#define ___PORT_HPP__

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

#define _SHDLC_FRAME_START								0x7e
#define _SHDLC_FRAME_STOP								0x7e

#define _SHDLC_FRAME_SVM40_ADR					0x00

typedef enum
{
    __t_no_error = 0x00,
    __t_wrong_data_len = 0x01,
    __t_unknown_cmd = 0x02,
    __t_no_access_right = 0x03,
    __t_illegal_cmd_para = 0x04,
    __t_internal_function_argument_out_of_range = 0x28,
    __t_cmdnot_allowed_in_current_state = 0x43,
} _execution_error_code_t;

typedef enum
{
    _cmd_t_svm40_start_measurement = 0x00,
    _cmd_t_svm40_get_version = 0xd1,
    _cmd_t_svm40_get_signals = 0x03,
    _cmd_t_svm40_stop_measurement = 0x01,
    _cmd_t_svm40_device_reset = 0xd3,
} _cmd_t;


#pragma pack (1)
//	===============			frame head	==================
typedef struct
{
    uint8_t start;
    uint8_t adr;
    uint8_t cmd;
    uint8_t len;
}mosi_frame_head_t;

typedef struct
{
    uint8_t start;
    uint8_t adr;
    uint8_t cmd;
    uint8_t state;
    uint8_t len;
}miso_frame_head_t;

//	===============			frame tail	==================
typedef struct
{
    uint8_t chk;
    uint8_t stop;
}mosi_frame_tail_t;

typedef struct
{
    uint8_t chk;
    uint8_t stop;
}miso_frame_tail_t;

//	=============== frame body ==================

typedef struct
{
    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;
}svm40_get_version_res_frame_body_t;

typedef struct
{
    uint16_t voc_index;
    uint16_t humidity;
    uint16_t temperature;
}svm40_get_signals_res_frame_body_t;

typedef struct
{
    uint8_t subcommand;
}svm40_start_measurement_frame_body_t;
typedef svm40_start_measurement_frame_body_t svm40_get_signals_frame_body_t;

typedef struct
{
    mosi_frame_head_t				head;
    mosi_frame_tail_t				tail;
}svm40_get_version_frame_t;

typedef svm40_get_version_frame_t svm40_stop_measurement_frame_t;
typedef svm40_get_version_frame_t svm40_device_reset_frame_t;

typedef struct
{
    mosi_frame_head_t				head;
    svm40_start_measurement_frame_body_t body;
    mosi_frame_tail_t				tail;
}svm40_start_measurement_frame_t;

typedef svm40_start_measurement_frame_t svm40_get_signals_frame_t;

typedef struct
{
    miso_frame_head_t					head;
    svm40_get_version_res_frame_body_t 	body;
    miso_frame_tail_t					tail;
}svm40_get_version_res_frame_t;

typedef struct
{
    miso_frame_head_t					head;
    svm40_get_signals_res_frame_body_t 	body;
    miso_frame_tail_t					tail;
}svm40_get_signals_res_frame_t;

#pragma pack ()

uint8_t _f_chk(uint8_t* buff, uint8_t len);
uint16_t _f_tail(uint8_t* buff, uint32_t len);
uint16_t _f_head(uint8_t* buff, uint32_t len, uint16_t packet_len, uint8_t cmd);

int f_check(uint8_t* buff, uint32_t len, uint8_t* cmd, uint8_t* state);

int f_pack_svm40_get_version_frame(uint8_t* buff, uint32_t len);

int f_unpack_svm40_get_version_res_frame(uint8_t* buff, uint32_t len, 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 f_pack_svm40_start_measurement_frame(uint8_t* buff, uint32_t len);

int f_pack_svm40_get_signals_frame(uint8_t* buff, uint32_t len);

int f_unpack_svm40_get_signals_res_frame(uint8_t* buff, uint32_t len, uint16_t* voc_index, uint16_t* humidity, uint16_t* temperature);

int f_pack_svm40_stop_measurement_frame(uint8_t* buff, uint32_t len);

int f_pack_svm40_device_reset_frame(uint8_t* buff, uint32_t len);
#endif	
#endif	

 

实现文件:svm40_port.c

#include "svm40_port.h"

//	============			Private	Function	===================
uint8_t _f_chk(uint8_t* buff, uint8_t len)
{
	uint8_t ret;
	uint32_t sum = 0;

	for (int i = 0; i < len; i++)
	{
		sum += buff[i];
	}
	ret = ~((sum << 24) >> 24);
	return ret;
}

uint16_t _f_tail(uint8_t* buff, uint32_t len)
{
	uint16_t ret;
	mosi_frame_tail_t* tail_ptr = (mosi_frame_tail_t*)(buff + len);
    tail_ptr->chk = _f_chk(buff + 1, len-1);
	tail_ptr->stop = _SHDLC_FRAME_STOP;
	ret = len + sizeof(mosi_frame_tail_t);
	return ret;
}
uint16_t _f_head(uint8_t* buff, uint32_t len, uint16_t packet_len, uint8_t cmd)
{
	uint16_t ret = 0;
	if (len > sizeof(mosi_frame_head_t))
	{
		mosi_frame_head_t* head_ptr = (mosi_frame_head_t*)buff;
		head_ptr->start = _SHDLC_FRAME_START;
		head_ptr->adr = _SHDLC_FRAME_SVM40_ADR;
		head_ptr->cmd = cmd;
		head_ptr->len = packet_len;
		ret = sizeof(mosi_frame_head_t);
	}
	return ret;
}


int f_check(uint8_t* buff, uint32_t len, uint8_t* cmd, uint8_t* state)
{
	int ret = -1;
	uint8_t chk;

	miso_frame_head_t* head_ptr = (miso_frame_head_t*)buff;
	miso_frame_tail_t* tail_ptr = NULL;
	if (len < sizeof(miso_frame_head_t))
	{
		//printf("len error!\r\n");
		goto return_flag;
	}
	if (head_ptr->start != _SHDLC_FRAME_START)
	{
		//printf("start error!\r\n");
		goto return_flag;
	}
	if (len < (sizeof(miso_frame_head_t) + sizeof(miso_frame_tail_t) + head_ptr->len))
	{
		//printf("len error!\r\n");
		goto return_flag;
	}
	tail_ptr = (miso_frame_tail_t*)(buff + (sizeof(miso_frame_head_t) + head_ptr->len));
	if (tail_ptr->stop != _SHDLC_FRAME_STOP)
	{
		//printf("stop error!\r\n");
		goto return_flag;
	}
	chk = _f_chk(buff + 1, (sizeof(miso_frame_head_t) + head_ptr->len - 1));
	if (tail_ptr->chk != chk)
	{
		//printf("chk error!\r\n");
		goto return_flag;
	}
	switch (head_ptr->cmd)
	{
	case _cmd_t_svm40_start_measurement:
	case _cmd_t_svm40_get_version:
	case _cmd_t_svm40_get_signals:
	case _cmd_t_svm40_device_reset:
		*cmd = head_ptr->cmd;
		*state = head_ptr->state;
		ret = sizeof(miso_frame_head_t) + sizeof(miso_frame_tail_t) + head_ptr->len;
		break;
	default:
		break;
	}
return_flag:
	return ret;
}

int f_pack_svm40_get_version_frame(uint8_t* buff, uint32_t len)
{
	int ret = -1;
	svm40_get_version_frame_t* frame_ptr;
	if (len >= sizeof(svm40_get_version_frame_t))
	{
		frame_ptr = (svm40_get_version_frame_t*)(buff);
		ret = _f_head(buff, len, 0, _cmd_t_svm40_get_version);
		ret = _f_tail(buff, ret);
	}
	return ret;
}

int f_unpack_svm40_get_version_res_frame(uint8_t* buff, uint32_t len, 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 ret = 1;
	svm40_get_version_res_frame_t* packet_ptr = (svm40_get_version_res_frame_t*)buff;
	*firmware_major_version = packet_ptr->body.firmware_major_version;
	*firmware_minor_version = packet_ptr->body.firmware_minor_version;
	*firmware_debug_state = packet_ptr->body.firmware_debug_state;
	*hardware_major_version = packet_ptr->body.hardware_major_version;
	*hardware_minor_version = packet_ptr->body.hardware_minor_version;
	*protocol_major_version = packet_ptr->body.protocol_major_version;
	*protocol_minor_version = packet_ptr->body.protocol_minor_version;
	ret = sizeof(svm40_get_version_res_frame_t);

	return ret;
}

int f_pack_svm40_start_measurement_frame(uint8_t* buff, uint32_t len)
{
	int ret = -1;
	svm40_start_measurement_frame_body_t* body_ptr;
	if (len >= sizeof(svm40_start_measurement_frame_t))
	{
		body_ptr = (svm40_start_measurement_frame_body_t*)(buff + sizeof(mosi_frame_head_t));
		ret = _f_head(buff, len, sizeof(svm40_start_measurement_frame_body_t), _cmd_t_svm40_start_measurement);
		body_ptr->subcommand = 0x00;
		ret = _f_tail(buff, ret + sizeof(svm40_start_measurement_frame_body_t));
	}
	return ret;
}


int f_pack_svm40_get_signals_frame(uint8_t* buff, uint32_t len)
{
	int ret = -1;
	svm40_get_signals_frame_body_t* body_ptr;
	if (len >= sizeof(svm40_get_signals_frame_t))
	{
		body_ptr = (svm40_get_signals_frame_body_t*)(buff + sizeof(mosi_frame_head_t));
        ret = _f_head(buff, len, sizeof(svm40_get_signals_frame_body_t), _cmd_t_svm40_get_signals);
		body_ptr->subcommand = 0x0A;
		ret = _f_tail(buff, ret + sizeof(svm40_get_signals_frame_body_t));
	}
	return ret;
}

int f_unpack_svm40_get_signals_res_frame(uint8_t* buff, uint32_t len, uint16_t* voc_index, uint16_t* humidity, uint16_t* temperature)
{
	int ret = 1;
	svm40_get_signals_res_frame_t* packet_ptr = (svm40_get_signals_res_frame_t*)buff;
	*voc_index = packet_ptr->body.voc_index;
	*humidity = packet_ptr->body.humidity;
	*temperature = packet_ptr->body.temperature;
	ret = sizeof(svm40_get_signals_res_frame_t);
	return ret;
}

int f_pack_svm40_stop_measurement_frame(uint8_t* buff, uint32_t len)
{  
    int ret = -1;
    svm40_stop_measurement_frame_t* frame_ptr;
    if (len >= sizeof(svm40_stop_measurement_frame_t))
    {
        frame_ptr = (svm40_stop_measurement_frame_t*)(buff);
        ret = _f_head(buff, len, 0, _cmd_t_svm40_stop_measurement);
        ret = _f_tail(buff, ret);
    }
    return ret;
}

int f_pack_svm40_device_reset_frame(uint8_t* buff, uint32_t len)
{
    int ret = -1;
    svm40_device_reset_frame_t* frame_ptr;
    if (len >= sizeof(svm40_device_reset_frame_t))
    {
        frame_ptr = (svm40_device_reset_frame_t*)(buff);
        ret = _f_head(buff, len, 0, _cmd_t_svm40_device_reset);
        ret = _f_tail(buff, ret);
    }
    return ret;
}

测试程序复位后首先发送svm40复位命令,然后进行数据的读取并解析。

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * [url=home.php?mod=space&uid=159083]@brief[/url] : Main program body
  ******************************************************************************
  * [url=home.php?mod=space&uid=1020061]@attention[/url] *
  * <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 "gpio.h"

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

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

/* 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 */
uint8_t aRxBuffer=0;
uint8_t tx_buff[64]={0};
uint8_t rx_buff[64]={0};
#define RB_MAX_LEN 2048
static uint8_t rbBuf[RB_MAX_LEN];
rb_t rb;
int idle_mode=0;
int ready=0;
/* 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 */
#define sw16(x) \
    ((short)( \
        (((short)(x) & (short)0x00ffU) << 8 ) | \
        (((short)(x) & (short)0xff00U) >> 8 ) ))
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if(huart->Instance == USART6)
    {
        //LD2_TOGGLE();
        if(rbWrite(&rb, &aRxBuffer, 1) != 1)
        {
            printf("ERR: Failed to rbWrite\n");
        }
        HAL_UART_Receive_IT(&huart6, (uint8_t *)&aRxBuffer, 1);
    }
}
void SerialSend(uint8_t* ptr,uint32_t len)
{
    if(HAL_OK!=HAL_UART_Transmit(&huart6, ptr,len, HAL_MAX_DELAY))
    {
        printf("Serial Send Error!\n");
    }
    else
    {
        //printf("Serial Send OK!\n");
    }
}

int ProcRecvProtocol(uint8_t* ptr,uint32_t len,uint8_t cmd, uint8_t state)
{
    //printf("cmd=0x%02X\n",cmd);
    //printf("state=0x%02X\n",state);
    if (state & 0x80)
    {
        printf("device error flag\n");
        printf("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:
            {
                printf("_cmd_t_svm40_start_measurement\n");
                ready=1;
            }
                break;
            case _cmd_t_svm40_device_reset:
            {
                printf("_cmd_t_svm40_device_reset\n");
                idle_mode=1;
            }
                break;
            case _cmd_t_svm40_get_signals:
            {
                printf("_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)
                {
                    uint16_t v=sw16(voc_index);
                    uint16_t h=sw16(humidity);
                    uint16_t t=sw16(temperature);
                    float v_f=v/10.0;
                    float h_f=h/100.0;
                    float t_f=t/200.0;
                    printf("voc_index:%0.1f humidity:%0.2f temperature:%0.2f\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)
        {
            printf("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)
        {
            printf("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)
        {
            printf("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)
        {
            printf("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_USART2_UART_Init();
  MX_USART1_UART_Init();
  MX_USART6_UART_Init();
  /* USER CODE BEGIN 2 */

    HAL_UART_Receive_IT(&huart6, (uint8_t *)&aRxBuffer, 1);

    printf("svm40 test,by eeworld dql2016!2021-02-01\n");

    rb.rbCapacity = RB_MAX_LEN;
    rb.rbBuff = rbBuf;
    if(0 == rbCreate(&rb))
    {
        printf("rbCreate Success\n");
    }
    else
    {
        printf("rbCreate Faild\n");
    }
    int len;

    /*len = f_pack_svm40_get_version_frame(tx_buff, 64);
    printf("Serial Send To SVM40 <svm40_get_version> [len:%d]", len);
    if (len > 0) {
        for (int i = 0; i < len; ++i) {
            printf("0x%02X ", tx_buff[i]);
        }
        printf("\n");
        SerialSend(tx_buff, len);
    }
*/

    len=f_pack_svm40_device_reset_frame(tx_buff,64);
    printf("Serial Send To SVM40 <cmd:svm40_device_reset> [len:%d]", len);
    if (len > 0) {
        for (int i = 0; i < len; ++i) {
            printf("0x%02X ", tx_buff[i]);
        }
        printf("\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);
      if(ret>=7)
      {
          if(ret==rbRead(&rb, (uint8_t*)rx_buff, ret))
          {
              printf("Serial Receive From SVM40[len:%d]", ret);
              for (int i = 0; i < ret; ++i)
              {
                  printf("%02X ", rx_buff[i]);
              }
              printf("\n");
              ProcRecvData(rx_buff,ret);
          }
      }

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

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

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

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

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = 8;
  RCC_OscInitStruct.PLL.PLLN = 100;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  RCC_OscInitStruct.PLL.PLLR = 2;
  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_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != 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****/

 

串口打印结果:

获取版本号

获取数据

 

 

跟我的小米甲醛检测仪测量的温湿度对比:

 

源码工程下载:

test.7z (422.31 KB, 下载次数: 13)

 

 

 

 

此帖出自传感器论坛

最新回复

很好的知识,有种豁然开朗的感觉,感谢楼主分享。   详情 回复 发表于 2021-12-22 09:50

赞赏

1

查看全部赞赏

点赞(1) 关注
 
 

回复
举报

1239

帖子

68

TA的资源

纯净的硅(中级)

沙发
 

代码复制粘贴,有个函数里面的括号被吞了。。。。正确的是这样的

 

 

此帖出自传感器论坛
 
 
 

回复

1942

帖子

2

TA的资源

版主

板凳
 

不错不错,干货满满!!!

此帖出自传感器论坛
 
 
 

回复

1239

帖子

68

TA的资源

纯净的硅(中级)

4
 

 

串口也是官方建议使用的接口

此帖出自传感器论坛
 
 
 

回复

1239

帖子

68

TA的资源

纯净的硅(中级)

5
 

 

串口也是官方建议使用的接口

此帖出自传感器论坛
 
 
 

回复

1544

帖子

1

TA的资源

五彩晶圆(初级)

6
 

干货满满!!!

此帖出自传感器论坛
 
 
 

回复

1239

帖子

68

TA的资源

纯净的硅(中级)

7
 

此帖出自传感器论坛
 
 
 

回复

25

帖子

0

TA的资源

一粒金砂(中级)

8
 

您能做BSD的开发吗? 我需要这样的伙伴

此帖出自传感器论坛

点评

keyi  详情 回复 发表于 2021-5-20 17:20
 
 
 

回复

1239

帖子

68

TA的资源

纯净的硅(中级)

9
 
Riku815 发表于 2021-5-19 21:31 您能做BSD的开发吗? 我需要这样的伙伴

keyi

此帖出自传感器论坛

点评

BSD。。。和Linux比,好微弱的声音  详情 回复 发表于 2021-5-20 17:41
 
 
 

回复

7671

帖子

2

TA的资源

五彩晶圆(高级)

10
 

BSD。。。和Linux比,好微弱的声音

此帖出自传感器论坛
个人签名

默认摸鱼,再摸鱼。2022、9、28

 
 
 

回复

51

帖子

0

TA的资源

一粒金砂(中级)

11
 

很好的知识,有种豁然开朗的感觉,感谢楼主分享。

此帖出自传感器论坛
 
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表