标题: 我的STM32单片机项目经验(加力器报警器) [打印本页]

作者: 51黑黑黑    时间: 2016-2-23 17:56
标题: 我的STM32单片机项目经验(加力器报警器)
以前为了解决单位实际需要制作了加力器报警器,其中里面的控制器是采用STM32单片机,这次去沈阳面试单片机岗位这个项目很适合做介绍,我把这个项目的过程介绍下。加力器是汽车中刹车系统的一部分,加力器是用气体顶动油液来完成加倍力量带动刹车片的。加力器的气活塞容易在运动中卡死,本报警作用就是在卡住时报警提示司机。
工作原理:
1.定义一个数组 u16 distance_l[2] = {0,0};作用是先后采集的两次ADC数据存储在这个数组中,其中ADC经过了取平均数,冒泡排序等滤波方法。
2.在主函数中首先对系统时钟,ADC,led,定时器初始化,然后完成一个超限报警功能,就是油液漏油气活塞没有阻力超过正常值时报警的功能。本程序采用函数模块化编程,调用了一个返回超限标志的函数bool isOverrun(distance_l[0]);这个函数传入ADC数据如果超限就返回一个超限标志值。
3.接着完成返回刹车中标志函数 bool isBrake_state(distance_l[0]);因为只有在踩刹车状态下才需要检测,所有控制需要知道是否踩刹车了,调用了返回刹车中标志函数传入了ADC数据中就可以返回是否是踩刹车状态。
4.然后调用警报函数voidAlarm_dispose(bool lim_l, bool lim_r, bool lock);需要传入3个值,两个超限标志值,一个活塞被卡标志位,这几个标志位任何一个成立就完成报警。
5.定时器中断服务程序是关键,定时器2的功能是控制蜂鸣器报警的,定时器3中断服务程序完成任务有,调用气活塞是否被卡函数voidStuck(void);
在采集数据方面首先采集了300个数据,然后采用了冒泡排序去掉了一个最高值和一个最值,再取平均数完成软件滤波的,滤波程序如下:
void filter(u8 ch)  
{  
int count,i,j;

for ( count=0; count
{  
value_buf[count]=Get_Adc(ch); //采集数据  
   }

for (j=0;j
{  
      for(i = 0; i < N-j; i++)  
     {
         if ( value_buf[i] >value_buf[i+1] )  
         {  
           temp =value_buf[i];  
          value_buf[i] = value_buf[i+1];  
          value_buf[i+1] = temp;  
         }
      }
    }
sum = 0;
for(count = 1;count < N-1; count++)
sum += value_buf[count];

sum = sum / (N - 2);  
//  sum = sum;
}


主函数程序如下:
#include
#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "exti.h"
#include "wdg.h"
#include "timer.h"   
#include "adc.h"
#include "alarm.h"

#define LIM 5 //卡住判断参数
u16 distance_l[2] = {0,0}; //卡住比较数组
u16 distance_r[2] = {0,0};
u8 i = 0;   //采集数据计数变量
bool brake_state_l, brake_state_r; //刹车状态标志位
bool lock_alarm_l, lock_alarm_r, lock_alarm;  //卡住报警标志位

u16 value_buf[N]; //滤波求平均缓存
u32 sum; //滤波求平均总和缓存
u16 temp; //滤波求排序缓存

void Stuck(void); //判断是否活塞卡住
int main(void)
{
bool lim_alarm_l, lim_alarm_r; //超限警报标志位

  Stm32_Clock_Init(9); //系统时钟设置
delay_init(72); //延时初始化
uart_init(72,9600); //串口1初始化  
LED_Init();
Adc_Init();
Timer2_Init(5000,7199); //定时报警
Timer3_Init(2000,7199); //定时采集ADC  
// Timer4_Init(5000,7199); //定时打印

while(1)
{
lim_alarm_l = isOverrun(distance_l[0]); //返回超限标志
lim_alarm_r = isOverrun(distance_r[0]);

brake_state_l = isBrake_state(distance_l[0]); //返回刹车中标志
brake_state_r = isBrake_state(distance_r[0]);
//报警处理函数
Alarm_dispose(lim_alarm_l, lim_alarm_r, lock_alarm);
}
}
void TIM2_IRQHandler(void)
{
        
if(TIM2->SR&0X0001) //溢出中断
{
BUZZER = 0;
delay_ms(100);
BUZZER = 1;
}   
TIM2->SR&=~(1<<0); //清除中断标志位   
}


void TIM3_IRQHandler(void)
{         
if(TIM3->SR&0X0001)//溢出中断
{
if( (lock_alarm_l || lock_alarm_r) && (brake_state_l|| brake_state_r) )
lock_alarm = 1;

  if( (brake_state_l == 0) &&(brake_state_r == 0))
lock_alarm = 0;

Stuck(); //数据采集后判断是否活塞卡住      
}   
TIM3->SR&=~(1<<0); //清除中断标志位   
}
void Stuck(void)
{
filter(ADC_CH0);
distance_l[i] = sum;

delay_ms(20);

filter(ADC_CH1);
distance_r[i] = sum;

i++;

  if(i > 1) //采集了两组数据后判断一次是否卡住
{
i = 0;

if( ( (distance_l[1]-distance_l[0]) < LIM) && ((distance_l[1]-distance_l[0]) > -50) )
lock_alarm_l = 1;

if( ( (distance_r[1]-distance_r[0]) < LIM) && ((distance_r[1]-distance_r[0]) > -50) )
lock_alarm_r = 1;

printf("%d\n",distance_l[1]-distance_l[0]);
// printf("%d\n",distance_r[1]-distance_r[0]);
}
}
void TIM4_IRQHandler(void)
{         
if(TIM4->SR&0X0001) //溢出中断
{
// printf("a1= %d\n",sum);
// printf("a1= %d,a2= %d\n",adc_l, adc_r);
// printf("a1 %d, d1 %d, %d\n",adc_l, distance_l[0],distance_l[1]);
// printf("a2 %d, d2 %d, %d\n",adc_r, distance_r[0],distance_r[1]);            
// printf("%b, %b\n",lock_alarm_l, lock_alarm_r );
}   
TIM4->SR&=~(1<<0); //清除中断标志位   
}








欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1