基于STM32、HAL库的MCP3421A0T模数转换器ADC驱动程序设计

news2025/7/15 22:33:07

一、简介:

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);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2343370.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

八大排序——冒泡排序/归并排序

八大排序——冒泡排序/归并排序 一、冒泡排序 1.1 冒泡排序 1.2 冒泡排序优化 二、归并排序 1.1 归并排序&#xff08;递归&#xff09; 1.2 递归排序&#xff08;非递归&#xff09; 一、冒泡排序 1.1 冒泡排序 比较相邻的元素。如果第一个比第二个大&#xff0c;就交换…

银发科技:AI健康小屋如何破解老龄化困局

随着全球人口老龄化程度的不断加深&#xff0c;如何保障老年人的健康、提升他们的生活质量&#xff0c;成为了社会各界关注的焦点。 在这场应对老龄化挑战的战役中&#xff0c;智绅科技顺势而生&#xff0c;七彩喜智慧养老系统构筑居家养老安全网。 而AI健康小屋作为一项创新…

命令行指引的尝试

效果 步骤 首先初始化一个空的项目&#xff0c;然后安装一些依赖 npm init -y npm install inquirer execa chalk ora至于这些依赖是干嘛的&#xff0c;如下图所示&#xff1a; 然后再 package.json 中补充一个 bin 然后再根目录下新建一个 index.js , 其中的内容如下 #!/…

【Dify系列教程重置精品版】第1课 相关概念介绍

文章目录 一、Dify是什么二、Dify有什么用三、如何玩转Dify?从螺丝刀到机甲战士的进阶指南官方网站:https://dify.ai github地址:https://github.com/langgenius/dify 一、Dify是什么 Dify(D​​efine + ​​I​​mplement + ​​F​​or ​​Y​​ou)。这是一款开源的大…

leetcode0106. 从中序与后序遍历序列构造二叉树-medium

1 题目&#xff1a;从中序与后序遍历序列构造二叉树 官方标定难度&#xff1a;中 给定两个整数数组 inorder 和 postorder &#xff0c;其中 inorder 是二叉树的中序遍历&#xff0c; postorder 是同一棵树的后序遍历&#xff0c;请你构造并返回这颗 二叉树 。 示例 1: 输入…

Spring Boot默认缓存管理

Spring框架支持透明地向应用程序添加缓存&#xff0c;以及对缓存进行管理&#xff0c;其管理缓存的核心是将缓存应用于操作数据的方法&#xff0c;从而减少操作数据的执行次数&#xff0c;同时不会对程序本身造成任何干扰。Spring Boot继承了Spring框架的缓存管理功能&#xff…

XYNU2024信安杯-REVERSE(复现)

前言 记录记录 1.Can_you_find_me? 签到题&#xff0c;秒了 2.ea_re 快速定位 int __cdecl main_0(int argc, const char **argv, const char **envp) {int v4; // [esp0h] [ebp-1A0h]const char **v5; // [esp4h] [ebp-19Ch]const char **v6; // [esp8h] [ebp-198h]char v7;…

MySQL的MVCC【学习笔记】

MVCC 事务的隔离级别分为四种&#xff0c;其中Read Committed和Repeatable Read隔离级别&#xff0c;部分实现就是通过MVCC&#xff08;Multi-Version Concurrency Control&#xff0c;多版本并发控制&#xff09; 版本链 版本链是通过undo日志实现的&#xff0c; 事务每次修改…

达梦数据库压力测试报错超出全局hash join空间,适当增加HJ_BUF_GLOBAL_SIZE解决

1.名词解释&#xff1a;达梦数据库中的HJ_BUF_GLOBAL_SIZE是所有哈希连接操作可用的最大哈希缓冲区大小&#xff0c;单位为兆字节&#xff08;MB&#xff09; 2.达梦压测报错&#xff1a; 3.找到达梦数据库安装文件 4.压力测试脚本 import http.client import multiprocessi…

Oracle--SQL性能优化与提升策略

前言&#xff1a;本博客仅作记录学习使用&#xff0c;部分图片出自网络&#xff0c;如有侵犯您的权益&#xff0c;请联系删除 一、导致性能问题的内在原因 系统性能问题的底层原因主要有三个方面&#xff1a; CPU占用率过高导致资源争用和等待内存使用率过高导致内存不足并需…

六个能够白嫖学习资料的网站

一、咖喱君的资源库 地址&#xff1a;https://flowus.cn/galijun/share/de0f6d2f-df17-4075-86ed-ebead0394a77 这是一个学习资料/学习网站分享平台&#xff0c;包含了英语、法语、德语、韩语、日语、泰语等几十种外国语言的学习资料及平台&#xff0c;这个网站的优势就是外语…

IntelliJ IDEA 中配置 Spring MVC 环境的详细步骤

以下是在 IntelliJ IDEA 中配置 Spring MVC 环境的详细步骤&#xff1a; 步骤 1&#xff1a;创建 Maven Web 项目 新建项目 File -> New -> Project → 选择 Maven → 勾选 Create from archetype → 选择 maven-archetype-webapp。输入 GroupId&#xff08;如 com.examp…

手机打电话时电脑坐席同时收听对方说话并插入IVR预录声音片段

手机打电话时电脑坐席同时收听对方说话并插入IVR预录声音片段 --本地AI电话机器人 前言 书接上一篇&#xff0c;《手机打电话通话时如何向对方播放录制的IVR引导词声音》中介绍了【蓝牙电话SDK示例App】可以实现手机app在电话通话过程中插播预先录制的开场白等语音片段的功能。…

SpringCloud——负载均衡

一.负载均衡 1.问题提出 上一篇文章写了服务注册和服务发现的相关内容。这里再提出一个新问题&#xff0c;如果我给一个服务开了多个端口&#xff0c;这几个端口都可以访问服务。 例如&#xff0c;在上一篇文章的基础上&#xff0c;我又新开了9091和9092端口&#xff0c;现在…

string的基本使用

string的模拟实现 string的基本用法string的遍历&#xff08;三种方式&#xff09;&#xff1a;关于auto&#xff08;自动推导&#xff09;:范围for: 迭代器普通迭代器(可读可改&#xff09;const迭代器&#xff08;可读不可改&#xff09; string细小知识点string的常见接口引…

深入解析Mlivus Cloud核心架构:rootcoord组件的最佳实践与调优指南

作为大禹智库的向量数据库高级研究员,同时也是《向量数据库指南》的作者,我在过去30年的向量数据库和AI应用实战中见证了这项技术的演进与革新。今天,我将以专业视角为您深入剖析Mlivus Cloud的核心组件之一——rootcoord,这个组件在系统架构中扮演着至关重要的角色。如果您…

Python常用的第三方模块之【pymysql库】操作数据库

pymysql是在Python3.x版本中用于连接MySQL服务器的一个实现库&#xff0c;Python2中则是使用musqldb。 PyMySQL 是一个纯 Python 实现的 MySQL 客户端库&#xff0c;它允许我们直接在 Python 中执行 SQL 语句并与 MySQL 数据库进行交互。下面我们将详细介绍如何使用 PyMySQL 进…

【Python数据分析】Pandas模块之pd.concat 函数

💭 写在前面:合并多个数据框,收集各种数据,并将其合并为一个数据框进行分析。本章我们介绍 Pandas 库中数据框合并的函数 —— concat。 0x00 引入:数据框的合并操作 合并多个数据框:收集各种数据,并将其合并为一个数据框进行分析。 下面介绍一些常用的 Pandas 库中数…

C# 综合示例 库存管理系统7 主界面(FormMain)

版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的 图99A-22 主界面窗口设计 主界面是多文档界面容器,需要将窗体属性IsMdiContainer设置为True。关于多文档界面编程请参看教程第7.12节《多文档界面》。 主界面并不提…

系统思考:看清问题背后的结构

组织的挑战&#xff0c;往往不是因为不努力&#xff0c;而是“看不清” 结束了为期两天系统思考课程的第一天&#xff0c;被学员的全情投入深深打动。我们用系统结构图&#xff0c;一步步揭示那些表面看起来“习以为常”的问题&#xff1a; 什么原因跨部门协作总是磕磕绊绊&am…