AUTOSAR笔记:IO系列驱动
I/O架构
Application SWC、Sensor SWC、Actuator SWC是什么关系?它们如何利用硬件读取数据、处理数据、执行动作?
下图展示了它们的关系:

from ref. [1]
Application SWC、Sensor SWC、Actuator SWC都是位于应用层,它们通过Port通信,利用RTE层接口访问硬件.
IoHwAb 可在Davinci中申请一个SWC为“I/O - Hardware Abstraction(application layer)”,来作为一个c文件,在其中添加c代码. 也就是当成SWC使用.
MCAL Drivers 是芯片原厂提供的MCU驱动.
I/O系列驱动
AUTOSAR中,I/O ≠ GPIO,而是指DIO(数字输入输出)、PORT、PWM、ICU(Input Compare Unit)、OCU(Output Compoare Unit)、ADC.
EB中配置MCAL,类似于CubeMX中配置MCU、ProcessorExpert中配置MCU,用图形工具配置底层,自动生成C代码.
PORT驱动
PORT驱动主要能配置以下功能:
- IO口模式选择:GPIO/功能复用
- IO口方向:输入/输出
- IO口是否允许在运行过程中改变方向:是/否
- IO口的初始化电平:高/低
- IO口的转换速率
- IO口是否上拉:是/否
- IO口的输入阈值
- IO口的驱动模式:推挽/开漏
- IO口的回读支持类型:电平、输出寄存器值
DIO驱动
DIO常用于
1)给IO口重命名,如pin33 ➡ LED_RED
2)将一些功能相近的通道分到一个组统一管理
PWM驱动
提供常用PWM操作,如:
- 访问硬件通道
- PWM周期
- PWM占空比
- PWM极性:高/低
- PWM空闲状态:高/低
- 相位移(Phase Shift)
下图展示了PWM使用方法:

from ref. [2]
ICU驱动
ICU(Input Compare Unit,输入比较单元),主要功能:
- 边沿计数(Edge Count)
- 边沿检测和通知
- 时间戳
- 信号测量
- 作为唤醒源用
边沿计数
捕获输入的脉冲信号的边沿.
支持以下API:
- Icu_Init: ICU初始化,设置计数模式
- Icu_EnableEdgeCount: 使能ICU边沿计数,这之后开始计数
- Icu_DisableEdgeCount:禁用ICU边沿计数,数据不会清零,会一直保持
- Icu_GetEdgeNumbers: 获取当前ICU的边沿计数
- Icu_ResetEdgeCount: 重置计数
下面例子,配置为边沿计数模式,对双边沿都进行计数:

from ref.[2]
边沿检测(Signal Edge Detection)
检测到对应类型边沿(上升沿、下降沿),会产生一个硬件中断,然后通知上层.
示例1:配置为检测下降沿,但通知函数设为NULL,因此即使能通知EnableNotification,也不会调用上层通知函数
- Icu_EnableNotification: 使能通知功能. 需要搭配通知函数使用,否则无效
- Icu_GetInputState: 获取输入状态,获取后状态重置为IDLE

from ref. [2]
示例2:启用通知功能,初始配置为检测下降沿,但在通知函数中修改为检测上升沿
- Icu_SetActivationCondition: 变更激活条件,由下降沿变为上升沿
- Icu_DisableNotification: 禁止通知

from ref. [2]
示例3:信号测量(signal measurement),测量信号的时间长度,支持低电平时长、高电平时长、周期时长、占空比
- Icu_StartSignalMeasurement: 开始信号测量
- Icu_GetTimeElapsed: 获取时间长度
- Icu_GetDutyCycleValue:过去pwm的周期和占空比

from ref. [2]
示例4:时间戳(Timestamping)
1)线性buffer模式
在Bsw层,设置一个数组作为缓存buffer,记录一定连续数量的边沿时间戳
-
BufferSize,buffer元素个数. 设置BufferPtr size=4,对应4个黄色方块(buffer 4个元素),后面4个是指随着时间变化后的buffer
-
NotifyInterval,通知间隔. 根据设置的间隔大小进行触发通知,如设置为4,那么bufferPtr[3]存入数据时触发通知
-
Icu_SetActivationCondition,设置触发条件,如下降沿,即下降沿到来时,写一个时间戳到buffer中
-
Icu_GetTimestampIndex,当前时间戳目录,每当周期循环一遍(从0x0000->0xFFFF),index+1. 注意不是每写一个时间戳,index加1
-
Icu_StartTimestamp,激活时间戳功能. 线性buffer模式下,记录的buffer满了,就会停止时间戳的记录,需要手动再次激活

2)循环buffer模式
线性buffer写满后,会停止记录时间戳,需要调用Icu_StartTimestamp重新激活. 而循环buffer则会一直自动记录
注:目前还不确定buffer满后,从头开始记录,还是丢弃最开始记录的时间戳(个人推测是后者)
OCU驱动
OCU(Output Compare Unit,输出比较单元),类似于PWM的生成机制,计数器值达到设定阈值时,比较成功,就执行某个指定动作. OCU主要功能:
- 开始或停止一个比较过程
- 设置比较阈值
- 使能或禁用通知机制
- 获取计数值
- 改变输出引脚状态
- 触发硬件资源(如ADC、PWM等)
ADC驱动
功能:
- 模拟信号 ➡ 数字信号
- 封装转换信号的访问接口
- 配置不同的模式
- 对转换的一个通知机制
分组(ADC Groups):
将某些功能相近ADC Channels划分到某个组里(每组至少1个通道). 一个组必须在一个ADC硬件单元内,不能跨硬件单元组成ADC组
转换模式:
- 循环转换
- 单词转换
触发模式:
- 硬件触发:配置后,可由其他外设触发ADC,如周期定时器,在定时中断内触发ADC;IO口上升沿触发ADC
- 软件触发:用户对芯片软件触发寄存器写值触发ADC. 软件调用API,直接触发
Buffer初始化:
ADC结果最终需要存放到一个buffer数组(用户定义)中,供用户使用. 但如何将设定好的buffer自动存入ADC数据?
可以通过MCAL中的Adc_SetupResultBuffer注册数组
/*
如果我们的ADC0的一个ADC_Group_0 包含5个通道,我们要将结果存入ADC_SW_GRP_RES[5]数组
*/
// 申请数组存放ADC数据
Adc_ValueGroupType ADC_SW_GRP_RES[5];
// 注册指针到ADC0的group 0(AdcGroup0_0)
Adc_SetupResultBuffer(AdcConf_AdcGroup_AdcGroup0_0, ADC_SW_GRP_RES);
Stream模式:
ADC可以存放多个时刻的采样值. 相当于为每个通道申请一个数组,该数组能存放多个ADC值.
例如,假设ADC0包含ADC_Group_0组,其中5个通道,每个通道开启Stream模式,且深度为2. 那么存放结果的ADC_SW_GRP_RES数组需要存放5x2=10个元素
这10个数据的存放如下:

每个通道有个FIFO,每个FIFO深度2. 有2种模式:循环模式、线性模式,都是针对每个FIFO刷新数据的.

浙公网安备 33010602011771号