当前位置: 首页 > news >正文

一、对iic类模块分析与使用

bmp280驱动代码

在这里插入图片描述

说明:

1、该模块用于获取气压,温度,海拔等数据。
vcc,gnd接电源
sda ,scl 接iic通信引脚
2、该模块使用iic通信,通过iic发送请求相关类的寄存器值,芯片获取对应寄存器返回的数据。
所以使用的时调用HAL_I2C_Mem_Write函数
3、调用:

	uint8_t ret = BMP280_Init();		if(ret != 0x58){printf("BMP280传感器初始化错误\n");while(1);}float P,T,ALT;BMP280GetData(&P, &T, &ALT);printf("BMP280传感器测试数据:\n");printf("气压: %0.4f hPa\n",P);printf("温度: %0.2f ℃\n",T);printf("海拔: %0.2f m\n",ALT);printf("\n\n");

.h文件

#define bmp280 hi2c2#define	INIT		    0xBE	//初始化
#define	SoftReset		0xBA	//软复位
#define	StartTest		0xAC	//开始测试#define BMP280_SLAVE_ADDRESS    0xec		/* I2C从机地址 0xee或0xec *//*calibration parameters */
#define BMP280_DIG_T1_LSB_REG                0x88
#define BMP280_DIG_T1_MSB_REG                0x89
#define BMP280_DIG_T2_LSB_REG                0x8A
#define BMP280_DIG_T2_MSB_REG                0x8B
#define BMP280_DIG_T3_LSB_REG                0x8C
#define BMP280_DIG_T3_MSB_REG                0x8D
#define BMP280_DIG_P1_LSB_REG                0x8E
#define BMP280_DIG_P1_MSB_REG                0x8F
#define BMP280_DIG_P2_LSB_REG                0x90
#define BMP280_DIG_P2_MSB_REG                0x91
#define BMP280_DIG_P3_LSB_REG                0x92
#define BMP280_DIG_P3_MSB_REG                0x93
#define BMP280_DIG_P4_LSB_REG                0x94
#define BMP280_DIG_P4_MSB_REG                0x95
#define BMP280_DIG_P5_LSB_REG                0x96
#define BMP280_DIG_P5_MSB_REG                0x97
#define BMP280_DIG_P6_LSB_REG                0x98
#define BMP280_DIG_P6_MSB_REG                0x99
#define BMP280_DIG_P7_LSB_REG                0x9A
#define BMP280_DIG_P7_MSB_REG                0x9B
#define BMP280_DIG_P8_LSB_REG                0x9C
#define BMP280_DIG_P8_MSB_REG                0x9D
#define BMP280_DIG_P9_LSB_REG                0x9E
#define BMP280_DIG_P9_MSB_REG                0x9F#define BMP280_CHIPID_REG                    0xD0  /*Chip ID Register */
#define BMP280_RESET_REG                     0xE0  /*Softreset Register */
#define BMP280_STATUS_REG                    0xF3  /*Status Register */
#define BMP280_CTRLMEAS_REG                  0xF4  /*Ctrl Measure Register */
#define BMP280_CONFIG_REG                    0xF5  /*Configuration Register */
#define BMP280_PRESSURE_MSB_REG              0xF7  /*Pressure MSB Register */
#define BMP280_PRESSURE_LSB_REG              0xF8  /*Pressure LSB Register */
#define BMP280_PRESSURE_XLSB_REG             0xF9  /*Pressure XLSB Register */
#define BMP280_TEMPERATURE_MSB_REG           0xFA  /*Temperature MSB Reg */
#define BMP280_TEMPERATURE_LSB_REG           0xFB  /*Temperature LSB Reg */
#define BMP280_TEMPERATURE_XLSB_REG          0xFC  /*Temperature XLSB Reg */#define BMP280_SLEEP_MODE				(0x00)
#define BMP280_FORCED_MODE				(0x01)
#define BMP280_NORMAL_MODE				(0x03)#define BMP280_TEMPERATURE_CALIB_DIG_T1_LSB_REG             (0x88)
#define BMP280_PRESSURE_TEMPERATURE_CALIB_DATA_LENGTH       (24)
#define BMP280_DATA_FRAME_SIZE			(6)#define BMP280_OVERSAMP_SKIPPED			(0x00)
#define BMP280_OVERSAMP_1X				(0x01)
#define BMP280_OVERSAMP_2X				(0x02)
#define BMP280_OVERSAMP_4X				(0x03)
#define BMP280_OVERSAMP_8X				(0x04)
#define BMP280_OVERSAMP_16X				(0x05)typedef struct
{uint16_t dig_T1;/* calibration T1 data */int16_t dig_T2; /* calibration T2 data */int16_t dig_T3; /* calibration T3 data */uint16_t dig_P1;/* calibration P1 data */int16_t dig_P2; /* calibration P2 data */int16_t dig_P3; /* calibration P3 data */int16_t dig_P4; /* calibration P4 data */int16_t dig_P5; /* calibration P5 data */int16_t dig_P6; /* calibration P6 data */int16_t dig_P7; /* calibration P7 data */int16_t dig_P8; /* calibration P8 data */int16_t dig_P9; /* calibration P9 data */int32_t t_fine; /* calibration t_fine data */
} bmp280Calib;
uint8_t BMP280_Init(void);
void BMP280GetData(float* pressure, float* temperature, float* asl);

.c文件

#include "bmp280.h"static int32_t bmp280RawPressure = 0;
static int32_t bmp280RawTemperature = 0;#define BMP280_PRESSURE_OSR			(BMP280_OVERSAMP_8X)
#define BMP280_TEMPERATURE_OSR		(BMP280_OVERSAMP_16X)
#define BMP280_MODE					(BMP280_PRESSURE_OSR << 2 | BMP280_TEMPERATURE_OSR << 5 | BMP280_NORMAL_MODE)bmp280Calib  bmp280Cal;uint8_t BMP280_Init(void)
{uint8_t bmp280_id;uint8_t tmp[10];HAL_I2C_Mem_Read(&bmp280,BMP280_SLAVE_ADDRESS, BMP280_CHIPID_REG, 1, (uint8_t *)&bmp280_id,1,0xff);HAL_I2C_Mem_Read(&bmp280,BMP280_SLAVE_ADDRESS, BMP280_DIG_T1_LSB_REG, 1, (uint8_t *)&bmp280Cal,24,0xff);tmp[0] = BMP280_MODE;HAL_I2C_Mem_Write(&bmp280,BMP280_SLAVE_ADDRESS,BMP280_CTRLMEAS_REG, 1,tmp ,1,0xff);tmp[0] = (5<<2);HAL_I2C_Mem_Write(&bmp280,BMP280_SLAVE_ADDRESS,BMP280_CONFIG_REG, 1,tmp ,1,0xff);		/*配置IIR滤波*/return bmp280_id;
}static void BMP280GetPressure2(void)
{uint8_t data[6];// read data from sensorHAL_I2C_Mem_Read(&bmp280,BMP280_SLAVE_ADDRESS, BMP280_PRESSURE_MSB_REG, 6, (uint8_t *)&data,6,0xff);bmp280RawPressure = (int32_t)((((uint32_t)(data[0])) << 12) | (((uint32_t)(data[1])) << 4) | ((uint32_t)data[2] >> 4));bmp280RawTemperature = (int32_t)((((uint32_t)(data[3])) << 12) | (((uint32_t)(data[4])) << 4) | ((uint32_t)data[5] >> 4));
}static int32_t BMP280CompensateT(int32_t adcT)
{int32_t var1, var2, T;var1 = ((((adcT >> 3) - ((int32_t)bmp280Cal.dig_T1 << 1))) * ((int32_t)bmp280Cal.dig_T2)) >> 11;var2  = (((((adcT >> 4) - ((int32_t)bmp280Cal.dig_T1)) * ((adcT >> 4) - ((int32_t)bmp280Cal.dig_T1))) >> 12) * ((int32_t)bmp280Cal.dig_T3)) >> 14;bmp280Cal.t_fine = var1 + var2;T = (bmp280Cal.t_fine * 5 + 128) >> 8;return T;
}// Returns pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 integer bits and 8 fractional bits).
// Output value of "24674867" represents 24674867/256 = 96386.2 Pa = 963.862 hPa
static uint32_t BMP280CompensateP(int32_t adcP)
{int64_t var1, var2, p;var1 = ((int64_t)bmp280Cal.t_fine) - 128000;var2 = var1 * var1 * (int64_t)bmp280Cal.dig_P6;var2 = var2 + ((var1*(int64_t)bmp280Cal.dig_P5) << 17);var2 = var2 + (((int64_t)bmp280Cal.dig_P4) << 35);var1 = ((var1 * var1 * (int64_t)bmp280Cal.dig_P3) >> 8) + ((var1 * (int64_t)bmp280Cal.dig_P2) << 12);var1 = (((((int64_t)1) << 47) + var1)) * ((int64_t)bmp280Cal.dig_P1) >> 33;if (var1 == 0)return 0;p = 1048576 - adcP;p = (((p << 31) - var2) * 3125) / var1;var1 = (((int64_t)bmp280Cal.dig_P9) * (p >> 13) * (p >> 13)) >> 25;var2 = (((int64_t)bmp280Cal.dig_P8) * p) >> 19;p = ((p + var1 + var2) >> 8) + (((int64_t)bmp280Cal.dig_P7) << 4);return (uint32_t)p;
}#define CONST_PF 0.1902630958	//(1/5.25588f) Pressure factor
#define FIX_TEMP 25				// Fixed Temperature. ASL is a function of pressure and temperature, but as the temperature changes so much (blow a little towards the flie and watch it drop 5 degrees) it corrupts the ASL estimates.// TLDR: Adjusting for temp changes does more harm than good.
/*** Converts pressure to altitude above sea level (ASL) in meters*/
static float BMP280PressureToAltitude(float* pressure/*, float* groundPressure, float* groundTemp*/)
{if (*pressure > 0){return ((pow((1015.7f / *pressure), CONST_PF) - 1.0f) * (FIX_TEMP + 273.15f)) / 0.0065f;}else{return 0;}
}#define FILTER_NUM	5
#define FILTER_A	0.1f/*限幅平均滤波法*/
static void presssureFilter(float* in, float* out)
{static uint8_t i = 0;static float filter_buf[FILTER_NUM] = {0.0};double filter_sum = 0.0;uint8_t cnt = 0;float deta;if(filter_buf[i] == 0.0f){filter_buf[i] = *in;*out = *in;if(++i >= FILTER_NUM)i=0;}else{if(i)deta = *in-filter_buf[i - 1];elsedeta = *in-filter_buf[FILTER_NUM - 1];if(fabs(deta) < FILTER_A){filter_buf[i] = *in;if(++i >= FILTER_NUM)i = 0;}for(cnt = 0; cnt < FILTER_NUM; cnt++){filter_sum += filter_buf[cnt];}*out = filter_sum / FILTER_NUM;}
}void BMP280GetData(float* pressure, float* temperature, float* asl)
{static float t;static float p;BMP280GetPressure2();t = BMP280CompensateT(bmp280RawTemperature) / 100.0;p = BMP280CompensateP(bmp280RawPressure) / 25600.0;presssureFilter(&p, pressure);*temperature = (float)t;/*单位度*/*asl = BMP280PressureToAltitude(pressure);	/*转换成海拔*/
}

mpu6050驱动代码

在这里插入图片描述

说明:

1、模块主要对外输出加速度,陀螺仪,温度等数据
vcc,gnd 接电源
scl,sda iic通信引脚
xda,xcl,iic主机通信引脚,(作为主机通信使用)
ad0,iic地址配置引脚
int,中断信号输出引脚
明确一点:scl,sda在通信时的目的是配置模块中的寄存器。
2、调用

	MPU6050_Init();if (MPU6050ReadID() == 0){	   printf("检测不到MPU6050,停机");while(1);}short Accel[3];short Gyro [3];short Temp;MPU6050ReadAcc(Accel);			printf("加速度: %d__%d__%d ",Accel[0],Accel[1],Accel[2]);MPU6050ReadGyro(Gyro);printf("陀螺仪:%8d %8d %8d",Gyro[0],Gyro[1],Gyro[2]);MPU6050_ReturnTemp(&Temp);printf("温度:%d",Temp);

.h文件


#define MPU6050_ADDRESS            0x68
#define MPU6050_WHO_AM_I           0x75
#define MPU6050_SMPLRT_DIV            0  //8000Hz
#define MPU6050_DLPF_CFG              0
#define MPU6050_GYRO_OUT           0x43  //MPU6050陀螺仪数据寄存器地址
#define MPU6050_ACC_OUT            0x3B  //MPU6050加速度数据寄存器地址#define MPU6050_SLAVE_ADDRESS      0xd0  //MPU6050器件读地址#define MPU6050_ADDRESS_AD0_LOW     0x68 // address pin low (GND), default for InvenSense evaluation board
#define MPU6050_ADDRESS_AD0_HIGH    0x69 // address pin high (VCC)
#define MPU6050_DEFAULT_ADDRESS     MPU6050_ADDRESS_AD0_LOW#define MPU6050_RA_XG_OFFS_TC       0x00 //[7] PWR_MODE, [6:1] XG_OFFS_TC, [0] OTP_BNK_VLD
#define MPU6050_RA_YG_OFFS_TC       0x01 //[7] PWR_MODE, [6:1] YG_OFFS_TC, [0] OTP_BNK_VLD
#define MPU6050_RA_ZG_OFFS_TC       0x02 //[7] PWR_MODE, [6:1] ZG_OFFS_TC, [0] OTP_BNK_VLD
#define MPU6050_RA_X_FINE_GAIN      0x03 //[7:0] X_FINE_GAIN
#define MPU6050_RA_Y_FINE_GAIN      0x04 //[7:0] Y_FINE_GAIN
#define MPU6050_RA_Z_FINE_GAIN      0x05 //[7:0] Z_FINE_GAIN
#define MPU6050_RA_XA_OFFS_H        0x06 //[15:0] XA_OFFS
#define MPU6050_RA_XA_OFFS_L_TC     0x07
#define MPU6050_RA_YA_OFFS_H        0x08 //[15:0] YA_OFFS
#define MPU6050_RA_YA_OFFS_L_TC     0x09
#define MPU6050_RA_ZA_OFFS_H        0x0A //[15:0] ZA_OFFS
#define MPU6050_RA_ZA_OFFS_L_TC     0x0B
#define MPU6050_RA_XG_OFFS_USRH     0x13 //[15:0] XG_OFFS_USR
#define MPU6050_RA_XG_OFFS_USRL     0x14
#define MPU6050_RA_YG_OFFS_USRH     0x15 //[15:0] YG_OFFS_USR
#define MPU6050_RA_YG_OFFS_USRL     0x16
#define MPU6050_RA_ZG_OFFS_USRH     0x17 //[15:0] ZG_OFFS_USR
#define MPU6050_RA_ZG_OFFS_USRL     0x18
#define MPU6050_RA_SMPLRT_DIV       0x19
#define MPU6050_RA_CONFIG           0x1A
#define MPU6050_RA_GYRO_CONFIG      0x1B
#define MPU6050_RA_ACCEL_CONFIG     0x1C
#define MPU6050_RA_FF_THR           0x1D
#define MPU6050_RA_FF_DUR           0x1E
#define MPU6050_RA_MOT_THR          0x1F
#define MPU6050_RA_MOT_DUR          0x20
#define MPU6050_RA_ZRMOT_THR        0x21
#define MPU6050_RA_ZRMOT_DUR        0x22
#define MPU6050_RA_FIFO_EN          0x23
#define MPU6050_RA_I2C_MST_CTRL     0x24
#define MPU6050_RA_I2C_SLV0_ADDR    0x25
#define MPU6050_RA_I2C_SLV0_REG     0x26
#define MPU6050_RA_I2C_SLV0_CTRL    0x27
#define MPU6050_RA_I2C_SLV1_ADDR    0x28
#define MPU6050_RA_I2C_SLV1_REG     0x29
#define MPU6050_RA_I2C_SLV1_CTRL    0x2A
#define MPU6050_RA_I2C_SLV2_ADDR    0x2B
#define MPU6050_RA_I2C_SLV2_REG     0x2C
#define MPU6050_RA_I2C_SLV2_CTRL    0x2D
#define MPU6050_RA_I2C_SLV3_ADDR    0x2E
#define MPU6050_RA_I2C_SLV3_REG     0x2F
#define MPU6050_RA_I2C_SLV3_CTRL    0x30
#define MPU6050_RA_I2C_SLV4_ADDR    0x31
#define MPU6050_RA_I2C_SLV4_REG     0x32
#define MPU6050_RA_I2C_SLV4_DO      0x33
#define MPU6050_RA_I2C_SLV4_CTRL    0x34
#define MPU6050_RA_I2C_SLV4_DI      0x35
#define MPU6050_RA_I2C_MST_STATUS   0x36
#define MPU6050_RA_INT_PIN_CFG      0x37
#define MPU6050_RA_INT_ENABLE       0x38
#define MPU6050_RA_DMP_INT_STATUS   0x39
#define MPU6050_RA_INT_STATUS       0x3A
#define MPU6050_RA_ACCEL_XOUT_H     0x3B
#define MPU6050_RA_ACCEL_XOUT_L     0x3C
#define MPU6050_RA_ACCEL_YOUT_H     0x3D
#define MPU6050_RA_ACCEL_YOUT_L     0x3E
#define MPU6050_RA_ACCEL_ZOUT_H     0x3F
#define MPU6050_RA_ACCEL_ZOUT_L     0x40
#define MPU6050_RA_TEMP_OUT_H       0x41
#define MPU6050_RA_TEMP_OUT_L       0x42
#define MPU6050_RA_GYRO_XOUT_H      0x43
#define MPU6050_RA_GYRO_XOUT_L      0x44
#define MPU6050_RA_GYRO_YOUT_H      0x45
#define MPU6050_RA_GYRO_YOUT_L      0x46
#define MPU6050_RA_GYRO_ZOUT_H      0x47
#define MPU6050_RA_GYRO_ZOUT_L      0x48
#define MPU6050_RA_EXT_SENS_DATA_00 0x49
#define MPU6050_RA_EXT_SENS_DATA_01 0x4A
#define MPU6050_RA_EXT_SENS_DATA_02 0x4B
#define MPU6050_RA_EXT_SENS_DATA_03 0x4C
#define MPU6050_RA_EXT_SENS_DATA_04 0x4D
#define MPU6050_RA_EXT_SENS_DATA_05 0x4E
#define MPU6050_RA_EXT_SENS_DATA_06 0x4F
#define MPU6050_RA_EXT_SENS_DATA_07 0x50
#define MPU6050_RA_EXT_SENS_DATA_08 0x51
#define MPU6050_RA_EXT_SENS_DATA_09 0x52
#define MPU6050_RA_EXT_SENS_DATA_10 0x53
#define MPU6050_RA_EXT_SENS_DATA_11 0x54
#define MPU6050_RA_EXT_SENS_DATA_12 0x55
#define MPU6050_RA_EXT_SENS_DATA_13 0x56
#define MPU6050_RA_EXT_SENS_DATA_14 0x57
#define MPU6050_RA_EXT_SENS_DATA_15 0x58
#define MPU6050_RA_EXT_SENS_DATA_16 0x59
#define MPU6050_RA_EXT_SENS_DATA_17 0x5A
#define MPU6050_RA_EXT_SENS_DATA_18 0x5B
#define MPU6050_RA_EXT_SENS_DATA_19 0x5C
#define MPU6050_RA_EXT_SENS_DATA_20 0x5D
#define MPU6050_RA_EXT_SENS_DATA_21 0x5E
#define MPU6050_RA_EXT_SENS_DATA_22 0x5F
#define MPU6050_RA_EXT_SENS_DATA_23 0x60
#define MPU6050_RA_MOT_DETECT_STATUS 0x61
#define MPU6050_RA_I2C_SLV0_DO      0x63
#define MPU6050_RA_I2C_SLV1_DO      0x64
#define MPU6050_RA_I2C_SLV2_DO      0x65
#define MPU6050_RA_I2C_SLV3_DO      0x66
#define MPU6050_RA_I2C_MST_DELAY_CTRL   0x67
#define MPU6050_RA_SIGNAL_PATH_RESET    0x68
#define MPU6050_RA_MOT_DETECT_CTRL      0x69
#define MPU6050_RA_USER_CTRL        0x6A
#define MPU6050_RA_PWR_MGMT_1       0x6B
#define MPU6050_RA_PWR_MGMT_2       0x6C
#define MPU6050_RA_BANK_SEL         0x6D
#define MPU6050_RA_MEM_START_ADDR   0x6E
#define MPU6050_RA_MEM_R_W          0x6F
#define MPU6050_RA_DMP_CFG_1        0x70
#define MPU6050_RA_DMP_CFG_2        0x71
#define MPU6050_RA_FIFO_COUNTH      0x72
#define MPU6050_RA_FIFO_COUNTL      0x73
#define MPU6050_RA_FIFO_R_W         0x74
#define MPU6050_RA_WHO_AM_I         0x75#define MPU6050_TC_PWR_MODE_BIT     7
#define MPU6050_TC_OFFSET_BIT       6
#define MPU6050_TC_OFFSET_LENGTH    6
#define MPU6050_TC_OTP_BNK_VLD_BIT  0#define MPU6050_VDDIO_LEVEL_VLOGIC  0
#define MPU6050_VDDIO_LEVEL_VDD     1#define MPU6050_CFG_EXT_SYNC_SET_BIT    5
#define MPU6050_CFG_EXT_SYNC_SET_LENGTH 3
#define MPU6050_CFG_DLPF_CFG_BIT    2
#define MPU6050_CFG_DLPF_CFG_LENGTH 3#define MPU6050_EXT_SYNC_DISABLED       0x0
#define MPU6050_EXT_SYNC_TEMP_OUT_L     0x1
#define MPU6050_EXT_SYNC_GYRO_XOUT_L    0x2
#define MPU6050_EXT_SYNC_GYRO_YOUT_L    0x3
#define MPU6050_EXT_SYNC_GYRO_ZOUT_L    0x4
#define MPU6050_EXT_SYNC_ACCEL_XOUT_L   0x5
#define MPU6050_EXT_SYNC_ACCEL_YOUT_L   0x6
#define MPU6050_EXT_SYNC_ACCEL_ZOUT_L   0x7#define MPU6050_DLPF_BW_256         0x00
#define MPU6050_DLPF_BW_188         0x01
#define MPU6050_DLPF_BW_98          0x02
#define MPU6050_DLPF_BW_42          0x03
#define MPU6050_DLPF_BW_20          0x04
#define MPU6050_DLPF_BW_10          0x05
#define MPU6050_DLPF_BW_5           0x06#define MPU6050_GCONFIG_FS_SEL_BIT      4
#define MPU6050_GCONFIG_FS_SEL_LENGTH   2#define MPU6050_GYRO_FS_250         0x00
#define MPU6050_GYRO_FS_500         0x01
#define MPU6050_GYRO_FS_1000        0x02
#define MPU6050_GYRO_FS_2000        0x03#define MPU6050_ACONFIG_XA_ST_BIT           7
#define MPU6050_ACONFIG_YA_ST_BIT           6
#define MPU6050_ACONFIG_ZA_ST_BIT           5
#define MPU6050_ACONFIG_AFS_SEL_BIT         4
#define MPU6050_ACONFIG_AFS_SEL_LENGTH      2
#define MPU6050_ACONFIG_ACCEL_HPF_BIT       2
#define MPU6050_ACONFIG_ACCEL_HPF_LENGTH    3#define MPU6050_ACCEL_FS_2          0x00
#define MPU6050_ACCEL_FS_4          0x01
#define MPU6050_ACCEL_FS_8          0x02
#define MPU6050_ACCEL_FS_16         0x03#define MPU6050_DHPF_RESET          0x00
#define MPU6050_DHPF_5              0x01
#define MPU6050_DHPF_2P5            0x02
#define MPU6050_DHPF_1P25           0x03
#define MPU6050_DHPF_0P63           0x04
#define MPU6050_DHPF_HOLD           0x07#define MPU6050_TEMP_FIFO_EN_BIT    7
#define MPU6050_XG_FIFO_EN_BIT      6
#define MPU6050_YG_FIFO_EN_BIT      5
#define MPU6050_ZG_FIFO_EN_BIT      4
#define MPU6050_ACCEL_FIFO_EN_BIT   3
#define MPU6050_SLV2_FIFO_EN_BIT    2
#define MPU6050_SLV1_FIFO_EN_BIT    1
#define MPU6050_SLV0_FIFO_EN_BIT    0#define MPU6050_MULT_MST_EN_BIT     7
#define MPU6050_WAIT_FOR_ES_BIT     6
#define MPU6050_SLV_3_FIFO_EN_BIT   5
#define MPU6050_I2C_MST_P_NSR_BIT   4
#define MPU6050_I2C_MST_CLK_BIT     3
#define MPU6050_I2C_MST_CLK_LENGTH  4#define MPU6050_CLOCK_DIV_348       0x0
#define MPU6050_CLOCK_DIV_333       0x1
#define MPU6050_CLOCK_DIV_320       0x2
#define MPU6050_CLOCK_DIV_308       0x3
#define MPU6050_CLOCK_DIV_296       0x4
#define MPU6050_CLOCK_DIV_286       0x5
#define MPU6050_CLOCK_DIV_276       0x6
#define MPU6050_CLOCK_DIV_267       0x7
#define MPU6050_CLOCK_DIV_258       0x8
#define MPU6050_CLOCK_DIV_500       0x9
#define MPU6050_CLOCK_DIV_471       0xA
#define MPU6050_CLOCK_DIV_444       0xB
#define MPU6050_CLOCK_DIV_421       0xC
#define MPU6050_CLOCK_DIV_400       0xD
#define MPU6050_CLOCK_DIV_381       0xE
#define MPU6050_CLOCK_DIV_364       0xF#define MPU6050_I2C_SLV_RW_BIT      7
#define MPU6050_I2C_SLV_ADDR_BIT    6
#define MPU6050_I2C_SLV_ADDR_LENGTH 7
#define MPU6050_I2C_SLV_EN_BIT      7
#define MPU6050_I2C_SLV_BYTE_SW_BIT 6
#define MPU6050_I2C_SLV_REG_DIS_BIT 5
#define MPU6050_I2C_SLV_GRP_BIT     4
#define MPU6050_I2C_SLV_LEN_BIT     3
#define MPU6050_I2C_SLV_LEN_LENGTH  4#define MPU6050_I2C_SLV4_RW_BIT         7
#define MPU6050_I2C_SLV4_ADDR_BIT       6
#define MPU6050_I2C_SLV4_ADDR_LENGTH    7
#define MPU6050_I2C_SLV4_EN_BIT         7
#define MPU6050_I2C_SLV4_INT_EN_BIT     6
#define MPU6050_I2C_SLV4_REG_DIS_BIT    5
#define MPU6050_I2C_SLV4_MST_DLY_BIT    4
#define MPU6050_I2C_SLV4_MST_DLY_LENGTH 5#define MPU6050_MST_PASS_THROUGH_BIT    7
#define MPU6050_MST_I2C_SLV4_DONE_BIT   6
#define MPU6050_MST_I2C_LOST_ARB_BIT    5
#define MPU6050_MST_I2C_SLV4_NACK_BIT   4
#define MPU6050_MST_I2C_SLV3_NACK_BIT   3
#define MPU6050_MST_I2C_SLV2_NACK_BIT   2
#define MPU6050_MST_I2C_SLV1_NACK_BIT   1
#define MPU6050_MST_I2C_SLV0_NACK_BIT   0#define MPU6050_INTCFG_INT_LEVEL_BIT        7
#define MPU6050_INTCFG_INT_OPEN_BIT         6
#define MPU6050_INTCFG_LATCH_INT_EN_BIT     5
#define MPU6050_INTCFG_INT_RD_CLEAR_BIT     4
#define MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT  3
#define MPU6050_INTCFG_FSYNC_INT_EN_BIT     2
#define MPU6050_INTCFG_I2C_BYPASS_EN_BIT    1
#define MPU6050_INTCFG_CLKOUT_EN_BIT        0#define MPU6050_INTMODE_ACTIVEHIGH  0x00
#define MPU6050_INTMODE_ACTIVELOW   0x01#define MPU6050_INTDRV_PUSHPULL     0x00
#define MPU6050_INTDRV_OPENDRAIN    0x01#define MPU6050_INTLATCH_50USPULSE  0x00
#define MPU6050_INTLATCH_WAITCLEAR  0x01#define MPU6050_INTCLEAR_STATUSREAD 0x00
#define MPU6050_INTCLEAR_ANYREAD    0x01#define MPU6050_INTERRUPT_FF_BIT            7
#define MPU6050_INTERRUPT_MOT_BIT           6
#define MPU6050_INTERRUPT_ZMOT_BIT          5
#define MPU6050_INTERRUPT_FIFO_OFLOW_BIT    4
#define MPU6050_INTERRUPT_I2C_MST_INT_BIT   3
#define MPU6050_INTERRUPT_PLL_RDY_INT_BIT   2
#define MPU6050_INTERRUPT_DMP_INT_BIT       1
#define MPU6050_INTERRUPT_DATA_RDY_BIT      0#define MPU6050_DMPINT_5_BIT            5
#define MPU6050_DMPINT_4_BIT            4
#define MPU6050_DMPINT_3_BIT            3
#define MPU6050_DMPINT_2_BIT            2
#define MPU6050_DMPINT_1_BIT            1
#define MPU6050_DMPINT_0_BIT            0#define MPU6050_MOTION_MOT_XNEG_BIT     7
#define MPU6050_MOTION_MOT_XPOS_BIT     6
#define MPU6050_MOTION_MOT_YNEG_BIT     5
#define MPU6050_MOTION_MOT_YPOS_BIT     4
#define MPU6050_MOTION_MOT_ZNEG_BIT     3
#define MPU6050_MOTION_MOT_ZPOS_BIT     2
#define MPU6050_MOTION_MOT_ZRMOT_BIT    0#define MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT   7
#define MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT   4
#define MPU6050_DELAYCTRL_I2C_SLV3_DLY_EN_BIT   3
#define MPU6050_DELAYCTRL_I2C_SLV2_DLY_EN_BIT   2
#define MPU6050_DELAYCTRL_I2C_SLV1_DLY_EN_BIT   1
#define MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT   0#define MPU6050_PATHRESET_GYRO_RESET_BIT    2
#define MPU6050_PATHRESET_ACCEL_RESET_BIT   1
#define MPU6050_PATHRESET_TEMP_RESET_BIT    0#define MPU6050_DETECT_ACCEL_ON_DELAY_BIT       5
#define MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH    2
#define MPU6050_DETECT_FF_COUNT_BIT             3
#define MPU6050_DETECT_FF_COUNT_LENGTH          2
#define MPU6050_DETECT_MOT_COUNT_BIT            1
#define MPU6050_DETECT_MOT_COUNT_LENGTH         2#define MPU6050_DETECT_DECREMENT_RESET  0x0
#define MPU6050_DETECT_DECREMENT_1      0x1
#define MPU6050_DETECT_DECREMENT_2      0x2
#define MPU6050_DETECT_DECREMENT_4      0x3#define MPU6050_USERCTRL_DMP_EN_BIT             7
#define MPU6050_USERCTRL_FIFO_EN_BIT            6
#define MPU6050_USERCTRL_I2C_MST_EN_BIT         5
#define MPU6050_USERCTRL_I2C_IF_DIS_BIT         4
#define MPU6050_USERCTRL_DMP_RESET_BIT          3
#define MPU6050_USERCTRL_FIFO_RESET_BIT         2
#define MPU6050_USERCTRL_I2C_MST_RESET_BIT      1
#define MPU6050_USERCTRL_SIG_COND_RESET_BIT     0#define MPU6050_PWR1_DEVICE_RESET_BIT   7
#define MPU6050_PWR1_SLEEP_BIT          6
#define MPU6050_PWR1_CYCLE_BIT          5
#define MPU6050_PWR1_TEMP_DIS_BIT       3
#define MPU6050_PWR1_CLKSEL_BIT         2
#define MPU6050_PWR1_CLKSEL_LENGTH      3#define MPU6050_CLOCK_INTERNAL          0x00
#define MPU6050_CLOCK_PLL_XGYRO         0x01
#define MPU6050_CLOCK_PLL_YGYRO         0x02
#define MPU6050_CLOCK_PLL_ZGYRO         0x03
#define MPU6050_CLOCK_PLL_EXT32K        0x04
#define MPU6050_CLOCK_PLL_EXT19M        0x05
#define MPU6050_CLOCK_KEEP_RESET        0x07#define MPU6050_PWR2_LP_WAKE_CTRL_BIT       7
#define MPU6050_PWR2_LP_WAKE_CTRL_LENGTH    2
#define MPU6050_PWR2_STBY_XA_BIT            5
#define MPU6050_PWR2_STBY_YA_BIT            4
#define MPU6050_PWR2_STBY_ZA_BIT            3
#define MPU6050_PWR2_STBY_XG_BIT            2
#define MPU6050_PWR2_STBY_YG_BIT            1
#define MPU6050_PWR2_STBY_ZG_BIT            0#define MPU6050_WAKE_FREQ_1P25      0x0
#define MPU6050_WAKE_FREQ_2P5       0x1
#define MPU6050_WAKE_FREQ_5         0x2
#define MPU6050_WAKE_FREQ_10        0x3#define MPU6050_BANKSEL_PRFTCH_EN_BIT       6
#define MPU6050_BANKSEL_CFG_USER_BANK_BIT   5
#define MPU6050_BANKSEL_MEM_SEL_BIT         4
#define MPU6050_BANKSEL_MEM_SEL_LENGTH      5#define MPU6050_WHO_AM_I_BIT        6
#define MPU6050_WHO_AM_I_LENGTH     6#define MPU6050_DMP_MEMORY_BANKS        8
#define MPU6050_DMP_MEMORY_BANK_SIZE    256
#define MPU6050_DMP_MEMORY_CHUNK_SIZE   16#define mpu_6050 hi2c4
void               I2C_MPU6050_WriteData(uint16_t Addr, uint8_t Reg, uint8_t Value);
HAL_StatusTypeDef  I2C_MPU6050_WriteBuffer(uint16_t Addr, uint8_t Reg, uint16_t RegSize, uint8_t *pBuffer, uint16_t Length);
uint8_t            I2C_MPU6050_ReadData(uint16_t Addr, uint8_t Reg);
HAL_StatusTypeDef  I2C_MPU6050_ReadBuffer(uint16_t Addr, uint8_t Reg, uint16_t RegSize, uint8_t *pBuffer, uint16_t Length);
HAL_StatusTypeDef  I2C_MPU6050_IsDeviceReady(uint16_t DevAddress, uint32_t Trials);void  WriteData(uint8_t Byte);
void WriteCommand(uint8_t Command);void MPU6050ReadTemp(short *tempData);
void MPU6050ReadGyro(short *gyroData);
void MPU6050ReadAcc(short *accData);
void MPU6050_ReturnTemp(short*Temperature);
void MPU6050_Init(void);
uint8_t MPU6050ReadID(void);
void PMU6050_ReadData(uint8_t reg_add,unsigned char*Read,uint8_t num);
void PMU6050_WriteReg(uint8_t reg_add,uint8_t reg_dat);void MPU6050_PWR_MGMT_1_INIT(void);

.c文件


//用于向设备发送指令。
void WriteCommand(uint8_t Command)
{uint8_t date=0;HAL_I2C_Mem_Write(&mpu_6050, 0x69,0x00, I2C_MEMADD_SIZE_8BIT,(uint8_t *)&Command, 1, 0xff);if(HAL_I2C_IsDeviceReady(&mpu_6050,0x69,100,0xffff)==HAL_OK){}}
//用于向从设备发送数据
void  WriteData(uint8_t Byte)
{HAL_I2C_Master_Transmit(&mpu_6050, 0x69,(uint8_t *)&Byte, 1, 0xff);if(HAL_I2C_IsDeviceReady(&mpu_6050,0x69,100,0xffff)==HAL_OK){}}/*** 函数功能: I2C通信错误处理函数* 输入参数: 无* 返 回 值: 无* 说    明: 一般在I2C通信超时时调用该函数*/
static void I2C_MPU6050_Error (void)
{/* 反初始化I2C通信总线 */HAL_I2C_DeInit(&mpu_6050);/* 重新初始化I2C通信总线*/MX_I2C2_Init();printf("MPU6050 I2C通信超时!!! 重新启动I2C...\n");
}/*** 函数功能: 通过I2C写入一个值到指定寄存器内* 输入参数: Addr:I2C设备地址*           Reg:目标寄存器*           Value:值* 返 回 值: 无* 说    明: 无*/
void I2C_MPU6050_WriteData(uint16_t Addr, uint8_t Reg, uint8_t Value)
{HAL_StatusTypeDef status = HAL_OK;status = HAL_I2C_Mem_Write(&mpu_6050, Addr, (uint16_t)Reg, I2C_MEMADD_SIZE_8BIT, &Value, 1, 1000);/* 检测I2C通信状态 */if(status != HAL_OK){/* 调用I2C通信错误处理函数 */I2C_MPU6050_Error();}
}/*** 函数功能: 通过I2C写入一段数据到指定寄存器内* 输入参数: Addr:I2C设备地址*           Reg:目标寄存器*           RegSize:寄存器尺寸(8位或者16位)*           pBuffer:缓冲区指针*           Length:缓冲区长度* 返 回 值: HAL_StatusTypeDef:操作结果* 说    明: 在循环调用是需加一定延时时间*/
HAL_StatusTypeDef I2C_MPU6050_WriteBuffer(uint16_t Addr, uint8_t Reg, uint16_t RegSize, uint8_t *pBuffer, uint16_t Length)
{HAL_StatusTypeDef status = HAL_OK;status = HAL_I2C_Mem_Write(&mpu_6050, Addr, (uint16_t)Reg, RegSize, pBuffer, Length, 1000); /* 检测I2C通信状态 */if(status != HAL_OK){/* 调用I2C通信错误处理函数 */I2C_MPU6050_Error();}        return status;
}/*** 函数功能: 通过I2C读取一个指定寄存器内容* 输入参数: Addr:I2C设备地址*           Reg:目标寄存器* 返 回 值: uint8_t:寄存器内容* 说    明: 无*/
uint8_t I2C_MPU6050_ReadData(uint16_t Addr, uint8_t Reg)
{HAL_StatusTypeDef status = HAL_OK;uint8_t value = 0;status = HAL_I2C_Mem_Read(&mpu_6050, Addr, Reg, I2C_MEMADD_SIZE_8BIT, &value, 1, 1000);/* 检测I2C通信状态 */if(status != HAL_OK){/* 调用I2C通信错误处理函数 */I2C_MPU6050_Error();}return value;
}/*** 函数功能: 通过I2C读取一段寄存器内容存放到指定的缓冲区内* 输入参数: Addr:I2C设备地址*           Reg:目标寄存器*           RegSize:寄存器尺寸(8位或者16位)*           pBuffer:缓冲区指针*           Length:缓冲区长度* 返 回 值: HAL_StatusTypeDef:操作结果* 说    明: 无*/
HAL_StatusTypeDef I2C_MPU6050_ReadBuffer(uint16_t Addr, uint8_t Reg, uint16_t RegSize, uint8_t *pBuffer, uint16_t Length)
{HAL_StatusTypeDef status = HAL_OK;status = HAL_I2C_Mem_Read(&mpu_6050, Addr, (uint16_t)Reg, RegSize, pBuffer, Length, 1000);/* 检测I2C通信状态 */if(status != HAL_OK){/* 调用I2C通信错误处理函数 */I2C_MPU6050_Error();}        return status;
}/*** 函数功能: 检测I2C设备是否处于准备好可以通信状态* 输入参数: DevAddress:I2C设备地址*           Trials:尝试测试次数* 返 回 值: HAL_StatusTypeDef:操作结果* 说    明: 无*/
HAL_StatusTypeDef I2C_MPU6050_IsDeviceReady(uint16_t DevAddress, uint32_t Trials)
{ return (HAL_I2C_IsDeviceReady(&mpu_6050, DevAddress, Trials, 1000));
}/*** 函数功能: 写数据到MPU6050寄存器* 输入参数: 无* 返 回 值: 无* 说    明: 无*/ 
void MPU6050_WriteReg(uint8_t reg_add,uint8_t reg_dat)
{I2C_MPU6050_WriteData(MPU6050_SLAVE_ADDRESS,reg_add,reg_dat);
}/*** 函数功能: 从MPU6050寄存器读取数据* 输入参数: 无* 返 回 值: 无* 说    明: 无*/ 
void MPU6050_ReadData(uint8_t reg_add,unsigned char *Read,uint8_t num)
{I2C_MPU6050_ReadBuffer(MPU6050_SLAVE_ADDRESS,reg_add,I2C_MEMADD_SIZE_8BIT,Read,num);
}/*** 函数功能: 初始化MPU6050芯片* 输入参数: 无* 返 回 值: 无* 说    明: 无*/ 
void MPU6050_Init(void)
{int i=0,j=0;//在初始化之前要延时一段时间,若没有延时,则断电后再上电数据可能会出错for(i=0;i<1000;i++){for(j=0;j<1000;j++){;}}// HAL_Delay(50);MPU6050_WriteReg(MPU6050_RA_PWR_MGMT_1, 0x00);	    //解除休眠状态MPU6050_WriteReg(MPU6050_RA_SMPLRT_DIV , 0x07);	    //陀螺仪采样率,1KHzMPU6050_WriteReg(MPU6050_RA_CONFIG , 0x06);	        //低通滤波器的设置,截止频率是1K,带宽是5KMPU6050_WriteReg(MPU6050_RA_ACCEL_CONFIG , 0x00);	  //配置加速度传感器工作在2G模式,不自检MPU6050_WriteReg(MPU6050_RA_GYRO_CONFIG, 0x18);     //陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s)
}/*** 函数功能: 读取MPU6050的ID* 输入参数: 无* 返 回 值: 无* 说    明: 无*/ 
uint8_t MPU6050ReadID(void)
{unsigned char Re = 0;MPU6050_ReadData(MPU6050_RA_WHO_AM_I,&Re,1);    //读器件地址if(Re != 0x68){printf("MPU6050 dectected error!\r\n检测不到MPU6050模块,请检查模块与开发板的接线");return 0;}else{printf("MPU6050 ID = %d\r\n",Re);return 1;}}/*** 函数功能: 读取MPU6050的加速度数据* 输入参数: 无* 返 回 值: 无* 说    明: 无*/ 
void MPU6050ReadAcc(short *accData)
{uint8_t buf[6];MPU6050_ReadData(MPU6050_ACC_OUT, buf, 6);accData[0] = (buf[0] << 8) | buf[1];accData[1] = (buf[2] << 8) | buf[3];accData[2] = (buf[4] << 8) | buf[5];
}/*** 函数功能: 读取MPU6050的角速度数据* 输入参数: 无* 返 回 值: 无* 说    明: 无*/ 
void MPU6050ReadGyro(short *gyroData)
{uint8_t buf[6];MPU6050_ReadData(MPU6050_GYRO_OUT,buf,6);gyroData[0] = (buf[0] << 8) | buf[1];gyroData[1] = (buf[2] << 8) | buf[3];gyroData[2] = (buf[4] << 8) | buf[5];
}/*** 函数功能: 读取MPU6050的原始温度数据* 输入参数: 无* 返 回 值: 无* 说    明: 无*/ 
void MPU6050ReadTemp(short *tempData)
{uint8_t buf[2];MPU6050_ReadData(MPU6050_RA_TEMP_OUT_H,buf,2);     //读取温度值*tempData = (buf[0] << 8) | buf[1];
}/*** 函数功能: 读取MPU6050的温度数据,转化成摄氏度* 输入参数: 无* 返 回 值: 无* 说    明: 无*/ 
void MPU6050_ReturnTemp(short*Temperature)
{short temp3;uint8_t buf[2];MPU6050_ReadData(MPU6050_RA_TEMP_OUT_H,buf,2);     //读取温度值temp3= (buf[0] << 8) | buf[1];*Temperature=(((double) (temp3 + 13200)) / 280)-13;
}

ATH20驱动文件

说明:

vcc,gnd供电相关
scl,sda iic通信相关引脚
该模块用于获取温湿度,使用iic通信,通过配置模块中芯片的寄存器来获取数据。
调用

	ATH20_Init();float temperaut,humtidiy;ATH20_Read_CTdata(&temperaut,&humtidiy);printf("温度: %.3lf ℃\n",temperaut);printf("湿度: %.3lf %%\n",humtidiy);

.h文件

#define ATH20_SLAVE_ADDRESS    0x70	/* I2C从机地址 */#define	INIT		    0xBE	//初始化
#define	SoftReset		0xBA	//软复位
#define	StartTest		0xAC	//开始测试uint8_t ATH20_Init(void);
void ATH20_Read_CTdata(float *temperature,float *Humidity);

.c文件

void ATH20_Read_CTdata(float *temperature,float *Humidity) //读取AHT10的温度和湿度数据
{uint32_t RetuData = 0;uint8_t Data[6]={0};static uint8_t tmp[3]={0xac,0x33,0x00};HAL_I2C_Master_Transmit(&hi2cx,ATH20_SLAVE_ADDRESS,tmp,3,0xffff);HAL_Delay(75);//等待75msHAL_I2C_Master_Receive(&hi2cx,ATH20_SLAVE_ADDRESS,Data,6,0xffff);if((Data[0]&0x80)==0x00){RetuData = 0;RetuData = ((uint32_t)Data[3]>>4)+((uint32_t)Data[2]<<4)+((uint32_t)Data[1]<<12);*Humidity = RetuData*100.0f/(1<<20);RetuData =  (((uint32_t)Data[3]&0x0f)<<16)+((uint32_t)Data[4]<<8)+((uint32_t)Data[5]);*temperature = RetuData*200.0f/(1<<20)-50;}
}uint8_t ATH20_Init(void)
{static uint8_t tmp[3]={0xbe,0x08,0x00};uint8_t read_buf={0};HAL_Delay(40);HAL_I2C_Master_Receive(&hi2cx,ATH20_SLAVE_ADDRESS,&read_buf,1,0xffff);if((read_buf&0x80)==0x00){HAL_I2C_Master_Transmit(&hi2cx,ATH20_SLAVE_ADDRESS,tmp,3,0xffff);}
}uint8_t ATH20_Read_Status(void)//读取AHT10的状态寄存器
{uint8_t Byte_first;HAL_I2C_Mem_Read(&hi2cx,ATH20_SLAVE_ADDRESS,0x00,1,&Byte_first,1,0xff);return Byte_first;
}uint8_t ATH20_Read_Cal_Enable(void)
{uint8_t val = 0;//ret = 0,val = ATH20_Read_Status();if((val & 0x68) == 0x08)  //判断NOR模式和校准输出是否有效return 1;elsereturn 0;
}void ATH20_Read_CTdata1(uint32_t *ct) //读取AHT10的温度和湿度数据
{uint32_t RetuData = 0;uint16_t cnt = 0;uint8_t Data[10];uint8_t tmp[10];tmp[0] = 0x33;tmp[1] = 0x00;HAL_I2C_Mem_Write(&hi2cx,ATH20_SLAVE_ADDRESS,StartTest,1,tmp,2,0xff);HAL_Delay(75);//等待75mscnt = 0;while(((ATH20_Read_Status()&0x80) == 0x80))//等待忙状态结束{HAL_Delay(1);if(cnt++ >= 100){break;}}HAL_I2C_Mem_Read(&hi2cx,ATH20_SLAVE_ADDRESS,0,1,Data,7,0xff);RetuData = 0;RetuData = (RetuData|Data[1]) << 8;RetuData = (RetuData|Data[2]) << 8;RetuData = (RetuData|Data[3]);RetuData = RetuData >> 4;ct[0] = RetuData;RetuData = 0;RetuData = (RetuData|Data[3]) << 8;RetuData = (RetuData|Data[4]) << 8;RetuData = (RetuData|Data[5]);RetuData = RetuData&0xfffff;ct[1] = RetuData;
}uint8_t count;
uint8_t ATH20_Init1(void)
{uint8_t tmp[10];HAL_Delay(40);tmp[0] = 0x08;tmp[1] = 0x00;HAL_I2C_Mem_Write(&hi2cx,ATH20_SLAVE_ADDRESS,INIT,1,tmp,2,0xff);HAL_Delay(500);count = 0;while(ATH20_Read_Cal_Enable() == 0)//需要等待状态字status的Bit[3]=1时才去读数据。如果Bit[3]不等于1 ,发软件复位0xBA给AHT10,再重新初始化AHT10,直至Bit[3]=1{HAL_I2C_Mem_Write(&hi2cx,ATH20_SLAVE_ADDRESS,SoftReset,1,tmp,2,0xff);HAL_Delay(200);HAL_I2C_Mem_Write(&hi2cx,ATH20_SLAVE_ADDRESS,INIT,1,tmp,2,0xff);count++;if(count >= 10)return 0;HAL_Delay(500);}return 1;
}

ads1115驱动文件

在这里插入图片描述

说明:

该模块是adc采集模块精度为16bit,使用iic进行数据通信
vcc,gnd供电
scl,sda iic通信
addr,配置模块iic地址
alrt,比较器输出/转换状态就绪引脚
a0~a3,adc采集通道
调用:

	float A0_Voltage;char buffer[]="";//显示存储数组A0_Voltage=ADS1115_Read_average_ADC(0);	//读取A0通道输入的电压,选择6.144V最大量程	sprintf(buffer,"%5.3f",A0_Voltage);//浮点型数据转为指定格式的字符串,5位,3位小数点printf("a0:%s\n",buffer);HAL_Delay(100);//等待100ms

.h文件

#define ADS1115_DEV_ADDR_GND            0x90//ADDR接GND,ADS1115地址
#define ADS1115_DEV_ADDR_VDD            0x92//ADDR接VDD,ADS1115地址
#define ADS1115_DEV_ADDR_SDA            0x94//ADDR接SDA,ADS1115地址
#define ADS1115_DEV_ADDR_SCL            0x96//ADDR接SCL,ADS1115地址#define ADS1115_DEV_ADDR            	0x90//ADDR接GND决定ADS1115的7位地址,如果是写命令就是0x90,读命令就是0x91     #define ADS1115_Conversion        	 	 0x00  //转换寄存器地址
#define ADS1115_Config              	 0x01  //配置寄存器地址#define REG_L_thresh 	 0x02// Low threshold value
#define REG_H_thresh 	 0x03	// High threshold valueextern uint8_t BYTE_BUF[2];//读取转换寄存器的数组值
float ADS1115_Read_ADC(uint8_t channel);
float ADS1115_Read_average_ADC(uint8_t channel);

.c文件

/*********************************************************************************
描述:配置01H寄存器,实现单次转换,读取00H寄存器,实现电压采样,并转换成电压值
输入:channel:需要采集的通道号,ADS1115是4通道,所以是0~3,分别代表A0~A3通道
返回:浮点数,对应通道采集到的电压值,单位V//配置寄存器说明//config register
/*CRH[15:8](R/W)BIT      15      14      13      12      11      10      9       8NAME     OS      MUX2    MUX1    MUX0    PGA2    PGA1    PGA0    MODE
CRL[7:0] (R/W)BIT      7       6       5       4       3       2       1       0NAME    DR0     DR1     DR0   COM_MODE COM_POL COM_LAT COM_QUE1 COM_QUE0-----------------------------------------------------------------------------------* 15    | OS             |  运行状态会单词转换开始*       |                | 写时:*       |                | 0   : 无效*       |                | 1   : 开始单次转换处于掉电状态时*       |                | 读时:*       |                | 0   : 正在转换*       |                | 1   : 未执行转换* -----------------------------------------------------------------------------------* 14:12 | MUX [2:0]      | 输入复用多路配置*       |                | 000 : AINP = AIN0 and AINN = AIN1 (default)*       |                | 001 : AINP = AIN0 and AINN = AIN3*       |                | 010 : AINP = AIN1 and AINN = AIN3*       |                | 011 : AINP = AIN2 and AINN = AIN3*       |                | 100 : AINP = AIN0 and AINN = GND*       |                | 101 : AINP = AIN1 and AINN = GND*       |                | 110 : AINP = AIN2 and AINN = GND*       |                | 111 : AINP = AIN3 and AINN = GND* -----------------------------------------------------------------------------------* 11:9  | PGA [2:0]      | 可编程增益放大器配置(FSR  full scale range)*       |                | 000 : FSR = В±6.144 V*       |                | 001 : FSR = В±4.096 V*       |                | 010 : FSR = В±2.048 V (默认)*       |                | 011 : FSR = В±1.024 V*       |                | 100 : FSR = В±0.512 V*       |                | 101 : FSR = В±0.256 V*       |                | 110 : FSR = В±0.256 V*       |                | 111 : FSR = В±0.256 V* -----------------------------------------------------------------------------------* 8     | MODE           | 工作模式*       |                | 0   : 连续转换*       |                | 1   : 单词转换* -----------------------------------------------------------------------------------* 7:5   | DR [2:0]       | 采样频率*       |                | 000 : 8 SPS*       |                | 001 : 16 SPS*       |                | 010 : 32 SPS*       |                | 011 : 64 SPS*       |                | 100 : 128 SPS (默认)*       |                | 101 : 250 SPS*       |                | 110 : 475 SPS*       |                | 111 : 860 SPS* -----------------------------------------------------------------------------------* 4     | COMP_MODE      | 比较器模式*       |                | 0   : 传统比较器 (default)*       |                | 1   : 窗口比较器* -----------------------------------------------------------------------------------* 3     | COMP_POL       | Comparator polarity*       |                | 0   : 低电平有效 (default)*       |                | 1   : 高电平有效* -----------------------------------------------------------------------------------* 2     | COMP_LAT       | Latching comparator*       |                | 0   : 非锁存比较器. (default)*       |                | 1   : 锁存比较器.* -----------------------------------------------------------------------------------* 1:0   | COMP_QUE [1:0] | Comparator queue and disable*       |                | 00  : Assert after one conversion*       |                | 01  : Assert after two conversions*       |                | 10  : Assert after four conversions*       |                | 11  : 禁用比较器并将ALERT/RDY设置为高阻抗 (default)* -----------------------------------------------------------------------------------**********************************************************************************/
float ADS1115_Read_ADC(uint8_t channel)//选择一个通道的单次转换
{uint8_t ConfigBuff[2];uint8_t PGA=0;//配置PGA[2:0]为000,采用FSR = ±6.144 Vint16_t tempData;float voltage;//实际电压值switch (channel){case 0:ConfigBuff[0] = (0xC0&0xf1)|(PGA<<1);   //bit[15]=OS=1:开始单次转换0xC1[单次]//bit[14:12]=MUX[2:0]=100 : AINP = AIN0 and AINN = GND,采集A0通道//bit[11:9]=PGA[2:0]=000 : FSR = ±6.144 V//bit[8]=MODE=1:单次模式或掉电状态break;case 1:ConfigBuff[0] =(0xD1&0xf1)|(PGA<<1) ;   //bit[15]=OS=1:开始单次转换0xD1[单次]//bit[14:12]=MUX[2:0]=101 : AINP = AIN1 and AINN = GND,采集A1通道//bit[11:9]=PGA[2:0]=000 : FSR = ±6.144 V//bit[8]=MODE=1:单次模式或掉电状态break;case 2:ConfigBuff[0] =(0xE1&0xf1)|(PGA<<1);    //bit[15]=OS=1:开始单次转换0xE1[单次]//bit[14:12]=MUX[2:0]=110 : AINP = AIN2 and AINN = GND,采集A2通道//bit[11:9]=PGA[2:0]=000 : FSR = ±6.144 V//bit[8]=MODE=1:单次模式或掉电状态break;case 3:ConfigBuff[0] =(0xF1&0xf1)|(PGA<<1);    //bit[15]=OS=1:开始单次转换0xF1[单次]//bit[14:12]=MUX[2:0]=111 : AINP = AIN3 and AINN = GND,采集A3通道//bit[11:9]=PGA[2:0]=000 : FSR = ±6.144 V//bit[8]=MODE=1:单次模式或掉电状态break;        }ConfigBuff[1] = 0xE3;     //bit[7:5]=DR[2:0]=111:860 SPS//bit[1:0]=COMP_QUE[1:0]=11:不使能比较器HAL_I2C_Mem_Write(&hi2c5,ADS1115_DEV_ADDR,ADS1115_Config,1,ConfigBuff,2,1000);//调用HAL库IIC写函数,按上面的参数,配置01H寄存器HAL_Delay(2);// 延时一定时间  HAL_I2C_Mem_Read(&hi2c5,ADS1115_DEV_ADDR,ADS1115_Conversion,1,BYTE_BUF,2,1000);//调用HAL库IIC读函数读取,00H寄存器的AD转换值,放入BYTE_BUFtempData = (int16_t)(BYTE_BUF[0] << 8) + (int16_t)BYTE_BUF[1];//FSR ±6.144 V,LSB 187.5 μV//FSR ±4.096 V,LSB 125 μV//FSR ±2.048 V,LSB 62.5 μV//FSR ±1.024 V,LSB 31.25 μV//FSR ±0.512 V,LSB 15.625 μV//FSR ±0.256 V,LSB 7.8125 μVswitch (PGA)//根据量程,采样值*LSB就是采集到的电压值{case 5:voltage = tempData * 0.0000078125;//单位Vbreak;case 4:voltage = tempData * 0.000015625;//单位Vbreak;case 3:voltage = tempData * 0.00003125;//单位Vbreak;case 2:voltage = tempData * 0.0000625;//单位Vbreak;case 1:voltage = tempData * 0.000125;//单位Vbreak;case 0:voltage = tempData * 0.0001875;//单位Vbreak;default:voltage = 0;break;}return voltage;}
/*********************************************************************************
描述:计算平均数
输入:channel:需要采集的通道号,ADS1115是4通道,所以是0~3,分别代表A0~A3通道
返回:浮点数,求平均后的电压,单位V
**********************************************************************************/
float ADS1115_Read_average_ADC(uint8_t channel)
{float sum[10],average;for(int i=0;i<10;i++){sum[i]=ADS1115_Read_ADC(channel);}average=(sum[3]+sum[4]+sum[5]+sum[6]+sum[7]+sum[8])/6;return average;
}

pcf8591驱动文件

在这里插入图片描述

说明:

该模块集成adc和dac转换功能,使用iic进行通信
vcc,gnd 供电
scl,sda iic通信
aout,输出dac电压
ain0~ain3,adc采集输入(跳线帽可接到对应adc采集通道)
调用:

	uint8_t Lival[4]={0};IICWriteOneByte(PCF8591Add,MODE0|CHNL1);   // Using channel 1HAL_Delay(350);Lival[0] = IICReadOneByte(PCF8591Add|0x01); //光敏信号The analog value of channel 0 is read and converted to a digital valueIICWriteOneByte(PCF8591Add,MODE0|CHNL2);   // Using channel 2HAL_Delay(350);Lival[1] = IICReadOneByte(PCF8591Add|0x01); //热敏信号The analog value of channel 1 is read and converted to a digital valueIICWriteOneByte(PCF8591Add,MODE0|CHNL3);   // Using channel 3HAL_Delay(350);Lival[2] = IICReadOneByte(PCF8591Add|0x01); //外部adc采集信号The analog value of channel 2 is read and converted to a digital valueIICWriteOneByte(PCF8591Add,MODE0|CHNL0);   // Using channel 0HAL_Delay(350);Lival[3] = IICReadOneByte(PCF8591Add|0x01); //滑动变阻器信号&dac输出信号 The analog value of channel 3 is read and converted to a digital valueIICWriteTwoByte(PCF8591Add,DAouputEn,Lival[3]);  //Converts the converted digital value to an analog valueHAL_Delay(100);printf("光敏信号channel0:%f \n 热敏信号channel1:%f \n 外部adc采集信号channel2:%d \n 滑动变阻器信号channel3:%f \n dac输出信号channel4:%f v\n",100.0-(float)Lival[0]*0.39,100.0-(float)Lival[1]*0.39,Lival[2],(float)Lival[3]*0.39,(float)Lival[3]*0.01294);

.h文件

//控制寄存器的模式
#define MODE0 	0x00	//Channel0 = AIN0; 全部开启//Channel1 = AIN1;//Channel2 = AIN2;//Channel3 = AIN3;
#define MODE1 	0x10	//Channel0 = AIN3-AIN0;开启0 1 2通道//Channel1 = AIN3-AIN1//Channel2 = AIN3-AIN2;
#define MODE2 	0x20	//Channel0 = AIN0;开启 0 1 3通道//Channel1 = AIN1;//Channel2 = AIN3-AIN2;//3 2通道合并
#define MODE3 	0x30	//Channel0 = AIN1-AIN0;开启 0 1通道//Channel1 = AIN3-AIN2;合并1 0 ,3 2为两个通道#define CHNL0 	0		//Using Channel0
#define CHNL1 	1		//Using Channel1
#define CHNL2 	2		//Using Channel2
#define CHNL3 	3		//Using Channel3/*
当使用dac是控制寄存器需配置为0x40 才不影响其他通道
b{ 0‘111’(控制模式) 00‘11’(通道)}
*/
#define DAouputEn 0x40//0x50 or 0x60 or 0x70 is also ok!#define PCF8591Add 0x90 //为默认写时设备地址0x90,当进行读取时设备地址为0x91uint8_t IICReadOneByte(uint8_t DevAddress);
void IICWriteTwoByte(uint8_t DevAddress,uint8_t control,uint8_t D_value);
void IICWriteOneByte(uint8_t DevAddress,uint8_t control);

.c文件


void IICWriteOneByte(uint8_t DevAddress,uint8_t control) 
{HAL_I2C_Master_Transmit(&hi2c4,DevAddress, &control,1,1000);
}void IICWriteTwoByte(uint8_t DevAddress,uint8_t control,uint8_t D_value) //WriteTwoByte
{uint8_t data[2]={0};data[0] = control;data[1] = D_value;HAL_I2C_Master_Transmit(&hi2c4,DevAddress,data,2,100);
}  
uint8_t IICReadOneByte(uint8_t DevAddress)
{uint8_t buf[1]={0};	HAL_I2C_Master_Receive(&hi2c4,DevAddress,buf,1,1000);return buf[0];
}

相关文章:

一、对iic类模块分析与使用

bmp280驱动代码 说明&#xff1a; 1、该模块用于获取气压&#xff0c;温度&#xff0c;海拔等数据。 vcc&#xff0c;gnd接电源 sda &#xff0c;scl 接iic通信引脚 2、该模块使用iic通信&#xff0c;通过iic发送请求相关类的寄存器值&#xff0c;芯片获取对应寄存器返回的数据…...

ROS 2机器人开发--CMakeLists.txt 文件详解

很多小白宝宝不懂CMakeLists.txt 究竟是干什么的&#xff0c;本文对CMakeLists.txt 文件进行详解 CMakeLists.txt 是 CMake 的核心文件&#xff0c;用户通过这个文件告诉 CMake 如何构建项目。这个文件通常包括设置项目名称、版本号、语言标准、编译器选项、查找依赖包、添加可…...

kan与小波,和不知所云的画图

文章目录 小波应用范围与pde小波的名字 画图图(a)&#xff1a;数值解向量 \( u \)图(b)&#xff1a;数值解向量 \( v \)结论图4 小波 在你提供的代码中&#xff0c;小波变换&#xff08;Wavelet Transform&#xff09;被用于 KANLinear 类中。具体来说&#xff0c;小波变换在 …...

使用DeepSeek实现自动化编程:类的自动生成

目录 简述 1. 通过注释生成C类 1.1 模糊生成 1.2 把控细节&#xff0c;让结果更精准 1.3 让DeepSeek自动生成代码 2. 验证DeepSeek自动生成的代码 2.1 安装SQLite命令行工具 2.2 验证DeepSeek代码 3. 测试代码下载 简述 在现代软件开发中&#xff0c;自动化编程工具如…...

算法题:快速排序

一、快速排序 1、快速排序总结 快速排序是一种高效的排序算法&#xff0c;基于分治法的思想。 分区操作是快速排序的核心&#xff0c;将数组分为两部分。 原地分区可以减少空间复杂度&#xff0c;提高效率。 快速排序的平均时间复杂度为 O(n log n)&#xff0c;但在最坏情况…...

Python的那些事第三十六篇:基于 Vega 和 Vega-Lite 的数据可视化解决方案,Altair 声明式可视化库

Altair 声明式可视化库:基于 Vega 和 Vega-Lite 的数据可视化解决方案 摘要 在数据科学和分析领域,有效的数据可视化是理解数据、发现模式和传达见解的关键。Python 作为数据科学的主要编程语言之一,提供了多种数据可视化库。其中,Altair 是一个基于 Vega 和 Vega-Lite 的…...

aws(学习笔记第三十课) 练习使用transit gateway

aws(学习笔记第三十课) 使用transit gateway 学习内容&#xff1a; 什么是transit gateway构造两个vpc&#xff0c;并且使用session manager访问private subnet的ec2练习使用transit gateway 1. 什么是transit gateway Transit Gateway的概念 Transit Gateway就是VPC和OnPro…...

Phpstudy中的MySQL无法正常启动或启动后自动暂停,以及sqlilab环境搭建出现的问题解决方法

【解决方法】 无法启动的原因是Phpstudy中的MySQL与本地的mysql重名&#xff0c;导致无法正常启动&#xff1b;所以这时我们就需要将本地的MySQL进行修改名称&#xff1b; 或者修改phpstudy中数据库的端口号&#xff0c;但是我觉得还是不是很好解决这种问题 最后一个方法&#…...

【Android】安卓付款密码输入框、支付密码输入框

如图 代码部分&#xff1a; public class PayPasswordDialog extends AppCompatDialogFragment {private String mPayPass "";private String mTitle, mMoney;private final TextView[] mPayPassTextViewArray new TextView[6];private List<Integer> mPayP…...

Python异常处理:从入门到精通的实用指南

Langchain系列文章目录 01-玩转LangChain&#xff1a;从模型调用到Prompt模板与输出解析的完整指南 02-玩转 LangChain Memory 模块&#xff1a;四种记忆类型详解及应用场景全覆盖 03-全面掌握 LangChain&#xff1a;从核心链条构建到动态任务分配的实战指南 04-玩转 LangChai…...

【AVL树】—— 我与C++的不解之缘(二十三)

什么是AVL树&#xff1f; AVL树发明者是G. M. Adelson-Velsky和E. M. Landis两个前苏联科学家&#xff0c;他们在1962年论文《An algorithm for the organization of information》中发表了AVL树。AVL树是最先发明的自平衡二叉搜索树&#xff0c;说白了就是能够自己控制平衡结构…...

用大白话解释日志处理Log4j 是什么 有什么用 怎么用

Log4j是什么&#xff1f; Log4j就像程序的“黑匣子”&#xff0c;专门用来记录软件运行时的各种信息&#xff0c;比如哪里报错、性能如何、用户操作轨迹等。它是Java领域最常用的日志框架之一&#xff0c;可以灵活控制日志内容、输出位置&#xff08;控制台、文件、数据库等&a…...

无人机遥控器的亮度 和 两个工作频率

工作频率 2.4000-2.4835 GHz &#xff0c; 5.725-5.850 GHz 1.这是一个无人机的遥控器的两个工作频率&#xff0c;为什么会有两个工作频率&#xff1f; 无人机的遥控器采用双频段设计&#xff08;2.4GHz 和 5.8GHz&#xff09;&#xff0c;主要是为了解决以下问题并优化性…...

【Linux】命令行参数 | 环境变量(四)

目录 前言&#xff1a; 一、命令行参数&#xff1a; 1.main函数参数 2.为什么有它&#xff1f; 二、环境变量&#xff1a; 1.main函数第三个参数 2.查看shell本身环境变量 3.PATH环境变量 4.修改PATH环境变量配置文件 5.HOME环境变量 6.SHELL环境变量 7.PWD环境变…...

算法002——复写零

力扣——复写零点击即可跳转 这道题还是运用 双指针&#xff0c;我们从左往右开始&#xff0c;让 cur 0&#xff0c;dest 0,当我们循环时&#xff0c;会覆盖后面的值&#xff0c;所以从左到右无法实现&#xff0c;我们运用 从右到左的方式。 以示例一数组为例&#xff0c;从…...

例子 DQN + CartPole: 深入思考一下,强化学习确实是一场智能冒险之旅!

强化学习的概念 在技术人员眼里&#xff0c;深度学习、强化学习&#xff0c;或者是大模型&#xff0c;都只是一些算法。无论是简单&#xff0c;还是复杂&#xff0c;我们都是平静的看待。当商业元素日益渗透进技术领域&#xff0c;人人言必称大模型的时候。技术人该反思一下&a…...

java 实现xxl-job定时任务自动注册到调度中心

xxl-job 自动注册(执行器和任务) 前言 xxl-job是一个功能强大、简单易用、高可用且可扩展性强的分布式定时任务框架/分布式任务调度平台。它适用于各种需要定时任务调度的场景,并可根据业务需求进行灵活配置和扩展。 xxl-job简介 xxl-job是一个开源的分布式定时任务框架,…...

esp32串口通信

1、线路图 2、打开电脑的串口终端 3、eps32通过串口往电脑的串口终端输出信息&#xff1a; from machine import UART, Pin import time# 初始化UART0&#xff0c;波特率设置为115200 uart UART(0, baudrate115200, tx1, rx3)# 主循环 while True:# 要发送的消息#某些串口终…...

蓝桥杯备赛-前缀和-可获得的最小取值

问题描述 妮妮学姐手头有一个长度为 nn 的数组 aa&#xff0c;她想进行 kk 次操作来取出数组中的元素。每次操作必须选择以下两种操作之一&#xff1a; 取出数组中的最大元素。取出数组中的最小元素和次小元素。 妮妮学姐希望在进行完 kk 次操作后&#xff0c;取出的数的和最…...

UniApp 中封装 HTTP 请求与 Token 管理(附Demo)

目录 1. 基本知识2. Demo3. 拓展 1. 基本知识 从实战代码中学习&#xff0c;上述实战代码来源&#xff1a;芋道源码/yudao-mall-uniapp 该代码中&#xff0c;通过自定义 request 函数对 HTTP 请求进行了统一管理&#xff0c;并且结合了 Token 认证机制 请求封装原理&#xff…...

7.4.分块查找

一.分块查找的算法思想&#xff1a; 1.实例&#xff1a; 以上述图片的顺序表为例&#xff0c; 该顺序表的数据元素从整体来看是乱序的&#xff0c;但如果把这些数据元素分成一块一块的小区间&#xff0c; 第一个区间[0,1]索引上的数据元素都是小于等于10的&#xff0c; 第二…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解

【关注我&#xff0c;后续持续新增专题博文&#xff0c;谢谢&#xff01;&#xff01;&#xff01;】 上一篇我们讲了&#xff1a; 这一篇我们开始讲&#xff1a; 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下&#xff1a; 一、场景操作步骤 操作步…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时&#xff0c;可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案&#xff1a; 1. 检查电源供电问题 问题原因&#xff1a;多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

MVC 数据库

MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面

代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口&#xff08;适配服务端返回 Token&#xff09; export const login async (code, avatar) > {const res await http…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序

一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...

Git常用命令完全指南:从入门到精通

Git常用命令完全指南&#xff1a;从入门到精通 一、基础配置命令 1. 用户信息配置 # 设置全局用户名 git config --global user.name "你的名字"# 设置全局邮箱 git config --global user.email "你的邮箱example.com"# 查看所有配置 git config --list…...

C语言中提供的第三方库之哈希表实现

一. 简介 前面一篇文章简单学习了C语言中第三方库&#xff08;uthash库&#xff09;提供对哈希表的操作&#xff0c;文章如下&#xff1a; C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...

水泥厂自动化升级利器:Devicenet转Modbus rtu协议转换网关

在水泥厂的生产流程中&#xff0c;工业自动化网关起着至关重要的作用&#xff0c;尤其是JH-DVN-RTU疆鸿智能Devicenet转Modbus rtu协议转换网关&#xff0c;为水泥厂实现高效生产与精准控制提供了有力支持。 水泥厂设备众多&#xff0c;其中不少设备采用Devicenet协议。Devicen…...