在电子电路基础中,触发方式有几种,包括高电平触发,低电平触发,上升沿触发,下降沿触发。在本文中将使用代码实现这几种方式。
其中 message/messager.hpp 中使用的消息传递方式,在另一篇文章中有所介绍。https://blog.csdn.net/xiaonuo911teamo/article/details/112044036
文章目录
应用场景
- 想要以一种规律,触发一个事件,并且这种规律最终可以转化为上述的触发方式。
- 本身接收的就是实时传感器信息,通过某种转换,可以转化为上述的触发方式。
使用方式
下面的几部分代码,并不表示在一个函数中,主要是为了表现使用的简洁。
// 前置声明
enum TriggerType{
TRUE, // 高电平触发
FALSE, // 低电平触发
UP, // 上升沿触发
DOWN, // 下降沿触发
UPDOWN // 跳变触发,即上升沿下降沿都触发
};
// ...
// 设置一个错误检查动作,当出现2次上升沿,视为一次错误,执行报错提示。
register_diag_action("ERROR_DETECTOR", [=](){
printf("find a error!\n");
}, UP, 2);
// ...
// 输送脉冲, 假设循环200次为一个脉冲周期
// 如此,我们便可以将state认为是电平信号,进行监控了
// 按照上面的设置,当出现从false变成true的时候,就会触发一次。
while (1) {
static int32_t count = 100;
static bool state = false;
if (count == 0) {
count = 100;
state = !state;
}
count--;
if (count % 10 == 0)
DIRECT() << "fire_diag_condition "<< state;
Diagnose::fire_diag_condition("ERROR_DETECTOR", state);
}
源码
// diagnose.hpp
#pragma once
#include <message/messager.hpp>
#include <regex>
enum TriggerType{
TRUE,
FALSE,
UP,
DOWN,
UPDOWN
};
class Diagnose{
public:
template<class T>
static void register_diag_action(const std::string& name,
std::function<void(const T&)> func,
TriggerType trigger_type = TRUE, int trigger_times = 1){
auto& trigger_times_map = get_trigger_times_map<T>();
auto& condition_map = get_condition_map<T>();
auto& last_condition_map = get_last_condition_map<T>();
static int trigger_times_id = 0;
trigger_times_id++;
int trigger_times_id_captured = trigger_times_id;
auto trigger_func = [=, &trigger_times_map](const T& data, bool is_change){
auto& func_trigger_times = trigger_times_map[trigger_times_id_captured];
if (is_change){
func_trigger_times = 0;
}
if (++func_trigger_times >= trigger_times){
func(data);
func_trigger_times = 0;
}
};
Messager::subcribe<bool, T>(name + "__diag", [=, &condition_map, &last_condition_map](bool condition, const T& data){
auto& last_condition = condition_map[name];
bool is_changed_true_false = last_condition ^ condition;
bool has_last_last_condition = last_condition_map.find(name) != last_condition_map.end();
bool is_changed_up_down = false;
if (has_last_last_condition){
is_changed_up_down = !last_condition_map[name] ^ last_condition;
}
switch (trigger_type) {
case TRUE:
if (condition){
trigger_func(data, is_changed_true_false);
}
break;
case FALSE:
if (!condition){
trigger_func(data, is_changed_true_false);
}
break;
case UP:
if (!last_condition && condition){
trigger_func(data, is_changed_up_down);
}
break;
case DOWN:
if (last_condition && !condition){
trigger_func(data, is_changed_up_down);
}
break;
case UPDOWN:
if (last_condition ^ condition){
trigger_func(data, is_changed_up_down);
}
break;
default:;
}
});
}
static void register_diag_action(const std::string& name,
std::function<void()> func,
TriggerType trigger_type = TRUE, int trigger_times = 1){
register_diag_action<bool>(name, [func](const bool&){
func();
}, trigger_type, trigger_times);
}
template<class T>