历史上的今天
今天是: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
史海拾趣
|
请教各位大虾,写了一个spwm的程序,出来是20Khz,但是接到示波器上无法得到想要的波形是怎么回事?是不是变换的速度太快了无法用示波器观察?… 查看全部问答> |
|
能源是一种极重要的资源。大家都知道,没有能源,汽车不能开,飞机不能飞,工业无法持续发展,经济提高也没有保证。 所以,开发油田的意义很大,现在咱国家原油产量在1.6亿吨左右。按现有资源的可获量以及目前开采利用情况和技术经济条件 ...… 查看全部问答> |
|
1、SPARTAN-6这块板子确实不错,32位软核MicroBlaze添加了MMU还有JTAG模式,可以在线调试。 2、新增的PCI高速接口对于高速数据开发很有帮助,参考示例中视频开发部分以及网络部分都是很有用的 3、调试需要的JTAG和UART接口它都做成USB转接口了, ...… 查看全部问答> |
|
今天问一个牛人(应该是斑竹)一个问题,他直接告诉我去看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 ...… 查看全部问答> |
|
现在网络差,上不了图,只能贴下载的反馈信息一片是20K,一片是65535K在串口COM8连接成功@115200bps,耗时261毫秒芯片内BootLoader版本号:2.1芯片PID:00000410芯片FLASH容量为128KB芯片SRAM容量为20KB96位的芯片唯一序列号:37006A065832373 ...… 查看全部问答> |
|
发现eeworld重大漏洞,可能造成数据泄露请管理速速pm我 发现eeworld重大漏洞,可能造成数据泄露请管理速速pm我 我给你们eeworld这个帐号留言了 不知道发送成功没,请管理看到迅速pm我。… 查看全部问答> |




