stm32 rtc闹钟到点时 时间快一秒

2019-07-21 00:42发布

本帖最后由 yuexiao46266 于 2019-5-28 23:14 编辑

本人基于mini版rtc用例,想实现多闹钟的功能出现了一个bug: 闹钟设置为20:01:00分,当时间从20:00:59到闹钟的时间时,时钟显示为20:01:01 而不是显示20:01:00而且现在删除掉闹钟中断里面多余的函数,只有一句printf,它时间点也是20:01:01

多闹钟设计思路是,用一个闹钟结构体数组,存储闹钟时间,然后把距离当前时间最近的闹钟放在数组的第一位,然后闹钟中断响应后设置数组下一个闹钟并把原先的闹钟从数组删除。

闹钟结构体:
typedef struct
{
        //vu8 year;
        //vu8 month;
        //vu8 day;
        vu8 hour;
        vu8 min;
        vu8 sec;
}_alr_obj;


自己的代码:
//记录闹钟数量
volatile int Alr_count=0;
volatile _alr_obj ALR[10]={0,0,0,0,0,0,0,0,0,0};



void RTC_IRQHandler(void)
{
        if(RTC_GetITStatus(RTC_IT_SEC)!=RESET)
        {
                RTC_Get();
        }
        
                RTC_ClearITPendingBit(RTC_IT_OW|RTC_IT_SEC);
                RTC_WaitForLastTask();
}
void RTCAlarm_IRQHandler(void)
{
        if(RTC_GetITStatus(RTC_IT_ALR) != RESET)
        {
                //RTC_Get();
                LED1=0;
                Alarming();
  }       
               
                EXTI_ClearITPendingBit(EXTI_Line17);
    RTC_WaitForLastTask();
                RTC_ClearITPendingBit(RTC_IT_ALR);
                RTC_WaitForLastTask();
}   
               
                EXTI_ClearITPendingBit(EXTI_Line17);
    RTC_WaitForLastTask();
                RTC_ClearITPendingBit(RTC_IT_ALR);
                RTC_WaitForLastTask();
}

void Alarming(void)
{
        printf("ÄÖÖóÕyÔúÏìó|ÖD£¡£¡£¡£¡");
                //删除闹钟
                Remove_Alr();
                if(!AlrIsEmpty())
                {
                                ALR_Set(calendar.w_year,calendar.w_month,calendar.w_date,ALR[0].hour,ALR[0].min,ALR[0].sec);
                }
}
u8 ALR_Set(u16 year,u8 month,u8 day,u8 hour,u8 min,u8 sec)
{
        u16 t;
        u32 seccount=0;
        if(year<1970||year>2099) return 1;
        for(t=1970;t<year;t++)
        {
                if(Is_Leap_Year(t)) seccount+=31622400;
                else seccount+=31536000;
        }
        month-=1;
        for(t=0;t<month;t++)
        {
                seccount+=(u32)mon_table[t]*86400;
                if(Is_Leap_Year(year)&&t==1) seccount+=86400;
        }
        seccount+=(u32)(day-1)*86400;
        seccount+=(u32)hour*3600;
        seccount+=(u32)min*60;
        seccount+=sec;
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP|RCC_APB1Periph_PWR,ENABLE);
        PWR_BackupAccessCmd(ENABLE);
        RTC_EnterConfigMode();
        RTC_SetAlarm(seccount);
        RTC_WaitForLastTask();
        return 0;
}


void Set_Alarm(u8 hour,u8 min,u8 sec)
{
        
        ALR[Alr_count].hour = hour;
        ALR[Alr_count].min = min;
        ALR[Alr_count].sec = 0;
        //数组排序
        Alr_count++;
        Sort_Alr();
        //设置闹钟
        ALR_Set(calendar.w_year,calendar.w_month,calendar.w_date,ALR[0].hour,ALR[0].min,ALR[0].sec);
}

void Show_Alarm(void)
{
        int t;
        printf("%d ",Alr_count);
        for(t=0;t<Alr_count;t++)
        {
                printf("%d %d %d ",ALR[t].hour,ALR[t].min,ALR[t].sec);
        }
}

void Sort_Alr(void)
{
        int i;
        int j;
        _alr_obj temp_alr;
        for(i=0;i<Alr_count;i++)
    {
       for(j=0;j<Alr_count-i-1;j++)
        {
            if(abs(calendar.hour-ALR[j].hour)>abs(calendar.hour-ALR[j+1].hour))
                                                {
                                                        temp_alr=ALR[j];
                                                        ALR[j]=ALR[j+1];
                                                        ALR[j+1]=temp_alr;
                                                }
                                                else
                                                        if(abs(calendar.hour-ALR[j].hour)==abs(calendar.hour-ALR[j+1].hour))
                                                        {
                                                                if(abs(calendar.min-ALR[j].min)>abs(calendar.hour-ALR[j+1].min))
                                                                {
                                                                        temp_alr=ALR[j];
                                                                        ALR[j]=ALR[j+1];
                                                                        ALR[j+1]=temp_alr;        
                                                                }
                                                        }
        }
                }
}

void Remove_Alr(void)
{
        u8 t;
  for(t=0;t<Alr_count;t++)
        {
                ALR[t]=ALR[t+1];
        }
        if(Alr_count>0)
                Alr_count--;
}

int AlrIsEmpty(void)
{
        if(Alr_count==0)
                return 1;
        else
                return 0;
}

MDK仿真的结果:

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
7条回答
yuexiao46266
1楼-- · 2019-07-21 01:31
lvkanger 发表于 2019-5-29 17:54
RTC_Get()放在RTC_Alarm中断里应该就好了吧

这个我尝试过了,不过我现在找到了 原因是因为中断函数执行时间太长了,我把原先中断函数拿到main函数执行 现在没这个bug了,谢谢了
yuexiao46266
2楼-- · 2019-07-21 02:34
 精彩回答 2  元偷偷看……
warship
3楼-- · 2019-07-21 04:13
 精彩回答 2  元偷偷看……
yuexiao46266
4楼-- · 2019-07-21 06:16
warship 发表于 2019-5-28 22:44
不要在中断服务里打印试试

那我把那些打印和删除闹钟的功能放在了另外一个函数Alarming,结果还是会有这个bug
正点原子
5楼-- · 2019-07-21 09:33
运行到这里就过了一秒吧?
yuexiao46266
6楼-- · 2019-07-21 12:19
正点原子 发表于 2019-5-29 02:11
运行到这里就过了一秒吧?

好像是的,所以我不知道怎么把这个中断处理的函数的时间给缩小,大佬有什么建议吗

一周热门 更多>