判断俩个区间定时器是否重叠

本文介绍了一种方法来判断两个具有特定周期性和时间范围的定时任务是否存在时间上的重叠。通过具体示例展示了如何利用Java编程语言实现这一功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

代码备份

定时器分开始时间和结束时间,而且可以设置按周一到周日的循环,怎么判断俩个时间段有重复

    public void overlapTest() {
        ArrayList<String> timer = new ArrayList<>();
        // 下面时间段进行俩俩比较,测试是否有重叠
        // true
        timer.add("00 00 13-15 ? * 1,2,3,4,5,6,7");
        timer.add("00 00 14-16 ? * 1,7");

        // false
        timer.add("00 00 13-15 ? * 1,3,5");
        timer.add("00 00 14-16 ? * 2,4,6");

        // true
        timer.add("00 00 18-8 ? * 1,2,3");
        timer.add("00 00 7-9 ? * 4,5,6");

        // false
        timer.add("00 00 13-14 ? * 1,2,3");
        timer.add("00 00 13-14 ? * 4,5,6,7");

        // true
        timer.add("00 00 18-8 ? * 1");
        timer.add("00 00 7-9 ? * 2");

        // true
        timer.add("00 00 13-14 ? * 2");
        timer.add("00 00 13-14 ? * 1,2,3");


        for (int i = 0; i+1 < timer.size(); i+=2) {
            String[] cronData1 = timer.get(i).split(" ");
            String[] cronData2 = timer.get(i+1).split(" ");

            String week1[];
            Calendar startTime1 = Calendar.getInstance();
            Calendar endTime1 = Calendar.getInstance();
            String week2[];
            Calendar startTime2 = Calendar.getInstance();
            Calendar endTime2 = Calendar.getInstance();

            week1 = cronData1[5].split(",");
            startTime1.set(Calendar.HOUR_OF_DAY, Integer.parseInt(cronData1[2].split("-")[0]));
            endTime1.set(Calendar.HOUR_OF_DAY, Integer.parseInt(cronData1[2].split("-")[1]));
            startTime1.set(Calendar.MINUTE, 0);
            startTime1.set(Calendar.SECOND, 0);
            endTime1.set(Calendar.MINUTE, 0);
            endTime1.set(Calendar.SECOND, 0);

            week2 = cronData2[5].split(",");
            startTime2.set(Calendar.HOUR_OF_DAY, Integer.parseInt(cronData2[2].split("-")[0]));
            endTime2.set(Calendar.HOUR_OF_DAY, Integer.parseInt(cronData2[2].split("-")[1]));
            startTime2.set(Calendar.MINUTE, 0);
            startTime2.set(Calendar.SECOND, 0);
            endTime2.set(Calendar.MINUTE, 0);
            endTime2.set(Calendar.SECOND, 0);

            boolean ret1, ret2;
            ret1= isOverlap(week1, startTime1, endTime1, week2, startTime2, endTime2);
            ret2= isOverlap(week2, startTime2, endTime2, week1, startTime1, endTime1);
            Log.i("test", timer.get(i) + " VS " +timer.get(i+1) + " = " + ret1 + " " + ret2 );

        }
    }

    /**
     * 比较startTime1~endTime1  和 startTime2~endTime2俩个时间段是否重复
     * @param week1 是第一个定时器的周循环模式,1=周日,2=周一
     * @param startTime1 只使用里面的时分秒信息
     * @param endTime1 只使用里面的时分秒信息
     * @param week2
     * @param startTime2
     * @param endTime2
     * @return
     */
    public static boolean isOverlap(String week1[], Calendar startTime1, Calendar endTime1, String week2[], Calendar startTime2, Calendar endTime2) {
        /**
         * week1 是第一个定时器的周循环模式,1=周日,2=周一
         * startTime, endTime,只使用里面的时分秒信息
         */

        for(String w1 : week1) {
            for(String w2 : week2) {
                Calendar start1 = Calendar.getInstance();
                Calendar start2 = Calendar.getInstance();
                Calendar end1 = Calendar.getInstance();
                Calendar end2 = Calendar.getInstance();

                start1.set(Calendar.DAY_OF_WEEK, Integer.parseInt(w1));
                end1.set(Calendar.DAY_OF_WEEK, Integer.parseInt(w1));
                start2.set(Calendar.DAY_OF_WEEK, Integer.parseInt(w2));
                end2.set(Calendar.DAY_OF_WEEK, Integer.parseInt(w2));

                setTime(start1, startTime1);
                setTime(end1, endTime1);
                setTime(start2, startTime2);
                setTime(end2, endTime2);

                if(start1.after(end1)) { // 跨天的情况
                    end1.add(Calendar.DAY_OF_YEAR, 1);
                }

                if(start2.after(end2)) { // 跨天的情况
                    end2.add(Calendar.DAY_OF_YEAR, 1);
                }

                if((!start1.after(start2) && end1.after(start2)) || (!start1.before(start2) && end2.after(start1))) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 拷贝date的时分秒数据到calender变量
     * @param calendar
     * @param date
     */
    public static void setTime(Calendar calendar, Calendar date) {
        calendar.set(Calendar.HOUR_OF_DAY, date.get(Calendar.HOUR_OF_DAY));
        calendar.set(Calendar.MINUTE, date.get(Calendar.MINUTE));
        calendar.set(Calendar.SECOND, date.get(Calendar.SECOND));
    }


<think>嗯,用户想用STM32C8T6、OLED、DHT11、两个水位传感器、继电器控制的水泵和蜂鸣器实现三个功能。首先,我需要理清楚每个模块的连接方式和代码结构。 首先,硬件部分。STM32C8T6的引脚分配很重要。OLED通常用I2C,所以可能需要GPIOB的6和7作为SCL和SDA。DHT11是单总线,可能接在PA0。水位传感器A和B是模拟输入,应该接在ADC的通道,比如PA1和PA2。继电器控制水泵可以用PA4,蜂鸣器用PA5。这样分配下来,需要确认引脚是否冲突,特别是ADC和普通IO是否重叠。 接下来是软件配置。需要初始化各个外设:I2C用于OLED,ADC用于水位传感器,GPIO用于DHT11、继电器和蜂鸣器。DHT11的驱动需要精确的时序,可能需要用定时器或者延时函数。ADC需要配置为连续转换模式,或者使用DMA,但考虑到用户可能对复杂度敏感,可能用轮询方式更简单。 功能实现方面,主循环里要不断读取温湿度和水位数据。OLED刷新频率不宜过高,可能每500ms更新一次。水位传感器A的控制逻辑是当达到2500时启动水泵排水到2000,低于500时吸水到2000。这里要注意状态机的设计,避免水泵频繁启停。可能需要一个标志位来记录当前水泵的状态,比如正在排水或吸水,或者空闲。 水位传感器B的处理是当值在2500到3000之间时,蜂鸣器间隔1秒响。这里需要定时器中断或者用系统滴答定时器来计时,每次到达1000ms切换蜂鸣器状态。如果B的值不在这个范围,则关闭蜂鸣器。 代码结构方面,可能需要将各个模块分开成.h和.c文件,比如OLED、DHT11、ADC、Relay、Buzzer等。主函数里初始化所有外设,然后在循环中处理数据。定时器中断处理蜂鸣器的闪烁,而主循环处理传感器读取和逻辑判断。 需要注意的问题包括:ADC的校准和滤波,避免水位值波动过大;DHT11的读取可能失败,需要错误处理;继电器的开关可能需要延时,防止电流冲击;蜂鸣器的频率和驱动方式是否正确。 此外,用户可能对如何配置Keil的项目设置不太清楚,比如添加正确的头文件路径,包含必要的库文件(如STM32的标准外设库或HAL库)。需要提示用户根据使用的库(标准库还是HAL)来调整代码。 最后,测试每个功能模块是否独立工作,再整合到一起。比如先测试OLED显示,再测试DHT11读取,接着水位传感器的ADC值,然后继电器控制,最后蜂鸣器。分步骤调试可以减少错误。</think>我将分步骤为您说明如何实现这个系统。以下是基于STM32标准外设库的开发思路: 一、硬件连接规划 1. OLED(I2C): PB6(SCL), PB7(SDA) 2. DHT11(单总线): PA0 3. 水位传感器A(ADC): PA1 4. 水位传感器B(ADC): PA2 5. 继电器控制: PA4 6. 蜂鸣器: PA5 二、工程文件结构 1. main.c - 主程序 2. oled.h/c - OLED驱动 3. dht11.h/c - 温湿度传感器驱动 4. adc.h/c - ADC采集处理 5. relay.h/c - 继电器控制 6. buzzer.h/c - 蜂鸣器控制 三、关键代码实现(节选): ```c /* main.c */ #include "stm32f10x.h" #include "oled.h" #include "dht11.h" #include "adc.h" #include "relay.h" #include "buzzer.h" // 全局变量 uint16_t waterLevelA = 0, waterLevelB = 0; uint8_t temp = 0, humi = 0; int main(void) { // 初始化各模块 SystemInit(); OLED_Init(); DHT11_Init(); ADC1_Init(); Relay_Init(); Buzzer_Init(); while(1) { // 读取传感器数据 DHT11_ReadData(&temp, &humi); waterLevelA = Get_WaterLevel(ADC_Channel_1); // PA1 waterLevelB = Get_WaterLevel(ADC_Channel_2); // PA2 // OLED显示 OLED_ShowString(0,0,"Temp: "); OLED_ShowNum(48,0,temp,2); OLED_ShowString(72,0,"C"); // 类似显示其他数据... // 水泵控制逻辑 if(waterLevelA >= 2500){ Pump_Drain(); // 排水到2000 } else if(waterLevelA <= 500){ Pump_Fill(); // 注水到2000 } else{ Pump_Stop(); } // 蜂鸣器控制 if(waterLevelB >= 2500 && waterLevelB <= 3000){ Buzzer_Alert(); // 间隔1秒报警 } else{ Buzzer_Stop(); } Delay_ms(500); // 控制刷新频率 } } ``` 四、关键驱动函数实现(示例): 1. ADC采集(adc.c): ```c uint16_t Get_WaterLevel(uint8_t ADC_Channel) { ADC_RegularChannelConfig(ADC1, ADC_Channel, 1, ADC_SampleTime_239Cycles5); ADC_SoftwareStartConvCmd(ADC1, ENABLE); while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)); return ADC_GetConversionValue(ADC1) * 3000 / 4096; // 转换为0-3000范围 } ``` 2. 水泵控制(relay.c): ```c void Pump_Drain(void) { if(waterLevelA > 2000){ GPIO_SetBits(GPIOA, GPIO_Pin_4); // 启动水泵 } else{ GPIO_ResetBits(GPIOA, GPIO_Pin_4); // 停止 } } ``` 五、时钟配置建议 1. 系统时钟:72MHz 2. ADC时钟:12MHz(6分频) 3. I2C时钟:100kHz 六、注意事项 1. ADC需要进行校准和滤波处理 2. DHT11时序要求严格,建议使用定时器 3. 水位临界值建议添加迟滞区间(如±50) 4. 蜂鸣器驱动需使用PWM或定时器中断实现间隔报警 5. 建议添加看门狗防止程序跑飞 完整实现需要根据实际硬件连接调整GPIO配置,建议使用STM32CubeMX生成初始化代码框架。各模块建议单独测试通过后再进行系统集成。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值