四缸汽油机曲轴及凸轮轴信号生成(基于STM32)

您所在的位置:网站首页 发动机信号1 四缸汽油机曲轴及凸轮轴信号生成(基于STM32)

四缸汽油机曲轴及凸轮轴信号生成(基于STM32)

2024-01-29 15:19| 来源: 网络整理| 查看: 265

曲轴凸轮轴位置信号对于发动机电控十分重要,通过它们可以确定曲轴当前转速,以及判定x缸活塞到达上止点(判缸),是喷油和点火的重要依据。本次实验我们尝试基于STM32F103的最小系统板,来模拟脉冲型曲轴和凸轮轴信号。

曲轴每旋转2圈,凸轮轴旋转1圈,完成4次点火(1-3-4-2)。4缸汽油机常见的曲轴信号为60-2,即一周58个周期脉冲加两个周期低电平;4缸汽油机常见凸轮轴信号为每转4个脉冲(对应x缸活塞上止点,曲轴换向),且在一缸脉冲后30°额外添加一个脉冲,作为1缸信号(类似于磁场定向中的Z脉冲信号)。实际的曲轴与凸轮轴通过正时链条(或皮带)连接,具有同步性。

 

本次实验采用两个定时器(定时器1,定时器2),一个定时器中断服务(定时器1更新中断)。定时器1通过PWM(硬件动作,节省计算资源)来模拟曲轴脉冲信号,脉冲计数则在定时器1中断服务中完成。定时器2通过PWM来模拟凸轮轴脉冲信号,而脉冲计数则在定时器1中断服务中完成。

首先给出两个定时器的配置,

void TIMER1_INIT(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//输出PWM需要配置为复用推挽 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA,&GPIO_InitStructure); TIM_InternalClockConfig(TIM1);//定时器1启用内部时钟 TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//时基单元配置 TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Down;//向下计数 TIM_TimeBaseInitStructure.TIM_Period = 100-1; TIM_TimeBaseInitStructure.TIM_Prescaler = 72-1; TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM1, &TIM_TimeBaseInitStructure); TIM_OCInitTypeDef TIM_OCInitStructure; TIM_OCStructInit(&TIM_OCInitStructure);//初始化其他未设置的变量 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//PWM1模式(高有效) TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 0; TIM_OC1Init(TIM1, &TIM_OCInitStructure);//(第1通道) TIM_ClearFlag(TIM1, TIM_FLAG_Update);//清中断标志位 TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);//开定时器中断 TIM_ClearITPendingBit(TIM1, TIM_IT_Update);//清定时器1中断标志位 TIM_Cmd(TIM1, DISABLE);//关定时器 TIM_CtrlPWMOutputs(TIM1, DISABLE);//关pwm主使能(高级定时器独有) NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断优先级配置 NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_Init(&NVIC_InitStructure);//配置中断通道 } void TIMER2_INIT(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA,&GPIO_InitStructure); TIM_InternalClockConfig(TIM2);//定时器1启用内部时钟 TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//时基单元配置 TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInitStructure.TIM_Period = 200-1; TIM_TimeBaseInitStructure.TIM_Prescaler = 1080-1; TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure); TIM_OCInitTypeDef TIM_OCInitStructure; TIM_OCStructInit(&TIM_OCInitStructure);//初始化其他未设置的变量 // TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//PWM1模式(高有效) // TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset; // TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; // TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;//关下路互补,做单(上)桥臂斩波 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 0; TIM_OC1Init(TIM2, &TIM_OCInitStructure);//(第1通道) TIM_SetCounter(TIM2, 197);//同步预装 TIM_Cmd(TIM2, DISABLE);//等待软件开定时器2 }

为了保证两个定时的PWM脉冲尽量对齐,在主程序中依次开启两个定时器,

int main() { TIMER1_INIT(); TIMER2_INIT(); TIM_Cmd(TIM1, ENABLE);//曲轴信号 TIM_Cmd(TIM2, ENABLE);//凸轮轴信号 TIM_SetCompare1(TIM1, 0); TIM_SetCompare1(TIM2, 0); while(1) { } }

考虑到曲轴和凸轮轴信号并非单纯的脉冲,其存在大周期,所以两定时器比较器的装载值在定时器1中断服务中根据脉冲计数值来给定。

这里有一些需要注意的地方:

PWM是硬件动作,软件对比较器装载值的实时修改有时是“不及时”的。具体来讲,以向上计数,上溢中断为例,当计数器周期为100,比较器装载50,我们将得到0.5占空比的PWM,当完成58个脉冲输出后,我们需要在下个中断服务中将比较器装载值改为1,或直接关PWM,这里就体现的软件“不及时”的问题,如下图

 可以看出,原本是完全低电平的最后两个周期出现了两个窄脉冲,这是因为由上溢中断到来至配置比较器装置(或关PWM),程序执行需要时间,而在这段时间中比较器值大于计数器,所以PWM会出高电平。考虑到上述问题,本次实验采用向下计数,这样当更新(下溢)中断到来时,比较器值小于计数器,PWM不会出高电平。如下图所示

 对于曲轴信号,脉冲计数器值58,59和118,119为全周期低电平,大于119则归零复位(曲轴转2圈,凸轮轴转1圈,进入下一周期)。

凸轮轴信号通过通过定时器2的PWM来模拟,曲轴完成两个60-2,凸轮轴完成一个4脉冲,+一个1后30°单脉冲,所以定时器1的PWM频率时定时器2的30倍,通过设置分频及计数器周期可以对定时器2的PWM周期灵活调整;通过定时器2计数器的预装值来微调其相位。最后对于1缸上止点后30°的单脉冲,可通过在中断服务中修改定时器2比较器装载值来实现,如下图,

这里30°可以通过曲轴脉冲数来确定,凸轮轴30°对应曲轴60°,即第10脉冲,至于凸轮轴脉冲宽度,可以自定。中断服务如下

void TIM1_UP_IRQHandler(void)//定时器1中断服务函数 { static uint16_t num;//曲轴脉冲计数器 if(TIM_GetITStatus(TIM1, TIM_IT_Update)==SET)//查定时器1中断标志位 { TIM_CtrlPWMOutputs(TIM1, ENABLE);//开pwm主使能(高级定时器独有) num++; if(num>=10&&num119) { num = 0; TIM_SetCompare1(TIM2, 20); TIM_SetCompare1(TIM1, 50); } else { TIM_SetCompare1(TIM2, 20); TIM_SetCompare1(TIM1, 50); } TIM_ClearITPendingBit(TIM1, TIM_IT_Update);//清定时器1中断标志位 } }

 最终效果如下,

介于本人水平有限,本次实验目的仅仅是抛砖引玉,希望大家能够贴上更简单的代码。

 



【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3