历史上的今天
返回首页

历史上的今天

今天是:2025年05月07日(星期三)

正在发生

2019年05月07日 | STM32闹钟的一个进阶使用

2019-05-07 来源:eefocus

概述:

在使用STM32的过程中,我们在项目中可能经常会用到它的闹钟功能,但是对于刚开始接触STM32闹钟时,我就是直接设置一个闹钟,然后等待中断,有时候如果有两个闹钟,我们可以用ALARM A和B,但是有4个5个或者更多的闹钟设置,这时就不知道怎么办了。我就根据我的使用需求想了一个办法(只涉及几点几分,不考虑年月日及周几),如果你也有这样的需求,可以直接使用,如果不是,也希望可以给你留下一个思考的方向。



思路:

因为我的需求是每天的几点几分有一个闹钟,然后去处理,所以我的思路也很简单,就是将所有闹钟都注册到一个数组里面,然后换算为分钟从小到大进行排序,再根据当前时间去选择我下一个要设置的闹钟是哪一个,比如我已经注册了3个闹钟,时间分别是:200 300 500,当前时间是360,那么我现在选择设置的闹钟肯定是500。所以每次我们当闹钟响了以后,再去用当前时间和数组里面的闹钟时间对比,我们就可以得到下个闹钟需要设定的时间,是不是解决了闹钟设定的问题了呢。当然,有人会说闹钟设定了,我不知道这个闹钟响的时候我需要处理啥事件,很简单,我们在注册闹钟时不仅只注册时间,同时还需要注册闹钟事件标志。比如下方结构体:


typedef enum {

  PRINT_PEACE = 0,

  PRINT_LOVE,

  PRINT_HAVE_FUN

}alarm_process_status_t;

typedef struct {

  uint32_t time;                             //闹钟时间

  alarm_process_status_t process_status;    //闹钟事件

}alarm_info_t;



Linux下的模拟代码

这里我写了一个测试代码,为了方便调试和个人习惯,我自己是在linux下写了一个C代码,闹钟响不响,无非是中断是不是产生,至于怎么设置闹钟,这些我觉得你如果需要设置多个闹钟时,你一定已经基本知道闹钟的设置,我这里就不用STM32的实例代码了,我这边都是模拟,但效果是一样的,理解了思路就可以拿去增删改后用了。


 

#include

#include

#include

#include

#define ALARM_SIZE        10

typedef enum {

  PRINT_PEACE = 0,

  PRINT_LOVE,

  PRINT_HAVE_FUN

}alarm_process_status_t;

typedef enum {

  ALARM_NOSET = 0,

  ALARM_SET

}alarm_set_status_t;

typedef struct {

  uint32_t time;

  alarm_process_status_t process_status;

}alarm_info_t;

typedef struct {

  uint8_t size;                 //闹钟注册个数

  alarm_set_status_t set_status;    //闹钟是否设置标志

  alarm_process_status_t process_status;    //当前设置的闹钟响后需要做的事件标志

  alarm_info_t info[ALARM_SIZE];    //存储注册的闹钟

}alarm_ctrl_t;

alarm_ctrl_t alarmctrl;

/*获取当前时间分钟*/

uint32_t get_local_time()

{

  time_t now;

  struct tm *tm_now;

  time(&now);

  tm_now = localtime(&now);

  uint32_t times = tm_now->tm_hour * 60 + tm_now->tm_min;

  return times;

}

/*初始化*/

void alarm_ctrl_init(alarm_ctrl_t *alarm_ctrl)

{

  alarm_ctrl->size = 0;

  alarm_ctrl->set_status = ALARM_NOSET;

}

/*获取闹钟响铃状态 1响 0 不响*/

uint8_t get_alarm_clock()

{

  //对于在STM32中,我们可以在处理中断的文件中定义一个全局变量,当产生中断事变量变为1,否则为0

  //此处测试,故一直返回1

  return 1;

}

/*数组数据展示*/

void display_alarm_info()

{

  alarm_ctrl_t *alarm_ctrl = &alarmctrl;

  uint8_t i;

  printf("show alarm info: rn");

  for (i = 0; i < alarm_ctrl->size; i++) {

    printf(" %d ", alarm_ctrl->info[i].time);

  }

  printf("rn");

}

/*数组冒泡排序*/

void sort_alarm_info(alarm_info_t *info, uint8_t size)

{

  uint8_t i, j;

  for (i =0; i < size - 1; i++)

  {

    for (j = 0; j < size-1-i; j++) {

      if (info[j].time > info[j+1].time) {

        alarm_info_t temp = info[j];

        info[j] = info[j+1];

        info[j+1] = temp;

      }

    }

  }

}

/*数组插入*/

void insert_alarm_info(alarm_ctrl_t *alarm_ctrl, alarm_info_t *alarm_info)

{

  uint8_t i;

  uint8_t size = alarm_ctrl->size;

  if (size >= ALARM_SIZE) {

    return;

  }

  //相同闹钟禁止插入

  for (i = 0; i < size; i++) {

    if (alarm_ctrl->info[i].time == alarm_info->time) {

      printf("alarm time is exist, errorrn");

      return ;

    }

  }

  //插入数组数据并通过时间从小到大排序

  alarm_ctrl->info[size].process_status = alarm_info->process_status;

  alarm_ctrl->info[size].time = alarm_info->time;

  alarm_ctrl->size ++;

  sort_alarm_info(alarm_ctrl->info, alarm_ctrl->size);

  display_alarm_info();

}

/*数组删除*/

void delete_alarm_info(alarm_ctrl_t *alarm_ctrl, uint32_t time)

{

  uint8_t i, j, point, flag = 0;

  uint8_t size = alarm_ctrl->size;

  //查找删除的时间点是否存在

  for (i = 0; i < size; i++) {

    if (alarm_ctrl->info[i].time == time) {

      flag = 1;

      point = i;

      break;

    }

  }

  if (flag) {

    //删除的是末尾数据,size直接减一即可

    if (point + 1 == size) {

      alarm_ctrl->size --;

      display_alarm_info();

      return;

    }

    //删除的数据不止末尾数据,则需将删除的数据后面的数据全部前移一位

    alarm_ctrl->size --;

    for (i = point; i < size; i++) {

      alarm_ctrl->info[i].time = alarm_ctrl->info[i+1].time;

      alarm_ctrl->info[i].process_status = alarm_ctrl->info[i+1].process_status;

    }

    display_alarm_info();

  }

}

/*获取要设置的闹钟信息*/

uint8_t get_willalarm_info(uint32_t current_time, alarm_info_t *alarm_info)

{

  alarm_ctrl_t *alarm_ctrl = &alarmctrl;

  uint8_t i, flag = 0;

  if (0 == alarm_ctrl->size) {

    return 1;

  } else {

    //由于我们的闹钟数组是从小到大顺序排列,通过我们当前的时间去和闹钟数组时间对比

    //找到第一个比当前时间大的闹钟,我们设置即可,若未找到说明我们当前时间太大,那么我们选择数据开始的闹钟设置即可

    //如 数组 10 20 50 当前时间为18,那下个闹钟设置即是20,当前时间80,那么下个闹钟就是10

    for (i = 0; i < alarm_ctrl->size; i++) {

      if (current_time < alarm_ctrl->info[i].time) {

        flag = 1;

        alarm_info->time = alarm_ctrl->info[i].time;

        alarm_info->process_status = alarm_ctrl->info[i].process_status;

        break;

      }

    }

    if (0 == flag) {

      alarm_info->time = alarm_ctrl->info[0].time;

      alarm_info->process_status = alarm_ctrl->info[0].process_status;

    }

  }

  return 0;

}

/*业务处理*/

void alarm_handle_service()

{

  static int k = 0;

  alarm_ctrl_t *alarm_ctrl = &alarmctrl;

  printf("size = %d, setstatus = %drn", alarm_ctrl->size, alarm_ctrl->set_status);

  //判断rtc是否同步,在STM32中,内置一个rtc,但当我们完全断电,rtc时间清掉,我们需重新同步

  uint8_t rtc_sync_status  = 1;

  if (!rtc_sync_status) {

    return;

  }

  //判断是否有闹钟需要设置

  if (0 == alarm_ctrl->size) {

    printf("not have alarm need set.....rn");

    return;

  }

  //判断闹钟是否设置

  if (ALARM_NOSET == alarm_ctrl->set_status) {

    //闹钟未设置

    //获取当前时间,设置闹钟

    uint32_t current_time;

    //current_time = get_local_time();//由于测试,此处不获取,自己赋值

    if (0 == k) {

      current_time = 5;

    } else if (1 == k) {

      current_time = 88;

    } else if (2 == k) {

      current_time = 300;

    } else {

      current_time = 1000;

      k = 0;

    }

    k ++;

    alarm_info_t alarm_info;

    uint8_t ret = get_willalarm_info(current_time, &alarm_info);

    if (0 == ret) {

      printf("set alarm %drn", alarm_info.time);

      alarm_ctrl->process_status = alarm_info.process_status;

      alarm_ctrl->set_status = ALARM_SET;

    }

  } else {

    if (0 == get_alarm_clock()) {

      return;

    }

    //闹钟响,处理

    printf("alarm is clock....rn");

    switch (alarm_ctrl->process_status) {

      case PRINT_PEACE: {

        printf("Peace.........rn");

        break;

      }

      case PRINT_LOVE: {

        printf("Love.........rn");

        break;

      }

      case PRINT_HAVE_FUN: {

        printf("Have Fun.........rn");

        break;

      }

      default: {

        break;

      }

    }

    alarm_ctrl->set_status = ALARM_NOSET;

  }

}

int main()

{

  alarm_ctrl_init(&alarmctrl);

  alarm_info_t alarm_info;

  alarm_info.time =  100;

  alarm_info.process_status = PRINT_LOVE;

  insert_alarm_info(&alarmctrl, &alarm_info);

  alarm_info.time =  10;

  alarm_info.process_status = PRINT_PEACE;

  insert_alarm_info(&alarmctrl, &alarm_info);

  alarm_info.time =  500;

  alarm_info.process_status = PRINT_HAVE_FUN;

  insert_alarm_info(&alarmctrl, &alarm_info);

  alarm_info.time =  1000;

  alarm_info.process_status = PRINT_HAVE_FUN;

  insert_alarm_info(&alarmctrl, &alarm_info);

  delete_alarm_info(&alarmctrl, 1000);

  while (1) {

    alarm_handle_service();

    sleep(10);

  }

  return 0;

}


代码输出结果

这里是代码运行后的部分结果如下:


 

sky@ubuntu:~$ ./alarm_test

show alarm info: 

 100 

show alarm info: 

 10  100 

show alarm info: 

 10  100  500 

show alarm info: 

 10  100  500  1000 

show alarm info: 

 10  100  500 

size = 3, setstatus = 0

set alarm 10

size = 3, setstatus = 1

alarm is clock....

Peace.........

size = 3, setstatus = 0

set alarm 100

size = 3, setstatus = 1

alarm is clock....

Love.........

size = 3, setstatus = 0

set alarm 500

size = 3, setstatus = 1

alarm is clock....

Have Fun.........

size = 3, setstatus = 0

set alarm 10

size = 3, setstatus = 1

alarm is clock....

Peace.........

size = 3, setstatus = 0

set alarm 100


推荐阅读

史海拾趣

珠海艾派克(APEXMIC)公司的发展小趣事

随着技术的不断进步,艾派克逐渐在打印机芯片领域取得了突破。公司成功研发出一系列从打印机主控SoC芯片到耗材加密芯片的全系列打印机芯片产品,不仅满足了国内市场的需求,还成功打入国际市场,成为全球打印机通用耗材芯片的重要供应商。这一成就标志着艾派克在打印机芯片领域的领先地位得到了进一步巩固。

Axiohm公司的发展小趣事

面对电子行业日益激烈的竞争,Axiohm公司意识到单纯的制造和销售已经无法满足市场需求。于是,公司开始着手进行产业链整合,通过收购和合作的方式,将上下游企业纳入自己的业务体系。这一举措使得Axiohm能够更好地控制产品质量和交货期,同时也降低了运营成本。整合后的Axiohm在市场中更具竞争力,业绩稳步增长。

台湾双羽公司的发展小趣事

在成为全球领先的电子企业之后,富士通并没有停下脚步。公司开始积极拓展海外市场,将先进的技术和产品带到世界各地。通过在全球各地设立分支机构、与当地企业建立合作关系等方式,富士通成功地将自己的业务版图扩展到了全球60多个国家和地区。这一过程中,富士通不仅为当地市场带来了先进的技术和产品,也促进了全球电子产业的交流与合作。

Fedco_Batteries公司的发展小趣事

面对日新月异的市场需求和技术变革,Fedco_Batteries始终保持创新的步伐。公司加大了研发投入,不断推出新型电池产品,满足客户的多样化需求。同时,公司还积极探索新的应用领域,将电池技术应用于更多领域,如新能源汽车、智能家居等。这种创新驱动的发展战略,让Fedco_Batteries在行业中始终保持领先地位。

Agere System(LSI Logic)公司的发展小趣事

在快速发展的同时,Fedco_Batteries始终关注社会责任。公司积极参与公益事业,捐款捐物支持灾区重建、教育扶贫等项目。同时,公司还注重环保和可持续发展,致力于研发环保型电池产品,减少对环境的影响。这种关注社会责任的企业精神,让Fedco_Batteries在社会上树立了良好的形象。

协顺电子(Finecables)公司的发展小趣事

在品质和创新的支撑下,协顺电子开始积极拓展市场。公司通过参加各类展会、举办技术交流会等方式加强与客户的沟通和交流,同时也不断完善自己的销售网络和售后服务体系。此外,协顺电子还注重品牌建设,通过广告宣传、公关活动等方式提升品牌知名度和美誉度。这些努力使得公司的市场份额不断扩大,品牌影响力也逐渐增强。

问答坊 | AI 解惑

用verilog写的SPWM程序无法用示波器观察

请教各位大虾,写了一个spwm的程序,出来是20Khz,但是接到示波器上无法得到想要的波形是怎么回事?是不是变换的速度太快了无法用示波器观察?…

查看全部问答>

Windows Embedded工控 油田开采效率高

  能源是一种极重要的资源。大家都知道,没有能源,汽车不能开,飞机不能飞,工业无法持续发展,经济提高也没有保证。   所以,开发油田的意义很大,现在咱国家原油产量在1.6亿吨左右。按现有资源的可获量以及目前开采利用情况和技术经济条件 ...…

查看全部问答>

刚参加完SPARTAN -6的现场活动

1、SPARTAN-6这块板子确实不错,32位软核MicroBlaze添加了MMU还有JTAG模式,可以在线调试。 2、新增的PCI高速接口对于高速数据开发很有帮助,参考示例中视频开发部分以及网络部分都是很有用的 3、调试需要的JTAG和UART接口它都做成USB转接口了, ...…

查看全部问答>

不懂HELP!!!郁闷死!!!

今天问一个牛人(应该是斑竹)一个问题,他直接告诉我去看HELP,果然是牛人,直接去看HELP. 算了自己慢慢学吧 :@   话说回来谁让咱是菜鸟呢,早知道用JLINK开发了,搞的连软件用起来都困难。 LPCXPRESSO太郁闷了!!! [ 本帖最后由 lil ...…

查看全部问答>

Windows Emabedded CE6.0下怎样在应用程序中加载驱动?

我做了一个看门狗驱动,想要在应用程序中动态加载驱动,使用ActivateDeviceEx()加载驱动,程序代码段: DrvDll = ActivateDeviceEx(_T(\"HKEY_LOCAL_MACHINE\\\\Drivers\\\\BuiltIn\\\\WDT\"),RegIniData,1,NULL); hWDT = CreateFile(_T(\"WDT1 ...…

查看全部问答>

你会优先选择TI还是ADI的DSP

大家来说说在自己的应用中会选用ADI的还是TI的DSP。   两家各有什么优势啊?  …

查看全部问答>

很强大65535KBSRAM的STM32F103RBT6

现在网络差,上不了图,只能贴下载的反馈信息一片是20K,一片是65535K在串口COM8连接成功@115200bps,耗时261毫秒芯片内BootLoader版本号:2.1芯片PID:00000410芯片FLASH容量为128KB芯片SRAM容量为20KB96位的芯片唯一序列号:37006A065832373 ...…

查看全部问答>

寻求DSP仿真器 HDS560pod 驱动

一个很好的朋友向我求助DSP仿真器 HDS560pod,有哪位好心的朋友有的话,帮助我这个朋友一下好吗?谢谢!…

查看全部问答>

TMS320F28335的头文件和库文件有哪些?

TMS320F28335的原始头文件有哪些,多少个? 原始库文件有哪些?多少个?…

查看全部问答>

发现eeworld重大漏洞,可能造成数据泄露请管理速速pm我

发现eeworld重大漏洞,可能造成数据泄露请管理速速pm我 我给你们eeworld这个帐号留言了 不知道发送成功没,请管理看到迅速pm我。…

查看全部问答>