-
ch32v307用HC-SR04 超声波测距和MQ2 烟雾浓度时会卡死,大家帮我看看代码
[i=s] 本帖最后由 nmmdw 于 2024-7-4 12:58 编辑 [/i] s1.c文件//============================================================================ // HC-SR04 超声波测距模块============================================================== void ultrasonic_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA,&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init( GPIOA, &GPIO_InitStructure); GPIO_ResetBits(GPIOA,GPIO_Pin_0|GPIO_Pin_1); } u16 count = 0; void Input_Capture_Init( u16 arr, u16 psc ) { TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; NVIC_InitTypeDef NVIC_InitStructure; //使能IM2时钟 RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM2, ENABLE); ultrasonic_GPIO_Init(); TIM_DeInit(TIM2); //定时器周期,实际就是设定自动重载寄存器 ARR 的值, ARR 为要装载到实际自动重载寄存器(即影子寄存器) 的值, 可设置范围为 0 至 65535。 TIM_TimeBaseInitStructure.TIM_Period = arr; //定时器预分频器设置,时钟源经该预分频器才是定时器计数时钟CK_CNT,它设定 PSC 寄存器的值。 //计算公式为: 计数器时钟频率 (fCK_CNT) 等于fCK_PSC / (PSC[15:0] + 1),可实现 1 至 65536 分频。 TIM_TimeBaseInitStructure.TIM_Prescaler = psc; //时钟分频,设置定时器时钟 CK_INT 频率与死区发生器以及数字滤波器采样时钟频率分频比。可以选择 1、 2、 4 分频。 TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //设置计数模式,向上计数模式 //TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0x00; //设置重复计数器的值,0。重复计数器,只有 8 位,只存在于高级定时器。 TIM_TimeBaseInit( TIM2, &TIM_TimeBaseInitStructure); //初始化 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //TIM1捕获比较中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//设置抢占优先级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //设置响应优先级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能通道 NVIC_Init(&NVIC_InitStructure); TIM_ClearFlag(TIM2, TIM_FLAG_Update); TIM_ITConfig( TIM2, TIM_IT_Update, ENABLE ); //使能TIM2更新中断 TIM_Cmd( TIM2, DISABLE ); //定时器使能 } void ENABLE_TIM(void) { //while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_1)==RESET) { TIM_SetCounter(TIM2,0); count = 0; TIM_Cmd(TIM2,ENABLE);//回响信号到来,开启定时器计数 } } void DISABLE_TIM(void) { //while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_1)==SET) { TIM_Cmd(TIM2,DISABLE);//回响信号到来,开启定时器计数 } } u32 GetCount(void) { u32 t = 0; t = count*1000; t += TIM_GetCounter(TIM2); TIM_SetCounter(TIM2,0); Delay_Ms(10); return t; } //一次获取超声波测距数据 两次测距之间需要相隔一段时间,隔断回响信号 //为了消除余震的影响,取五次数据的平均值进行加权滤波。 float Ultrasoniclength(void ) { // MQ2_run(); // Delay_Ms(2000); u32 t = 0; int i = 0; float length = 0 , sum = 0; while(i!=5) { Trig_H; Delay_Us(20); Trig_L; while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_1)==RESET); //此处一直等,等到为1,进行下一步 ENABLE_TIM();//回响信号到来,开启定时器计数 i++; while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_1)==SET); //此处一直等,等到为0,进行下一步,这两段while之间的时间就是高电平时间,即发出到返回接收的时间 DISABLE_TIM();//回响信号到来,开启定时器计数 t = TIM_GetCounter(TIM2); length=(t+count*1000)/58.0;//通过回响信号计算距离 sum = length + sum ; TIM_SetCounter(TIM2,0); count = 0; Delay_Ms(100); } length = sum/5.0; return length; } void TIM2_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast"))); void TIM2_IRQHandler(void) { if(TIM_GetITStatus(TIM2,TIM_IT_Update)!=RESET) { TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//清除中断标志 count++; } } //============================================================================= // MQ2 烟雾浓度模块============================================================ u8 times; void MQ2_Init() { GPIO_InitTypeDef GPIO_Initstructre; ADC_InitTypeDef ADC_InitStruct; RCC_APB2PeriphClockCmd(MQ2_RCC_GPIOx | MQ2_RCC_ADCx,ENABLE); //PA1 作为模拟通道输入引脚 GPIO_Initstructre.GPIO_Mode=GPIO_Mode_AIN;//模拟输入引脚 GPIO_Initstructre.GPIO_Pin=MQ2_GPIOx_Pinx; GPIO_Initstructre.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOA,&GPIO_Initstructre); GPIO_SetBits(MQ2_GPIOx,MQ2_GPIOx_Pinx); RCC_ADCCLKConfig(RCC_PCLK2_Div6);//设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M ADC_DeInit(MQ2_ADCx);//复位ADC1 ADC_InitStruct.ADC_ContinuousConvMode = DISABLE;//模数转换工作在单次转换模式 ADC_InitStruct.ADC_DataAlign=ADC_DataAlign_Right;//ADC数据右对齐 ADC_InitStruct.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;//转换由软件而不是外部触发启动 ADC_InitStruct.ADC_Mode=ADC_Mode_Independent;//ADC工作模式:ADC1和ADC2工作在独立模式 ADC_InitStruct.ADC_NbrOfChannel = 1;//顺序进行规则转换的ADC通道的数目 ADC_InitStruct.ADC_ScanConvMode = DISABLE;//模数转换工作在单通道模式 ADC_Init(MQ2_ADCx,&ADC_InitStruct);//根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器 ADC_Cmd(MQ2_ADCx,ENABLE);//使能指定的ADC1 ADC_ResetCalibration(MQ2_ADCx);//使能复位校准 while(ADC_GetResetCalibrationStatus(MQ2_ADCx));//等待复位校准结束 ADC_StartCalibration(MQ2_ADCx);//开启AD校准 while(ADC_GetCalibrationStatus(MQ2_ADCx));//等待校准结束 ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能 } //获得ADC值 ch:通道值 0~3 u16 Get_Adc(u8 ch)//设置指定ADC的规则组通道,一个序列,采样时间 { ADC_RegularChannelConfig(MQ2_ADCx,ch,1,ADC_SampleTime_239Cycles5);//ADC1,ADC通道,采样时间为239.5周期 ADC_SoftwareStartConvCmd(MQ2_ADCx,ENABLE);//使能指定的ADC1的软件转换启动功能 while(!ADC_GetFlagStatus(MQ2_ADCx,ADC_FLAG_EOC));//等待转换结束 return ADC_GetConversionValue(MQ2_ADCx);//返回最近一次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; } float MQ2_Value;//adc值 float temp_one;//电压值 void MQ2_run() { MQ2_Value = Get_Adc_Average(ADC_Channel_1,10) * 100 / 4095;//模拟烟雾浓度的值 temp_one = (float) MQ2_Value / 4096*3.3; printf("烟雾浓度= %3.2f %,电压值=%3.2f\r\n",MQ2_Value,temp_one); Delay_Ms(1000); } //=========================================================================== s1.h文件====================================================================== #ifndef USER_S1_H_ #define USER_S1_H_ #include "ch32v30x_conf.h" // HC-SR04 超声波测距模块======================================================== #define Trig_H GPIO_SetBits(GPIOA,GPIO_Pin_0) #define Trig_L GPIO_ResetBits(GPIOA,GPIO_Pin_0) #define Echo_H GPIO_SetBits(GPIOA,GPIO_Pin_1) #define Echo_L GPIO_ResetBits(GPIOA,GPIO_Pin_1) void ultrasonic_GPIO_Init(void); void Start_Trig(void); void Input_Capture_Init( u16 arr, u16 psc ); void ENABLE_TIM(void); void DISABLE_TIM(void); u32 GetCount(void); float Ultrasoniclength(void); // MQ2 烟雾浓度模块============================================================= #define MQ2_GPIOx GPIOD //修改 A 时,GPIO 使能的 A 也要修改 #define MQ2_GPIOx_Pinx GPIO_Pin_3 //引脚 #define MQ2_RCC_GPIOx RCC_APB2Periph_GPIOD //GPIO 使能 #define MQ2_ADCx ADC1 //修改 1 时,ADC 使能的 1 也要修改 #define MQ2_RCC_ADCx RCC_APB2Periph_ADC1 //ADC 使能 void MQ2_Init(void); u16 Get_Adc(u8 ch); u16 Get_Adc_Average(u8 ch,u8 times); void MQ2_Check(void); void MQ2_run(void); #endif /* USER_S1_H_ */
2320浏览量 2回复量 关注量