MCAL配置之ADC模块及IO抽象层源码分析

ADC模块是将外部模拟信号转化为芯片内可识别的数字信号的中间模块,与MCU的关联为使用了MCU提供的GTM模块中的TOM/ATOM部分的定时效果。

1 ADC界面分析

在ADC界面中,主要配置界面为General, AdcGlobalInputClass和AdcHwUnit三个选项卡。在General选项卡中,通常会使能AdcErrorDetect、AdcReadGroup、AdcEnableStartStopGroup、AdcHwTrigger等选项。第一项将使能ADC的DET检测功能;第二三项将使能软件触发ADC开始、停止组内AD转换和读取组内转换结果的功能;第三项将使能软件控制硬件触发AD转换的接口。

AdcResultHandlingImplementation选择中断模式处理,在第四章中会讲述OS中配置的具体中断。

AdcResultAlignment指定ADC结果的对其方式,一般以右对齐为主,将数据按字节顺序组合起来即得到正确结果。

AdcMaxChConvTimeCount将指定ADC驱动停止转换时需要将转换器状态变化至idle的最大时间,在此软件中默认值为6000ms。

在AdcGlobalInputClass选项卡中,定义了AdcGlobalInputClass的两种类型,包含ADC通道转换模式(指定接收信号的噪声滤波模式)、ADC时钟预分频系数、ADC采样时间长度设置(当前采样时间为2 / fADCI)和ADC传播早期采样点的使能(用于衰减同步噪声)四个配置项。理论上两种类型可以配置为不同的性质组合,但由于这里的类型不会被HwUnit中使用,故配置为统一默认选项。

在AdcHwUnit选项卡中,需要配置所有ADC硬件group的信息。根据硬件原理图的显示,我们需要配置Group0, Group1, Group2和Group8。

在每一个HwUnit选项卡中,包含了ADC时钟源、预分频系数、通道信息、触发条件等配置选项。在下一节中将结合数据手册和硬件原理图对部分重要选项作详细介绍。

2 ADC关键配置选项

①AdcHwUnitId

由DataSheet中定义的EVADC管脚复用状态可知AdcHwUnit一共分为0,1,2,3,8,9,10和11几种Group号码,在本项目中仅使用0,1,2和8四个Group号。

②AdcClockSource

指定ADC的时钟源,在Aurix2G中仅能选择系统时钟,与General选项卡中的AdcSystemClock呼应,通过该选项指定系统时钟源。

③AdcChannelId

在每一个Group中需要指定的通道号,该号码需要和硬件原理图上的号码对应起来。

④AdcAnChannelNum

AdcHwUnitId和AdcChannelId共同决定了该参数的配置,格式为GxCHy。

⑤AdcInputClassSelection

指定ADC信号输入类型,可在AdcHwUnitInputClass和AdcGlobalInputClass中选择。此处选择HwUnit中自定义的类型。

⑥AdcGroupAccessMode

当该参数为ADC_ACCESS_MODE_SINGLE时,ADC上层在一次触发后只读取一次结果,当该参数为ADC_ACCESS_MODE_STREAMING时,ADC上层便可在一次触发后可读取多次结果,同时该参数需配合AdcStreamingBufferMode共同使用。本项目中使用ADC_ACCESS_MODE_SINGLE。

⑦AdcGroupConversionMode

该参数代表Adc启动转换的模式,有ONESHOT和CONTINUOUS两种。前者表示转换触发后每个通道仅做一次转换,后者表示转换触发后每个通道可做多次连续的转换。本项目中使用ONESHOT方式。

⑧AdcGroupTriggSrc

有HW和SW两种触发方式,使用HW触发时,只能配合ONESHOT的转换模式,此时若配合定时器则可产生连续采样的效果,一般通过一个二维数组(结果缓存)直接读取硬件触发的转换结果,该二维数组包含了每一个Group中的所有通道结果。使用SW触发时,可配合Adc_StartGroupConversion、Adc_ReadGroup等函数读取转换后的数值。本项目中使用HW触发。

⑨AdcStreamingBufferMode

该参数配合AdcGroupAccessMode为ADC_ACCESS_MODE_STREAMING时使用,软件中会在每个通道中开辟一段空间作为采样空间。当参数为LINEAR时,ADC转换数量等于采样数,当采样数用完后自动停止;当参数为CIRCULAR时,ADC转换不会主动停止,当采样数用完后会从头进行采样并放置,直到调用停止函数。

⑩AdcHwExtTrigSelect

此选项配合AdcGroupTriggSrc为HW方式时使用,指定硬件触发源。

⑪AdcHwTrigSignal

此选项配合AdcGroupTriggSrc为HW方式时使用,指定在哪个信号跳变沿会进行硬件触发。次处选择ADC_HW_TRIG_RISING_EDGE。

⑫GtmTimerUsed

指定使用MCU模块中的哪一个定时器,此处我们使用TOM,在MCU中需要将对应通道配置为ADC的使用方式。

3 MCU关键配置选项

在MCU中需要配置用于ADC转换的GTM时钟,同时,在配置前需要清楚哪些通道可以用来作为该转换使用。

①McuGtmTomChannelAllocationConf

指定该TOM通道被分配用于ADC转换的时间触发源,故选择GTM_TOM_CHANNEL_USED_BY_ADC。

②McuTomChannelEventHandledByDsadc

指定TOM通道的触发事件将是否被DSADC模块处理,我们使用的转换模块为EVADC,故此项选择为FALSE。

4 OS关键配置选项

根据第一章中对AdcHwUnit部分的分析,四个Group各自需要一个中断关联至硬件触发源,故需要在OS中配置四个ADC中断:ADC0SR0, ADC1SR0, ADC2SR0, ADC8SR0。下图展示的是其中之一的配置,注意需将Address/Vector的选项和ISR的名字保持一致,四个ISR都属于二类中断,优先级保持连续即可。

5 与IoHwAb层相关的源码分析

ADC部分的IO抽象层源码会通过枚举体定义每个HwUnit和通道信号的名称,在Buffer读取函数中可方便管理。同时,我们需要定义一个GroupType和Channel相关信息的结构体,前者用于设定每个Group的状态,后者用于对接收值做转换管理。最后,定义一个用于管理每个Group中信号值的数组。定义部分源码如下所示:

typedef enum
{
    ADC_VBAT_12V,
    ADC_IG_12V,
    ......
    ADC_PROJ_ID,
    ADC_PCB_TEMP,

    IoHwAb_ADC_Signal_MAX
}IoHwAb_ADC_Signal;

typedef enum
{
    ADC_HWUNIT_0,
    ADC_HWUNIT_1,
    ADC_HWUNIT_2,
    ADC_HWUNIT_8,
    IoHwAb_ADC_HwUnit_MAX
} IoHwAb_ADC_HwUnit;

typedef struct
{
    Adc_GroupType group;
} IoHwAb_ADC_Group_Config;

typedef struct
{
    IoHwAb_ADC_HwUnit hwunit;
    uint8 channel;
    Adc_GroupType  immediateGroup;
    float32 coff;
} IoHwAb_ADC_Channel_Config;

static Adc_ValueGroupType IoHwAb_ADC_Buffer[IoHwAb_ADC_HwUnit_MAX][IOHWAB_ADC_CHANNELS_PER_HWUNIT];

在初始化函数中,会对每一个HwUnit进行结果缓存的初始化,最后打开硬件触发源。之后,IoHwAb_ADC_Buffer数组会被自动更新。

void IoHwAb_ADC_Init(void)
{
    uint8 grp_idx;
    Adc_GroupType adc_group;
    Adc_ValueGroupType* adc_valueGroup;

    for (grp_idx = 0; grp_idx < IoHwAb_ADC_HwUnit_MAX; grp_idx++)
    {
        adc_group = IoHwAb_ADC_Group_Cfg[grp_idx].group;
        adc_valueGroup = &IoHwAb_ADC_Buffer[grp_idx][0];

        /* Initialise the Result buffer for group */
        ret_t[grp_idx] = Adc_SetupResultBuffer(adc_group, adc_valueGroup);

        /* Start the group */
        Adc_EnableHardwareTrigger(adc_group);
    }
}

在缓存读取函数中,会将读取的数字量转换为模拟量。值得注意的是,AD转换的二进制位总共有12bit,故分辨率为1/4095。在硬件部分使用的电压阈值上限为5V,故最终乘以5得到模拟电压。

float32 IoHwAb_ADC_GetBufferedValue(IoHwAb_ADC_Signal in_ad)
{    
    IoHwAb_ADC_HwUnit ad_hwunit; 
    uint8 ad_channel;
    uint16 ad_value_raw;
    float32 ad_value;    
    float32 ad_coff;

    ad_hwunit = IoHwAb_ADC_Channel_Cfg[in_ad].hwunit;
    ad_channel = IoHwAb_ADC_Channel_Cfg[in_ad].channel;
    ad_coff = IoHwAb_ADC_Channel_Cfg[in_ad].coff * 4095 / 5;

    ad_value_raw = IoHwAb_ADC_Buffer[ad_hwunit][ad_channel];

    ad_value = (float32)ad_value_raw / (float32)ad_coff;

    return ad_value;
}
  • 9
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值