目录

01.01_ADC-软件触发

测试步骤

  1. 初始化ADC0以采样指定的通道(通道9)。
  2. 在主循环中,进行100次ADC采样,并计算采样结果的平均值。
  3. 将平均值转换为实际电压值

实测数据

浮点

右对齐

val = -0.276070

参考代码

01.01_ADC_DualRangeSample.c

/**
 * @brief ADC-软件触发
 * @details
 * 1. 初始化ADC0以采样指定的通道(通道9)。
 * 2. 在主循环中,进行100次ADC采样,并计算采样结果的平均值。
 * 3. 将平均值转换为实际电压值
 */

#include "lks32mc09x_adc.h"
#include "lks32mc09x_gpio.h"

#define ADC_SAMPLE_COUNT 1024
volatile float average = 0;
volatile s16 ADCSample[ADC_SAMPLE_COUNT];
volatile int flg;
volatile int adcval;
/**
 * @brief 初始化ADC0
 */
void ADC0_Init(void)
{
    ADC_InitTypeDef ADC_InitStruct;

    // 复位ADC0模块
    // Adc_Reset(ADC0);

    // 初始化ADC结构体
    ADC_StructInit(&ADC_InitStruct);

    // 配置ADC参数
    ADC_InitStruct.IE = 0;               // 禁用中断
    ADC_InitStruct.RE = 0;               // 禁用DMA请求
    ADC_InitStruct.NSMP = 0;             // 禁用两段采样
    ADC_InitStruct.DATA_ALIGN = 0;       // 右对齐
    ADC_InitStruct.CSMP = 0;             // 禁用连续采样
    ADC_InitStruct.TCNT = 0;             // 触发一次采样
    ADC_InitStruct.TROVS = 0;            // 禁用过采样
    ADC_InitStruct.OVSR = 0;             // 过采样率
    ADC_InitStruct.TRIG = ADC_TRIG_SOFT; // 软件触发
    ADC_InitStruct.S1 = 1;               // 触发1次采样1次
    ADC_InitStruct.S2 = 0;               // 第二段常规采样次数
    ADC_InitStruct.IS1 = 0;              // 空闲采样次数
    ADC_InitStruct.GAIN = ADC_GAIN_3V6;  // 3.6V量程
    ADC_InitStruct.LTH = 0;              // 禁用模拟看门狗
    ADC_InitStruct.HTH = 0xFFFF;         // 禁用模拟看门狗
    ADC_InitStruct.GEN = 0;              // 禁用模拟看门狗

    // 初始化ADC0
    ADC_Init(ADC0, &ADC_InitStruct);
    // 设置ADC0通道9
    ADC_SetChn(ADC0, ADC_DAT_0, ADC_CHN_11);
}
/**
 * @brief 主函数
 */
int main(void)
{
    uint32_t i;
    int32_t sum = 0;

    GPIO_Config(GPIO0, 0, GPIO_Mode_OUT, GPIO_AF_GPIO);
    // 初始化ADC0
    ADC0_Init();
    flg = 0;

    SYS_WR_PROTECT = 0x7a83;
    SYS_AFE_REG0 &= ~BIT15;
    while (1)
    {
        if (flg)
        {
            GPIO_SetBits(GPIO0, GPIO_Pin_0);
            // 进行100次采样
            for (i = 0; i < ADC_SAMPLE_COUNT; i++)
            {
                ADC_ClearIRQFlag(ADC0, ADC_IF_SF1);
                // 软件触发ADC采样
                ADC_SoftTrig(ADC0);
                while (ADC_GetIRQFlag(ADC0, ADC_IF_SF1) == 0)
                    ;
                // 获取采样结果
                ADCSample[i] = ADC_GetConversionValue(ADC0, ADC_DAT_0);
            }
            // 重置总和,为下一次采样做准备
            sum = 0;
            // 计算采样结果的总和
            for (i = 0; i < ADC_SAMPLE_COUNT; i++)
            {
                sum += (int32_t)ADCSample[i];
            }

            adcval = sum / ADC_SAMPLE_COUNT;
            // 计算平均值
            average = (float)sum * ((3.6f / 32752.0f) / ADC_SAMPLE_COUNT);
            GPIO_ResetBits(GPIO0, GPIO_Pin_0);
            flg = 0;
        }
    }
}

使用到的库函数

库函数部分代码

#define ADC0 ((ADC_TypeDef *)ADC0_BASE)
#define ADC0_CFG_DATA_ALIGN_BIT BIT10
#define ADC0_CHN0_PDS0(x) (uint32_t)(((x) & 0xF) << ADC0_CHN0_PDS0_POS)
#define ADC0_CHN0_PDS1(x) (uint32_t)(((x) & 0xF) << ADC0_CHN0_PDS1_POS)
#define ADC0_CHN0_PDS2(x) (uint32_t)(((x) & 0xF) << ADC0_CHN0_PDS2_POS)
#define ADC0_CHN0_PDS3(x) (uint32_t)(((x) & 0xF) << ADC0_CHN0_PDS3_POS)
#define ADC0_CHN1_PDS4(x) (uint32_t)(((x) & 0xF) << ADC0_CHN1_PDS4_POS)
#define ADC0_CHN1_PDS5(x) (uint32_t)(((x) & 0xF) << ADC0_CHN1_PDS5_POS)
#define ADC0_CHN1_PDS6(x) (uint32_t)(((x) & 0xF) << ADC0_CHN1_PDS6_POS)
#define ADC0_CHN1_PDS7(x) (uint32_t)(((x) & 0xF) << ADC0_CHN1_PDS7_POS)
#define ADC0_CHN2_PDS10(x) (uint32_t)(((x) & 0xF) << ADC0_CHN2_PDS10_POS)
#define ADC0_CHN2_PDS11(x) (uint32_t)(((x) & 0xF) << ADC0_CHN2_PDS11_POS)
#define ADC0_CHN2_PDS8(x) (uint32_t)(((x) & 0xF) << ADC0_CHN2_PDS8_POS)
#define ADC0_CHN2_PDS9(x) (uint32_t)(((x) & 0xF) << ADC0_CHN2_PDS9_POS)
#define ADC1 ((ADC_TypeDef *)ADC1_BASE)
#define GPIO_AF_I2C 6
#define NVR_ADDR_ADC_0_AMC0 0x00001424
#define NVR_ADDR_ADC_0_AMC1 0x0000142C
#define NVR_ADDR_ADC_0_DC0 0x00001420
#define NVR_ADDR_ADC_0_DC1 0x00001428
#define NVR_ADDR_ADC_1_AMC0 0x00001434
#define NVR_ADDR_ADC_1_AMC1 0x0000143C
#define NVR_ADDR_ADC_1_DC0 0x00001430
#define NVR_ADDR_ADC_1_DC1 0x00001438
#define REG_READ(reg) (reg)
#define REG_READ_BIT(reg,mask) ((reg) & (mask))
#define REG_READ_BIT_POS_MASK(reg,mask) (((reg) & (mask##_MASK)) >> mask##_POS)
#define REG_RESET(reg,mask) reg &= ~(mask)
#define REG_SET(reg,mask) reg |= (mask)
#define REG_WRITE(reg,mask) reg = (mask)
#define REG_WRITE_BIT(reg,mask,val) reg = ((reg) & ~(mask)) | (val)
#define SYS0 ((SYS_TypeDef *)(SYS_BASE))
#define SYS_MODULE_ADC0 BIT22
#define SYS_MODULE_ADC1 BIT23
#define SYS_MODULE_GPIO BIT11
/**
 * @brief ADC初始化结构体定义
 */
typedef struct ADC_InitTypeDef {
    uint16_t IE;
    uint16_t RE;
    uint16_t NSMP;
    uint16_t DATA_ALIGN;
    uint16_t CSMP;
    uint16_t TCNT;
    uint16_t TROVS;
    uint16_t OVSR;
    uint32_t TRIG;
    uint16_t S1;
    uint16_t S2;
    uint16_t IS1;
    uint16_t GAIN;
    uint16_t LTH;
    uint16_t HTH;
    uint16_t GEN;
    uint16_t IDLE_PRI;
};
/**
 * @brief ADC数据寄存器序号枚举定义
 */
typedef enum ADC_DAT_x {
    ADC_DAT_0 = 0,
    ADC_DAT_1 = 1,
    ADC_DAT_2 = 2,
    ADC_DAT_3 = 3,
    ADC_DAT_4 = 4,
    ADC_DAT_5 = 5,
    ADC_DAT_6 = 6,
    ADC_DAT_7 = 7,
    ADC_DAT_8 = 8,
    ADC_DAT_9 = 9,
    ADC_DAT_10 = 10,
    ADC_DAT_11 = 11,
}} {enum_name};
/**
 * @brief ADC采样通道序号枚举定义
 */
typedef enum ADC_CHN_x {
    ADC_CHN_0 = 0,
    ADC_CHN_1 = 1,
    ADC_CHN_2 = 2,
    ADC_CHN_3 = 3,
    ADC_CHN_4 = 4,
    ADC_CHN_5 = 5,
    ADC_CHN_6 = 6,
    ADC_CHN_7 = 7,
    ADC_CHN_8 = 8,
    ADC_CHN_9 = 9,
    ADC_CHN_10 = 10,
    ADC_CHN_11 = 11,
    ADC_CHN_12 = 12,
    ADC_CHN_13 = 13,
    ADC_CHN_14 = 14,
    ADC_CHN_15 = 15,
    ADC0_CHN_OPA0 = 0,
    ADC0_CHN_OPA1 = 1,
    ADC0_CHN_OPA2 = 2,
    ADC0_CHN_OPA3 = 3,
    ADC0_CHN_ADC01_CH4 = 4,
    ADC0_CHN_ADC01_CH5 = 5,
    ADC0_CHN_ADC01_CH6 = 6,
    ADC0_CHN_ADC01_CH7 = 7,
    ADC0_CHN_ADC0_CH8 = 8,
    ADC0_CHN_REF24 = 9,
    ADC0_CHN_ADC01_CH10 = 10,
    ADC0_CHN_ADC01_CH11 = 11,
    ADC0_CHN_ADC0_CH12 = 12,
    ADC0_CHN_ADC0_CH13 = 13,
    ADC0_CHN_DAC = 14,
    ADC0_CHN_AVSS = 15,
    ADC1_CHN_OPA0 = 0,
    ADC1_CHN_OPA1 = 1,
    ADC1_CHN_OPA2 = 2,
    ADC1_CHN_OPA3 = 3,
    ADC1_CHN_ADC01_CH4 = 4,
    ADC1_CHN_ADC01_CH5 = 5,
    ADC1_CHN_ADC01_CH6 = 6,
    ADC1_CHN_ADC01_CH7 = 7,
    ADC1_CHN_ADC1_CH8 = 8,
    ADC1_CHN_ADC1_CH9 = 9,
    ADC1_CHN_ADC01_CH10 = 10,
    ADC1_CHN_ADC01_CH11 = 11,
    ADC1_CHN_ADC1_CH12 = 12,
    ADC1_CHN_ADC1_CH13 = 13,
    ADC1_CHN_TMP = 14,
    ADC1_CHN_AVDD = 15,
}} {enum_name};
/**
 * @brief GPIO功能配置结构体句柄
 */
typedef struct GPIO_InitTypeDef {
    uint32_t GPIO_Pin;
    GPIO_Mode_TypeDef GPIO_Mode;
    GPIO_PuPd_TypeDef GPIO_PuPd;
    uint32_t GPIO_PODEna;
    uint32_t GPIO_PFLT;
};
/**
 * @brief GPIO模式选择枚举
 */
typedef enum GPIO_Mode_TypeDef {
    GPIO_Mode_IN = 0,
    GPIO_Mode_OUT = 1,
    GPIO_Mode_ANA = 2,
    GPIO_Mode_IO = 3,
}} {enum_name};
/**
 * @brief  GPIO配置函数
 * @param  GPIOx: GPIO端口
 * @param  GPIO_PinSource: GPIO引脚
 * @param  mode: GPIO模式
 * @param  GPIO_AF_x: GPIO复用功能选择
 */
void GPIO_Config(GPIO_TypeDef *GPIOx, uint32_t GPIO_PinSource, GPIO_Mode_TypeDef mode, uint32_t GPIO_AF_x)
{
    GPIO_PinAFConfig(GPIOx, GPIO_PinSource, GPIO_AF_x);
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_StructInit(&GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin  = 1 << GPIO_PinSource;
    GPIO_InitStructure.GPIO_Mode = mode;
    if (GPIO_AF_x == GPIO_AF_I2C)
    {
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    }
    else
    {
        __NOP();
    }
    GPIO_Init(GPIOx, &GPIO_InitStructure);
}
/**
 * @brief 使能ADC模块
 * @param ADCx: ADC模块指针,指向ADC0或ADC1
 */
void ADC_Enable(ADC_TypeDef *ADCx)
{
    REG_WRITE(SYS0->PROTECT, 0x7a83);
    // 使能ADC模块时钟
    REG_SET(SYS0->AFE_REG7, BIT8 | BIT9);
    REG_WRITE(SYS0->PROTECT, 0);
}
/**
 * @brief 初始化ADC模块
 * @param ADCx: ADC模块指针,指向ADC0或ADC1
 * @param ADC_InitStruct: 指向ADC初始化结构体的指针
 */
void ADC_Init(ADC_TypeDef *ADCx, ADC_InitTypeDef *ADC_InitStruct)
{
    ADC_Enable(ADCx);
    SYS_ModuleClockCmd(SYS_MODULE_ADC0, 1);
    SYS_ModuleClockCmd(SYS_MODULE_ADC1, 1);

    if (ADC_InitStruct->S2 == 0)
    {
        ADC_InitStruct->NSMP = DISABLE; // 当第二段采样次数为0时,不允许配置第二段使能
    }

    // 解锁SYS寄存器
    REG_WRITE(SYS0->PROTECT, 0x7a83);

    // 配置ADC初始化结构体中的各个成员
    REG_WRITE(ADCx->IE, ADC_InitStruct->IE | ADC_InitStruct->RE);

    // 计算并一次性配置CFG寄存器
    REG_WRITE(ADCx->CFG, ((ADC_InitStruct->NSMP << 12) |
                          (1 << 11) | // 初始化时复位adc状态机
                          (ADC_InitStruct->DATA_ALIGN << 10) |
                          (ADC_InitStruct->IDLE_PRI << 9) |
                          (ADC_InitStruct->CSMP << 8) |
                          (ADC_InitStruct->TCNT << 4) |
                          (ADC_InitStruct->TROVS << 3) |
                          (ADC_InitStruct->OVSR << 0)));

    REG_WRITE(ADCx->TRIG, ADC_InitStruct->TRIG);

    // 配置CHNT寄存器
    REG_WRITE(ADCx->CHNT, (REG_READ(ADCx->CHNT) & ~((0x0F << 0) | (0x0F << 4) | (0x0F << 8))) |
                              ((ADC_InitStruct->S1 << 0) |
                               (ADC_InitStruct->S2 << 4) |
                               (ADC_InitStruct->IS1 << 8)));

    // 配置GAIN寄存器
    REG_WRITE_BIT(ADCx->GAIN, 1 << 0, ADC_InitStruct->GAIN << 0);

    REG_WRITE(ADCx->LTH, ADC_InitStruct->LTH);
    REG_WRITE(ADCx->HTH, ADC_InitStruct->HTH);
    REG_WRITE(ADCx->GEN, ADC_InitStruct->GEN);
    if (ADCx == ADC0)
    {
        REG_WRITE(ADCx->AMC0, TRIM_Read(NVR_ADDR_ADC_0_AMC0));
        REG_WRITE(ADCx->DC0, TRIM_Read(NVR_ADDR_ADC_0_DC0));
        REG_WRITE(ADCx->AMC1, TRIM_Read(NVR_ADDR_ADC_0_AMC1));
        REG_WRITE(ADCx->DC1, TRIM_Read(NVR_ADDR_ADC_0_DC1));
    }
    else if (ADCx == ADC1)
    {
        REG_WRITE(ADCx->AMC0, TRIM_Read(NVR_ADDR_ADC_1_AMC0));
        REG_WRITE(ADCx->DC0, TRIM_Read(NVR_ADDR_ADC_1_DC0));
        REG_WRITE(ADCx->AMC1, TRIM_Read(NVR_ADDR_ADC_1_AMC1));
        REG_WRITE(ADCx->DC1, TRIM_Read(NVR_ADDR_ADC_1_DC1));
    }
    else
    {
        __NOP();
    }
}
/**
 * @brief 初始化GPIO
 * @param GPIOx GPIO模块指针
 * @param GPIO_InitStruct 指向包含初始化参数的GPIO_InitTypeDef结构体
 */
void GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_InitStruct)
{
    // 使能GPIO时钟
    SYS_ModuleClockCmd(SYS_MODULE_GPIO, ENABLE);

    // 配置引脚模式
    if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IN)
    {
        GPIOx->PIE |= GPIO_InitStruct->GPIO_Pin;  // 打开输入使能
        GPIOx->POE &= ~GPIO_InitStruct->GPIO_Pin; // 关闭输出使能
        GPIOx->PUE &= ~GPIO_InitStruct->GPIO_Pin; // 关闭上拉使能
    }
    else if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_OUT)
    {
        GPIOx->PIE &= ~GPIO_InitStruct->GPIO_Pin; // 关闭输入使能
        GPIOx->POE |= GPIO_InitStruct->GPIO_Pin;  // 使能输出
    }
    else if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IO)
    {
        GPIOx->PIE |= GPIO_InitStruct->GPIO_Pin; // 使能输入
        GPIOx->POE |= GPIO_InitStruct->GPIO_Pin; // 使能输出
    }
    else // GPIO_Mode_ANA
    {
        GPIOx->PIE &= ~GPIO_InitStruct->GPIO_Pin; // 关闭输入使能
        GPIOx->POE &= ~GPIO_InitStruct->GPIO_Pin; // 关闭输出使能
        GPIOx->PUE &= ~GPIO_InitStruct->GPIO_Pin; // 关闭上拉使能
    }

    if (GPIO_InitStruct->GPIO_PuPd == GPIO_PuPd_UP)
    {
        GPIOx->PUE |= GPIO_InitStruct->GPIO_Pin; // 使能上拉
    }
    else
    {
        GPIOx->PUE &= ~GPIO_InitStruct->GPIO_Pin; // 关闭上拉
    }
    // 配置开漏使能
    if (GPIO_InitStruct->GPIO_PODEna)
    {
        GPIOx->PODE |= GPIO_InitStruct->GPIO_Pin;
    }
    else
    {
        GPIOx->PODE &= ~GPIO_InitStruct->GPIO_Pin;
    }

    // 配置滤波使能
    if (GPIO_InitStruct->GPIO_PFLT)
    {
        GPIOx->PFLT |= GPIO_InitStruct->GPIO_Pin;
    }
    else
    {
        GPIOx->PFLT &= ~GPIO_InitStruct->GPIO_Pin;
    }
}
/**
 * @brief 初始化GPIO结构体为默认值
 * @param GPIO_InitStruct 指向要初始化的GPIO_InitTypeDef结构体
 */
void GPIO_StructInit(GPIO_InitTypeDef *GPIO_InitStruct)
{
    for (int i = 0; i < sizeof(GPIO_InitTypeDef); i++)
    {
        ((uint8_t *)GPIO_InitStruct)[i] = 0;
    }
}
/**
 * @brief 复位指定的GPIO引脚位
 * @param GPIOx GPIO模块指针
 * @param GPIO_Pin 要复位的引脚
 */
void GPIO_ResetBits(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
{
    GPIOx->PDO &= ~GPIO_Pin;
}
/**
 * @brief 将ADC初始化结构体置为默认值
 * @param ADC_InitStruct: 指向ADC初始化结构体的指针
 */
void ADC_StructInit(ADC_InitTypeDef *ADC_InitStruct)
{
    for (int i = 0; i < sizeof(ADC_InitTypeDef) / sizeof(uint16_t); i++)
    {
        ((uint16_t *)ADC_InitStruct)[i] = 0;
    }
}
/**
 * @brief 执行软件触发ADC采样,采样次数取决于ADC_InitTypeDef里的S1的配置
 * @param ADCx: ADC模块指针,指向ADC0或ADC1
 */
void ADC_SoftTrig(ADC_TypeDef *ADCx)
{
    // 写入软件触发值
    REG_WRITE(ADCx->SWT, 0x5AA5);
}
/**
 * @brief 数字模块时钟使能
 * @param nModule 模块编号
 * @param state 使能或禁用状态
 */
void SYS_ModuleClockCmd(uint32_t nModule, uint8_t state)
{
    REG_WRITE(SYS0->PROTECT, 0x7a83);
    if (state)
    {
        REG_SET(SYS0->CLK_FEN, nModule);
    }
    else
    {
        REG_RESET(SYS0->CLK_FEN, nModule);
    }
    REG_WRITE(SYS0->PROTECT, 0);
}
/**
 * @brief 清除ADC中断标志位
 * @param ADCx: ADC模块指针,指向ADC0或ADC1
 * @param INT_flag: 中断标志位,可以是ADC_IF_ISF等
 */
void ADC_ClearIRQFlag(ADC_TypeDef *ADCx, uint16_t INT_flag)
{
    REG_WRITE(ADCx->IF, INT_flag);
}
/**
 * @brief 获取ADC中断标志位状态
 * @param ADCx: ADC模块指针,指向ADC0或ADC1
 * @param INT_flag: 中断标志位,可以是ADC_IF_ISF等
 * @return 中断标志位状态
 */
uint16_t ADC_GetIRQFlag(ADC_TypeDef *ADCx, uint16_t INT_flag)
{
    return REG_READ_BIT(ADCx->IF, INT_flag) ? 1 : 0;
}
/**
 * @brief 获取ADC通道的转换值
 * @param ADCx: ADC模块指针,指向ADC0或ADC1
 * @param DATNum: 数据寄存器序号,如ADC_DAT_0
 * @return 转换值
 */
s16 ADC_GetConversionValue(ADC_TypeDef *ADCx, ADC_DAT_x DATNum)
{
    int32_t adc_dat = ADC_GetConversionValueS32(ADCx, DATNum);
    // adc_dat不会小于-32767,这里不做判断
    if (adc_dat > 32767)
    {
        adc_dat = 32767;
    }
    return adc_dat;
}
/**
 * @brief 获取ADC通道的转换值(按int32返回,采样通道4、5、6、7时,返回值大于32767)
 * @param ADCx: ADC模块指针,指向ADC0或ADC1
 * @param DATNum: 数据寄存器序号,如ADC_DAT_0
 * @return 转换值
 */
int32_t ADC_GetConversionValueS32(ADC_TypeDef *ADCx, ADC_DAT_x DATNum)
{

    int32_t adc_dat  = 0;
    uint16_t adc_chn = 0;
    switch (DATNum)
    {
        case ADC_DAT_0:
            adc_dat = REG_READ(ADCx->DAT0);
            adc_chn = REG_READ_BIT_POS_MASK(ADCx->CHN0, ADC0_CHN0_PDS0);
            break;
        case ADC_DAT_1:
            adc_dat = REG_READ(ADCx->DAT1);
            adc_chn = REG_READ_BIT_POS_MASK(ADCx->CHN0, ADC0_CHN0_PDS1);
            break;
        case ADC_DAT_2:
            adc_dat = REG_READ(ADCx->DAT2);
            adc_chn = REG_READ_BIT_POS_MASK(ADCx->CHN0, ADC0_CHN0_PDS2);
            break;
        case ADC_DAT_3:
            adc_dat = REG_READ(ADCx->DAT3);
            adc_chn = REG_READ_BIT_POS_MASK(ADCx->CHN0, ADC0_CHN0_PDS3);
            break;
        case ADC_DAT_4:
            adc_dat = REG_READ(ADCx->DAT4);
            adc_chn = REG_READ_BIT_POS_MASK(ADCx->CHN1, ADC0_CHN1_PDS4);
            break;
        case ADC_DAT_5:
            adc_dat = REG_READ(ADCx->DAT5);
            adc_chn = REG_READ_BIT_POS_MASK(ADCx->CHN1, ADC0_CHN1_PDS5);
            break;
        case ADC_DAT_6:
            adc_dat = REG_READ(ADCx->DAT6);
            adc_chn = REG_READ_BIT_POS_MASK(ADCx->CHN1, ADC0_CHN1_PDS6);
            break;
        case ADC_DAT_7:
            adc_dat = REG_READ(ADCx->DAT7);
            adc_chn = REG_READ_BIT_POS_MASK(ADCx->CHN1, ADC0_CHN1_PDS7);
            break;
        case ADC_DAT_8:
            adc_dat = REG_READ(ADCx->DAT8);
            adc_chn = REG_READ_BIT_POS_MASK(ADCx->CHN2, ADC0_CHN2_PDS8);
            break;
        case ADC_DAT_9:
            adc_dat = REG_READ(ADCx->DAT9);
            adc_chn = REG_READ_BIT_POS_MASK(ADCx->CHN2, ADC0_CHN2_PDS9);
            break;
        case ADC_DAT_10:
            adc_dat = REG_READ(ADCx->DAT10);
            adc_chn = REG_READ_BIT_POS_MASK(ADCx->CHN2, ADC0_CHN2_PDS10);
            break;
        case ADC_DAT_11:
            adc_dat = REG_READ(ADCx->DAT11);
            adc_chn = REG_READ_BIT_POS_MASK(ADCx->CHN2, ADC0_CHN2_PDS11);
            break;
        default:
            adc_dat = 0;
            break;
    }
    // 先按照int16处理一下
    adc_dat = (int16_t)(adc_dat & 0xffff);
    // ADC0/1采样公共通道4/5/6/7时,负端电压为2.4V,实际允许的输入电压范围是
    // if ((adc_chn == 4) || (adc_chn == 5) || (adc_chn == 6) || (adc_chn == 7))
    // {
    //     int32_t dat = adc_dat;
    //     if (REG_READ_BIT(SYS_AFE_REG4, BIT4) == 0)
    //     {
    //         if (REG_READ_BIT(ADC0_CFG, ADC0_CFG_DATA_ALIGN_BIT) == 0)
    //         { // 左对齐
    //             dat = dat + 0x5550;
    //             adc_dat = dat;
    //         }
    //         else
    //         { // 右对齐
    //             dat = dat + 0x555;
    //             adc_dat = dat;
    //         }
    //     }
    // }
    return adc_dat;
}
/**
 * @brief 设置指定的GPIO引脚位
 * @param GPIOx GPIO模块指针
 * @param GPIO_Pin 要设置的引脚
 */
void GPIO_SetBits(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
{
    GPIOx->PDO |= GPIO_Pin;
}
/**
 * @brief 设置第每次的采样通道,例如ADC_SetChn(ADC0,ADC_DAT_0,ADC_CHN_0),把adc第一次采样的通道设置为通道0
 * @param ADCx: ADC模块指针,指向ADC0或ADC1
 * @param datx: 数据寄存器序号,如ADC_DAT_0
 * @param chnx: ADC采样通道序号枚举定义,如ADC_CHN_0
 */
void ADC_SetChn(ADC_TypeDef *ADCx, ADC_DAT_x datx, ADC_CHN_x chnx)
{
    uint8_t n = (datx & 0x3) * 4;
    switch (datx)
    {
        case ADC_DAT_0:
            REG_WRITE(ADCx->CHN0, (REG_READ(ADCx->CHN0) & (~(0xf << n))) | (chnx << n));
            break;
        case ADC_DAT_1:
            REG_WRITE(ADCx->CHN0, (REG_READ(ADCx->CHN0) & (~(0xf << n))) | (chnx << n));
            break;
        case ADC_DAT_2:
            REG_WRITE(ADCx->CHN0, (REG_READ(ADCx->CHN0) & (~(0xf << n))) | (chnx << n));
            break;
        case ADC_DAT_3:
            REG_WRITE(ADCx->CHN0, (REG_READ(ADCx->CHN0) & (~(0xf << n))) | (chnx << n));
            break;
        case ADC_DAT_4:
            REG_WRITE(ADCx->CHN1, (REG_READ(ADCx->CHN1) & (~(0xf << n))) | (chnx << n));
            break;
        case ADC_DAT_5:
            REG_WRITE(ADCx->CHN1, (REG_READ(ADCx->CHN1) & (~(0xf << n))) | (chnx << n));
            break;
        case ADC_DAT_6:
            REG_WRITE(ADCx->CHN1, (REG_READ(ADCx->CHN1) & (~(0xf << n))) | (chnx << n));
            break;
        case ADC_DAT_7:
            REG_WRITE(ADCx->CHN1, (REG_READ(ADCx->CHN1) & (~(0xf << n))) | (chnx << n));
            break;
        case ADC_DAT_8:
            REG_WRITE(ADCx->CHN2, (REG_READ(ADCx->CHN2) & (~(0xf << n))) | (chnx << n));
            break;
        case ADC_DAT_9:
            REG_WRITE(ADCx->CHN2, (REG_READ(ADCx->CHN2) & (~(0xf << n))) | (chnx << n));
            break;
        case ADC_DAT_10:
            REG_WRITE(ADCx->CHN2, (REG_READ(ADCx->CHN2) & (~(0xf << n))) | (chnx << n));
            break;
        case ADC_DAT_11:
            REG_WRITE(ADCx->CHN2, (REG_READ(ADCx->CHN2) & (~(0xf << n))) | (chnx << n));
            break;
    }
}
/**
 * @brief 配置GPIO引脚复用功能
 * @param GPIOx GPIO模块指针
 * @param GPIO_PinSource 引脚源
 * @param GPIO_AF 复用功能选择
 */
void GPIO_PinAFConfig(GPIO_TypeDef *GPIOx, uint32_t GPIO_PinSource, uint32_t GPIO_AF)
{
    uint8_t offset;
    uint8_t pins = GPIO_PinSource >> 2;
    offset       = ((GPIO_PinSource & 0x3) * 4);
    switch (pins)
    {
        case 0:
            GPIOx->F3210 = (GPIOx->F3210 & ~(0xf << offset)) | (GPIO_AF << offset);
            break;
        case 1:
            GPIOx->F7654 = (GPIOx->F7654 & ~(0xf << offset)) | (GPIO_AF << offset);
            break;
        case 2:
            GPIOx->FBA98 = (GPIOx->FBA98 & ~(0xf << offset)) | (GPIO_AF << offset);
            break;
        case 3:
            GPIOx->FFEDC = (GPIOx->FFEDC & ~(0xf << offset)) | (GPIO_AF << offset);
            break;
        default:
            break;
    }
}