Files
CHJ/user/MCU/lhl_adc.c
2026-03-20 21:16:58 +08:00

188 lines
7.3 KiB
C
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "../main/SystemInclude.h"
////使能内部温度传感器
//pAFE->REF_CTRL |=AFE_REF_CTRL_TEMP_SENSER_EN_Msk;
/**------------------------------------------------------------------------
* @brief 初始化 ADC 内部基准源配置
* @note 使用内部参考电压 VREF可配置 VREF 和 VDRIVE 输出电压。
* @param vref: 内部基准电压选择,如 REF_INTERNAL_2P5V
* @param vdrive: VDrive 输出电压选择,如 REF_INTERNAL_1P25V 或 REF_INTERNAL_OFF
* @example ADC_REF_Init(REF_INTERNAL_2P5V, REF_INTERNAL_1P25V);
**/
void ADC_REF_Init(u8 vref,u8 vdrive)
{
REF_InitTypeDef REF_InitStructure;
REF_InitStructure.VREF = vref; // 内部基准电压
REF_InitStructure.VDRIVE = vdrive;// VDrive输出电压
REF_InitStructure.VREF_Boost = DISABLE;
LHL_REF_Init(&REF_InitStructure);
}
/**------------------------------------------------------------------------
* @brief 初始化 ADC 为连续转换模式,软件触发
* @note 基准源使用内部 VREF输出为双极性数据使能数据就绪中断。
* @param ADCx: ADC 实例 (ADC_0 / ADC_1)
* @param SPS: 输出速率,如 SPS_977
* @param Gain: 内部 PGA 增益,如 GAIN32
* @param PChan: 正输入通道,如 ADC0_AIN0
* @param NChan: 负输入通道,如 ADC0_AIN1
* @example ADC_Init(ADC_0, SPS_977, GAIN32, ADC0_AIN0, ADC0_AIN1);
**/
void ADC_Init(ADC_ID_t ADCx ,u8 SPS ,u8 Gain, u8 PChan, u8 NChan )
{
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.AINP = PChan; // ADC0输入通道
ADC_InitStructure.AINM = NChan;
ADC_InitStructure.PGA = Gain; // 内部PGA增益x1
ADC_InitStructure.FS = SPS; // ADC输出速率
ADC_InitStructure.Code = ADC_CODE_BIPOLAR; // 双极性数据
ADC_InitStructure.Mode = ADC_MODE_CONTINUOUS_CONVERSION; // 连续转换模式
ADC_InitStructure.Trigger = ADC_TRIGGER_SOFTWARE; // 软件触发
ADC_InitStructure.ReferenceSelect = ADC_REF_REFP_to_REFN; // 内部基准
ADC_InitStructure.REF_BUFP = ENABLE; // 使能基准缓冲
ADC_InitStructure.REF_BUFM = ENABLE;
ADC_InitStructure.REF_Precharge= DISABLE;
// ADC_InitStructure.Reference = 1250.0f; //基准值 init没用到
LHL_ADC_Init(ADCx, &ADC_InitStructure);
LHL_ADC_ITConfig(ADCx, ADC_IT_RDY, ENABLE);
}
/**------------------------------------------------------------------------
* @brief 使能或禁止 ADC0 与 ADC1 同步转换模式
* @note 同步转换要求两个 ADC 的配置SPS、模式、触发源完全相同
* ADC0 的启动源将自动应用到 ADC1。
* @param NewState: ENABLE 或 DISABLE
* @example ADC_SyncCmd(ENABLE);
**/
void ADC_SyncCmd(FunctionalState NewState)
{
LHL_ADC_SetSync(NewState);
}
/**------------------------------------------------------------------------
* @brief 启动指定 ADC 的转换(软件触发时立即启动)
* @param ADCx: ADC 实例 (ADC_0 / ADC_1)
* @example StartADC(ADC_0);
**/
void StartADC(ADC_ID_t ADCx)
{
(ADCx == ADC_0) ? LHL_ADC_Start(ADC_0): LHL_ADC_Start(ADC_1);
}
/**------------------------------------------------------------------------
* @brief 停止指定 ADC 的转换
* @param ADCx: ADC 实例 (ADC_0 / ADC_1)
* @example StopADC(ADC_0);
**/
void StopADC(ADC_ID_t ADCx)
{
(ADCx == ADC_0) ? LHL_ADC_Stop(ADC_0): LHL_ADC_Stop(ADC_1);
}
/**------------------------------------------------------------------------
* @brief 读取 ADC 转换数据24 位原始数据转 16 位并偏移 32768
* @note 转换公式:((原始数据符号扩展 >> 8) + 32768) & 0xFFFF
* @param ADCx: ADC 实例 (ADC_0 / ADC_1)
* @return 16 位 ADC 值0~65535
* @example u32 val = ADC_ReadData(ADC_0);
**/
u32 ADC_ReadData(ADC_ID_t ADCx)
{
volatile u32 reg_data = 0;
reg_data = (ADCx == ADC_0) ? LHL_ADC_GetData(ADC_0) : LHL_ADC_GetData(ADC_1);
reg_data = ((((reg_data & 0xFFFFFF) | ((reg_data & 0x800000) ? 0xFF000000 : 0)) >> 8) + 32768) & 0xFFFF;
return reg_data ;
}
/*===========================================================================*/
/* 小睡模式自动触发转换
选择此模式,在转换开始前配置为单次转换,并且将触发方式配置为硬件触发。
在进入到休眠模式(小睡模式)后,自动启动转换。
转换结束后自动停止转换,随后进入深度睡眠模式或者核心被唤醒进入正常工作模式。
需要将SNOOZE触发信号通过交叉路径至模数转换器(ADC)硬件触发源。
*/
/**------------------------------------------------------------------------
* @brief 初始化 ADC 为低功耗模式(单次转换 + 硬件触发)
* @note 适用于 SNOOZE 模式下的自动采样,转换完成后可选择唤醒或继续睡眠。
* @param ADCx: ADC 实例 (ADC_0 / ADC_1)
* @param SPS: 输出速率,如 SPS_10
* @param Gain: 内部 PGA 增益,如 GAIN32
* @param PChan: 正输入通道,如 ADC0_AIN2
* @param NChan: 负输入通道,如 ADC0_AVSS
* @example ADC_Init_For_LowerPower(ADC_0, SPS_10, GAIN32, ADC0_AIN2, ADC0_AVSS);
**/
void ADC_Init_For_LowerPower(ADC_ID_t ADCx, u8 SPS, u8 Gain, u8 PChan, u8 NChan)
{
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.AINP = PChan; // ADC输入通道
ADC_InitStructure.AINM = NChan;
ADC_InitStructure.PGA = Gain; // 内部PGA增益
ADC_InitStructure.FS = SPS; // ADC输出速率
ADC_InitStructure.Code = ADC_CODE_BIPOLAR; // 双极性数据
ADC_InitStructure.Mode = ADC_MODE_SINGLE_CONVERSION; // 单次转换模式
ADC_InitStructure.Trigger = ADC_TRIGGER_HARDWARE; // 硬件触发 ADC_TRIGGER_HARDWARE ADC_TRIGGER_SOFTWARE
ADC_InitStructure.ReferenceSelect = ADC_REF_REFP_to_REFN; // 内部基准
ADC_InitStructure.REF_BUFP = ENABLE; // 使能基准缓冲
ADC_InitStructure.REF_BUFM = ENABLE;
ADC_InitStructure.REF_Precharge = DISABLE;
LHL_ADC_Init(ADCx, &ADC_InitStructure);
LHL_ADC_ITConfig(ADCx, ADC_IT_RDY, ENABLE); //RDY_INT = 1
NVIC_EnableIRQ(ADC0_IRQn);
NVIC_SetPriority(ADC0_IRQn, 0);
NVIC_EnableIRQ(ADC1_IRQn);
NVIC_SetPriority(ADC1_IRQn, 0);
}
/*===========================================================================*/
//ADC中断回调==============================================================================================================
static adc_irq_callback_t adc0_irq_callback ,adc1_irq_callback;
/**------------------------------------------------------------------------
* @brief 注册 ADC 转换完成中断回调函数
* @param ADCx: ADC 实例 (ADC_0 / ADC_1)
* @param tim_irq_callback: 用户回调函数指针(无参数无返回值)
* @note 注册后自动使能对应 ADC 的 NVIC 中断 。
* @example ADC_register_irq_callback(ADC_0, my_adc_callback);
**/
void ADC_register_irq_callback(ADC_ID_t ADCx, adc_irq_callback_t tim_irq_callback)
{
if(ADCx == ADC_0) {adc0_irq_callback = tim_irq_callback; NVIC_EnableIRQ(ADC0_IRQn);NVIC_SetPriority(ADC0_IRQn, 0);}
else if(ADCx == ADC_1) {adc1_irq_callback = tim_irq_callback; NVIC_EnableIRQ(ADC1_IRQn);NVIC_SetPriority(ADC1_IRQn, 0);}
}
/**------------------------------------------------------------------------
* @brief ADC0 中断服务函数
* @note 当 ADC0 数据就绪时调用已注册的回调函数(若存在)。
**/
void ADC0_IRQHandler(void)
{
if(LHL_ADC_GetPending(ADC_0, ADC_FLAG_RDY) == SET)
{
if(adc0_irq_callback != NULL) adc0_irq_callback();
}
}
/**------------------------------------------------------------------------
* @brief ADC1 中断服务函数
* @note 当 ADC1 数据就绪时调用已注册的回调函数(若存在)。
**/
void ADC1_IRQHandler(void)
{
if(LHL_ADC_GetPending(ADC_1, ADC_FLAG_RDY) == SET)
{
if(adc1_irq_callback != NULL) adc1_irq_callback();
}
}