首页 > 其他分享 >[单片机框架][bsp层][AT32F415][bsp_adc] adc配置和使用

[单片机框架][bsp层][AT32F415][bsp_adc] adc配置和使用

时间:2022-10-31 18:03:10浏览次数:46  
标签:ch AT32F415 adc0 ADC1 bsp adc ADC0 BS ADC


12.1 ADC介绍

12 位 ADC 是一种逐次逼近型模拟数字转换器。它有多达 18 个通道,可测量 16 个外部和 2 个内部信号源。各通道的 A/D 转换可以单次、连续、扫描或间断模式执行。ADC 的结果可以左对齐或右对齐方式存储在 16 位数据寄存器中。
模拟看门狗特性允许应用程序检测输入电压是否超出用户定义的高/低阀值。
ADC 的输入时钟不得超过 28 MHz,它是由 PCLK2 经分频产生,参见图 3-2。

12.2 ADC主要特征

  • 12位分辨率
  • 转换结束、注入转换结束和发生模拟看门狗事件时产生中断
  • 单次和连续转换模式
  • 从通道0到通道n的自动扫描模式
  • 自校準時間: 156個ADC時鐘週期
  • 带内嵌数据一致性的数据对齐
  • 采样间隔可以按通道分别编程
  • 规则转换和注入转换均有外部触发选项
  • 间断模式
  • ADC转换时间 – 时钟为28MHz时为0.5 μs
  • ADC供电要求:2.6V到3.6V
  • ADC输入范围:VSSA ≤ VIN ≤ VDDA
  • 规则通道转换期间有DMA请求产生

[单片机框架][bsp层][AT32F415][bsp_adc] adc配置和使用_#endif

名称

信号类型

注解

VDDA

输入,模拟电源

等效于 VDD的模拟电源且:2.6V ≤ VDDA ≤ VDD(3.6V)

VSSA

输入,模拟电源地

等效于 VSS的模拟电源地

ADCx_IN[9:0]

模拟输入信号

18 个模拟输入通道

注意: 温度传感器和 VREFINT 只能出现在主 ADC1 中。

温度传感器和通道 ADC1_IN16 相连接, 内部参照电压 VREFINT和 ADC1_IN17 相连接。 可以按注入或规则通道对这两个内部通道进行转换。

/********************************************************************************
* @file bsp_adc.c
* @author jianqiang.xue
* @version V1.0.0
* @date 2022-02-10
* @brief NULL
********************************************************************************/

/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>

#include "RTE_Components.h"
#include CMSIS_device_header
#include "at32f4xx.h"
#include "at32f4xx_adc.h"

#include "bsp_gpio.h"
#include "bsp_exti.h"
#include "bsp_adc.h"

/* Private Includes ----------------------------------------------------------*/
#include "business_gpio.h"
#include "business_function.h"

/* Private Define ------------------------------------------------------------*/
#define ADC0_CH_NUM 18

#define ADC0_CH0 0
#define ADC0_CH1 1
#define ADC0_CH2 2
#define ADC0_CH3 3
#define ADC0_CH4 4
#define ADC0_CH5 5
#define ADC0_CH6 6
#define ADC0_CH7 7
#define ADC0_CH8 8
#define ADC0_CH9 9
#define ADC0_CH10 10
#define ADC0_CH11 11
#define ADC0_CH12 12
#define ADC0_CH13 13
#define ADC0_CH14 14
#define ADC0_CH15 15
#define ADC0_CH16 16
#define ADC0_CH17 17

#define CH_NUM (BS_ADC0_CH0 + BS_ADC0_CH1 + BS_ADC0_CH2 + BS_ADC0_CH3 + BS_ADC0_CH4 + BS_ADC0_CH5 + BS_ADC0_CH6 + BS_ADC0_CH7 + BS_ADC0_CH8 + BS_ADC0_CH9 + BS_ADC0_CH10 + BS_ADC0_CH11 + BS_ADC0_CH12 + BS_ADC0_CH13 + BS_ADC0_CH14 + BS_ADC0_CH15 + BS_ADC0_CH16 + BS_ADC0_CH17)
/* Private Variables ---------------------------------------------------------*/
// ADC初始化状态(0--deinit 1--init)
static bool g_adc_init = false;
// ADC采集数据存储buff
uint16_t bsp_adc0_val[ADC0_CH_NUM] = {0};
uint16_t bsp_adc0_temp_val[CH_NUM] = {0};

// 定义ADC采集完毕回调函数
typedef void(*bsp_adc0_callback)(void);
static bsp_adc0_callback irq_callback;
static uint8_t adc0_sample_tick = 0;
/****************结构体定义****************/
#if BS_ADC0_EN
ADC_InitType adc0_handle_t =
{
.ADC_Mode = ADC_Mode_Independent,
.ADC_ScanMode = ENABLE, // DISABLE 单通道 ENABLE 双通道
.ADC_ContinuousMode = DISABLE, // DISABLE 单次 ENABLE 连续
.ADC_ExternalTrig = ADC_ExternalTrig_None,
.ADC_DataAlign = ADC_DataAlign_Right,
.ADC_NumOfChannel = CH_NUM
};
#endif
/* External Variables --------------------------------------------------------*/
/* Public Function Prototypes ------------------------------------------------*/
#if BS_ADC0_EN
/**
* @brief 将ADC采集的值重新排序到另一个数组
*/
static void bsp_adc0_val_copy(void)
{
uint8_t num = 0;
bool flag = false;

for (uint8_t i = 0; i < ADC0_CH_NUM; i++)
{
if (i == ADC0_CH0 && BS_ADC0_CH0)
{
flag = true;
}
else if(i == ADC0_CH1 && BS_ADC0_CH1)
{
flag = true;
}
else if(i == ADC0_CH2 && BS_ADC0_CH2)
{
flag = true;
}
else if(i == ADC0_CH3 && BS_ADC0_CH3)
{
flag = true;
}
else if(i == ADC0_CH4 && BS_ADC0_CH4)
{
flag = true;
}
else if(i == ADC0_CH5 && BS_ADC0_CH5)
{
flag = true;
}
else if(i == ADC0_CH6 && BS_ADC0_CH6)
{
flag = true;
}
else if(i == ADC0_CH7 && BS_ADC0_CH7)
{
flag = true;
}
else if(i == ADC0_CH8 && BS_ADC0_CH8)
{
flag = true;
}
else if(i == ADC0_CH9 && BS_ADC0_CH9)
{
flag = true;
}
else if(i == ADC0_CH10 && BS_ADC0_CH10)
{
flag = true;
}
else if(i == ADC0_CH11 && BS_ADC0_CH11)
{
flag = true;
}
else if(i == ADC0_CH12 && BS_ADC0_CH12)
{
flag = true;
}
else if(i == ADC0_CH13 && BS_ADC0_CH13)
{
flag = true;
}
else if(i == ADC0_CH14 && BS_ADC0_CH14)
{
flag = true;
}
else if(i == ADC0_CH15 && BS_ADC0_CH15)
{
flag = true;
}
else if(i == ADC0_CH16 && BS_ADC0_CH16)
{
flag = true;
}
else if(i == ADC0_CH17 && BS_ADC0_CH17)
{
flag = true;
}
if (flag)
{
flag = false;
bsp_adc0_val[i] = bsp_adc0_temp_val[num];
num++;
if (num == CH_NUM)
{
break;
}
}
}
}


/**
* @brief ADC0初始化,并使能通道
*/
void bsp_adc0_init(void)
{
uint8_t ch = 0;
#if CH_NUM
if (g_adc_init)
{
return;
}
/* ADCCLK = PCLK2/4 */
RCC_ADCCLKConfig(RCC_APB2CLK_Div4);
/* Enable ADC1 clocks */
RCC_APB2PeriphClockCmd(RCC_APB2PERIPH_ADC1, ENABLE);
/* ADC1 configuration */
ADC_Init(ADC1, &adc0_handle_t);
// 使能通道
#if BS_ADC0_CH0
ch++;
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, ch, ADC_SampleTime_28_5);
#endif
#if BS_ADC0_CH1
ch++;
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, ch, ADC_SampleTime_28_5);
#endif
#if BS_ADC0_CH2
ch++;
ADC_RegularChannelConfig(ADC1, ADC_Channel_2, ch, ADC_SampleTime_28_5);
#endif
#if BS_ADC0_CH3
ch++;
ADC_RegularChannelConfig(ADC1, ADC_Channel_3, ch, ADC_SampleTime_28_5);
#endif
#if BS_ADC0_CH4
ch++;
ADC_RegularChannelConfig(ADC1, ADC_Channel_4, ch, ADC_SampleTime_28_5);
#endif
#if BS_ADC0_CH5
ch++;
ADC_RegularChannelConfig(ADC1, ADC_Channel_5, ch, ADC_SampleTime_28_5);
#endif
#if BS_ADC0_CH6
ch++;
ADC_RegularChannelConfig(ADC1, ADC_Channel_6, ch, ADC_SampleTime_28_5);
#endif
#if BS_ADC0_CH7
ch++;
ADC_RegularChannelConfig(ADC1, ADC_Channel_7, ch, ADC_SampleTime_28_5);
#endif
#if BS_ADC0_CH8
ch++;
ADC_RegularChannelConfig(ADC1, ADC_Channel_8, ch, ADC_SampleTime_28_5);
#endif
#if BS_ADC0_CH9
ch++;
ADC_RegularChannelConfig(ADC1, ADC_Channel_9, ch, ADC_SampleTime_28_5);
#endif
#if BS_ADC0_CH10
ch++;
ADC_RegularChannelConfig(ADC1, ADC_Channel_10, ch, ADC_SampleTime_28_5);
#endif
#if BS_ADC0_CH11
ch++;
ADC_RegularChannelConfig(ADC1, ADC_Channel_11, ch, ADC_SampleTime_28_5);
#endif
#if BS_ADC0_CH12
ch++;
ADC_RegularChannelConfig(ADC1, ADC_Channel_12, ch, ADC_SampleTime_28_5);
#endif
#if BS_ADC0_CH13
ch++;
ADC_RegularChannelConfig(ADC1, ADC_Channel_13, ch, ADC_SampleTime_28_5);
#endif
#if BS_ADC0_CH14
ch++;
ADC_RegularChannelConfig(ADC1, ADC_Channel_14, ch, ADC_SampleTime_28_5);
#endif
#if BS_ADC0_CH15
ch++;
ADC_RegularChannelConfig(ADC1, ADC_Channel_15, ch, ADC_SampleTime_28_5);
#endif
#if BS_ADC0_CH16
ch++;
ADC_RegularChannelConfig(ADC1, ADC_Channel_16, ch, ADC_SampleTime_28_5);
#endif
#if BS_ADC0_CH17
ch++;
ADC_RegularChannelConfig(ADC1, ADC_Channel_17, ch, ADC_SampleTime_28_5);
#endif
/* Regular discontinuous mode channel number configuration */
ADC_DiscModeChannelCountConfig(ADC1, 1);
/* Enable regular discontinuous mode */
ADC_DiscModeCtrl(ADC1, ENABLE);

/* Enables Temperature Sensor and Vrefint Channel */
ADC_TempSensorVrefintCtrl(ENABLE);
ADC_INTConfig(ADC1, ADC_INT_EC, ENABLE);

/* Enable ADC1 */
ADC_Ctrl(ADC1, ENABLE);

/* Enable ADC1 reset calibration register */
ADC_RstCalibration(ADC1);
/* Check the end of ADC1 reset calibration register */
while(ADC_GetResetCalibrationStatus(ADC1));

/* Start ADC1 calibration */
ADC_StartCalibration(ADC1);
/* Check the end of ADC1 calibration */
while(ADC_GetCalibrationStatus(ADC1));

NVIC_InitType NVIC_InitStructure;
/* Configure and enable ADC interrupt */
NVIC_InitStructure.NVIC_IRQChannel = ADC1_2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
g_adc_init = true;
#endif
}

/**
* @brief ADC0功能关闭,并移除
*/
void bsp_adc0_deinit(void)
{
#if CH_NUM
if (!g_adc_init)
{
return;
}
ADC_Reset(ADC1);
g_adc_init = false;
#endif
}

/**
* @brief ADC0 启动采样功能
*/
void bsp_adc0_start(void)
{
#if CH_NUM
if (!g_adc_init)
{
return;
}
/* Enable ADC1 */
ADC_Ctrl(ADC1, ENABLE);
/* Start ADC1 Software Conversion */
ADC_SoftwareStartConvCtrl(ADC1, ENABLE); // 启动ADC中断转换
adc0_sample_tick = 0;
#endif
}

/**
* @brief ADC0 停止采样功能
*/
void bsp_adc0_stop(void)
{
#if CH_NUM
if (!g_adc_init)
{
return;
}
/* Stop ADC1 Software Conversion */
ADC_SoftwareStartConvCtrl(ADC1, DISABLE); // 停止ADC中断转换
/* Stop ADC1 */
ADC_Ctrl(ADC1, DISABLE);
#endif
}

#else
void bsp_adc0_init(void)
{
}

void bsp_adc0_deinit(void)
{
}

void bsp_adc0_start(void)
{
}
void bsp_adc0_stop(void)
{
}
#endif

/**
* @brief This function handles ADC1 and ADC2 global interrupts requests.
*/
#define CTRL2_EXTTRIG_SWSTR_Set ((uint32_t)0x00500000)
void ADC1_2_IRQHandler(void)
{
#if BS_ADC0_EN
if (ADC_GetINTStatus(ADC1, ADC_INT_EC))
{
bsp_adc0_temp_val[adc0_sample_tick] = (uint16_t) ADC1->RDOR;
adc0_sample_tick ++;
if (adc0_sample_tick > CH_NUM - 1)
{
adc0_sample_tick = 0;
bsp_adc0_stop();
bsp_adc0_val_copy();
if (irq_callback)
{
irq_callback();
}
}
else
{
ADC1->CTRL2 |= CTRL2_EXTTRIG_SWSTR_Set;
}
/* Clear ADC1 EC pending interrupt bit */
ADC_ClearINTPendingBit(ADC1, ADC_INT_EC);
}
#endif
}

/**
* @brief 得到ADC0采样值
* @param ch_num: 通道值
* @retval 通道对应的ADC值
*/
uint16_t bsp_adc0_get_ch_val(uint8_t ch_num)
{
if (ch_num >= ADC0_CH_NUM)
{
return 0xFFFF;
}
return bsp_adc0_val[ch_num];
}

/**
* @brief 注册ADC0采样完毕回调函数
* @param *event: 绑定回调事件
* @retval 0--失败 1--成功
*/
bool bsp_adc0_irq_callback(void *event)
{
if (irq_callback != NULL)
{
return false;
}
else
{
irq_callback = (bsp_adc0_callback)event;
}
return true;
}
/********************************************************************************
* @file bsp_adc.h
* @author jianqiang.xue
* @version V1.0.0
* @date 2021-04-10
* @brief ADC操作
********************************************************************************/

#ifndef __BSP_ADC_H
#define __BSP_ADC_H

/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>

/* Public Function Prototypes -----------------------------------------------*/

void bsp_adc0_init(void);
void bsp_adc0_deinit(void);

void bsp_adc0_start(void);
void bsp_adc0_stop(void);

uint16_t bsp_adc0_get_ch_val(uint8_t ch_num);

bool bsp_adc0_irq_callback(void *event);

#endif


标签:ch,AT32F415,adc0,ADC1,bsp,adc,ADC0,BS,ADC
From: https://blog.51cto.com/xuejianqiang/5810731

相关文章

  • [单片机框架][bsp层][AT32F415][bsp_exti] EXTI配置和使用
    7.2.1主要特性EXTI控制器的主要特性如下:●每个中断/事件都有独立的触发和屏蔽●每个中断线都有专用的状态位●支持多达23个软件的中断/事件请求●检测脉冲宽度......
  • [单片机框架][bsp层][AT32F415][bsp_led] LED配置和使用
    重新封装一层函数,用于bsp层函数,方便调用。voidbsp_led_init(void);voidbsp_led_deinit(void);voidbsp_led_on(bsp_led_tch);voidbsp_led_off(bsp_led_tch);voidb......
  • [单片机框架][bsp层][AT32F415][bsp_gpio] GPIO配置和使用
    6.1简介GPIO接口包括5组通用输入/输出端口。每个GPIO组提供16个通用输入/输出引脚;每个GPIO端口都有相关的控制和配置寄存器来满足特定的功能,GPIO引脚上的外部......
  • CH573/579/582 ADC例程介绍
    在adc的例程中共有六种AD测量,1、温度测量,2、单通道测量,3、DMA单通道测量,4、差分通道测量,5、触摸按键测量,6、中断方式单通道测量,接下来我们逐一描述。一、温度测量首先调......
  • ADC采样信号RMS测量值的Verilog实现
    术语“RMS”代表“Root-Mean-Squared”。大多数书籍将此定义为“产生与等效直流电源相同的加热效果的交流电量”,或者沿着这些线路类似的东西,但RMS值不仅仅是这个。RMS......
  • webSphere下关闭项目后定时任务还在继续执行
     一、问题描述程序描述:程序中有一个定时任务(java.util.Timer)调用存储过程,一天调用一次,存储过程内部会插入"执行开始"和"执行结束"的记录到数据库的日志表中问题描述:......
  • osiThreadCallback 什么用途
    看下实现,就是给一个任务发送了一个事件。event有3个参数,第一个参数是回调,第2个参数是回调函数的实现,第3个参数是回调函数的参数。boolosiThreadCallback(osiThread_t*......
  • STC32G12K128-ADC
    最近开发一个12VBMS的项目,为了降成本和提高开发周期,硬件工程师选择了一款国产MCU作为主控,基本上能满足功能要求项目主要模块就是AD采样,CAN报文发送,故障诊断今天记录一下A......
  • 怎样理解ADC的噪声、有效分辨率
     一个24位的ADC,真正能使用的位数能达到24位吗?答案是否定的,由于器件本身噪声的存在,且噪声范围已经超过了ADC的最小分辨率。所以,基本上24位ADC都不能做到24位无跳动。 那......
  • 外设驱动库开发笔记47:ADS111x系列ADC驱动
      关于ADC我们已经讨论过不少了,但在不同的应用需求下,我们会选择不同的原件。在这里我们将讨论ADS111x系列ADC驱动的设计与实现。1、功能概述  ADS1113、ADS1114和......