网站做关键词排名每天要做什么/简述搜索引擎的工作原理
一、搜集芯片资料
1.LIS3DHTR:加速度传感器
查找链接:
https://www.st.com/zh/mems-and-sensors/lis3dh.html
2. NUCLEO-L432KC:芯片
查找连接:
https://www.st.com/zh/evaluation-tools/nucleo-l432kc.html#cad-resources
1.原理图
引脚定义
2.芯片图
开发板和外设之间通信需要使用到引脚
二、三轴传感器:LIS3DHTR
三轴传感器:只有加速度
六轴传感器:MPU6050【加速度+陀螺仪】
九轴传感器:【磁力计+加速度+陀螺仪】
1.芯片内部的基本功能描述
1.加速度
比如跑步2m/s,我在1s后的速度3m/s,这个时候我的加速度就是1m/s,我此时的加速度是1m每平方秒,(1m/s)/s=1m每平方秒。
单位:g(重力 9.8米每平方秒)
当我们把【LIS3DHTR】正放在桌面上,看似z轴方向上是没有再变化的,实际上z轴上面有一个固定的值。【不为零--->因为受到地球重力】
当静止不动的时候,默认是没有动的。
2.陀螺仪:计算角速度
3.磁力计
磁力计指针会固定指向一个方向
为什么要一直旋转??因为会容易受到干扰,所以需要转动进行校准。
手机的横屏,竖屏
2.LIS3DH的重要寄存器
1.STATUS_REG_AUX
2.WHO_AM_I
每一个厂商的ID值是不同的
3.CTRL_REG1
如果要设置为低功耗模式,则再待机的时候就将不需要的修改为0。
采样率:要看具体的使用场景,要尽量选高一点,采样出来的结果才会比较接近,但是也要保持精度。但是还是要靠近实际需求。
4.CTRL_REG4
满量程选择:查看这个芯片可以承受的数据范围
3.LIS3DH芯片数据手册
主要:特征,芯片引脚,寄存器,量程(电压,电流的范围)
1.芯片基本特征
这个芯片是16bit的数据输出位。如果我们设置量程是8g(记得有正负)
如果我们设置量程是16g(记得有正负)---》这个结果相当于1g的测量范围(比8g的大)--》所以精确度变低了
量程越大,所计算出来的精确度越低。
2.温度适应范围
3.块状图
4.引脚描述
1)注意不要把芯片方向装反了(方向很重要)
NC:没有封装【公模】
RES:保留引脚【一般默认接地--》这样对芯片移植没有影响】
CS:片选(判断是选中哪一个芯片)---》SPI使用的
IN1,IN2:中断
5.机器性能
量程选择,机械特性
6.供电范围
7.寄存器映射
4.SPI
LIS3DH支持IIC和SPI
1.IIC和SPI对比
需要几条线
1)IIC:SCL,SDA【只有一条数据线-->半双工】
2)SPI:CS,MOSI,MISO,SCK【有两条数据线-->全双工】
MOSI,MISO,SCK共用
SPI的速率比IIC快
地址/片选
IIC和SPI都可以挂载多个设备
SPI有CS(片选线)可以选择从机【SPI是通过CS选择来区分不同设备的】
IIC是通过传输要进行通信的地址【通过帧格式】
读取数据的位置
IIC是在时钟线的高电平的时候读取【并且在此期间要保持数据的稳定】
SPI是在时钟线的跳变沿读取数据
IIC:先将时钟拉高,然后SDA从低到高表示要开始发数据,SDA从高到低表示要结束发送数据。
IIC信号在数据传输过程中,当SCL=1高电平时,数据线SDA必须保持稳定状态,不允许有电平跳变,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。
ACK:表示是数据接收到的响应
支持挂载设备数量
IIC取决于地址位
SPI取决于CS
SPI通信线的含义
CS:Chip Select片选
SCK:serial clock时钟线
MOSI:Master(主机) Output Salve(从机)In
MISO:Master(主机)In Salve(从机)Output
GND
2.SPI配置和时序分析
参考博客:
一文搞懂spi协议4种模式时序 - 知乎
1.上升沿取数据
2.下降沿取数据
3.时钟线空闲时为高电平
4.时钟线空闲时为低电平
3.SPI传输速率
取决于通信设置,采样率能否低于SPI通信速率
4.LIS3DH时序图分析
1)速率不高于10MHZ
2)时钟线空闲时为高电平
3)在时钟线的第二个跳变沿取数据(也就是第一个上升沿)
5. 软件设计模式-低耦合 高内聚
低耦合好处:提升可移植性、高可维护性、便于合作、提高问题的解决效率等等
内聚表示一个模块内各个元素彼此结合的紧密程度,标志是不可再拆分
三、LIS3DH驱动移植
1.官方代码的下载
根据相关模块的名字我们可以去百度搜索。由我上面的【LIS3DHTR:加速度传感器】第一部分中可以知道官方的driver文件夹是空的。所以我们根据官方的github去下载
然后将下载的真正的drivers驱动文件复制到drivers中
2.ST官方驱动解析(lis3dh_reg.c/h)
1.stmdev_ctx_t
2.lis3dh_read_data_polling
轮询读取数据
初始化后面要延时一下,等待一下。
判断一下当前操作的寄存器是否是我们要进行操作的
初始化传感器的配置,可以根据自身需求进行初始化
加速度数据的获取,处理和输出
温度数据的获取,处理和输出
tx_com:串口输出
3.platform_init
根据所使用的平台来进行判断
4.platform_write
5.platform_read
5.lis3dh_xl_data_ready_get:判断速度是否读取成功
6.lis3dh_acceleration_raw_get:读取速度原始数据
6.lis3dh_temp_data_ready_get:判断温度是否读取成功
我们通过寄存器的地址可以直接去数据手册中查看
3.使用CubeMX
0.CubeMXL4xx的安装
下载相关CubeMX安装包
下载地址:意法半导体-STMicroelectronics
参考博客:【STM32】STM32的Cube和HAL生态-CSDN博客
将依赖包导入
1.使能调试接口
2.使能外部时钟(准确)
3.串口配置
4.配置SPI
5.配置GPIO用于驱动LED
1.使能调试接口
2.使能内部时钟(准确)
判断是否有外部时钟,查看原理图
3.串口配置
对应开发板上有已经设置好的串口引脚,我们直接使用,比较方便。
4.配置SPI
查看这几个引脚是否有接到其他外设上,如果没有则可以使用
设置SPI参数,我们不知道可以直接去百度或者查看datasheet【SPI章节】
数据位
数据传输速率
5.配置GPIO用于驱动LED
设置为Output
6.接线
4.代码编写
0.MDK pack安装
下载地址:Arm Keil | Devices
参考博客:【STM32】STM32的Cube和HAL生态-CSDN博客
Arm Keil | Devices
1.点亮led
while (1){//高电平有效// HAL_GPIO_WritePin(LED_Green_GPIO_Port, LED_Green_Pin, GPIO_PIN_SET);HAL_GPIO_TogglePin(LED_Green_GPIO_Port, LED_Green_Pin);HAL_Delay(500);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}
2.代码移动
5.代码移植
1.结构体等基本移植
2.write移植
3.read移植
与write的思路一样
4.tx_com移植
5.移植后的mian
/* USER CODE BEGIN Header */
/********************************************************************************* @file : main.c* @brief : Main program body******************************************************************************* @attention** Copyright (c) 2023 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "spi.h"
#include "usart.h"
#include "gpio.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "lis3dh_reg.h"
#define SENSOR_BUS hspi1
static uint8_t whoamI;
/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */stmdev_ctx_t dev_ctx;
extern UART_HandleTypeDef huart1;
/* 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 */static int32_t platform_write(void *handle, uint8_t reg, const uint8_t *bufp,uint16_t len);
static int32_t platform_read(void *handle, uint8_t reg, uint8_t *bufp,uint16_t len);static void tx_com(uint8_t *tx_buffer, uint16_t len);
/** @brief Write generic device register (platform dependent)** @param handle customizable argument. In this examples is used in* order to select the correct sensor bus handler.* @param reg register to write* @param bufp pointer to data to write in register reg* @param len number of consecutive register to write**/
static int32_t platform_write(void *handle, uint8_t reg, const uint8_t *bufp,uint16_t len)
{reg |= 0x40;HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_RESET);HAL_SPI_Transmit(handle, ®, 1, 1000);HAL_SPI_Transmit(handle, (uint8_t*) bufp, len, 1000);HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_SET);return 0;
}/** @brief Read generic device register (platform dependent)** @param handle customizable argument. In this examples is used in* order to select the correct sensor bus handler.* @param reg register to read* @param bufp pointer to buffer that store the data read* @param len number of consecutive register to read**/
static int32_t platform_read(void *handle, uint8_t reg, uint8_t *bufp,uint16_t len)
{reg |= 0xC0;HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_RESET);HAL_SPI_Transmit(handle, ®, 1, 1000);HAL_SPI_Receive(handle, bufp, len, 1000);HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_SET);return 0;
}/** @brief Send buffer to console (platform dependent)** @param tx_buffer buffer to transmit* @param len number of byte to send**/
static void tx_com(uint8_t *tx_buffer, uint16_t len)
{HAL_UART_Transmit(&huart1, tx_buffer, len, 1000);
}/* 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_USART1_UART_Init();MX_SPI1_Init();/* USER CODE BEGIN 2 */dev_ctx.write_reg = platform_write;dev_ctx.read_reg = platform_read;dev_ctx.handle = &SENSOR_BUS;lis3dh_device_id_get(&dev_ctx, &whoamI);if (whoamI != LIS3DH_ID) {while (1) {/* manage here device not found */}}/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){//高电平有效// HAL_GPIO_WritePin(LED_Green_GPIO_Port, LED_Green_Pin, GPIO_PIN_SET);HAL_GPIO_TogglePin(LED_Green_GPIO_Port, LED_Green_Pin);HAL_Delay(500);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* 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*/if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK){Error_Handler();}/** Initializes the RCC Oscillators according to the specified parameters* in the RCC_OscInitTypeDef structure.*/RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;RCC_OscInitStruct.MSIState = RCC_MSI_ON;RCC_OscInitStruct.MSICalibrationValue = 0;RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;RCC_OscInitStruct.PLL.PLLM = 1;RCC_OscInitStruct.PLL.PLLN = 40;RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7;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();}
}/* 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 */
6.polling的移植
将相关缺少的定义补全即可
7.完整移植代码
/* USER CODE BEGIN Header */
/********************************************************************************* @file : main.c* @brief : Main program body******************************************************************************* @attention** Copyright (c) 2023 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "spi.h"
#include "usart.h"
#include "gpio.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "lis3dh_reg.h"
#include <string.h>
#define SENSOR_BUS hspi1
static uint8_t whoamI;
/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */stmdev_ctx_t dev_ctx;
extern UART_HandleTypeDef huart1;
/* 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 */
static int16_t data_raw_acceleration[3];
static int16_t data_raw_temperature;
static float acceleration_mg[3];
static float temperature_degC;
static uint8_t whoamI;
static uint8_t tx_buffer[1000];/* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */static int32_t platform_write(void *handle, uint8_t reg, const uint8_t *bufp,uint16_t len);
static int32_t platform_read(void *handle, uint8_t reg, uint8_t *bufp,uint16_t len);static void tx_com(uint8_t *tx_buffer, uint16_t len);
/** @brief Write generic device register (platform dependent)** @param handle customizable argument. In this examples is used in* order to select the correct sensor bus handler.* @param reg register to write* @param bufp pointer to data to write in register reg* @param len number of consecutive register to write**/
static int32_t platform_write(void *handle, uint8_t reg, const uint8_t *bufp,uint16_t len)
{reg |= 0x40;HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_RESET);HAL_SPI_Transmit(handle, ®, 1, 1000);HAL_SPI_Transmit(handle, (uint8_t*) bufp, len, 1000);HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_SET);return 0;
}/** @brief Read generic device register (platform dependent)** @param handle customizable argument. In this examples is used in* order to select the correct sensor bus handler.* @param reg register to read* @param bufp pointer to buffer that store the data read* @param len number of consecutive register to read**/
static int32_t platform_read(void *handle, uint8_t reg, uint8_t *bufp,uint16_t len)
{reg |= 0xC0;HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_RESET);HAL_SPI_Transmit(handle, ®, 1, 1000);HAL_SPI_Receive(handle, bufp, len, 1000);HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_SET);return 0;
}/** @brief Send buffer to console (platform dependent)** @param tx_buffer buffer to transmit* @param len number of byte to send**/
static void tx_com(uint8_t *tx_buffer, uint16_t len)
{HAL_UART_Transmit(&huart1, tx_buffer, len, 1000);
}/* 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_USART1_UART_Init();MX_SPI1_Init();/* USER CODE BEGIN 2 */dev_ctx.write_reg = platform_write;dev_ctx.read_reg = platform_read;dev_ctx.handle = &SENSOR_BUS;lis3dh_device_id_get(&dev_ctx, &whoamI);if (whoamI != LIS3DH_ID) {while (1) {/* manage here device not found */}}/* Enable Block Data Update. */lis3dh_block_data_update_set(&dev_ctx, PROPERTY_ENABLE);/* Set Output Data Rate to 1Hz. */lis3dh_data_rate_set(&dev_ctx, LIS3DH_ODR_1Hz);/* Set full scale to 2g. */lis3dh_full_scale_set(&dev_ctx, LIS3DH_2g);/* Enable temperature sensor. */lis3dh_aux_adc_set(&dev_ctx, LIS3DH_AUX_ON_TEMPERATURE);/* Set device in continuous mode with 12 bit resol. */lis3dh_operating_mode_set(&dev_ctx, LIS3DH_HR_12bit);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){//高电平有效// HAL_GPIO_WritePin(LED_Green_GPIO_Port, LED_Green_Pin, GPIO_PIN_SET);HAL_GPIO_TogglePin(LED_Green_GPIO_Port, LED_Green_Pin);HAL_Delay(500);/* USER CODE END WHILE *//* USER CODE BEGIN 3 *///加速度数据的获取,处理和输出lis3dh_reg_t reg;/* Read output only if new value available */lis3dh_xl_data_ready_get(&dev_ctx, ®.byte);if (reg.byte) {/* Read accelerometer data */
//清空缓存memset(data_raw_acceleration, 0x00, 3 * sizeof(int16_t));
//获取原始数据(未加工)lis3dh_acceleration_raw_get(&dev_ctx, data_raw_acceleration);//将原始数据进行转换acceleration_mg[0] =lis3dh_from_fs2_hr_to_mg(data_raw_acceleration[0]);acceleration_mg[1] =lis3dh_from_fs2_hr_to_mg(data_raw_acceleration[1]);acceleration_mg[2] =lis3dh_from_fs2_hr_to_mg(data_raw_acceleration[2]);//将数据打印出来并且存储到tx_buffersprintf((char *)tx_buffer,"Acceleration [mg]:%4.2f\t%4.2f\t%4.2f\r\n",acceleration_mg[0], acceleration_mg[1], acceleration_mg[2]);tx_com(tx_buffer, strlen((char const *)tx_buffer));}//温度数据的获取,处理和输出lis3dh_temp_data_ready_get(&dev_ctx, ®.byte);if (reg.byte) {/* Read temperature data */memset(&data_raw_temperature, 0x00, sizeof(int16_t));lis3dh_temperature_raw_get(&dev_ctx, &data_raw_temperature);temperature_degC =lis3dh_from_lsb_hr_to_celsius(data_raw_temperature);sprintf((char *)tx_buffer,"Temperature [degC]:%6.2f\r\n",temperature_degC);tx_com(tx_buffer, strlen((char const *)tx_buffer));}}/* 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*/if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK){Error_Handler();}/** Initializes the RCC Oscillators according to the specified parameters* in the RCC_OscInitTypeDef structure.*/RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;RCC_OscInitStruct.MSIState = RCC_MSI_ON;RCC_OscInitStruct.MSICalibrationValue = 0;RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;RCC_OscInitStruct.PLL.PLLM = 1;RCC_OscInitStruct.PLL.PLLN = 40;RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7;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();}
}/* 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 */
四、NanoEdge AI Studio异常检测工程创建
1.初识
官方说明:
NanoEdgeAIStudio - 面向STM32开发人员的自动化机器学习(ML)工具 - 意法半导体STMicroelectronics
官方参考文档:
AI:NanoEdge AI Studio - stm32mcu (stmicroelectronics.cn)
1)异常检测(AD)库用于检测机器上的异常行为,经过初始的原位训练阶段,使用增量学习模式的动态模型。
2)n类分类库(nCC)用于区分和识别不同类型的行为,无论异常与否,并使用静态模型将其分类到预先建立的类别中。
3)1类分类(1CC)库用于使用静态模型检测机器上的异常行为,而不提供任何有关预期可能出现的异常的上下文。
4)外推(E)库用于使用静态(回归)模型,使用其他已知参数估计未知目标值。
2.NanoEdge AI Studio工程创建
0.注意点
1)名字中不要带空格
2)数据收集格式--->每一次传输的数据都要是2的n次方【一组数据是3个(x,y,z)】-->如果我们要传输512个数据,则实际上需要传输【3*512=1,536】
1.硬件选择
2.传感器选择
3.数据传输方式选择
4.量程,精度和采样率的设置!!
我们需要根据实际需要对传感器的量程,精度,采样率等参数进行修改。可以参考相关文档。
3.二次移植修改官方驱动代码
1.量程设置
1)量程太大,精确度低
2)根据下图要求,传感器要设置采样频率为1.6KHZ,量程为4g
2.将加速度值获取封装为一个函数
#define BUFFER_SIZE 512*3//一组数据(x,y,z)有3个数值static int16_t data_raw_acceleration[3];
static int16_t data_raw_temperature;
static float acceleration_mg[3];
static float temperature_degC;
static uint8_t whoamI;
static uint8_t tx_buffer[1000];//参数大小与【data_raw_acceleration】一样的
static int16_t acc_buffer[BUFFER_SIZE]={0};void fill_accelerometer_buffer(void){lis3dh_reg_t reg;for(uint16_t i=0;i<BUFFER_SIZE ;i++){/* Read output only if new value available */lis3dh_xl_data_ready_get(&dev_ctx, ®.byte);if (reg.byte){//New data is available// lis3dh.read_data(&lis3dh_xyz[0]);//获取原始数据(未加工)lis3dh_acceleration_raw_get(&dev_ctx, data_raw_acceleration);acc_buffer[i]=data_raw_acceleration[0];//存放x轴数据acc_buffer[i+1]=data_raw_acceleration[1];//存放y轴数据acc_buffer[i+2]=data_raw_acceleration[2];//存放z轴数据}else{i--;//New data not ready}}
}
3.printf重定向
最终获取到的数据存放在【acc_buffer】中,因为要将数据通过串口输出给NanoEdge AI 中,所以我们需要将数据输出。【使用printf】
#ifdef __GNUC__#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
/*** @brief Retargets the C library printf function to the USART.* @param None* @retval None*/
PUTCHAR_PROTOTYPE
{/* Place your implementation of fputc here *//* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);return ch;
}
设置后记得测试一下串口打印是否正常
4.将数据通过串口的方式推送到NanoEdge AI
由于我们上面设置了【#define BUFFER_SIZE 512*3//一组数据(x,y,z)有3个数值】的时候是512组数据,一组数据3个,所以我们可以直接一一对应上数组,所以我们不需要设置其几轴。
5.问题查找
由上面测试可以知道,并没有打印出结果
我们分析可以知道,for循环内部可以打印,for循环外部无法打印
说明可能是for栈溢出,导致进入while(1)循环,无法退出。
6.一定要按照官方例程去移植代码!!!
重新设置临界条件,就可以输出
但是输出结果还是会卡住!!!!!
原因:我们没有按照官方示例代码去写,因为我们之前默认我们是使用512*3的数据,所以会出现问题。
#define BUFFER_SIZE 512
#define NB_AXES 3//参数大小与【data_raw_acceleration】一样的
static float acc_buffer[BUFFER_SIZE]={0};//存放获取到的加速度数据//填充加速度获取到的数据
void fill_accelerometer_buffer(void){lis3dh_reg_t reg;for(uint16_t i=0;i<BUFFER_SIZE ;i++){/* Read output only if new value available */lis3dh_xl_data_ready_get(&dev_ctx, ®.byte);if (reg.byte){//New data is available// lis3dh.read_data(&lis3dh_xyz[0]);//获取原始数据(未加工)lis3dh_acceleration_raw_get(&dev_ctx, data_raw_acceleration);acc_buffer[NB_AXES*i]=data_raw_acceleration[0];//存放x轴数据acc_buffer[(NB_AXES*i)+1]=data_raw_acceleration[1];//存放y轴数据acc_buffer[(NB_AXES*i)+2]=data_raw_acceleration[2];//存放z轴数据}else{i--;//New data not ready}}
}void output_data(void){for(uint16_t isample=0;isample<(NB_AXES*BUFFER_SIZE)-1;isample++){printf("%.4f",acc_buffer[isample]);}printf("%.4f",acc_buffer[(NB_AXES*BUFFER_SIZE)-1]);
}
我们经过上面的修改后,还是无法正常打印出参数。
经过检测发现,可能是我们设置的buffer溢出。因为我们要的是BUFFER_SIZE (512)*3
但是我们设置存储数据的acc_buffer容量才为BUFFER_SIZE(512),所以导致溢出。
最后才打印正确
#define BUFFER_SIZE 512
#define NB_AXES 3//参数大小与【data_raw_acceleration】一样的
static float acc_buffer[BUFFER_SIZE * 3]={0};//存放获取到的加速度数据//填充加速度获取到的数据
void fill_accelerometer_buffer(void){lis3dh_reg_t reg;for(uint16_t i=0;i<BUFFER_SIZE ;i++){/* Read output only if new value available */lis3dh_xl_data_ready_get(&dev_ctx, ®.byte);if (reg.byte){//New data is available// lis3dh.read_data(&lis3dh_xyz[0]);//获取原始数据(未加工)lis3dh_acceleration_raw_get(&dev_ctx, data_raw_acceleration);acc_buffer[NB_AXES*i]=data_raw_acceleration[0];//存放x轴数据acc_buffer[(NB_AXES*i)+1]=data_raw_acceleration[1];//存放y轴数据acc_buffer[(NB_AXES*i)+2]=data_raw_acceleration[2];//存放z轴数据}else{i--;//New data not ready}}
}void output_data(void){for(uint16_t isample=0;isample<(NB_AXES*BUFFER_SIZE)-1;isample++){printf("%.4f",acc_buffer[isample]);}printf("%.4f",acc_buffer[(NB_AXES*BUFFER_SIZE)-1]);
}
7.结合NanoEdge AI使用
注意:此时我们要将传感器严实的粘在风扇上~~~一定要粘严实,不能产生缝隙,如果产生缝隙采集出来的结果会不正确。
4.数据采集
1.采取正常的数据
2.采集异常的数据
我们在风扇前拿一本书,将气道阻挡住进行测试。
5.算法筛选
1.将正常和异常算法结合起来
2.使用仿真
去下载相对应的算法库
6.算法验证
1.正常学习
这个时候让风扇正常转动
2.异常学习
我们在风扇前拿一本书,将气道阻挡住进行测试。
3.最终结果生成
4.为什么每一次启动前都要学习?
因为像风扇,电机类型的期间,随着时间的使用,他会出现老化现象,如果我们就让其学习一次。则会有可能一年后面,本来是使用正常但是由于跟第一次学习相差过大而被判断为异常。所以应该伴随着老化而学习。
7.将生成的文件部署到STM32L432中
1.生成过程
生成.a和.h【包括应该调用.a中的什么函数】文件
这个一定要勾选!!!!!!!【要不然会导入.a文件失败】
2.生成的示例代码
3.查看最终使用的算法AI库
.a:是将c进行编译成的文件,如果不想让甲方知道源码,也可以配合.h文件一起使用
4.将.h和.a文件添加到Keil中跟源程序一起运行
参考博客:
KEIL 编译带.a后缀文件出现的问题_keil调取.a文件-CSDN博客
.a文件打开后一堆乱码
.h文件
5.初始化算法库
由上面的.h文件【neai_anomalydetection_init】
6.调用函数让单片机学习
/* Learning process ----------------------------------------------------------*/for (uint16_t iteration = 0 ; iteration < 100 ; iteration++) {//fill_buffer(input_user_buffer);fill_accelerometer_buffer();neai_anomalydetection_learn(acc_buffer);}
7.在主函数中调用检测函数
通过这个函数判断:单片机通过学习之后,对于新获取的数据检测是否敏感【相似度】
//判断准确度
static uint8_t similarity=0;while (1){fill_accelerometer_buffer();//output_data();//检测数据是否正常neai_anomalydetection_detect(acc_buffer,&similarity);printf("similarity=\%%d\r\n");}
8.注意点:
我们在编写完上面代码后出现了问题,检查发现了
1)我们在生成.a和.h文件时,要勾选下面两个选项!!!!!!!!!
2)导入.a文件后,一定要将其文件类型选择为“Library File"!!!!!!!!!!
移植 IAR 静态库(.a)到 keil(MDK)_keil5 移植.a库-CSDN博客
8.识别率低的解决方法
增加Flash、RAM
修改频率、精度
修改缓冲区:缓冲区的长度表示此次采集持续的时间
增加更多的传感器
检查信号质量:是否引入了寄生信号、噪音等
9.优化代码
基于之前的工程,添加宏定义。
一方面可以加载模型,一方面可以收集数据
如果想要单独跑算法,则直接将COLLECT_DATA注释起来即可。如果单纯想要打印数据,则不需要注释。
10.NanoEdge AI Studio创建分类检测工程
官方参考文件
AI:How to create a current sensing classifier using NanoEdge AI Studio - stm32mcu
1)一个工程是异常检测【前面的】
2)一个工程是分类(根据手动调节几档风速,使得LIS3DH也可以判断出来)
1.数据采集
1)关闭off
2)一档level1
3)二挡level2
4)二挡异常level2_ano
重复上面的操作
2.算法筛选和训练
这个时候我们就可以开始模拟
3.下载库和部署
算法的总结
将原来的文件复制一份出来,然后将其修改为class【我们要将其修改为按分类】
我们将下载好的文件解压,然后将其.a和.h进行替换我们原来的文件
4.代码编写
0.官方NanoEdge AI给的参考代码
/* =============
Copyright (c) 2022, STMicroelectronicsAll rights reserved.Redistribution and use in source and binary forms, with or without modification, are permitted provided that
the following conditions are met:* Redistributions of source code must retain the above copyright notice, this list of conditions and thefollowing disclaimer.* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and thefollowing disclaimer in the documentation and/or other materials provided with the distribution.* Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promoteproducts derived from this software without specific prior written permission.*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER / OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*
*/
/***************************************************************************** Demo: NanoEdge AI process to include in main program body** @note This program must be completed and customized by the user***************************************************************************//* Includes --------------------------------------------------------------------*/
#include "NanoEdgeAI.h"
#include "knowledge.h"
/* Private define --------------------------------------------------------------*/
/* Private variables defined by user -------------------------------------------*/
float input_user_buffer[DATA_INPUT_USER * AXIS_NUMBER]; // Buffer of input values
float output_class_buffer[CLASS_NUMBER]; // Buffer of class probabilities
/* Private function prototypes defined by user ---------------------------------*/
/** @brief Collect data process** This function is defined by user, depends on applications and sensors** @param sample_buffer: [in, out] buffer of sample values* @retval None* @note If AXIS_NUMBER = 3 (cf NanoEdgeAI.h), the buffer must be* ordered as follow:* [x0 y0 z0 x1 y1 z1 ... xn yn zn], where xi, yi and zi* are the values for x, y and z axes, n is equal to* DATA_INPUT_USER (cf NanoEdgeAI.h)*/
void fill_buffer(float sample_buffer[])
{/* USER BEGIN *//* USER END */
}
/* -----------------------------------------------------------------------------*/
int main(void)
{/* Initialization ------------------------------------------------------------*/enum neai_state error_code = neai_classification_init(knowledge);if (error_code != NEAI_OK) {/* This happens if the knowledge does not correspond to the library or if the library works into a not supported board. */}/* Classification ------------------------------------------------------------*/uint16_t id_class = 0;while (1) {fill_buffer(input_user_buffer);neai_classification(input_user_buffer, output_class_buffer, &id_class);/* USER BEGIN *//** e.g.: Trigger functions depending on id_class* (print output class probabilities using output_class_buffer[],* print the name of the identified class using id2class[id_class],* blink LED, ring alarm, etc.).*//* USER END */}
}
1.导入头文件
2.初始化
3.将获取到的数据输出
4.id分类
5.测试结果
5.如何获取knowledge.h文件
我们在最后生成代码中
【第一次从官方下载的.zip中是只包含:NanoEdgeAI.h和libneai.a】
但是我们在“NanoEdgeAI.h”中使用到的AI初始化函数中需要调用另外一个头文件“#include "42_knowledge.h"”中定义的变量【 knowledge[992]】
【那么我们从哪里获取这个“knowledge.h”文件呢???】--->【其实我们在NanoEdge AI Studio 最后从官方下载AI驱动代码的位置,在一次选择下载,则第二次下载的就是对应AI的knowledge.h文件】
在这一次代码中我们的【#include "NanoEdgeAI.h"】
11.额外模块:蜂鸣器
1.有源蜂鸣器VS无源蜂鸣器
2.基本控制
当风扇的风道被挡住的时候,让蜂鸣器响。【当风速为1档的时候,持续响1s,当风速为2档的时候,持续响3s】
因为是我们人为的控制蜂鸣器响与否,所以应该将这个Buzzer设置为输出模式【如果你要读从引脚取数据,则设置为输入模式】
while (1){//由于我们的GND引脚不足,所以我们手动的将一个GPIO设置为低电平/*Configure GPIO pin Output Level */HAL_GPIO_WritePin(GPIOB, Buzzzer_Pin|USER_GND_Pin, GPIO_PIN_RESET);fill_accelerometer_buffer();//output_data();// This function returns the class identifiedneai_classification(acc_buffer, output_class_buffer, &id_class);//CLASS_NUMBER:对应的模式个数for (uint8_t i=0; i<CLASS_NUMBER; i++){printf("%f ", output_class_buffer[i]);}printf("\r\n");switch(id_class){case 0:printf("unknown\r\n");break;case 1:printf("fan_off\r\n");break;case 2:printf("fan_grade1_form\r\n");break;case 3:printf("fan_grade2_form\r\n");break;case 4:printf("fan_grade_break\r\n");//让蜂鸣器响HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);HAL_Delay(1000);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET);break;case 5:printf("fan_grade2_break\r\n");//让蜂鸣器响HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);HAL_Delay(3000);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET);break;case 6:printf("fan_grade3_form\r\n");break;}}
12.额外模块:OLED
https://www.cnblogs.com/xuyan123/p/14134246.html
相关文章:

STM32L432+LIS3DH【加速度传感器】:端侧AI
一、搜集芯片资料 1.LIS3DHTR:加速度传感器 查找链接: https://www.st.com/zh/mems-and-sensors/lis3dh.html 2. NUCLEO-L432KC:芯片 查找连接: https://www.st.com/zh/evaluation-tools/nucleo-l432kc.html#cad-resources 1.原理图 引…...

VCG Mesh刚性旋转(变换矩阵)
文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 旋转矩阵如果从线性空间的角度来看,它类似于一个投影过程。假设坐标 P ( x 1 , y 1 , z 1 ) P(x_1,y_1,z_1)...

R语言【base】——system.file() 在软件包等中查找文件的完整文件名。
Package base version 4.3.2 Parameters system.file(..., package "base", lib.loc NULL,mustWork FALSE) 参数【...】:字符向量,指定某个软件包中的子目录和文件。默认情况下,没有值则返回软件包的根目录。不支持通配符。 …...

HTML制作暴雨特效
🎀效果展示 🎀代码展示 <body> <!-- partial:index.partial.html --> <canvas id="canvas-club">...

cesium实现区域贴图及加载多个gif动图
1、cesium加载多个gif动图 Cesium的Billboard支持单帧纹理贴图,如果能够将gif动图进行解析,获得时间序列对应的每帧图片,然后按照时间序列动态更新Billboard的纹理,即可实现动图纹理效果。为此也找到了相对于好一点的第三方库libg…...

blackbox黑盒监控部署(k8s内)tensuns专用
一、前言 部署在k8s中需要用到deployment、configmap、service服务 二、部署 创建存放yaml的目录 mkdir /opt/blackbox-exporter && cd /opt/blackbox-exporter 编辑blackbox配置文件,使用configmap挂在这 vi configmap.yaml apiVersion: v1 kind: Confi…...

“C语言“——scanf()、getchar() 、putchar()、之间的关系
scanf函数说明 scanf函数是对来自于标准输入流的输入数据作格式转换,并将转换结果保存至format后面的实参所指向的对象。 而const char*format 指向的字符串为格式控制字符串,它指定了可输入的字符串以及赋值时转换方法。 简单来说给一个打印格式(输入…...

Spring Boot3 Web开发技术
前期回顾 springboot项目常见的配置文件类型有哪些?哪种类型的优先级最高 yml properties yaml 读取配置文件里的数据用什么注解? value restful风格 RESTful 风格与传统的 HTTP 请求方式相比,更加简洁,安全,能隐…...

学习笔记:数据挖掘与机器学习
文章目录 一、数据挖掘、机器学习、深度学习的区别(一)数据挖掘(二)机器学习(三)深度学习(四)总结 二、数据挖掘体系三、数据挖掘的流程四、典型的数据挖掘系统 一、数据挖掘、机器学…...

highcharts的甘特图设置滚动时表头固定,让其他内容跟随滚动
效果图:最左侧的分类列是跟随甘特图滚动的,因为这一列如果需要自定义,比如表格的话可能会存在行合并的情况,这个时候甘特图是没有办法做的,然后甘特图的表头又需要做滚动时固定,所以设置了甘特图滚动时&…...

ElasticSearch 架构设计
介绍 ElasticSearchMySQLIndexTableDocumentRowFieldColumnMappingSchemaQuery DSLSQLaggregationsgroup by,avg,sumcardinality去重 distinctreindex数据迁移 ElasticSearch 中的一个索引由一个或多个分片组成 每个分片包含多个 segment(分…...

HTML---定位
目录 文章目录 一.定位属性概述 二.position 基础数值 三.z-index属性 网页元素透明度 练习 一.定位属性概述 HTML中的定位属性指的是用来控制HTML元素在页面中的位置和布局的属性,包括position、top、bottom、left和right等。 position属性指定了元素的定位方式&a…...

JVM高频面试题(2023最新版)
JVM面试题 1、JVM内存区域 Jvm包含两个子系统和两个组件。 1.1子系统 Class loader(类加载器):根据给定的全限定名类名(java.lang.object)来装载class文件到Runtime data area(运行时数据区)…...

webpack学习-7.创建库
webpack学习-7.创建库 1.暴露库1.1概念1.2验证1.2.1 不导出方法1.2.2 导出方法 2.外部化 lodash3.外部化的限制4.最终步骤5.使用自己的库5.1坑 6.总结 1.暴露库 这个模块学习有点坑。看名字就是把自己写的个包传到npm,而且还要在项目中使用到它,支持各种…...

MQTT - 笔记
1 Mosquitto 官网 https://mosquitto.org/ 2 Windows环境下安装配置Mosquitto服务及入门操作介绍 Windows环境下安装配置Mosquitto服务及入门操作介绍-CSDN博客 3 开源:MQTT安装与配置使用 【C++】开源:MQTT安装与配置使用_c++ mqtt-CSDN博客 4 一文搞懂Qt-MQTT开发...

Django 安装
各位小伙伴想要博客相关资料的话,关注公众号:chuanyeTry即可领取相关资料! Django 安装 在安装 Django 前,系统需要已经安装了 Python 的开发环境。 如果你还没有安装 Python,请先从 Python 官网 https://www.python…...

推荐一个vscode看着比较舒服的主题:Dark High Contrast
主题名称:Dark High Contrast (意思就是,黑色的,高反差的) 步骤:设置→Themes→Color Theme→Dark High Contrast 效果如下: 感觉这个颜色的看起来比较舒服。...

YCSB 测试表预分区
最近使用 YCSB 测试时,一直使用如下方法创建预分区: TABLE_NAME"usertable" REGIN_SPLITS$((510-1)) cat << EOF | sudo -u hbase hbase shell create ${TABLE_NAME}, cf, {SPLITS > (1..${REGIN_SPLITS}).map {|i| "user#{100…...

K8s 教程
一文让你全面了解K8s(Kubernetes) - 知乎 Install and Set Up kubectl on Linux | Kubernetes阿里巴巴开源镜像站-OPSX镜像站-阿里云开发者社区 留存一份地址...

python:改进型鳟海鞘算法(SSALEO)求解23个基本函数
一、改进型鳟海鞘算法SSALEO 改进型鳟海鞘算法(SSALEO)由Mohammed Qaraad等人于2022年提出。 参考文献:M. Qaraad, S. Amjad, N. K. Hussein, S. Mirjalili, N. B. Halima and M. A. Elhosseini, "Comparing SSALEO as a Scalable Larg…...

Hive-数据模型详解(超详细)
文章目录 一、Hive数据模型1. 概述2. 数据库和表(1) 创建数据库(2) 使用数据库(3) 创建表格(4) 查看表结构 3. 分区与桶(1) 分区(2) 桶 4. 数据加载与查询(1) 数据导入(2) 查询语句 5. 总结 一、Hive数据模型 1. 概述 Hive是基于Hadoop的数据仓库工具,它提供了类似…...

docker的常规使用总结
不安装docker下载镜像,或者下载异构镜像,模拟docker客户端 https://pull.7ii.win/ 1、启动docker服务 systemctl start docker 设置开机自启 systemctl enable docker 2、查看镜像 docker images --查看下载镜像架构 docker inspect 镜像名字 |…...

CSS 文字弹跳效果
鼠标移过去 会加快速度 <template><div class"bounce"><p class"text" :style"{animationDuration: animationDuration}">欢迎使用UniApp Vue3!</p></div> </template><script> export d…...

什么是动态IP?静态IP和动态IP有什么区别?
动态IP(Dynamic IP)和静态IP(Static IP)它是指在计算机网络中分配给设备的两种不同类型的IP地址。 动态IP是指每次设备连接到网络时,网络服务提供商(ISP)IP地址的动态分配。当设备重新连接到网络时,它可能会被分配到不同的IP地址。动态IP适用于传统的家…...

Linux 与 Shell
Linux系统的四部分:Linux系统的核心是内核。内核主要负责四种功能: 系统内存管理 操作系统内核的主要功能之一:内存管理。(物理内存 虚拟内存)内核通过硬盘上称为交换空间(swap space)的存储区…...

大数据-Hive练习-环比增长率、同比增长率、复合增长率
目录 🥙12.1 环比增长率 1. 概述 2. 公式 3. 示例 4.练习-需求:计算各类商品的月环比增长率 🥙12.2 同比增长率 1. 概述 2. 公式 3. 示例 4. 练习-需求:计算各类商品的月同比增长率 🥙12.3 复合增长率 1. 概述 2. 公式 3. 示例…...

C++ 考前难点总结
前言 后天考c,但这几天得甲流了,特别难受!复习c的时候复习着忘着,所以用csdn记录一下不熟悉的知识点,等后天考前再看一遍! 函数模板 #include <iostream>// 定义一个模板类 template <class T1…...

ARM 汇编语言知识积累
博文参考: arm中SP,LR,PC寄存器以及其它所有寄存器以及处理器运行模式介绍 arm平台根据栈进行backtrace的方法-腾讯云开发者社区-腾讯云 (tencent.com) 特殊功能寄存器: SP: 即 R13,栈指针,…...

k8s面试之——简述网络模型
kubernetes网络模型是kubernetes集群中管理容器网络通信的一种机制,用于实现pod间、pod与外部网络间的通信和互联,并提供了多种网络插件和配置选项来满足不同应用场景下的需求。kubernetes网络模型可以分为一下几个部分: 1. pod网络模型 在…...

C语言中关于if else的理解
if else我们可以理解为 if(条件1) //如果条件1成立 语句1; //执行语句1 else //如果条件1不成立 语句2; //执行语句2 这是一个经典的if els…...