S32K3学习笔记—S32K3之ICU模块
1.前言
本文将Emios用于输入捕获测量信号周期、频率、占空比,在实际中,ICU的作用还是比较多,Hall采集、边缘捕获、跳沿唤醒等等。本文简单的记录几种使用情况的配置及实现的方式。
2.原理
关于Emios的原理可以参考S32K3学习笔记—S32K3之PWM模块原理此处不再重复。
3.EB配置
ICU依赖于Port、Mcu、Platform、Mcl、Icu模块
在配置ICU模块之前,可以先参考PWM的配置S32K3学习笔记—S32K3之PWM模块,PWM和ICU其依赖的很多模块几乎是一样的。
1.Port
Port主要是配置IO模式,具体Port配置可参考之前文章 S32K3学习笔记—S32K3之Gpt、Dio、Platform
1.选择EMIOS_IN模式
2.映射对应的EMIOS通道
2.Mcu
Icu和Pwm都是eMOIS的一部分,此处时钟源还是CORE_CLK,如果PWM配置完成,MCU模块就不需要再配置,关于MCU的详细配置可以参考 S32K3学习笔记—S32K3之MCU模块,此处简单记录。
1.此处选择的系统时钟160M,此参数用于最后的Master Bus频率
1.使能eMIOS模块时钟,此处勿忘
3.Platform
1.此处使能对应的中断
4.Mcl
1.支持多核使能
2.需要用到eMIOS必须使能
1.使能支持调试状态
2.使能全局时基
3.时钟分频,此参数用于最后的Master Bus频率
4.资源映射到给哪个核
1.根据需求注册counter bus, 此处将eMIOS通道0的所有counter bus全部分配,习惯BUS_F只用于ICU
1.选择eMIOS通道
2.此处选择向上计数模式 MCB_UP_COUNTER,可以根据需求选择方式
3.对于ICU模块,此参数固定65535。
4.此偏移仅在通道启动时适用
5.Counter Bus分频系数,此参数用于最后的Counter Bus频率
6.是否支持DEBUG模式
7.ICU模式下不使能
注: Counter Bus频率 == CoreClock / ClockDividerValue / DefaultPeriod / MasterBusPrescaler 。
5.ICU模块
1.是否需要上报唤醒源
2.使能支持多核
3.根据需求使能一些非Autosar标准的API和使能一些宏
4.按照需求使能相应的API
1.注册我们所需要的硬件中断
1.是否支持DEBUG模式,在debug的时候状态保持
2.内部分频系数,此处不使用内部定时器
3.输入滤波器
4.选择Counter Bus,此处将BUS_F用于输入捕获
5.选择将在其上实现当前emios通道功能的主总线通道。主总线通道将参考Mcl主总线配置,与 4 对应
6.测量模式:SAIC、IPWM、IPM。几种模式适合不同场景,具体参考手册,此处默认SAIC
7.Icu是否无中断信号测量,此处带中断
1.选择emios通道
2.是否支持DMA,此处不使用DMA
3.默认激活边缘,此处选择上升沿
4.测量模式选择,ICU_MODE_EDGE_COUNTER、ICU_MODE_SIGNAL_EDGE_DETECT、 ICU_MODE_SIGNAL_MEASUREMENT、ICU_MODE_TIMESTAMP模式
5.超时回调通知
6.该通道是否支持wakeup,取决于硬件通道
7.ICU_MODE_EDGE_COUNTER模式下的回调通知
8.根据4选择不同的模式使能对应的测量属性
1.此处选择ICU_MODE_SIGNAL_MEASUREMENT模式,轮询查询周期和频率
2.使能对应的测量属性
**注意:**根据不同的测量模,其开始测量的方式也不一样,总结如下:
1.ICU_MODE_SIGNAL_EDGE_DETECT,采用Icu_EnableEdgeDetection来启动测量
2.ICU_MODE_SIGNAL_MEASUREMENT,采用Icu_StartSignalMeasurement来启动测量
3.ICU_MODE_EDGE_COUNTER,采用Icu_EnableEdgeCount启动测量
4.ICU_MODE_TIMESTAMP,采用Icu_StartTimestamp来启动测量
4.代码调试
PTE14是边缘采样,PTG10是Siul2的边缘触发,PTA22是测量模式轮询查询周期和频率,PTE14是边缘唤醒,基本涵盖所有的方式。对于测量模式需要关注测量时间的长度,如果测量时间较长,可能会导致counter溢出,因为寄存器限制,我们可以改变时钟频率来得到我们所需的周期,具体计算如下。
void ICU_EDGE_DETECT_PTE14(void)
{
/* user code */
}
void ICU_EDGE_DETECT_PTG10(void)
{
/* user code */
}
int main_c0(void)
{
uint8 num_blink = 0U;
/* Initialize the Mcu driver */
Mcu_Init(NULL_PTR);
/* Initialize the clock tree */
Mcu_InitClock(McuClockSettingConfig_0);
/* Apply a mode configuration */
Mcu_SetMode(McuModeSettingConf_0);
/* Initialize Platform driver */
Platform_Init(NULL_PTR);
/* Install Emios ISR */
Platform_InstallIrqHandler(EMIOS0_1_IRQn, &EMIOS0_1_IRQ, NULL_PTR);
Platform_SetIrq(EMIOS0_1_IRQn,TRUE);
Platform_InstallIrqHandler(EMIOS1_4_IRQn, &EMIOS1_4_IRQ, NULL_PTR);
Platform_SetIrq(EMIOS1_4_IRQn,TRUE);
/* Install Siul2 ISR */
Platform_InstallIrqHandler(SIUL_3_IRQn, &SIUL2_EXT_IRQ_24_31_ISR, NULL_PTR);
Platform_SetIrq(SIUL_3_IRQn,TRUE);
/* Install Wkpu ISR */
Platform_InstallIrqHandler(WKPU_IRQn, &WKPU_EXT_IRQ_SINGLE_ISR, NULL_PTR);
Platform_SetIrq(WKPU_IRQn,TRUE);
/* Initialize all pins using the Port driver */
Port_Init(NULL_PTR);
/* Initialize Mcl driver */
Mcl_Init(NULL_PTR);
/* Initialize the Icu driver */
Icu_Init(NULL_PTR);
/*start the ICU measurement */
Icu_EnableEdgeDetection(IcuChannel_PTE14);
Icu_EnableNotification(IcuChannel_PTE14);
Icu_StartSignalMeasurement(IcuChannel_PTA22);
Icu_EnableEdgeDetection(IcuChannel_PTG10);
Icu_EnableNotification(IcuChannel_PTG10);
Icu_EnableEdgeDetection(IcuChannel_wake_PTE14);
Icu_EnableNotification(IcuChannel_wake_PTE14);
while(1)
{
OsTask_10ms();
}
return 0U;
}
/*Polling query cycle and frequency*/
Icu_DutyCycleType ICU_SM;
void OsTask_10ms(void)
{
if(ICU_ACTIVE == Icu_GetInputState(IcuChannel_PTA22))
{
Icu_GetDutyCycleValues(IcuChannel_PTA22,&ICU_SM);
if(ICU_SM.PeriodTime > 0)
{
ICU_SM.ActiveTime = (uint16)(ICU_SM.ActiveTime * 100U / ICU_SM.PeriodTime);
ICU_SM.PeriodTime = (uint16)(1000000U /ICU_SM.PeriodTime); /*1M*/
}
else
{
/*do nothing*/
}
}
else
{
/*do nothing*/
}
ICU_MODE_EDGE_COUNTER模式相对简单,调用相应的API可以获取counter,对于ICU_MODE_TIMESTAMP模式,实际种使用的也不多,此处也不做介绍,有需要的可以私聊,之前也试过这个有一个简单的demo。
5.展望
希望后面坚持更新,年底较忙,没有时间记录,今年不论多忙争取不断更。