基于STM32、HAL库的MCP3421A0T模数转换器ADC驱动程序设计
一、简介:
MCP3421A0T是Microchip公司生产的一款18位Δ-Σ模数转换器(ADC),具有以下特点:
-
18位分辨率
-
单通道差分输入
-
可编程增益放大器(PGA):×1, ×2, ×4, ×8
-
可选的转换速率(3.75/15/60/240SPS)
-
内部基准电压(2.048V ±0.05%)
-
I²C接口(最大400kHz)
-
低功耗(连续转换模式下仅145μA)
-
工作电压范围:2.7V-5.5V
二、硬件接口:
MCP3421A0T STM32L4xx ---------------------------- VDD ---> 3.3V VSS ---> GND SCL ---> PB6/I2C1_SCL SDA ---> PB7/I2C1_SDA ADDR ---> GND (地址0x68)
三、头文件:
#ifndef MCP3421_H
#define MCP3421_H
#include "stm32l4xx_hal.h"
#define MCP3421_ADDR 0x68 // 默认地址(ADDR接地)
// 增益设置
typedef enum {
MCP3421_GAIN_X1 = 0x00,
MCP3421_GAIN_X2 = 0x01,
MCP3421_GAIN_X4 = 0x02,
MCP3421_GAIN_X8 = 0x03
} MCP3421_Gain;
// 采样率设置
typedef enum {
MCP3421_SPS_240 = 0x00,
MCP3421_SPS_60 = 0x01,
MCP3421_SPS_15 = 0x02,
MCP3421_SPS_3_75 = 0x03
} MCP3421_SampleRate;
// 转换模式
typedef enum {
MCP3421_MODE_ONESHOT = 0x00,
MCP3421_MODE_CONTINUOUS = 0x10
} MCP3421_ConversionMode;
// 初始化状态
typedef enum {
MCP3421_OK = 0x00,
MCP3421_ERROR = 0x01
} MCP3421_Status;
typedef struct {
I2C_HandleTypeDef *hi2c;
uint8_t address;
MCP3421_Gain gain;
MCP3421_SampleRate sample_rate;
MCP3421_ConversionMode mode;
} MCP3421_HandleTypeDef;
// 函数声明
MCP3421_Status MCP3421_Init(MCP3421_HandleTypeDef *hdev, I2C_HandleTypeDef *hi2c, uint8_t address);
MCP3421_Status MCP3421_StartConversion(MCP3421_HandleTypeDef *hdev);
MCP3421_Status MCP3421_ReadData(MCP3421_HandleTypeDef *hdev, int32_t *result);
MCP3421_Status MCP3421_SetConfig(MCP3421_HandleTypeDef *hdev, MCP3421_Gain gain,
MCP3421_SampleRate rate, MCP3421_ConversionMode mode);
#endif // MCP3421_H
四、源文件:
#include "mcp3421.h"
#include <string.h>
/**
* @brief 初始化MCP3421
* @param hdev: MCP3421句柄
* @param hi2c: I2C句柄
* @param address: 设备地址
* @retval 初始化状态
*/
MCP3421_Status MCP3421_Init(MCP3421_HandleTypeDef *hdev, I2C_HandleTypeDef *hi2c, uint8_t address)
{
if(hi2c == NULL)
return MCP3421_ERROR;
hdev->hi2c = hi2c;
hdev->address = address << 1; // HAL库需要左移一位
// 默认配置: 18位, 连续转换, PGA=1
hdev->gain = MCP3421_GAIN_X1;
hdev->sample_rate = MCP3421_SPS_3_75;
hdev->mode = MCP3421_MODE_CONTINUOUS;
// 发送配置命令
uint8_t config = 0x80; // RDY=1(启动转换), 18位
config |= hdev->mode;
config |= (hdev->gain << 1);
config |= (hdev->sample_rate << 2);
if(HAL_I2C_Master_Transmit(hdev->hi2c, hdev->address, &config, 1, HAL_MAX_DELAY) != HAL_OK)
return MCP3421_ERROR;
return MCP3421_OK;
}
/**
* @brief 启动转换
* @param hdev: MCP3421句柄
* @retval 操作状态
*/
MCP3421_Status MCP3421_StartConversion(MCP3421_HandleTypeDef *hdev)
{
uint8_t config = 0x80; // RDY=1(启动转换), 18位
config |= hdev->mode;
config |= (hdev->gain << 1);
config |= (hdev->sample_rate << 2);
if(HAL_I2C_Master_Transmit(hdev->hi2c, hdev->address, &config, 1, HAL_MAX_DELAY) != HAL_OK)
return MCP3421_ERROR;
return MCP3421_OK;
}
/**
* @brief 读取转换结果
* @param hdev: MCP3421句柄
* @param result: 存储转换结果的指针
* @retval 操作状态
*/
MCP3421_Status MCP3421_ReadData(MCP3421_HandleTypeDef *hdev, int32_t *result)
{
uint8_t data[4] = {0};
// 读取3字节数据(18位模式)
if(HAL_I2C_Master_Receive(hdev->hi2c, hdev->address, data, 3, HAL_MAX_DELAY) != HAL_OK)
return MCP3421_ERROR;
// 检查转换是否完成(第3字节的第7位)
if((data[2] & 0x80) == 0x80)
return MCP3421_ERROR; // 转换未完成
// 组合18位数据
*result = ((int32_t)data[0] << 16) | ((int32_t)data[1] << 8) | data[2];
// 符号扩展
if(*result & 0x20000) // 检查符号位(18位数据的第17位)
*result |= 0xFFFC0000; // 符号扩展到32位
return MCP3421_OK;
}
/**
* @brief 设置MCP3421配置
* @param hdev: MCP3421句柄
* @param gain: 增益设置
* @param rate: 采样率设置
* @param mode: 转换模式
* @retval 操作状态
*/
MCP3421_Status MCP3421_SetConfig(MCP3421_HandleTypeDef *hdev, MCP3421_Gain gain,
MCP3421_SampleRate rate, MCP3421_ConversionMode mode)
{
hdev->gain = gain;
hdev->sample_rate = rate;
hdev->mode = mode;
uint8_t config = 0x80; // RDY=1(启动转换), 18位
config |= hdev->mode;
config |= (hdev->gain << 1);
config |= (hdev->sample_rate << 2);
if(HAL_I2C_Master_Transmit(hdev->hi2c, hdev->address, &config, 1, HAL_MAX_DELAY) != HAL_OK)
return MCP3421_ERROR;
return MCP3421_OK;
}
五、应用:
#include "main.h"
#include "i2c.h"
#include "mcp3421.h"
MCP3421_HandleTypeDef hmcp3421;
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_I2C1_Init();
// 初始化MCP3421
if(MCP3421_Init(&hmcp3421, &hi2c1, MCP3421_ADDR) != MCP3421_OK)
{
Error_Handler();
}
// 设置配置: 增益×8, 15SPS, 连续转换
MCP3421_SetConfig(&hmcp3421, MCP3421_GAIN_X8, MCP3421_SPS_15, MCP3421_MODE_CONTINUOUS);
while(1)
{
int32_t adc_value;
float voltage;
// 读取ADC值
if(MCP3421_ReadData(&hmcp3421, &adc_value) == MCP3421_OK)
{
// 计算实际电压值
// 18位模式下,LSB = 2.048V / (2^17) = 15.625μV
// 增益×8时,LSB = 15.625μV / 8 = 1.953125μV
voltage = (float)adc_value * 1.953125f / 1000000.0f;
printf("ADC Value: %ld, Voltage: %.6f V\r\n", adc_value, voltage);
}
else
{
printf("Error reading ADC value\r\n");
}
HAL_Delay(1000);
}
}
#include "i2c.h"
I2C_HandleTypeDef hi2c1;
void MX_I2C1_Init(void)
{
hi2c1.Instance = I2C1;
hi2c1.Init.Timing = 0x00707CBB; // 100kHz
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
{
Error_Handler();
}
/** Configure Analogue filter */
if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
{
Error_Handler();
}
/** Configure Digital filter */
if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK)
{
Error_Handler();
}
}
void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(i2cHandle->Instance==I2C1)
{
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_I2C1_CLK_ENABLE();
/**I2C1 GPIO Configuration
PB6 ------> I2C1_SCL
PB7 ------> I2C1_SDA
*/
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
}