【测评SGP40】+自己动手丰衣足食-驱动编写&踩坑记录
<p><span style="font-size:24px;">拿到板子迫不及待的去官方网站寻找开发资料,官方提供了嵌入式、Arduino、Python驱动代码:</span></p><p> </p>
<p></p>
<p> </p>
<p></p>
<p> </p>
<p><strong><span style="color:#e74c3c;"><span style="font-size:24px;">原计划使用Arduino uno开发板的I2C接口驱动,安装手册连线,烧写最简单的测试程序,结果一直不对。。。</span></span></strong></p>
<p><strong><span style="color:#2ecc71;"><span style="font-size:26px;">后来仔细看了开发手册,使用I2C居然要外接上拉电阻,板子上没有集成。。。。哎,手头也没有合适的电阻了。</span></span></strong></p>
<p> </p>
<p></p>
<p><span style="font-size:24px;">于是只好看看其它的接口,还好板子支持串口,但是回头找了一圈,官方居然没有提供任何平台的串口驱动。。。。<img height="28" src="https://bbs.eeworld.com.cn/static/editor/plugins/hkemoji/sticker/facebook/loudly-crying-face_1f62d.png" width="28" /><img height="28" src="https://bbs.eeworld.com.cn/static/editor/plugins/hkemoji/sticker/facebook/loudly-crying-face_1f62d.png" width="28" /><img height="28" src="https://bbs.eeworld.com.cn/static/editor/plugins/hkemoji/sticker/facebook/loudly-crying-face_1f62d.png" width="28" /></span></p>
<p><span style="font-size:24px;">于是发扬自己动手丰衣足食的精神,svm40串口驱动使用了自家开发的SHDLC协议,比较简单。。。基本就是数据帧的封装。</span></p>
<p><span style="font-size:24px;">一共有13个串口命令。</span></p>
<p></p>
<p><span style="font-size:24px;">进行简单测试,只需要实现几个必须的就可以了,我这里基于stm32f410rb实现了获取版本号、复位、获取数据三个命令。</span></p>
<p><span style="font-size:24px;">stm32串口2用于打印调试,串口1备用,串口6连接svm40,配置成115200波特率、8位数据、无校验、1位停止位、无流控,开启中断接收。</span></p>
<p></p>
<p><span style="font-size:24px;">接下来就是按照手册进行数据帧的封装了。三个基本命令描述如下:</span></p>
<p></p>
<p> </p>
<p></p>
<p> </p>
<p><strong><span style="font-size:24px;"><span style="background-color:#e74c3c;">驱动头文件:svm40_port.h</span></span></strong></p>
<pre>
<code class="language-cpp">#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
</code></pre>
<p> </p>
<p><span style="font-size:24px;"><span style="background-color:#e74c3c;">实现文件:</span><strong><span style="background-color:#e74c3c;">svm40_port.c</span></strong></span></p>
<pre>
<code class="language-cpp">#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;
}
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;
}
</code></pre>
<p>测试程序复位后首先发送svm40复位命令,然后进行数据的读取并解析。</p>
<pre>
<code class="language-cpp">/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention *
* <h2><center>&copy; 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={0};
uint8_t rx_buff={0};
#define RB_MAX_LEN 2048
static uint8_t rbBuf;
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==0x7D && ptr==0x33)
{
printf("detect Byte-Stuffing!\n");
ptr=0x13;
for(int j=i+1;j<len;j++)
{
ptr=ptr;
}
len=len-1;
break;
}
else if(ptr==0x7D && ptr==0x31)
{
printf("detect Byte-Stuffing!\n");
ptr=0x11;
for(int j=i+1;j<len;j++)
{
ptr=ptr;
}
len=len-1;
break;
}
else if(ptr==0x7D && ptr==0x5D)
{
printf("detect Byte-Stuffing!\n");
ptr=0x7D;
for(int j=i+1;j<len;j++)
{
ptr=ptr;
}
len=len-1;
break;
}
else if(ptr==0x7D && ptr==0x5E)
{
printf("detect Byte-Stuffing!\n");
ptr=0x7E;
for(int j=i+1;j<len;j++)
{
ptr=ptr;
}
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 */
/**
* @briefThe 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);
if (len > 0) {
for (int i = 0; i < len; ++i) {
printf("0x%02X ", tx_buff);
}
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);
if (len > 0) {
for (int i = 0; i < len; ++i) {
printf("0x%02X ", tx_buff);
}
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", ret);
for (int i = 0; i < ret; ++i)
{
printf("%02X ", rx_buff);
}
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);
if (len > 0) {
for (int i = 0; i < len; ++i) {
printf("0x%02X ", tx_buff);
}
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);
if (len > 0) {
for (int i = 0; i < len; ++i) {
printf("0x%02X ", tx_buff);
}
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 */
/**
* @briefThis 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 */
}
#ifdefUSE_FULL_ASSERT
/**
* @briefReports the name of the source file and the source line number
* where the assert_param error has occurred.
* @paramfile: pointer to the source file name
* @paramline: 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****/
</code></pre>
<p> </p>
<p></p>
<p><span style="font-size:26px;"><span style="background-color:#3498db;">串口打印结果:</span></span></p>
<p><span style="font-size:26px;"><span style="background-color:#3498db;">获取版本号</span></span></p>
<p></p>
<p><strong><span style="font-size:26px;"><span style="background-color:#3498db;">获取数据</span></span></strong></p>
<p></p>
<p> </p>
<p></p>
<p> </p>
<p></p>
<p><span style="font-size:26px;"><span style="background-color:#3498db;">跟我的小米甲醛检测仪测量的温湿度对比:</span></span></p>
<p></p>
<p> </p>
<p><span style="color:#2ecc71;"><strong><span style="font-size:26px;"><span style="background-color:#e74c3c;">源码工程下载:</span></span></strong></span></p>
<p></p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p><span style="color:#e74c3c;"><strong><span style="font-size:26px;">代码复制粘贴,有个函数里面的括号被吞了。。。。正确的是这样的</span></strong></span></p>
<p></p>
<p> </p>
<p> </p>
<p>不错不错,干货满满!!!</p>
<p></p>
<p> </p>
<p><span style="color:#e74c3c;"><strong><span style="font-size:26px;"><span style="font-family:宋体;">串口也是官方建议使用的接口</span></span></strong></span></p>
<p></p>
<p> </p>
<p><span style="color:#e74c3c;"><strong><span style="font-size:26px;"><span style="font-family:宋体;">串口也是官方建议使用的接口</span></span></strong></span></p>
<p>干货满满!!!</p>
jinglixixi 发表于 2021-2-7 10:51
干货满满!!!
<p><img height="48" src="https://bbs.eeworld.com.cn/static/editor/plugins/hkemoji/sticker/facebook/handshake.gif" width="48" /><img height="48" src="https://bbs.eeworld.com.cn/static/editor/plugins/hkemoji/sticker/facebook/handshake.gif" width="48" /><img height="48" src="https://bbs.eeworld.com.cn/static/editor/plugins/hkemoji/sticker/facebook/handshake.gif" width="48" /></p>
<p>您能做BSD的开发吗? 我需要这样的伙伴</p>
Riku815 发表于 2021-5-19 21:31
您能做BSD的开发吗? 我需要这样的伙伴
<p>keyi</p>
dql2016 发表于 2021-5-20 17:20
keyi
<p>BSD。。。和Linux比,好微弱的声音</p>
<p>很好的知识,有种豁然开朗的感觉,感谢楼主分享。</p>
页:
[1]