资讯详情

STM32智能雨刷器

基于STM32智能雨刷器

功能演示

基于STM32智能雨刷器

  • 中段
  • PWM
  • ADC

使用雨滴传感器ADC传输给stm32,stm32实时检测雨滴信号,然后根据判断控制PWM按了实现舵机的不同动作,按钮触发中断控制PWM

主函数 main.c

#include "led.h" #include "delay.h" #include "key.h" #include "sys.h" #include "usart.h" #include "exti.h" #include "beep.h" #include "timer.h" #include "adc.h"  int main(void) { 
               u16 adcx;  int i = 0;//用于舵机转动的for循环  int frequency = 175;//舵机转动的初始角度 175-195  float temp;     //通过ADC转换获得雨滴传感器的值  int  integer;     delay_init();      //延迟函数初始化   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2抢占优先级,2响应优先级  uart_init(115200);     //串口初始化为115200  LED_Init();      ///初始化和LED连接的硬件接口   BEEP_Init();    ///初始化蜂鸣器IO  EXTIX_Init();          ///   LED0=0;     ///先点红灯  TIM3_PWM_Init(199,
       
        7199
        )
        ; 
        //不分频。PWM频率=72000000/900=80Khz 
        Adc_Init
        (
        )
        ; 
        //ADC初始化 
        while
        (
        1
        ) 
        { 
          adcx
        =
        Get_Adc_Average
        (ADC_Channel_1
        ,
        2
        )
        ; temp
        =
        (
        float
        )adcx
        *
        (
        3.3
        /
        4096
        )
        ; temp
        *
        =
        100
        ; integer 
        = temp
        ; 
        if
        (integer 
        > NUMERICAL_THREEHUNDRED 
        && integer 
        < NUMERICAL_FOURHUNDRED
        )
        //不下雨 
        { 
          
        delay_ms
        (
        1
        )
        ; 
        } 
        if
        (integer 
        > NUMERICAL_TWOHUNDREDANDTWENT 
        && integer 
        <= NUMERICAL_THREEHUNDRED
        )
        //小雨 
        { 
          
        for
        (i 
        = 
        0
        ;i
        <
        20
        ;i
        ++
        ) 
        { 
          
        TIM_SetCompare2
        (TIM3
        ,frequency
        )
        ; frequency
        ++
        ; 
        delay_ms
        (DELAYMIN
        )
        ; 
        } 
        for
        (i 
        = 
        0
        ;i
        <
        20
        ;i
        ++
        ) 
        { 
          
        TIM_SetCompare2
        (TIM3
        ,frequency
        )
        ; frequency
        --
        ; 
        delay_ms
        (DELAYMIN
        )
        ; 
        } 
        } 
        if
        (integer 
        > NUMERICAL_ONEHUNDREDANDFORTY 
        && integer 
        <= NUMERICAL_TWOHUNDREDANDTWENT
        )
        //中雨 
        { 
          
        for
        (i 
        = 
        0
        ;i
        <
        20
        ;i
        ++
        ) 
        { 
          
        TIM_SetCompare2
        (TIM3
        ,frequency
        )
        ; frequency
        ++
        ; 
        delay_ms
        (DELAYMID
        )
        ; 
        } 
        for
        (i 
        = 
        0
        ;i
        <
        20
        ;i
        ++
        ) 
        { 
          
        TIM_SetCompare2
        (TIM3
        ,frequency
        )
        ; frequency
        --
        ; 
        delay_ms
        (DELAYMID
        )
        ; 
        } 
        } 
        if
        (integer 
        > NUMERICAL_TEN 
        && integer 
        <= NUMERICAL_ONEHUNDREDANDFORTY
        )
        //大雨 
        { 
          
        for
        (i 
        = 
        0
        ;i
        <
        20
        ;i
        ++
        ) 
        { 
          
        TIM_SetCompare2
        (TIM3
        ,frequency
        )
        ; frequency
        ++
        ; 
        delay_ms
        (DELAYMAX
        )
        ; 
        } 
        for
        (i 
        = 
        0
        ;i
        <
        20
        ;i
        ++
        ) 
        { 
          
        TIM_SetCompare2
        (TIM3
        ,frequency
        )
        ; frequency
        --
        ; 
        delay_ms
        (DELAYMAX
        )
        ; 
        } 
        } 
        //printf("%d\r\n",integer);//串口发送LOG值 
        //delay_ms(500);  
        } 
        } 
       

雨滴传感器数据传输 ADC数模转换,将模拟信号转换成数字信号,以下是配置代码 代码下载链接(开源)https://download.csdn.net/download/m0_48216397/84200504 下面是各个代码简述 adc.h

#ifndef __ADC_H
#define __ADC_H 
#include "sys.h"

void Adc_Init(void);
u16  Get_Adc(u8 ch); 
u16 Get_Adc_Average(u8 ch,u8 times); 
 
#endif 

adc.c

 #include "adc.h"
 #include "delay.h"
		   
//初始化ADC
//这里仅以规则通道为例
//我们默认将开启通道0~3 
void  Adc_Init(void)
{ 
         	
	ADC_InitTypeDef ADC_InitStructure; 
	GPIO_InitTypeDef GPIO_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1	, ENABLE );	  //使能ADC1通道时钟
 

	RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M

	//PA1 作为模拟通道输入引脚 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;		//模拟输入引脚
	GPIO_Init(GPIOA, &GPIO_InitStructure);	

	ADC_DeInit(ADC1);  //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值

	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;	//ADC工作模式:ADC1和ADC2工作在独立模式
	ADC_InitStructure.ADC_ScanConvMode = DISABLE;	//模数转换工作在单通道模式
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;	//模数转换工作在单次转换模式
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;	//转换由软件而不是外部触发启动
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;	//ADC数据右对齐
	ADC_InitStructure.ADC_NbrOfChannel = 1;	//顺序进行规则转换的ADC通道的数目
	ADC_Init(ADC1, &ADC_InitStructure);	//根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器 

  
	ADC_Cmd(ADC1, ENABLE);	//使能指定的ADC1
	
	ADC_ResetCalibration(ADC1);	//使能复位校准 
	 
	while(ADC_GetResetCalibrationStatus(ADC1));	//等待复位校准结束
	
	ADC_StartCalibration(ADC1);	 //开启AD校准
 
	while(ADC_GetCalibrationStatus(ADC1));	 //等待校准结束
 
// ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能

}				  
//获得ADC值
//ch:通道值 0~3
u16 Get_Adc(u8 ch)   
{ 
        
  	//设置指定ADC的规则组通道,一个序列,采样时间
	ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 );	//ADC1,ADC通道,采样时间为239.5周期 
  
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);		//使能指定的ADC1的软件转换启动功能 
	 
	while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束

	return ADC_GetConversionValue(ADC1);	//返回最近一次ADC1规则组的转换结果
}

u16 Get_Adc_Average(u8 ch,u8 times)
{ 
        
	u32 temp_val=0;
	u8 t;
	for(t=0;t<times;t++)
	{ 
        
		temp_val+=Get_Adc(ch);
		delay_ms(5);
	}
	return temp_val/times;
} 	 

PWM时钟配置 time.h

#ifndef __TIMER_H
#define __TIMER_H
#include "sys.h"

void TIM3_Int_Init(u16 arr,u16 psc);
void TIM3_PWM_Init(u16 arr,u16 psc);
#endif

time.c

#include "timer.h"
#include "led.h"
#include "usart.h"
   	  
//通用定时器3中断初始化
//这里时钟选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器3!
void TIM3_Int_Init(u16 arr,u16 psc)
{ 
        
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能

	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 计数到5000为500ms
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 10Khz的计数频率 
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
 
	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断

	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
	NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

	TIM_Cmd(TIM3, ENABLE);  //使能TIMx外设
							 
}
//定时器3中断服务程序
void TIM3_IRQHandler(void)   //TIM3中断
{ 
        
	if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源 
		{ 
        
		    TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIMx的中断待处理位:TIM 中断源 
		    LED1=!LED1;
		}
}
//TIM3 PWM部分初始化 
//PWM输出初始化
//arr:自动重装值
//psc:时钟预分频数
void TIM3_PWM_Init(u16 arr,u16 psc)
{ 
          
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;
	

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);	//使能定时器3时钟
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB  | RCC_APB2Periph_AFIO, ENABLE);  //使能GPIO外设和AFIO复用功能模块时钟
	
	GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //Timer3部分重映射 TIM3_CH2->PB5 
 
   //设置该引脚为复用输出功能,输出TIM3 CH2的PWM脉冲波形 GPIOB.5
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //TIM_CH2
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO
 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //TIM_CH2
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIO
	
   //初始化TIM3
	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
	
	//初始化TIM3 Channel2 PWM模式 
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
 	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
	TIM_OC2Init(TIM3, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM3 OC2

	TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);  //使能TIM3在CCR2上的预装载寄存器
 
	TIM_Cmd(TIM3, ENABLE);  //使能TIM3
}

中断配置 exti.h

#ifndef __EXTI_H
#define __EXIT_H 
#include "sys.h"
	 
void EXTIX_Init(void);//外部中断初始化 
#endif

exti.c

#include "exti.h"
#include "led.h"
#include "key.h"
#include "delay.h"
#include "usart.h"
#include "beep.h"

void EXTIX_Init(void)
{ 
        
 
   	EXTI_InitTypeDef EXTI_InitStructure;
 	NVIC_InitTypeDef NVIC_InitStructure;

    KEY_Init();	 // 按键端口初始化
  	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);	//使能复用功能时钟

   //GPIOE.3 中断线以及中断初始化配置 下降沿触发 //KEY1
  	GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource3);
  	EXTI_InitStructure.EXTI_Line=EXTI_Line3;
  	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	
  	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
  	EXTI_Init(&EXTI_InitStructure);	  	//根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器

   //GPIOE.4 中断线以及中断初始化配置 下降沿触发 //KEY0
  	GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource4);
  	EXTI_InitStructure.EXTI_Line=EXTI_Line4;
  	EXTI_Init(&EXTI_InitStructure);	  	//根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器


   //GPIOA.0 中断线以及中断初始化配置 上升沿触发 PA0 WK_UP
 	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0); 

  	EXTI_InitStructure.EXTI_Line=EXTI_Line0;
  	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
  	EXTI_Init(&EXTI_InitStructure);		//根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器


  	NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;			//使能按键WK_UP所在的外部中断通道
  	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;	//抢占优先级2, 
  	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03;					//子优先级3
  	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;								//使能外部中断通道
  	NVIC_Init(&NVIC_InitStructure); 

  	NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;			//使能按键KEY1所在的外部中断通道
  	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;	//抢占优先级2 
  	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;					//子优先级1 
  	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;								//使能外部中断通道
  	NVIC_Init(&NVIC_InitStructure);  	  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

  	NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;			//使能按键KEY0所在的外部中断通道
  	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;	//抢占优先级2 
  	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;					//子优先级0 
  	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;								//使能外部中断通道
  	NVIC_Init(&NVIC_InitStructure);  	  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
 
}
//外部中断0服务程序 
void EXTI0_IRQHandler(void)//亮度最亮
{ 
        
	delay_ms(10);//消抖
	if(WK_UP==1)	 	 //WK_UP按键
	{ 
        				 
        for(i = 0;i<10;i++)
		{ 
        
			for(i = 0;i<20;i++)
			{ 
        
			    TIM_SetCompare2(TIM3,frequency);
				frequency++;
				delay_ms(DELAYMIN);
			}
			for(i = 0;i<20;i++)
			{ 
        
			    TIM_SetCompare2(TIM3,frequency);
				frequency--;
				delay_ms(DELAYMIN);
			}
		}  
		delay_ms(1000);	
	}
	EXTI_ClearITPendingBit(EXTI_Line0); //清除LINE0上的中断标志位 
}
//外部中断3服务程序
void EXTI3_IRQHandler(void)//亮度
{ 
        
	delay_ms(10);//消抖
	if(KEY1==0)	 //按键KEY1
	{ 
        				 
		for(i = 0;i<10;i++)
		{ 
        
			for(i = 0;i<20;i++)
			{ 
        
			    TIM_SetCompare2(TIM3,frequency);
				frequency++;
				delay_ms(DELAYMIN);
			}
			for(i = 0;i<20;i++)
			{ 
        
			    TIM_SetCompare2(TIM3,frequency);
				frequency--;
				delay_ms(DELAYMIN);
			}
		}  
        delay_ms(1000);	  		
	}		 
	EXTI_ClearITPendingBit(EXTI_Line3);  //清除LINE3上的中断标志位 
}
void EXTI4_IRQHandler(void)//亮度在中间
{ 
        
	delay_ms(10);//消抖
	if(KEY0==0)	 //按键KEY0
	{ 
        
	    for(i = 0;i<10;i++)
		{ 
        
			for(i = 0;i<20;i++)
			{ 
        
			    TIM_SetCompare2(TIM3,frequency);
				frequency++;
				delay_ms(DELAYMIN);
			}
			for(i = 0;i<20;i++)
			{ 
        
			    TIM_SetCompare2(TIM3,frequency);
				frequency--;
				delay_ms(DELAYMIN);
			}
		}  
		delay_ms(1000);	
	}		 
	EXTI_ClearITPendingBit(EXTI_Line4);  //清除LINE4上的中断标志位 
}

按键中断配置 key.h

#ifndef __KEY_H
#define __KEY_H 
#include "sys.h" 

#define KEY0 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)//读取按键0
#define KEY1 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)//读取按键1
#define WK_UP GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)//读取按键3(WK_UP) 

# 

标签: c08连接器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台