This commit is contained in:
2026-03-20 21:16:58 +08:00
parent 286ff98b8e
commit 90c3d919df
248 changed files with 94554 additions and 0 deletions

742
library/src/lh32m0g3x_adc.c Executable file
View File

@@ -0,0 +1,742 @@
/******************************************************************************
* 版权所有:苏州领慧立芯科技有限公司
* Copyright (c) 2020-2025 Suzhou Legendsemi Technology Co., Ltd.
******************************************************************************
* All rights reserved. Distributed under MIT license.
* The file is encoded in UTF-8 without signature.
* @file lh32m0g30x_adc.c
* @version 2025-09-22
******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "lh32m0xx_lhl.h"
/* Functions -----------------------------------------------------------------*/
/**
* @brief 初始化ADCx
* @note Configures control registers, channel settings, reference voltages,
* filter settings and interrupt controls for both ADCs
* @param ADCx x取值0或1
* ADC_Init ADC初始值参数指针
* @retval LHL_OKADC初始化成功LHL_ERROR参数错误。
*/
LHL_StatusTypeDef LHL_ADC_Init(ADC_ID_t ADCx, ADC_InitTypeDef* ADC_Init)
{
// 开启AFE时钟
RCC_APB2PeriphClockCmd(RCC_APB2ENR_AFEEN_Msk, ENABLE);
if (ADC_Init == NULL) return LHL_ERROR;
if (ADCx == ADC_0)
{
// 开启ADC0时钟
RCC_APB2PeriphClockCmd(RCC_APB2ENR_ADC0EN_Msk, ENABLE);
// 默认配置前停止转换
pADC->ADC_CONTROL_0 &= ~(ADC_SUBSYS_USER_ADC_CONTROL_0_START_Msk | \
ADC_SUBSYS_USER_ADC_CONTROL_0_MODE_Msk | \
ADC_SUBSYS_USER_ADC_CONTROL_0_TRIG_SRC_SEL_Msk);
// 写入CONTROL寄存器
pADC->ADC_CONTROL_0 |= (((uint32_t)ADC_Init->Mode << ADC_SUBSYS_USER_ADC_CONTROL_0_MODE_Pos) | \
((uint32_t)ADC_Init->Trigger << ADC_SUBSYS_USER_ADC_CONTROL_0_TRIG_SRC_SEL_Pos));
// 写入CHANNEL CFG寄存器
pADC->CHANNEL_CFG_0 = (((uint32_t)ADC_Init->AINP << ADC_SUBSYS_USER_CHANNEL_CFG_0_AINP_Pos) | ADC_Init->AINM);
// 写入CONFIGURATION寄存器
pADC->CONFIGURATION_0 = ((uint32_t)ADC_Init->Code << ADC_SUBSYS_USER_CONFIGURATION_0_BIPOLAR_Pos) | \
((uint32_t)ADC_Init->REF_BUFP << ADC_SUBSYS_USER_CONFIGURATION_0_REF_BUFP_Pos) | \
((uint32_t)ADC_Init->REF_BUFM << ADC_SUBSYS_USER_CONFIGURATION_0_REF_BUFM_Pos) | \
((uint32_t)ADC_Init->ReferenceSelect << ADC_SUBSYS_USER_CONFIGURATION_0_REF_SEL_Pos) | \
((uint32_t)ADC_Init->PGA << ADC_SUBSYS_USER_CONFIGURATION_0_PGA_Pos);
// 写入FILTER寄存器
pADC->FILTER_0 = ADC_Init->FS;
// 使能DRDY
pADC->ADC_DRDY |= (ADC_0 << ADC_SUBSYS_USER_ADC_DRDY_DRDY_SEL_Pos);
return LHL_OK;
}
else if (ADCx == ADC_1)
{
// 开启ADC1时钟
RCC_APB2PeriphClockCmd(RCC_APB2ENR_ADC1EN_Msk, ENABLE);
// 默认配置前停止转换
pADC->ADC_CONTROL_1 &= ~(ADC_SUBSYS_USER_ADC_CONTROL_1_START_Msk | \
ADC_SUBSYS_USER_ADC_CONTROL_1_MODE_Msk | \
ADC_SUBSYS_USER_ADC_CONTROL_1_TRIG_SRC_SEL_Msk);
// 写入CONTROL寄存器
pADC->ADC_CONTROL_1 |= (((uint32_t)ADC_Init->Mode << ADC_SUBSYS_USER_ADC_CONTROL_1_MODE_Pos) | \
((uint32_t)ADC_Init->Trigger << ADC_SUBSYS_USER_ADC_CONTROL_1_TRIG_SRC_SEL_Pos));
// 写入CHANNEL CFG寄存器
pADC->CHANNEL_CFG_1 = (((uint32_t)ADC_Init->AINP << ADC_SUBSYS_USER_CHANNEL_CFG_1_AINP_Pos) | ADC_Init->AINM);
// 写入CONFIGURATION寄存器
pADC->CONFIGURATION_1 = ((uint32_t)ADC_Init->Code << ADC_SUBSYS_USER_CONFIGURATION_1_BIPOLAR_Pos) | \
((uint32_t)ADC_Init->REF_BUFP << ADC_SUBSYS_USER_CONFIGURATION_1_REF_BUFP_Pos) | \
((uint32_t)ADC_Init->REF_BUFM << ADC_SUBSYS_USER_CONFIGURATION_1_REF_BUFM_Pos) | \
((uint32_t)ADC_Init->ReferenceSelect << ADC_SUBSYS_USER_CONFIGURATION_1_REF_SEL_Pos) | \
((uint32_t)ADC_Init->PGA << ADC_SUBSYS_USER_CONFIGURATION_1_PGA_Pos);
// 写入FILTER寄存器
pADC->FILTER_1 = ADC_Init->FS;
// 使能DRDY
pADC->ADC_DRDY |= (ADC_1 << ADC_SUBSYS_USER_ADC_DRDY_DRDY_SEL_Pos);
}
else
{
return LHL_ERROR;
}
if (ADC_Init->REF_Precharge != ENABLE)
{
pADC->IO_CONTROL_IOUT &= ~ADC_SUBSYS_USER_IO_CONTROL_IOUT_REF_BUF_PREQ_ENABLE_Msk;
}
else
{
pADC->IO_CONTROL_IOUT |= ADC_SUBSYS_USER_IO_CONTROL_IOUT_REF_BUF_PREQ_ENABLE_Msk;
}
return LHL_OK;
}
void LHL_ADC_DeInit(ADC_ID_t ADCx)
{
if (ADCx == ADC_0)
{
RCC_APB2PeriphResetCmd(RCC_APB2RSTR_ADC0RST_Msk, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2RSTR_ADC0RST_Msk, DISABLE);
RCC_APB2PeriphClockCmd(RCC_APB2ENR_ADC0EN_Msk, DISABLE);
}
else
{
RCC_APB2PeriphResetCmd(RCC_APB2RSTR_ADC1RST_Msk, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2RSTR_ADC1RST_Msk, DISABLE);
RCC_APB2PeriphClockCmd(RCC_APB2ENR_ADC1EN_Msk, DISABLE);
}
}
/**
* @brief 立即启动ADCx转换
* @param ADCx x取值0或1
* @retval None
*/
void LHL_ADC_Start(ADC_ID_t ADCx)
{
if (ADCx == ADC_0)
{
pADC->ADC_CONTROL_0 |= ADC_SUBSYS_USER_ADC_CONTROL_0_START_Msk;
}
else
{
pADC->ADC_CONTROL_1 |= ADC_SUBSYS_USER_ADC_CONTROL_1_START_Msk;
}
}
/**
* @brief 立即停止ADCx转换
* @param ADCx x取值0或1
* @retval None
*/void LHL_ADC_Stop(ADC_ID_t ADCx)
{
if (ADCx == ADC_0)
{
pADC->ADC_CONTROL_0 &= ~ADC_SUBSYS_USER_ADC_CONTROL_0_START_Msk;
}
else
{
pADC->ADC_CONTROL_1 &= ~ADC_SUBSYS_USER_ADC_CONTROL_1_START_Msk;
}
}
/**
* @brief 设置ADCx中断
* @param ADCx x取值0或1
* ADC_IT 指定ADC中断
* NewState ENABLE or DISABLE
* @retval None
*/
void LHL_ADC_ITConfig(ADC_ID_t ADCx, uint32_t ADC_IT, FunctionalState NewState)
{
if (NewState == ENABLE)
{
if (ADCx == ADC_0)
{
pADC->INTERRUPT_CONTROL_0 |= ADC_IT;
}
else
{
pADC->INTERRUPT_CONTROL_1 |= ADC_IT;
}
}
else
{
if (ADCx == ADC_0)
{
pADC->INTERRUPT_CONTROL_0 &= ~ADC_IT;
}
else
{
pADC->INTERRUPT_CONTROL_1 &= ~ADC_IT;
}
}
}
/**
* @brief 获取ADCx中断标志位
* @param ADCx x取值0或1
* ADC_IT_FLAG 指定ADC中断标志位
* @retval SET or RESET
*/
ITStatus LHL_ADC_GetPending(ADC_ID_t ADCx, uint32_t ADC_IT_FLAG)
{
uint32_t reg;
if (ADCx == ADC_0)
{
/* Check the status of the specified ADC0 interrupt */
reg = pADC->ADC_STATUS_0;
}
else
{
/* Check the status of the specified ADC1 interrupt */
reg = pADC->ADC_STATUS_1;
}
if (ADC_IT_FLAG != ADC_IT_ERR)
{
return SET;
}
else
{
if ((reg & ADC_IT_FLAG) != (uint32_t)RESET)
{
return SET;
}
}
return RESET;
}
/**
* @brief 获取ADCx转换数据读取数据前需保证ADC已转换完成
* @param ADCx x取值0或1
* @retval ADC Raw Data
*/
uint32_t LHL_ADC_GetData(ADC_ID_t ADCx)
{
if (ADCx == ADC_0)
{
return pADC->ADC_DATA_0;
}
else
{
return pADC->ADC_DATA_1;
}
}
/**
* @brief 使用堵塞方式查询ADCx是否转换完成
* @param ADCx x取值0或1
* Timeout 超时时间
* @retval LHL_OK转换完成LHL_TIMEOUT超时未完成。
*/
LHL_StatusTypeDef LHL_ADC_PollForConversion (ADC_ID_t ADCx, uint32_t Timeout)
{
uint32_t t = Timeout;
if (ADCx == ADC_0)
{
while ((pADC->ADC_STATUS_0 & ADC_SUBSYS_USER_ADC_STATUS_0_RDYN_Msk) == 0)
{
if ((t--) == 0) return LHL_TIMEOUT;
}
return LHL_OK;
}
else
{
while ((pADC->ADC_STATUS_1 & ADC_SUBSYS_USER_ADC_STATUS_1_RDYN_Msk) == 0)
{
if ((t--) == 0) return LHL_TIMEOUT;
}
return LHL_OK;
}
}
///**
// * @brief 将ADC Raw Data转换为实际电压值单位毫伏/mV
// * @param raw_data ADC原始数据
// * REF_Init ADC基准参数
// * ADC_Init ADC初始参数
// * @retval 以单精度浮点数float表达的电压值单位毫伏/mV
// */
//float LHL_ADC_GetmVoltage(const uint32_t raw_data, REF_InitTypeDef* REF_Init, ADC_InitTypeDef* ADC_Init)
//{
// float ref_mv;
//
// switch (REF_Init->REF0_Mode)
// {
// case REF_INTERNAL_1P25_V: ref_mv = 1250; break;
// case REF_INTERNAL_2P048_V: ref_mv = 2048; break;
// case REF_INTERNAL_2P5_V: ref_mv = 2500; break;
// case REF_INTERNAL_4P096_V: ref_mv = 4096; break;
// }
//
// if (ADC_Init->Code == ADC_CODE_BIPOLAR)
// {
// return (float)(((int32_t)raw_data << 8) >> 8) * ref_mv / (1<<23);
// }
// else
// {
// return (float)raw_data * ref_mv / (1<<24);
// }
//}
/**
* @brief 将ADC Raw Data转换为电压值
* @param raw_data ADC原始数据
* ADC_Init ADC初始参数
* @retval 以单精度浮点数float表达的电压值单位伏/V
*/
float LHL_ADC_GetVoltage(const uint32_t raw_data, ADC_InitTypeDef* ADC_Init)
{
uint32_t pga;
float ref;
pga = 1u << (ADC_Init->PGA & 7u);
ref = ADC_Init->Reference / (float)pga;
if (ADC_Init->Code == ADC_CODE_BIPOLAR)
{
return (float)(((int32_t)raw_data << 8) >> 8) * ref / (1<<23);
}
else
{
return (float)raw_data * ref / (1<<24);
}
}
/**
* @brief 使能或禁用内部基准源VREF
* @param voltage 内部基准的电压
* @param NewState ENABLE or DISABLE
* @retval None
*/
void LHL_ADC_SetVREF(REF_VOLTAGE_t voltage, FunctionalState NewState)
{
RCC_APB2PeriphClockCmd(RCC_APB2ENR_AFEEN_Msk, ENABLE);
if (NewState == DISABLE)
{
/* 关闭内部基准VREF */
pAFE->REF_CTRL &= ~(AFE_REF_CTRL_REF0_EN_Msk);
}
else
{
/* 设定内部基准电压并开启VREF */
pAFE->REF_CTRL &= ~AFE_REF_CTRL_REF0_MODE_Msk;
pAFE->REF_CTRL |= (((uint32_t)voltage << AFE_REF_CTRL_REF0_MODE_Pos) | AFE_REF_CTRL_REF0_EN_Msk);
}
}
/**
* @brief 使能或禁用内部驱动源VDRIVE
* @param voltage 驱动电压
* @param NewState ENABLE or DISABLE
* @retval None
*/
void LHL_ADC_SetVDRIVE(REF_VOLTAGE_t voltage, FunctionalState NewState)
{
RCC_APB2PeriphClockCmd(RCC_APB2ENR_AFEEN_Msk, ENABLE);
if (NewState == DISABLE)
{
/* 关闭内部驱动VDRIVE */
pAFE->REF_CTRL &= ~(AFE_REF_CTRL_REF1_EN_Msk);
}
else
{
/* 设定内部驱动电压并开启VDRIVE */
pAFE->REF_CTRL &= ~AFE_REF_CTRL_REF1_MODE_Msk;
pAFE->REF_CTRL |= (((uint32_t)voltage << AFE_REF_CTRL_REF1_MODE_Pos) | AFE_REF_CTRL_REF1_EN_Msk);
}
}
/**
* @brief 初始化ADC基准源设置
* @param REF_Init ADC基准参数指针
* @retval LHL_OK基准源设置成功
*/
LHL_StatusTypeDef LHL_REF_Init(REF_InitTypeDef* REF_Init)
{
// 开启AFE时钟
RCC_APB2PeriphClockCmd(RCC_APB2ENR_AFEEN_Msk, ENABLE);
if (REF_Init == NULL) return LHL_ERROR;
if (REF_Init->VREF == REF_INTERNAL_OFF)
{
// 关闭内部基准REF0
pAFE->REF_CTRL &= ~(AFE_REF_CTRL_REF0_EN_Msk);
}
else
{
// 设定内部基准电压并开启REF0
pAFE->REF_CTRL &= ~(AFE_REF_CTRL_REF0_MODE_Msk | AFE_REF_CTRL_REFBUF0_BOOST_EN_Msk);
pAFE->REF_CTRL |= ((uint32_t)REF_Init->VREF << AFE_REF_CTRL_REF0_MODE_Pos) | \
((uint32_t)REF_Init->VREF_Boost << AFE_REF_CTRL_REFBUF0_BOOST_EN_Pos) | \
AFE_REF_CTRL_REF0_EN_Msk;
}
if (REF_Init->VDRIVE == REF_INTERNAL_OFF)
{
// 关闭内部基准REF1
pAFE->REF_CTRL &= ~(AFE_REF_CTRL_REF1_EN_Msk);
}
else
{
// 设定内部基准电压并开启REF1
pAFE->REF_CTRL &= ~ (AFE_REF_CTRL_REF1_MODE_Msk | AFE_REF_CTRL_REFBUF1_BOOST_EN_Msk);
pAFE->REF_CTRL |= ((uint32_t)REF_Init->VDRIVE << AFE_REF_CTRL_REF1_MODE_Pos) | \
((uint32_t)REF_Init->VDRIVE_Boost << AFE_REF_CTRL_REFBUF1_BOOST_EN_Pos) | \
AFE_REF_CTRL_REF1_EN_Msk;
}
return LHL_OK;
}
/**
* @brief 设置ADC同步方式
* @note 需保证ADC0.FILTER0和ADC1.FILTER1的配置相同并且ADC处于同一种转换模式单次或连续转换两个ADC的输出速率才能完全一致。
* @note 使能同步则ADC_0的启动源软件寄存器或者硬件trigger自动被应用到ADC_1此时两个ADC的启动同时受ADC_0的启动源控制。
* @param NewState ENABLE or DISABLE
* @retval None
*/
void LHL_ADC_SetSync(FunctionalState NewState)
{
if (NewState == ENABLE)
{
pADC->ADC_CONTROL_0 |= ADC_SUBSYS_USER_ADC_CONTROL_0_SIMU_Msk;
}
else
{
pADC->ADC_CONTROL_0 &= ~ADC_SUBSYS_USER_ADC_CONTROL_0_SIMU_Msk;
}
}
/**
* @brief 在指定的模拟通道上输出指定大小的激励电流
* @param source 分别设置激励电流源0或激励电流源1或者两路电流源同步
* range 电流大小
* channel 电流输出通道即AINx引脚
* @retval None
*/
void LHL_ADC_StartExcitationCurrent(IEXC_SOURCE_t source, IEXC_RANGE_t range, IEXC_CHANNEL_t channel)
{
uint32_t tmp0 = pAFE->IEXC_CTRL;
uint32_t tmp1 = pAFE->IEXC_RANGE;
switch (source)
{
case EXC_CURRENT_DUAL:
// 双路激励电流源在同一个通道上输出,电流大小翻倍
tmp1 = (uint32_t)(range << AFE_IEXC_RANGE_IEXC1_RANGE_Pos) | \
(uint32_t)(range << AFE_IEXC_RANGE_IEXC0_RANGE_Pos);
tmp0 &= ~(AFE_IEXC_CTRL_IEXC0_CHAN_Msk | AFE_IEXC_CTRL_IEXC1_CHAN_Msk);
tmp0 |= (uint32_t)(source << AFE_IEXC_CTRL_IEXC0_EN_Pos) | \
(uint32_t)(channel << AFE_IEXC_CTRL_IEXC1_CHAN_Pos) | \
(uint32_t)(channel << AFE_IEXC_CTRL_IEXC0_CHAN_Pos);
break;
case EXC_CURRENT_SRC0:
// 激励电流源0
tmp1 &= ~AFE_IEXC_RANGE_IEXC0_RANGE_Msk;
tmp1 |= (uint32_t)(range << AFE_IEXC_RANGE_IEXC0_RANGE_Pos);
tmp0 &= ~AFE_IEXC_CTRL_IEXC0_CHAN_Msk;
tmp0 |= (uint32_t)(source << AFE_IEXC_CTRL_IEXC0_EN_Pos) | \
(uint32_t)(channel << AFE_IEXC_CTRL_IEXC0_CHAN_Pos);
break;
case EXC_CURRENT_SRC1:
// 激励电流源1
tmp1 &= ~AFE_IEXC_RANGE_IEXC1_RANGE_Msk;
tmp1 |= (uint32_t)(range << AFE_IEXC_RANGE_IEXC1_RANGE_Pos);
tmp0 &= ~AFE_IEXC_CTRL_IEXC1_CHAN_Msk;
tmp0 |= (uint32_t)(source << AFE_IEXC_CTRL_IEXC0_EN_Pos) | \
(uint32_t)(channel << AFE_IEXC_CTRL_IEXC1_CHAN_Pos);
}
pAFE->IEXC_RANGE = tmp1;
pAFE->IEXC_CTRL = tmp0;
}
/**
* @brief 停止指定的激励电流源输出
* @param source 分别设置激励电流源0或激励电流源1或者两路电流源同步
* @retval None
*/
void LHL_ADC_StopExcitationCurrent(IEXC_SOURCE_t source)
{
pAFE->IEXC_CTRL &= ~((uint32_t)(source << AFE_IEXC_CTRL_IEXC0_EN_Pos));
}
/**
* @brief 在指定通道上使能偏置电压输出
* @param source 电压输出通道
* @retval None
*/
void LHL_ADC_StartBiasVoltage(VBIAS_CHANNEL_t channel)
{
pADC->IO_CONTROL_VBIAS = channel;
}
/**
* @brief 禁用偏置电压输出
* @param None
* @retval None
*/
void LHL_ADC_StopBiasVoltage(void)
{
pADC->IO_CONTROL_VBIAS = 0u;
}
/**
* @brief 使能指定ADCx的Burnout Current Detection
* @param ADCx 进行检测的ADC0或者ADC1
* current Burnout检测电流输出大小
* @retval None
*/
void LHL_ADC_StartBurnoutCurrent(ADC_ID_t ADCx, BURNOUT_CURRENT_t current)
{
uint32_t tmp = pADC->IO_CONTROL_IOUT;
tmp &= ~ADC_SUBSYS_USER_IO_CONTROL_IOUT_BURNOUT_STRENTH_Msk;
tmp |= (uint32_t)ADCx << ADC_SUBSYS_USER_IO_CONTROL_IOUT_BURNOUT_ADC_0_ENABLE_Pos | \
(uint32_t)current << ADC_SUBSYS_USER_IO_CONTROL_IOUT_BURNOUT_STRENTH_Pos;
pADC->IO_CONTROL_IOUT = tmp;
}
/**
* @brief 禁用指定ADCx的Burnout Current Detection
* @param ADCx 停止检测的ADC0或者ADC1
* @retval None
*/
void LHL_ADC_StopBurnoutCurrent(ADC_ID_t ADCx)
{
pADC->IO_CONTROL_IOUT &= ~(ADC_SUBSYS_USER_IO_CONTROL_IOUT_BURNOUT_STRENTH_Msk | \
(uint32_t)ADCx << ADC_SUBSYS_USER_IO_CONTROL_IOUT_BURNOUT_ADC_0_ENABLE_Pos);
}
/**
* @brief 使能或禁用ADC ERROR功能
* @param ADC_ERRs: 指定的ADC错误诊断功能可选多个
* @param NewState: ENABLE or DISABLE.
* @retval None
*/
void LHL_ADC_ErrorConfig(uint32_t ADC_ERRs,FunctionalState NewState)
{
if (NewState != DISABLE)
{
pADC->ERROR_EN |= ADC_ERRs;
}
else
{
pADC->ERROR_EN &= ~ADC_ERRs;
}
}
FlagStatus LHL_ADC_GetError(uint32_t ADC_ERR)
{
if(pADC->ERROR_STATUS & ADC_ERR)
{
return SET;
}
else
{
return RESET;
}
}
/**
* @brief 使能或禁用ADC DMA请求功能
* @param ADCx: where x can be 1 or 2 to select the ADC peripheral.
* @param NewState: ENABLE or DISABLE.
* @retval None
*/
void LHL_ADC_DMACmd(ADC_ID_t ADCx, FunctionalState NewState)
{
if (NewState != DISABLE)
{
pADC->DMA_MODE |= ADCx;
}
else
{
pADC->DMA_MODE &= ~ADCx;
}
}
// Original正序
//LHL_StatusTypeDef LHL_ADC_ChannelSequencer0Init(ADC_CS0InitTypeDef* CS0_Init)
//{
// if (CS0_Init->Active_Channels > ADC_MAX_SEQUENCER_CHANNELS) return LHL_ERROR;
// for (uint8_t i=0; i< CS0_Init->Active_Channels; i++)
// {
// /* 设为ADC为单次转换模式软件触发并启动转换 */
// CS0_Init->ADC_CFG[i*2] = ADC_SUBSYS_USER_ADC_CONTROL_0_START_Msk | (2u << ADC_SUBSYS_USER_ADC_CONTROL_0_MODE_Pos);
// /* 设为ADC输入通道 */
// CS0_Init->ADC_CFG[i*2+1] = ((uint32_t)CS0_Init->AINP_Channel[i] << ADC_SUBSYS_USER_CHANNEL_CFG_0_AINP_Pos) | \
// ((uint32_t)CS0_Init->AINM_Channel[i] << ADC_SUBSYS_USER_CHANNEL_CFG_0_AINM_Pos);
// }
// return LHL_OK;
//}
LHL_StatusTypeDef LHL_ADC_SingleChannelSequencerInit(ADC_InitTypeDef* ADC_Init, ADC_SingleCSInitTypeDef* ADC_CSInit)
{
if ((ADC_CSInit == NULL) || (ADC_Init == NULL)) return LHL_ERROR;
if ((ADC_CSInit->Active_Channels > ADC_MAX_SEQUENCER_CHANNELS) || (ADC_CSInit->Active_Channels < 2)) return LHL_ERROR;
/* 设置ADC参数链表 */
for (uint8_t i = 0; i < ADC_CSInit->Active_Channels; i++)
{
if (i == 0)
{
/* 首通道,设置触发模式 */
if (ADC_CSInit->Sequencer_Trigger == ADC_TRIGGER_SOFTWARE)
{
if (ADC_CSInit->Cycle_Mode == DISABLE)
{
ADC_CSInit->ADC_CFG[ADC_CSInit->Active_Channels-1].ADC_CONTROL = (2u << ADC_SUBSYS_USER_ADC_CONTROL_0_MODE_Pos);
}
else
{
ADC_CSInit->ADC_CFG[ADC_CSInit->Active_Channels-1].ADC_CONTROL = ADC_SUBSYS_USER_ADC_CONTROL_0_START_Msk | (2u << ADC_SUBSYS_USER_ADC_CONTROL_0_MODE_Pos);
}
}
else
{
ADC_CSInit->ADC_CFG[ADC_CSInit->Active_Channels-1].ADC_CONTROL = ADC_SUBSYS_USER_ADC_CONTROL_0_TRIG_SRC_SEL_Msk | (2u << ADC_SUBSYS_USER_ADC_CONTROL_0_MODE_Pos);
}
/* 设ADC输入通道 */
ADC_CSInit->ADC_CFG[ADC_CSInit->Active_Channels-1].CHANNEL_CFG = ((uint32_t)ADC_CSInit->AINP_Channel[i] << ADC_SUBSYS_USER_CHANNEL_CFG_0_AINP_Pos) | \
((uint32_t)ADC_CSInit->AINM_Channel[i] << ADC_SUBSYS_USER_CHANNEL_CFG_0_AINM_Pos);
}
else
{
/* 其他通道,设置触发和循环模式 */
if ((ADC_CSInit->Cycle_Mode == DISABLE) && (ADC_CSInit->Sequencer_Trigger == ADC_TRIGGER_HARDWARE))
{
ADC_CSInit->ADC_CFG[i-1].ADC_CONTROL = ADC_SUBSYS_USER_ADC_CONTROL_0_TRIG_SRC_SEL_Msk | (2u << ADC_SUBSYS_USER_ADC_CONTROL_0_MODE_Pos);
}
else
{
ADC_CSInit->ADC_CFG[i-1].ADC_CONTROL = ADC_SUBSYS_USER_ADC_CONTROL_0_START_Msk | (2u << ADC_SUBSYS_USER_ADC_CONTROL_0_MODE_Pos);
}
/* 设ADC输入通道 */
ADC_CSInit->ADC_CFG[i-1].CHANNEL_CFG = ((uint32_t)ADC_CSInit->AINP_Channel[i] << ADC_SUBSYS_USER_CHANNEL_CFG_0_AINP_Pos) | \
((uint32_t)ADC_CSInit->AINM_Channel[i] << ADC_SUBSYS_USER_CHANNEL_CFG_0_AINM_Pos);
}
}
/* 初始化ADC寄存器 */
ADC_Init->AINP = ADC_CSInit->AINP_Channel[0]; // 装载首个通道
ADC_Init->AINM = ADC_CSInit->AINM_Channel[0];
ADC_Init->Mode = ADC_MODE_SINGLE_CONVERSION; // 序列器模式固定为单次转换
ADC_Init->Trigger = ADC_CSInit->Sequencer_Trigger; // 首个通道触发源
LHL_ADC_Init(ADC_CSInit->ADC_ID, ADC_Init);
return LHL_OK;
}
LHL_StatusTypeDef LHL_ADC_DualChannelSequencerInit(ADC_InitTypeDef* ADC_Init, ADC_DualCSInitTypeDef* ADC_DualCSInit)
{
if ((ADC_DualCSInit == NULL) || (ADC_Init == NULL)) return LHL_ERROR;
if ((ADC_DualCSInit->Active_Channels > ADC_MAX_SEQUENCER_CHANNELS) || (ADC_DualCSInit->Active_Channels < 2)) return LHL_ERROR;
/* 设置ADC参数链表 */
for (uint8_t i = 0; i < ADC_DualCSInit->Active_Channels; i++)
{
if (i == 0)
{
/* 首通道,设置触发模式 */
if (ADC_DualCSInit->Sequencer_Trigger == ADC_TRIGGER_SOFTWARE)
{
if (ADC_DualCSInit->Cycle_Mode == DISABLE)
{
ADC_DualCSInit->ADC_CFGs[ADC_DualCSInit->Active_Channels-1].ADC_CONTROL_0 = (2u << ADC_SUBSYS_USER_ADC_CONTROL_0_MODE_Pos) | ADC_SUBSYS_USER_ADC_CONTROL_0_SIMU_Msk;
}
else
{
ADC_DualCSInit->ADC_CFGs[ADC_DualCSInit->Active_Channels-1].ADC_CONTROL_0 = ADC_SUBSYS_USER_ADC_CONTROL_0_START_Msk | (2u << ADC_SUBSYS_USER_ADC_CONTROL_0_MODE_Pos) | ADC_SUBSYS_USER_ADC_CONTROL_0_SIMU_Msk;
}
ADC_DualCSInit->ADC_CFGs[ADC_DualCSInit->Active_Channels-1].ADC_CONTROL_1 = ADC_SUBSYS_USER_ADC_CONTROL_1_START_Msk | (2u << ADC_SUBSYS_USER_ADC_CONTROL_1_MODE_Pos);
}
else
{
ADC_DualCSInit->ADC_CFGs[ADC_DualCSInit->Active_Channels-1].ADC_CONTROL_0 = ADC_SUBSYS_USER_ADC_CONTROL_0_TRIG_SRC_SEL_Msk | (2u << ADC_SUBSYS_USER_ADC_CONTROL_0_MODE_Pos) | ADC_SUBSYS_USER_ADC_CONTROL_0_SIMU_Msk;
ADC_DualCSInit->ADC_CFGs[ADC_DualCSInit->Active_Channels-1].ADC_CONTROL_1 = ADC_SUBSYS_USER_ADC_CONTROL_1_TRIG_SRC_SEL_Msk | (2u << ADC_SUBSYS_USER_ADC_CONTROL_1_MODE_Pos);
}
/* 设ADC输入通道 */
ADC_DualCSInit->ADC_CFGs[ADC_DualCSInit->Active_Channels-1].CHANNEL_CFG_0 = ((uint32_t)ADC_DualCSInit->AINP0_Channel[i] << ADC_SUBSYS_USER_CHANNEL_CFG_0_AINP_Pos) | \
((uint32_t)ADC_DualCSInit->AINM0_Channel[i] << ADC_SUBSYS_USER_CHANNEL_CFG_0_AINM_Pos);
ADC_DualCSInit->ADC_CFGs[ADC_DualCSInit->Active_Channels-1].CHANNEL_CFG_1 = ((uint32_t)ADC_DualCSInit->AINP1_Channel[i] << ADC_SUBSYS_USER_CHANNEL_CFG_1_AINP_Pos) | \
((uint32_t)ADC_DualCSInit->AINM1_Channel[i] << ADC_SUBSYS_USER_CHANNEL_CFG_1_AINM_Pos);
}
else
{
/* 其他通道,设置触发和循环模式 */
if ((ADC_DualCSInit->Cycle_Mode == DISABLE) && (ADC_DualCSInit->Sequencer_Trigger == ADC_TRIGGER_HARDWARE))
{
ADC_DualCSInit->ADC_CFGs[i-1].ADC_CONTROL_0 = ADC_SUBSYS_USER_ADC_CONTROL_0_TRIG_SRC_SEL_Msk | (2u << ADC_SUBSYS_USER_ADC_CONTROL_0_MODE_Pos) | ADC_SUBSYS_USER_ADC_CONTROL_0_SIMU_Msk;
ADC_DualCSInit->ADC_CFGs[i-1].ADC_CONTROL_1 = ADC_SUBSYS_USER_ADC_CONTROL_1_TRIG_SRC_SEL_Msk | (2u << ADC_SUBSYS_USER_ADC_CONTROL_1_MODE_Pos);
}
else
{
ADC_DualCSInit->ADC_CFGs[i-1].ADC_CONTROL_0 = ADC_SUBSYS_USER_ADC_CONTROL_0_START_Msk | (2u << ADC_SUBSYS_USER_ADC_CONTROL_0_MODE_Pos) | ADC_SUBSYS_USER_ADC_CONTROL_0_SIMU_Msk;
ADC_DualCSInit->ADC_CFGs[i-1].ADC_CONTROL_1 = ADC_SUBSYS_USER_ADC_CONTROL_1_START_Msk | (2u << ADC_SUBSYS_USER_ADC_CONTROL_1_MODE_Pos);
}
/* 设ADC输入通道 */
ADC_DualCSInit->ADC_CFGs[i-1].CHANNEL_CFG_0 = ((uint32_t)ADC_DualCSInit->AINP0_Channel[i] << ADC_SUBSYS_USER_CHANNEL_CFG_0_AINP_Pos) | \
((uint32_t)ADC_DualCSInit->AINM0_Channel[i] << ADC_SUBSYS_USER_CHANNEL_CFG_0_AINM_Pos);
ADC_DualCSInit->ADC_CFGs[i-1].CHANNEL_CFG_1 = ((uint32_t)ADC_DualCSInit->AINP1_Channel[i] << ADC_SUBSYS_USER_CHANNEL_CFG_1_AINP_Pos) | \
((uint32_t)ADC_DualCSInit->AINM1_Channel[i] << ADC_SUBSYS_USER_CHANNEL_CFG_1_AINM_Pos);
}
}
/* 初始化ADC寄存器 */
ADC_Init->AINP = ADC_DualCSInit->AINP0_Channel[0]; // 装载首个通道
ADC_Init->AINM = ADC_DualCSInit->AINM0_Channel[0];
ADC_Init->Mode = ADC_MODE_SINGLE_CONVERSION; // 序列器模式固定为单次转换
ADC_Init->Trigger = ADC_DualCSInit->Sequencer_Trigger; // 首个通道触发源
LHL_ADC_Init(ADC_0, ADC_Init);
ADC_Init->AINP = ADC_DualCSInit->AINP1_Channel[0]; // 装载首个通道
ADC_Init->AINM = ADC_DualCSInit->AINM1_Channel[0];
LHL_ADC_Init(ADC_1, ADC_Init);
//LHL_ADC_SetSync(ENABLE);
/* Dummy寄存器赋值 */
for (uint8_t i = 0; i < ADC_DualCSInit->Active_Channels; i++)
{
ADC_DualCSInit->ADC_CFGs[i].INTERRUPT_CONTROL_0 = ADC_SUBSYS_USER_INTERRUPT_CONTROL_0_RESET;
ADC_DualCSInit->ADC_CFGs[i].CONFIGURATION_0 = pADC->CONFIGURATION_0;
ADC_DualCSInit->ADC_CFGs[i].CONFIGURATION_1 = pADC->CONFIGURATION_1;
ADC_DualCSInit->ADC_CFGs[i].FILTER_1 = pADC->FILTER_1;
}
return LHL_OK;
}
/*********************************End of File**********************************/