杰发科技AC7801——ADC简单理解

news2024/10/7 4:31:21

前言

7801资料读起来不是很好理解,大概率是之前MTK的大佬写的。在此以简单的方式进行描述。我们做一个简单的规则组软件触发Demo。因为规则组通道只有一个数据寄存器,因此还需要用上DMA方式搬运数据到内存

AC7801的ADC简介

7801的ADC是一种 12 逐次逼近型 模拟数字转换器,拥有 12 路外部通道和 2 路内部通道,支持单次、连续、扫描或间断转换多种模式。模拟监控器特性允许应用程序监测输入电压是否超出设定的电压范围。

特性

12 位分辨率
通道输入电压范围: AVSS < Vin < AVDD
最大转换速率: 1Msps
14 路通道: 12 路外部通道, 1 路内部温度传感器( T-Sensor ), 1 路内部带隙基准(Bandgap ),每路通道可单独配置采样时间
转换序列分为 规则组( regular group )和注入组( injection group
        − 规则组:最多可配置 12 个通道
        − 注入组:最多可配置 4 个通道
8 种操作模式 ( 方便起见,称为 mode x x=1~8)
        − 规则组单通道单次转换 (mode1)
        − 规则组单通道连续转换 (mode2)
        − 规则组扫描 + 注入组扫描模式多通道单次转换 (mode3 注入组扫描模式 )
        − 规则组扫描 + 注入组间隔模式多通道单次转换 (mode3 注入组间隔模式 )
        − 规则组扫描 + 自动触发注入组扫描模式多通道单次转换 (mode4)
        − 规则组扫描 + 注入组扫描模式多通道连续转换 (mode5 注入组扫描模式 )
        − 规则组扫描+注入组间隔模式多通道连续转换(mode5 注入组间隔模式 )
        − 规则组扫描 + 自动触发注入组扫描模式多通道连续转换 (mode6)
        − 规则组子组扫描模式转换 (mode7)
        − 注入组子组扫描模式转换 (mode8)
通过内部软件触发或外部硬件触发启动 ADC
模拟监控器功能:
        − 配置为单个或所有通道电压检查
        − 监控通道电压是否低于低阈值或高于高阈值
中断:
        − 规则或注入组转换结束 (EOC End Of Conversion)
        − 注入组转换结束 (IEOC)
        − 模拟监控器事件 (AMO)
DMA 访问,仅用于规则组通道

典型操作流程

ADC 首先上电,然后可以通过内部 SWSTART 或外部触发源触发 ADC ,该触发来源于其它模块。触发后ADC 转换器单元开始工作,并将选择信号发送至输入通道选择器,根据规则或注入组通道序列逐个选择所需的通道。在一个通道完成转换后,转换结果将根据当前转换通道所属的组存储到 RDR 或 IDRx 中,并且产生相应的 EOC IEOC 标志置位。模拟监控器工作时,如果发生相应的事件则会出现相关的状态标志。

使用DMA

由于规则组通道只有一个数据寄存器,因此建议使用 DMA 功能 ,以避免在有多个规则组通道进行转换时,丢失转换结果。DMA 功能专用于规则组通道。只有规则组通道转换结束标志才会产生 DMA 请求。只有产生了 DMA 请求, DMA 才会将转换数据从ADC_RDR 搬运到用户指定的目标位置。

ADC流程

经典的初始化,DMA初始化。

ADC的初始化,185/186两行注释看的一脸懵逼

ADC的回调

DMA的回调

业务代码

旋转电位器查看打印值

由单个ADC改成多个ADC

AC7801的ADC写的注释相对比较完整,但是没说明软件触发从1个怎么改到多个。

使用时候需要注意下图中红框部分有些DISABLE和ABLE的参数,错了大概率就不可能正常采样。黄框部分就是从1个ADC改成3个需要修改的地方。

读取时候,只需要触发一次ADC0即可

具体代码如下:

#include "adc_sample.h"

#define Delay5us                      (APB_BUS_FREQ/200000-1)
#define Delay5ms                      (APB_BUS_FREQ/200-1)
#define Delay1s                       (APB_BUS_FREQ-1)

uint8_t g_dmaFinish = 0;     // DMA传输完成
uint8_t g_halfDmaFinish = 0; // DMA传输半完成
uint8_t g_dmaTransError = 0; // DMA传输错误
uint32_t g_ADCValueBuffer[DMA_TRANSFER_NUM + 1] = {0};
uint32_t g_timerCnt = 0;
uint16_t g_regularAverageSampleValue = 0; // 规则组采样平均值
uint16_t g_injectAverageSampleValue = 0;  // 注入组采样平均值
uint16_t g_adcInjectValue[4];
uint8_t g_AMOFlag = 0; // 模拟看门狗事件标志
/*
注意:EOC标志写0或读取ADC_RDR都会清除该标志位。
在进行debug时,如果有打开memory窗口或打开ADC寄存器。
该标志会被debug清除。
*/
uint8_t g_EOCFlag = 0;  // 规则组转换结束标志。
uint8_t g_IEOCFlag = 0; // 注入组转换结束标志。

void ADC_Callback(void *device, uint32_t wpara, uint32_t lpara)
{
    if (wpara & ADC_STR_EOC_Msk) // 规则组中断标志
    {
        g_EOCFlag = 1;
    }
    if (wpara & ADC_STR_AMO_Msk) // 模拟监控中断标志
    {
        g_AMOFlag = 1;
    }
}

void ADC_DMACallback(void *device, uint32_t wpara, uint32_t lpara)
{
    /*
     wparam为DMA通道状态,状态含义可参考CHANNELx_STATUS寄存器,
     CHANNELx_STATUS[2] 传输错误
     CHANNELx_STATUS[1] 半传输完成(相对设置的transferNum,如果半传输中断有使能,transferNum设为6,则DATA_TRANS_NUM为3时产生中断,进入回调)
     CHANNELx_STATUS[0] 传输完成
    */
    if ((wpara & 0x01) == 0x1)
    {
        g_dmaFinish = 1;
    }
    if ((wpara & 0x02) == 0x2)
    {
        g_halfDmaFinish = 1;
    }
    if ((wpara & 0x04) == 0x4)
    {
        g_dmaTransError = 1;
    }
}

void ADC_DMAInit(void)
{
    uint32_t tmpMemStartAddr = (uint32_t)&g_ADCValueBuffer[0];
    uint32_t tmpMemEndAddr = (uint32_t)&g_ADCValueBuffer[DMA_TRANSFER_NUM + 1]; ///< Setting memory DMA address
    DMA_ConfigType tmpDMAConfig;
    memset(&tmpDMAConfig, 0x00, sizeof(DMA_ConfigType));

    tmpDMAConfig.memStartAddr = tmpMemStartAddr;             // 设置DMA开始地址
    tmpDMAConfig.memEndAddr = tmpMemEndAddr;                 // 设置DMA结束地址
    tmpDMAConfig.periphStartAddr = (uint32_t)(&(ADC0->RDR)); ///< Move ADC DR to memory
    tmpDMAConfig.channelEn = ENABLE;                         ///< 使能DMAx通道
    tmpDMAConfig.finishInterruptEn = ENABLE;                 ///< 使能DMA传输完成中断
    tmpDMAConfig.halfFinishInterruptEn = DISABLE;            ///< 去能DMA半传输完成中断
    tmpDMAConfig.errorInterruptEn = ENABLE;                  ///< 使能DMA传输错误中断
    tmpDMAConfig.channelPriority = DMA_PRIORITY_VERY_HIGH;   ///< 设置DMA通道优先级,0~3 :优先级由低到高
    tmpDMAConfig.circular = ENABLE;                          ///< 使能循环模式,如果只想工作一次,设为0即可。
    tmpDMAConfig.direction = DMA_READ_FROM_PERIPH;           ///< 0: 从外设读取,1:从存储器读取
    tmpDMAConfig.MEM2MEM = DISABLE;                          ///< 0:在非存储器与存储器之间传输,1:在存储器与存储器之间传输
    tmpDMAConfig.memByteMode = DMA_MEM_BYTE_MODE_1TIME;      ///< MEM字分割传输数,0:32-bit,1:16-bit[15:0]; 2:16-bit[23:16][7:0];3:8-bit。详情可参考AC781X芯片手册  表20-2 可编程数据宽度&数据对齐
    tmpDMAConfig.memIncrement = ENABLE;                      ///< 1:MEM地址增加
    tmpDMAConfig.periphIncrement = DISABLE;                  ///< 0:外设地址固定
    tmpDMAConfig.memSize = DMA_MEM_SIZE_32BIT;               ///< 0:8-bit,1:16-bit,2:32-bit
    tmpDMAConfig.periphSize = DMA_PERIPH_SIZE_16BIT;         ///< 0:8-bit,1:16-bit,2:32-bit
    tmpDMAConfig.transferNum = DMA_TRANSFER_NUM;             ///< DMA通道传输长度
    tmpDMAConfig.periphSelect = DMA_PEPIRH_ADC0;             // 外设选择
    tmpDMAConfig.callBack = ADC_DMACallback;                 ///< 设置DMA中断回调

    DMA_Init(DMA0_CHANNEL0, &tmpDMAConfig); ///< ADC 使用DMA1通道,每个模块对应的DMA通道,可参考 AC781X芯片手册 表20-1 DMA请求列表
    NVIC_EnableIRQ(DMA0_CHANNEL0_IRQn);     ///< 使能DMA1中断请求
}

void ADC_init()
{
    ADC_ConfigType tempAdcConfig;
    ADC_ConfigType *adcConfig;
    adcConfig = &tempAdcConfig;
    // 配置PINMUX
    GPIO_SetFunc(GPIOA, GPIO_PIN4, GPIO_FUN2);            ///< ADC_IN6 Analog function enable
    GPIO_SetFunc(GPIOA, GPIO_PIN3, GPIO_FUN2);            ///< ADC_IN7 Analog function enable
    GPIO_SetFunc(GPIOA, GPIO_PIN2, GPIO_FUN2);            ///< ADC_IN8 Analog function enable
    adcConfig->clkPsc = ADC_CLK_PRESCALER_1;              ///< Set ADC Clk = 24M/2/(0+1)
    adcConfig->scanModeEn = ENABLE;                       // 扫描模式
    adcConfig->continousModeEn = DISABLE;                 // 连续模式
    adcConfig->regularDiscontinousModeEn = DISABLE;       // 1:打开规则组间断转换模式
    adcConfig->injectDiscontinousModeEn = DISABLE;        // 1:打开注入组间断转换模式
    adcConfig->injectAutoModeEn = DISABLE;                // 1:自动注入模式
    adcConfig->intervalModeEn = DISABLE;                  // 1:注入组为间隔转换模式
    adcConfig->regularDiscontinousNum = 0;                //
    adcConfig->EOCInterruptEn = ENABLE;                   // EOC中断使能
    adcConfig->IEOCInterruptEn = ENABLE;                  // IEOC中断使能
    adcConfig->interruptEn = ENABLE;                      // 中断使能
    adcConfig->regularDMAEn = ENABLE;                     // 使能ADC DMA
    adcConfig->regularTriggerMode = ADC_TRIGGER_INTERNAL; // ADC触发源,内部触发
    adcConfig->regularSequenceLength = 3;                 // 规则组长度设为3
    adcConfig->dataAlign = ADC_DATA_ALIGN_RIGHT;          // 右对齐
    adcConfig->callBack = ADC_Callback;                   // 回调
    adcConfig->powerMode = ADC_POWER_ON;                  // 上电
    ADC_Init(ADC0, adcConfig);                            ///< ADC works Mode Config
    // ADC转换率计算公式: 转换时间= 采样时间+转换时间+同步时间  转换时间= (SPT+12)/ADC模块时钟频率+5/APB时钟频率
    // 备注:1.同步时间为5个APB CLK。2.ADC时钟频率 = APB时钟频率 /(分频系数+1)
    // 规则组通道设置
    ADC_SetRegularGroupChannel(ADC0, ADC_CH_7, ADC_SPT_CLK_7, 0); // 采样&转换时间= (7+12)/24000000 + 5/24000000 = 1us
    ADC_SetRegularGroupChannel(ADC0, ADC_CH_8, ADC_SPT_CLK_7, 1); // 采样&转换时间= (7+12)/24000000 + 5/24000000 = 1us
    ADC_SetRegularGroupChannel(ADC0, ADC_CH_6, ADC_SPT_CLK_7, 2); // 采样&转换时间= (7+12)/24000000 + 5/24000000 = 1us
}

void ADC_SampleSoftwareTrigerADC(void)
{
    ADC_init();
    ADC_DMAInit(); // ADC DMA初始化

    while (1)
    {
        // 每次转换数据清零
        memset(g_ADCValueBuffer, 0x00, sizeof(g_ADCValueBuffer));
        ADC_SoftwareStartRegularConvert(ADC0); /// 软件触发规则组采样

        udelay(8); // 需要采样8个通道,延时8us以保证数据采样完成
        printf("%d %d %d\r\n", g_ADCValueBuffer[0],g_ADCValueBuffer[1],g_ADCValueBuffer[2]);
        mdelay(100);
    }
}

转换率公式

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

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

相关文章

7-22 龟兔赛跑

import java.util.Scanner; class Main {public static void main(String[] args) {Scanner scnew Scanner(System.in);int timesc.nextInt();sc.close();int wugui 0;//乌龟里程int tuzi 0;//兔子里程int tuzi_run0;int tuzi_rest0;int is_rest0;//是否需要休息&#xff1a;…

Python大语言模型实战-记录一次用ChatDev框架实现爬虫任务的完整过程

1、模型选择&#xff1a;GPT4 2、需求&#xff1a;在win10操作系统环境下&#xff0c;基于python3.10解释器&#xff0c;爬取豆瓣电影Top250的相关信息&#xff0c;包括电影详情链接&#xff0c;图片链接&#xff0c;影片中文名&#xff0c;影片外国名&#xff0c;评分&#x…

游戏是第一生产力!Python实现生命游戏的示例代码(tkinter版)

文章目录 生命游戏(Game of Life)游戏概述生存定律图形结构 代码实现运行界面使用简介后续改进关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源码合集①Python工具包②Python实战案例③Python小游戏源码五…

【Linux】匿名管道+进程池

文章目录 前置知识一、管道的原理二、管道的特性三、管道的接口四、使用管道实现简单的进程池解决进程池的一个小问题 前置知识 一个进程在创建时&#xff0c;会默认打开三个文件&#xff0c;分别是&#xff1a;stdin&#xff0c;stdout&#xff0c;stderr 进程中有一个维护进…

社区物联网云服务架构设计

文章目录 1 摘要2 架构图2.1 社区物联网云服务网络拓扑图2.2 社区物联网云服务通讯流程图2.3 社区远程开锁功能流程图 3 应用场景 1 摘要 随着社区管理越来越智能化&#xff0c;社区物联网升级与改造的市场空间也越来越大。社区物联网包含楼宇对讲、门禁门锁、通道闸等等设备系…

浅谈国内智能制造现状和未来发展趋势

进人二十一世纪&#xff0c;互联网、新能源、大数据等技术的迅猛发展&#xff0c;从而使得社会发生巨大的改变&#xff0c;人类生产工业发生变革。为应对全球挑战&#xff0c;我国根据发展的实际情况&#xff0c;提出《中国制造2025》的国家战略规划。毋庸置疑的是&#xff0c;…

大数据题目的解题技巧

目录 大数据题目的技巧总括 实例精析 实例一 实例二 实例三 大数据题目的技巧总括 &#xff08;1&#xff09;哈希函数可以把数据按照种类均匀分流&#xff1b; &#xff08;2&#xff09;布隆过滤器用于集合的建立与查询&#xff0c;并可以节省大量空间&#xff1b; &…

Git永久或者限时保存用户名及密码,解决每次拉取或者提交代码时都需要手动输入验证信息

介绍 这里以我自身项目情况为例: 依据项目要求,这边使用了 TortoiseGit进行项目的统一管理,下载了 TortoiseGit克隆项目之后,每次拉取或者提交代码,都会弹出一个提示框,要求输入用户名及密码。 解决方式 单个仓库内设置,只作用于对当前仓库 在当前项目目录文件夹下,…

vue3之echarts渐变柱状图

vue3之echarts渐变柱状图 效果&#xff1a; 核心代码&#xff1a; <template><div class"abnormal"><div class"chart" ref"chartsRef"></div></div> </template><script setup> import * as echa…

【EI会议征稿】第三届电子信息技术国际学术会议(EIT 2024)

The 3rd International Conference on Electronic Information Technology 第三届电子信息技术国际学术会议&#xff08;EIT 2024&#xff09; 电子信息工程在我国信息化产业的发展过程中举足轻重&#xff0c;且随着现代社会的发展&#xff0c;航空航天领域、制造业领域和智能…

2024年度投资策略:AI大模型和半导体国产化加速

今天分享的是AI系列深度研究报告&#xff1a;《2024年度投资策略&#xff1a;AI大模型和半导体国产化加速》。 &#xff08;报告出品方&#xff1a;东方证券&#xff09; 报告共计&#xff1a;48页 前言: 行情回顾与未来展望 电子板块涨幅转正&#xff0c;信心逐渐回归。截至…

7000家门店的盈利增长,从导购的人效提升开始

管理是艺术&#xff0c;还是科学&#xff1f; 说管理是艺术&#xff0c;是因为管理面向的是人&#xff0c;而人是动态复杂的&#xff1b;说管理是科学&#xff0c;是因为我们可以研究动态的人背后的共性需求&#xff0c;并使管理的模型、策略、工具与之契合。 在绫致时装看来…

搭建Angular并引入NG-ZORRO组件库

作者&#xff1a;baekpcyyy&#x1f41f; 1.安装node.js 注&#xff1a;安装 16.0 或更高版本的 Node.js node官网&#xff1a;https://nodejs.org/en 2.进入angular官网 https://angular.cn/guide/setup-local 新建一个文件夹 vsc打开 打开终端 1.首先安装angular手脚架…

静电放电模型中的阻容参数

依据静电放电产生原因及其对集成电路放电方式的不同&#xff0c;静电放电模型可分成以下四类模型&#xff1a;1、人体放电模型(HBM, Human-Body Model)、2、机器放电模型(MM, Machine Model)、3、器件充电模型(CDM, Charged-Device Model)、4、电场感应模型(FIM, Field-Induced…

从设计上理解JDK动态代理

作者简介&#xff1a;大家好&#xff0c;我是smart哥&#xff0c;前中兴通讯、美团架构师&#xff0c;现某互联网公司CTO 联系qq&#xff1a;184480602&#xff0c;加我进群&#xff0c;大家一起学习&#xff0c;一起进步&#xff0c;一起对抗互联网寒冬 照理说&#xff0c;动态…

【Django-DRF】md笔记第6篇:Django-DRF的视图、认证、分页和其他功能详解

本文从分析现在流行的前后端分离Web应用模式说起&#xff0c;然后介绍如何设计REST API&#xff0c;通过使用Django来实现一个REST API为例&#xff0c;明确后端开发REST API要做的最核心工作&#xff0c;然后介绍Django REST framework能帮助我们简化开发REST API的工作。 DR…

win10 tensorrt源码编译onnx

直接利用官方源码&#xff0c;如下图&#xff0c;trtexec源码在TensorRT安装目录下&#xff0c;双击trtexec.sln文件&#xff0c;使用vs2019打开源码工程。 如下图&#xff0c;以yolov8为例子&#xff0c;编译成功项目之后&#xff0c;设置命令行参数&#xff1a; --onnxd:/yo…

表单邮箱密码登录 原生+Jquery实现

文章目录 效果代码邮箱验证正则表达式HTMLCSS JS 效果 正确密码为&#xff1a;123456 点击登录按钮校验。 代码 表单校验 - CodeSandbox 邮箱验证正则表达式 /(?:[a-z0-9!#$%&*/?^_{|}~-](?:\.[a-z0-9!#$%&*/?^_{|}~-])*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1…

实现HTTP服务监听,快来试试springboot服务端接口公网远程调试

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;网络奇遇记、Cpolar杂谈 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;前言一. 本地环境搭建1.1 环境参数1.2 搭建springboot服务项目 二. 内网穿透2.1 安装…

AND/选品机制算法/用户表设计

3大步骤总结 大步骤总结&#xff1a; 第一大步骤&#xff1a; 生成AND算法机制所需要的8个表 AND musics Works Pool Table(音乐作品池表) 需要创建表 所需归类 AND算法池 AND videos Works Pool Table(视频作品池表) 需要创建表 所需归类 AND算法池 AND image…