STM32常用小驱动

2023-10-27


因为疫情,最近在做红外温度检测设备,一些设备组合控制逻辑

灯控及蜂鸣器驱动

支持循环响,响多少次,响多少秒

/*
 *  FILE: misc_drv.c
 *
 *  Created on: 2020/2/23
 *
 *         Author: aron566
 *
 *  DESCRIPTION:--
 */
#ifdef __cplusplus //use C compiler
extern "C" {
#endif
#include "misc_drv.h"
#include "relay_control.h"
#include "modbus_reg.h"
Misc_device_t light_relay_device[LAMP_RELAY_DEVICE_MAX] = 
{
    {
      .mode = RUN_DELAY,     //运行模式--设置
      .set_run_time = 1,     //运行时间--设置
      .set_stop_time = 1,    //停止时间--auto
      .is_active = 0,        //是否激活--设置
      .is_run_flag = 0,      //不是运行态
      .start = fault_LED_on, //执行开启--初始化
      .stop = fault_LED_off  //执行关闭--初始化 
    },
    {
      .mode = RUN_DELAY,     //运行模式--设置
      .set_run_time = 1,     //运行时间--设置
      .set_stop_time = 1,    //停止时间--auto
      .is_active = 0,        //是否激活--设置
      .is_run_flag = 0,      //不是运行态
      .start = Relay1_Start_Out, //执行开启--初始化
      .stop = Relay1_Stop_Out  //执行关闭--初始化 
    },
    {
      .mode = RUN_DELAY,     //运行模式--设置
      .set_run_time = 1,     //运行时间--设置
      .set_stop_time = 1,    //停止时间--auto
      .is_active = 0,        //是否激活--设置
      .is_run_flag = 0,      //不是运行态
      .start = Relay2_Start_Out, //执行开启--初始化
      .stop = Relay2_Stop_Out  //执行关闭--初始化 
    }

};
start_beep_mode_t beep_device[BEEP_DEVICE_MAX] = 
{
    {
      .mode = ONCE_MODE,
      .statrt_times = 1,   //运行次数
      .interval_ms = 500,  //间隔时间
      .run_time_ms = 0,   //运行时间
      .is_active = 0,     //是否激活
      .transpose = 0,     //翻转标志
      .start = beep1_on,   //执行开启
      .stop = beep1_off    //执行关闭
    },
    {
      .mode = ALWAYS_ON_MODE,
      .statrt_times = 1,  //运行次数
      .interval_ms = 500,  //间隔时间
      .run_time_ms = 0,   //运行时间
      .is_active = 0,     //是否激活
      .transpose = 0,     //翻转标志
      .start = beep2_on,   //执行开启
      .stop = beep2_off    //执行关闭  
    }
 };
  
/*启动按照模式启动蜂鸣器*/
void Start_Beep_out_loop(start_beep_mode_t *beep_device)
{
    for(uint8_t index = 0; index < BEEP_DEVICE_MAX;index++)
    {
        if(beep_device[index].is_active == 1)
        {
            //启动对应beep
            Real_start_beep(index);

            if(beep_device[index].statrt_times == 0)
            {
                //取消激活      
                beep_device[index].is_active = 0;
                //恢复参数
                Init_beep_par(index);
            }
        }
        else
        {
            //停止运行
            Real_stop_beep(index);
        }
    }  
}

void Real_start_beep(uint8_t index)
{
    beep_device[index].run_time_ms++;
    if(!(beep_device[index].run_time_ms % beep_device[index].interval_ms))
    {
        //反转电平
        if(beep_device[index].mode != ALWAYS_ON_MODE)
        {
            beep_device[index].transpose ^= 1;
            //每切换到运行状态,运行次数减小
            if(beep_device[index].transpose == 0)
            {
                //运行次数--
                beep_device[index].statrt_times--;
            }
        }
    }
    if(beep_device[index].transpose == 0)
    {
        beep_device[index].start();
    }
    else
    {
        beep_device[index].stop();
    }
}

void Real_stop_beep(uint8_t index)
{
    beep_device[index].is_active = 0;
    beep_device[index].stop();   
}

/*设置运行间隔时间*/
void Set_run_interval_ms(uint8_t index ,uint32_t interval_ms)
{
    beep_device[index].interval_ms = interval_ms;
}
/*设置运行次数 == 运行次数*间隔时间 = 运行时间*/
void Set_run_time(uint8_t index ,uint32_t time_ms)
{
    beep_device[index].user_start_times = (time_ms/(beep_device[index].interval_ms*2));
    beep_device[index].user_start_times = (beep_device[index].user_start_times>0)?beep_device[index].user_start_times:1;
}

void Init_beep_par(uint8_t index)
{
    switch(beep_device[index].mode)
    {
    case ONCE_MODE:
        beep_device[index].statrt_times = 1;
        break;
    case THREE_TIMES_MODE:
        beep_device[index].statrt_times = 3;
        break;
    case ALWAYS_ON_MODE:
        beep_device[index].statrt_times = 0xFFFF;
        break;
    case SPECIFIED_MODE: //指定参数
        beep_device[index].statrt_times = beep_device[index].user_start_times;
        break;
    }
    beep_device[index].transpose = 0;
    beep_device[index].run_time_ms = 0;
}

void Set_beep_run_mode(uint8_t index ,start_mode_t mode)
{
    beep_device[index].mode = mode;
    Init_beep_par(index);
}

void  Enable_beep_out(uint8_t index ,start_mode_t mode)
{

    beep_device[index].is_active = 1;
    //更新参数
    if(mode != beep_device[index].mode)
    {
        beep_device[index].mode = mode;
        Init_beep_par(index);
    }
}
void Disable_beep_out(uint8_t index)
{
    beep_device[index].is_active = 0;
    Init_beep_par(index);
}

/* 轮询遥控器复位报警是否有效
 *
 * 参数:遥控器当前使能状态
 *
 * 返回:1有效 0无效
 */
uint8_t Get_Remote_Reset_Alarm_Button_State(void)
{
    if(device_v_info.set_remote_ctl_active == 1)
    {
        if(device_v_info.command_val == 2)
        {
            device_v_info.command_val = 0;
            return 1;
        }
    }
    return 0;
}

/* 轮询复位报警按钮状态
 *
 * 按键设置 - 是否启用
 *
 * 返回 1代表有效 0无效
 */
uint8_t Get_Reset_Alarm_Button_State(uint16_t setting)
{
    static uint16_t s_time = 0;
    //检测按钮状态
    if(Key_State_Check(Button_GPIO_Port ,Button_Pin ,GPIO_PIN_RESET ,KEY_DELAY_DEFAULT_VAL ,&s_time))
    {
        //按键终止报警有效
        if(setting == 0)
        {
            return 1;
        }
    }
    return 0;
}

/*
 * 每1ms检测按键按下事件处理 ,需将方法1ms调用一次
 *                                                             - - - - - - - - - - -- - - -----
 * 参数:端口号 引脚号 需检测的状态 检测标准时间(消抖时间ms)|_全局或静态数据保存区指针赋值0_|time
 *
 * 返回:1状态正确 0状态错误
 */
uint8_t Key_State_Check(GPIO_TypeDef* GPIOx ,uint16_t GPIO_Pin 
                        ,GPIO_PinState state ,uint16_t check_time 
                          ,uint16_t *static_time)
{
    if(state == HAL_GPIO_ReadPin(GPIOx, GPIO_Pin))//读取按键状态
    {
        //消除抖动
        (*static_time)++;
        if(*static_time >= check_time)
        {
            *static_time = check_time;
            return 1;
        }
    }
    else
    {
        *static_time = 0;
        return 0;
    }
    return 0;
}  

/*
 * 轮询定时运行设备 /ms
 */
void Start_Misc_device_loop(Misc_device_t *device)
{
    for(uint8_t index = 0;index < LAMP_RELAY_DEVICE_MAX;index++)
    {
        if(device[index].is_active != 0)
        {
            //轮询已启动的设备
            Run_Misc_Task_execute(&device[index]);
        }
        else
        {
            Stop_Misc_task(&device[index]);
        }
    }
}
/*
 * 运行指定时间长度 任务放入 1ms 轮询执行
 *                                            
 * 参数:启动任务 停止任务 运行时间set_run_time 
 */
void Run_Misc_Task_execute(Misc_device_t *device)
{
   //持续计算时间
    if(device->mode != ALWAYS_ON)
    {
        device->set_stop_time++;
    }
   if(device->set_stop_time >= device->set_run_time)
   {
      device->set_stop_time = 0;
      if(device->mode != ALWAYS_ON)
      {
          device->is_active = 0;
          device->is_run_flag = 0;
          device->stop();
      }
   }
   else
   {
       if(device->is_run_flag == 0)
       {
          device->is_run_flag = 1;
          device->start();
       }
   }
}
void Stop_Misc_task(Misc_device_t *device)
{
    device->is_active = 0;    //停止运行
    device->is_run_flag = 0;  //初始化运行标志
    device->set_stop_time = 0;//初始化参数
}

void Enable_Misc_device(uint8_t index ,Misc_Run_mode_t mode ,uint32_t run_time)
{
    if(mode != light_relay_device[index].mode)
    {
        light_relay_device[index].mode = mode;
    }
    if(light_relay_device[index].mode == RUN_DELAY)
    {
        if(light_relay_device[index].is_active == 0)
        {
            light_relay_device[index].is_active = 1;            //使能轮询
            light_relay_device[index].is_run_flag = 0;          //初始化运行标志
            light_relay_device[index].set_stop_time = 0;        //初始化参数
            light_relay_device[index].set_run_time = run_time;  //设置运行时间ms
        }
    }
    else if(light_relay_device[index].mode == ALWAYS_ON)
    {
        light_relay_device[index].is_active = 1;                //使能轮询
        light_relay_device[index].is_run_flag = 0;              //初始化运行标志
        light_relay_device[index].set_stop_time = 0;            //初始化参数
        light_relay_device[index].set_run_time = 0xFFFF;        //最大化
    }
}

void Set_Misc_device_run_time(uint8_t index ,uint32_t time_ms)
{
    light_relay_device[index].set_run_time = time_ms;
}
void Disable_Misc_device(uint8_t index)
{
    light_relay_device[index].is_active = 0;//禁用轮询
    light_relay_device[index].stop();       //stop now
}
/*
 * 1Khz 每1ms调用
 *
 * 参数:全局或静态 device参数
 */
void Simulation_Pwm_Control(PWM_Control_t *device)
{
    //依据总运行时间,pwm是否正在运行
    if(device->total_runn_time == 0)
    {
        device->total_runn_time = device->total_time;
        device->time_cnt = 0;
    }
    else
    {
        device->time_cnt++;
        device->total_runn_time--;
        if((device->time_cnt % device->run_time) && device->transpose == 0)//属于运行时间范围内,则运行(高电平时间)
        {
            device->start_operate();//run;
        }
        else    
        {
            device->transpose = 1;//高电平周期到,反转电平
        }
        if((device->time_cnt % device->run_time) && device->transpose == 1)
        {
            device->stop_operate();//stop
        }
        else    
        {
            device->transpose = 0;//低电平周期到,反转电平
        }
    }
}

/*继电器控制接口*/
void Relay1_Stop_Out(void)
{
    stop_relay(RELAY_1);
}
void Relay2_Stop_Out(void)
{
    stop_relay(RELAY_2);
}
void Relay1_Start_Out(void)
{
    start_relay(RELAY_1);
}
void Relay2_Start_Out(void)
{
   start_relay(RELAY_2); 
}
#ifdef __cplusplus //end extern c
}
#endif

头文件

/*
 *  FILE: misc_drv.h
 *
 *  Created on: 2020/2/23
 *
 *         Author: aron66
 *
 *  DESCRIPTION:--
 */
#ifndef MISC_DRV_H
#define MISC_DRV_H
#ifdef __cplusplus //use C compiler
extern "C" {
#endif
#include <stdint.h>
#include "peripheral.h"
#include "misc_task.h"
    
#define BEEP_DEVICE_MAX         2U
#define LAMP_RELAY_DEVICE_MAX   3U
typedef void (*p_misc_process)(void); 

/**********************************pwm仿真输出*********************************/
typedef struct{
    uint32_t time_cnt; 
    uint8_t  transpose; 
    uint32_t total_runn_time;
    uint32_t run_time; 
    uint32_t total_time;
    p_misc_process start_operate;
    p_misc_process stop_operate;
}PWM_Control_t;
/*****************运行指定次数指定间隔 or 长久运行****************************/
typedef enum
{
    ONCE_MODE = 0,
    THREE_TIMES_MODE,
    ALWAYS_ON_MODE,
    SPECIFIED_MODE
}start_mode_t;

typedef struct 
{
    start_mode_t mode;               //启动模式--设置
    volatile uint32_t statrt_times;  //运行次数--auto
    volatile uint32_t user_start_times;//用户自定义运行时间 
    volatile uint32_t interval_ms;   //间隔时间--auto
    volatile uint32_t run_time_ms;   //运行时间--auto
    volatile uint8_t  transpose;     //翻转标志--auto
    volatile uint8_t  is_active;     //是否激活--设置
    volatile p_misc_process start;   //执行开启--初始化
    volatile p_misc_process stop;    //执行关闭--初始化
}start_beep_mode_t;

/*****************运行一段时间自动关闭 or 长久运行****************************/
typedef enum
{
    ALWAYS_ON = 0,
    RUN_DELAY
}Misc_Run_mode_t;
typedef struct
{
    Misc_Run_mode_t mode;       //运行模式--设置
    uint32_t set_run_time;      //运行时间--设置
    uint32_t set_stop_time;     //停止时间--auto
    uint8_t  is_active;         //是否激活--设置
    uint8_t  is_run_flag;       //是运行态--auto
    p_misc_process start;       //执行开启--初始化
    p_misc_process stop;        //执行关闭--初始化    
}Misc_device_t;

extern start_beep_mode_t beep_device[];
/***************遥控器报警消除检测*************/
uint8_t Get_Remote_Reset_Alarm_Button_State(void);
/******************按键检测驱动****************/
uint8_t Key_State_Check(GPIO_TypeDef* GPIOx ,uint16_t GPIO_Pin ,GPIO_PinState state 
                        ,uint16_t check_time ,uint16_t *static_time);
uint8_t Get_Reset_Alarm_Button_State(uint16_t setting);  
/******************定时任务******************/
extern Misc_device_t light_relay_device[];
void Start_Misc_device_loop(Misc_device_t *device);
void Run_Misc_Task_execute(Misc_device_t *device);
void Enable_Misc_device(uint8_t index ,Misc_Run_mode_t mode ,uint32_t run_time);
void Set_Misc_device_run_time(uint8_t index ,uint32_t time_ms);
void Disable_Misc_device(uint8_t index);
void Stop_Misc_task(Misc_device_t *device);
/******************模拟pwm******************/
void Simulation_Pwm_Control(PWM_Control_t *device);
/******************beep控制******************/
void Start_Beep_out_loop(start_beep_mode_t *beep_device);
void Real_start_beep(uint8_t index);
void Real_stop_beep(uint8_t index);
void Init_beep_par(uint8_t index);
void Set_beep_run_mode(uint8_t index ,start_mode_t mode);
void Set_run_interval_ms(uint8_t index ,uint32_t interval_ms);//设置运行间隔
void Set_run_time(uint8_t index ,uint32_t time_ms);
void Enable_beep_out(uint8_t index ,start_mode_t mode);/*依据参数开启输出*/
void Disable_beep_out(uint8_t index);

void Relay1_Stop_Out(void);
void Relay2_Stop_Out(void);
void Relay1_Start_Out(void);
void Relay2_Start_Out(void);
#ifdef __cplusplus //end extern c
}
#endif
#endif

按键消抖使用例子

/* 轮询复位报警按钮状态
 *
 * 按键设置 - 是否启用
 *
 * 返回 1代表有效 0无效
 */
static uint8_t Get_Reset_Alarm_Button_State(uint16_t setting)
{
    static uint16_t s_time = 0;
    //检测按钮状态
    if(Key_State_Check(Button_GPIO_Port ,Button_Pin ,GPIO_PIN_RESET ,KEY_DELAY_DEFAULT_VAL ,&s_time))
    {
        //按键终止报警有效
        if(setting == 0)
        {
            return 1;
        }
    }
    return 0;
}

蜂鸣器控制列子

//任务中,检测事件,设置相关报警,Start_Beep_out_loop循环1ms检测一次
//Start_Misc_device_loop1ms检测一次
    for(;;)
    {
      Check_Complete_Alarm();
      
      Check_Temperature_Is_Alarm(1);
      
      alarm_task_excute();
      
      Start_Beep_out_loop(beep_device);
      
      Start_Misc_device_loop(light_relay_device);
      
      osDelay(1);
    }
/*其他人数根据要求启动设备*/
void alarm_task_excute(void)
{
    static uint16_t last_event = 0;

    //检测复位按键状态
    uint8_t button_state = Get_Reset_Alarm_Button_State(0);
    //获取实时人员检测状态
    People_State_t state = Check_People_Is_Exist();
    if(button_state)                             //is manual stop
    {
        Disable_beep_out(0);                    
        Disable_beep_out(1);                     //is manual
        Disable_Misc_device(0);
        Disable_Misc_device(1);
        Disable_Misc_device(2);
        alarm_task_event = 0;
    }
    
    if(state == PEOPLE_LEAVE)
    {
        normal_LED_off();              //人员离开必须关闭正常指示灯
    }
    if(alarm_task_event & SET_NORMAL_EVENT)
    {
        normal_LED_on();              //开绿灯 leave stop
        if(last_event == SET_NO_CHECK_EVENT)
        {
            Disable_beep_out(0);      //the last event is no check关闭板载蜂鸣器
        }
        Enable_beep_out(0 ,ONCE_MODE);//开板载蜂鸣器 滴一声 auto stop
        if(device_v_info.set_next_test_auto_stop != 0 ||
           last_event != SET_HEAT_ALARM_EVENT) //is new test device stop
        {
            Disable_Misc_device(0);             //is new test stop 关红灯
            Disable_beep_out(1);                //is new test stop 关外报
        }
        last_event = SET_NORMAL_EVENT;
        alarm_task_event &= ~SET_NORMAL_EVENT;
    }
    /*漏测和测到发热:外接红灯亮、外接声报警响、继电器动作,
    收到按键确认后,红灯灭、声报警停、继电器恢复*/
    if(alarm_task_event & SET_HEAT_ALARM_EVENT)
    {
        last_event = SET_HEAT_ALARM_EVENT;
        if(device_v_info.set_auto_stop_s != 0) //指定运行时间
        {
            Set_run_time(1 ,device_v_info.set_auto_stop_s*1000);
            Enable_beep_out(1 ,SPECIFIED_MODE);//外部蜂鸣器 滴三声 auto stop
            Enable_Misc_device(0 ,RUN_DELAY ,device_v_info.set_auto_stop_s*1000);    //开红灯 manual stop
            Enable_Misc_device(1 ,RUN_DELAY ,device_v_info.set_auto_stop_s*1000);    //开继电器1 manual stop
            Enable_Misc_device(2 ,RUN_DELAY ,device_v_info.set_auto_stop_s*1000);    //开继电器2 manual stop
            alarm_task_event &= ~SET_HEAT_ALARM_EVENT;
        }
        else
        {
            Set_run_interval_ms(1 ,500);
            Enable_beep_out(1 ,THREE_TIMES_MODE);   //外部蜂鸣器 持续滴三声 manual stop
            Enable_Misc_device(0 ,ALWAYS_ON ,0);    //开红灯 manual stop
            Enable_Misc_device(1 ,ALWAYS_ON ,0);    //开继电器1 manual stop
            Enable_Misc_device(2 ,ALWAYS_ON ,0);    //开继电器2 manual stop
        }

    }
    if(alarm_task_event & SET_NO_CHECK_EVENT)
    {
        last_event = SET_NO_CHECK_EVENT;
//        Enable_beep_out(1 ,ALWAYS_ON_MODE);        //外部蜂鸣器 持续响 new test stop
        Set_run_time(0 ,30*1000);                  //板载蜂鸣器 持续响 30s new test stop
        Enable_beep_out(0 ,SPECIFIED_MODE);
//        Enable_Misc_device(0 ,ALWAYS_ON ,0);       //开红灯 new test stop
        alarm_task_event &= ~SET_NO_CHECK_EVENT;
    }  
}

数据处理校验计算类

/*
 * 计算连续数据中,中位值 最大值 平均值 最小值
 *
 * 参数:返回数据类型 数据地址 数据长度
 * 
 * 返回:依据设置mode 中位值 最大值 平均值 最小值
 */
uint16_t Calc_Tmp(Calc_Mode_t mode ,uint16_t *data ,uint16_t len)
{
    uint16_t ret = 0;
    uint8_t index = 0;
    uint16_t i,j,temp;
    //插入
    for(i = 1;i < len ;i++) //从数组元素1开始
    {
        temp = data[i];     //将当前数组元素的值给临时变量temp
        for( j = i ;j > 0 && data[j-1] > temp ;j--) //将当前的数组元素号给J 满足j>0且当前元素的前一个元素 大于当前值。则
        {
           data[j] = data[j-1];//将大值给
        }
        data[j] = temp;
        
    }
    switch(mode)
    {
    case MEDIAN_VALUE_MODE:
        //查询中位值
        if(mode == MEDIAN_VALUE_MODE)
        {
            if(len % 2)
            {
                index = (len-1) /2;
                ret = data[index];
            }
            else
            {
                index = len /2;
                ret = (data[index]+data[index-1])/2;
            }
        }
        return ret;
    case MAX_VALUE_MODE:
        //查询最大值
        return data[len-1]; 
    case AVERAGE_VALUE_MODE:
        //查询平均值
        ret = data[0];
        for(uint16_t index = 1;index < len;index++)
        {
            ret = (ret+data[index])/2;
        }
        return ret;
    case MIN_VALUE_MODE:
        //查询最小值
        return data[0];
    default:
      return 0;
    }
}  

/*
 * 计算连续数据中,最大值 最小值
 *
 * 参数:返回数据类型 数据地址 数据长度
 * 
 * 返回:依据设置mode 最大值 最小值
 */
uint16_t Calc2_Tmp(Calc_Mode_t mode ,uint16_t *data ,uint16_t len)
{
    uint16_t ret = data[0];
    uint8_t index = 0;
    switch(mode)
    {
    case MEDIAN_VALUE_MODE:
        //查询中位值
        if(mode == MEDIAN_VALUE_MODE)
        {
            if(len % 2)
            {
                index = (len-1) /2;
                ret = data[index];
            }
            else
            {
                index = len /2;
                ret = (data[index]+data[index-1])/2;
            }
        }
        return ret;
    case MAX_VALUE_MODE:
        //查询最大值
        for(uint16_t index = 1;index < len;index++)
        {
            if(data[index] > ret)
            {
                ret = data[index];
            }
        }
        return ret;
    case AVERAGE_VALUE_MODE:
        //查询平均值
        for(uint16_t index = 1;index < len;index++)
        {
            ret = (ret+data[index])/2;
        }
        return ret;
    case MIN_VALUE_MODE:
        //查询最小值
        for(uint16_t index = 1;index < len;index++)
        {
            if(data[index] < ret)
            {
                ret = data[index];
            }
        }
        return ret;
    default:
      return 0;
    }
}  
/* 检测温度值是否整定完毕
 *
 * 参数:数据地址 数据长度 标准最小值 极限值
 * 返回:1数据稳定 0数据不稳定
 */
uint8_t Check_Data_Is_Ture(uint16_t *data ,uint16_t len ,uint16_t standrad_min
                                  ,uint16_t standrad_max)
{
    uint16_t max_val = 0;
    uint16_t min_val = 0;
    max_val = Calc_Tmp(MAX_VALUE_MODE ,data ,len);
    min_val = Calc_Tmp(MIN_VALUE_MODE ,data ,len);
    //最大最小值相同
    if(max_val == min_val && min_val > standrad_min && min_val < standrad_max)
    {
        printf("*******1*******\n");
        return 1;
    }
    else
    {
        return 0;
    }  
}
//判断温度稳定,在人体范围内的温度,且最大最小偏差<0.1度
uint16_t Check2_Data_Is_Ture(uint16_t *data ,uint16_t len ,uint16_t standrad_min
                                  ,uint16_t standrad_max)
{
    uint16_t max_val = 0;
    uint16_t min_val = 0;
    max_val = Calc2_Tmp(MAX_VALUE_MODE ,data ,len);
    min_val = Calc2_Tmp(MIN_VALUE_MODE ,data ,len);
//    min_val = Calc_Tmp(MEDIAN_VALUE_MODE ,data ,len);
    //最大最小值相同
    if(((max_val - min_val) <= 5) && min_val > standrad_min && min_val < standrad_max)
    {
        return max_val;
    }
    else
    {
        return 0;
    }
}

/* 代入最新稳点温度值,判断数据变化是否>=standrad_val
 *
 * 返回:符合>20返回
 */
uint16_t Check_Tmp_Is_Modified(uint8_t new_test_flag ,uint16_t current_tmp ,uint16_t standrad_val)
{
    static uint16_t last_tmp = 0;
    if(new_test_flag == 1)
    {
        //当前测量温度不同于上次温度,且大于上次温度
        if(current_tmp > last_tmp && (current_tmp - last_tmp) >= standrad_val)
        {
           last_tmp = current_tmp;  //更新大值返回
           return last_tmp;
        }
    }
    else
    {
        last_tmp = 0;
        return last_tmp;
    }
    return last_tmp;
}

/* 16bit和校验 -判断连续len个数据和 ,CL在前 CH在后 判断与 len len+1位置的数据是否一致
 *
 * 参数:连续数据地址的首地址 校验的数据长度
 *
 * 返回:校验结果:1 正确  0错误 
 */

uint8_t Check_16bitData_Sum(uint8_t *data ,uint16_t len)
{
    uint16_t result = 0;
    uint16_t value16 = 0;
    uint16_t value_num = 0; //值的数量
    
    value_num = len / 2 - 1;
    
    for(uint16_t i = 0;i < value_num; i++)
    {
        value16 = data[2 * i] + data[2 * i+ 1] * 256;
        result += value16;
    }
    value16 = data[len - 2] + data[len - 1] * 256;
    if( result == value16 )
    {
        return 1;
    }
    return 0;
}

/* 16bit和校验 -判断连续len个字节数据和保留16bit ,CL在前 CH在后 判断与 len len+1位置的数据是否一致
 *
 * 参数:连续数据地址的首地址 校验的数据长度
 *
 * 返回:校验结果:1 正确  0错误 
 */

uint8_t Check2_16bitData_Sum(uint8_t *data ,uint16_t len)
{
    uint16_t result = 0;
    uint16_t value16 = 0;
    
    for(uint16_t i = 0;i < len; i++)
    {
        result += data[i];
    }
    value16 = data[len] + data[len+1] * 256;
    if( result == value16 )
    {
        return 1;
    }
    return 0;
}

/* 8bit和校验 -判断连续len个数据和 ,与len+1位置的数据是否一致
 *
 * 参数:连续数据地址的首地址 校验的数据长度
 *
 * 返回:校验结果:1 正确  0错误 
 */

uint8_t Check_Data_Sum(uint8_t *data ,uint16_t len)
{
    uint8_t ret = 0;  
    for(uint16_t i = 0;i < len;i++)
    {
        ret += data[i];
    }
    if(ret == data[len])
    {
        return 1;
    }
    return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32常用小驱动 的相关文章

  • c项目makefile多重定义错误

    这个问题是一个对应于创建的repexthis问题 在我的嵌入式 C 项目中 我有两个独立的板 我想为每个板创建两个 c 文件 master c 和 Slave c 其中包含自己的特定main 功能 我使用 stm32cumbemx 生成带有
  • 如何让printf在STM32F103上工作?

    我是 STM32F103 世界的新手 我有一个STM32F103的演示代码 我正在使用arm none eabi来编译它 我尝试了在谷歌上可以找到的内容 但到目前为止没有任何效果 我已经花了三天时间来解决这个问题 任何人都可以给我一个运行良
  • STM32 F072上的软件如何跳转到bootloader(DFU模式)?

    STM32应用笔记2606对此进行了讨论 但没有简单的代码示例 该答案已使用 IAR EWARM 在 STM32F072 Nucleo 板上进行了测试 这个答案使用 STM32标准外设库 仅此而已 请注意 验证您是否成功进入引导加载程序模式
  • CMSIS 库是否应该包含在版本控制中? [复制]

    这个问题在这里已经有答案了 通常 我曾经在版本控制中包含芯片供应商 ST 提供的设备特定标头和源以及 CMSIS Core 标头 数量不多 也没有更新的习惯 我使用STM32微控制器 但我不使用立方体框架 or the 标准外设库 最近 我
  • rt-thread studio中新建5.0不能用

    文章目录 一 版本对比 二 文件和文件夹打斜杠 在使用RT Thread studio创建新工程5 0版本的时候 结果发现新建完成之后程序不能正常运行 但是创建4 10版本的时候却能运行 那肯定是新版本出现了BUG 一 版本对比 首先对比了
  • STM32超声波——HC_SR04

    文章目录 一 超声波图片 二 时序图 三 超声波流程 四 单位换算 五 取余计算 六 换算距离 七 超声波代码 一 超声波图片 测量距离 2cm 400cm 二 时序图 1 以下时序图要先提供一个至少10us的脉冲触发信号 告诉单片机我准备
  • 物联网网关

    物联网网关是 连接物联网设备和互联网的重要桥梁 它负责将物联网设备采集到的数据进行处理 存储和转发 使其能够与云端或其它设备进行通信 物联网网关的作用是实现物联网设备与云端的无缝连接和数据交互 物联网网关功能 数据采集 物联网网关可以从物联
  • 毕业设计 江科大STM32的智能温室控制蓝牙声光报警APP系统设计

    基于STM32的智能温室控制蓝牙声光报警APP系统设计 1 项目简介 1 1 系统构成 1 2 系统功能 2 部分电路设计 2 1 stm32f103c8t6单片机最小系统电路设计 2 2 LCD1602液晶显示电路设计 2 2 风
  • STM32 GPIO工作原理详解

    STM32 GPIO介绍 1 STM32引脚说明 GPIO是通用输入 输出端口的简称 是STM32可控制的引脚 GPIO的引脚与外部硬件设备连接 可实现与外部通讯 控制外部硬件或者采集外部硬件数据的功能 以STM32F103ZET6芯片为例
  • VS Code 有没有办法导入 Makefile 项目?

    正如标题所说 我可以从现有的 Makefile 自动填充 c cpp properties json 吗 Edit 对于其他尝试导入 makefile 的人 我找到了一组脚本 它们完全可以实现我想要实现的目标 即通过 VS Code 管理
  • 擦除后无法写入闪存

    所以我不能在擦除后直接写入内部闪存 如果写操作之前没有擦除操作 那么我可以 有什么想法吗 编程函数返回 成功写入 值 但查看内存时 没有写入任何数据 这是代码 uint32 t pageAddress 0x08008000 uint16 t
  • 无法使用 OpenOCD 找到脚本文件

    我正在尝试按照本教程将 OpenOCD 与我的 ST 发现板一起使用 https japaric github io discovery README html https japaric github io discovery READM
  • 毕设开题分享 单片机智能教室系统(智能照明+人数统计)

    1 简介 Hi 大家好 今天向大家介绍一个学长做的单片机项目 单片机智能教室系统 智能照明 人数统计 大家可用于 课程设计 或 毕业设计 项目分享 https gitee com feifei1122 simulation project
  • CMSIS & STM32,如何开始? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我想在 STM32 上使用 CMSIS 启动项目 网上一搜 没找到具体的教程 有些使用 SPL 开始项
  • for循环延时时间计算

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 前言 一 pandas是什么 二 使用步骤 1 引入库 2 读入数据 总结 前言 之前做led点亮的实验 好像是被delay函数影响了 因为delay参数设置的不对
  • STM32 Nucleo 上的上升沿中断多次触发

    我正在使用 STM32 NUCLEO F401RE 微控制器板 我有一个扬声器 经过编程 当向上 向下推操纵杆时 可以按设定的量改变频率 我的问题是 有时 通常 当向上 向下推动操纵杆时 频率会增加 减少多次 这意味着 ISR 正在执行多次
  • STM32F0、ST-link v2、OpenOCD 0.9.0:打开失败

    我在用着发射台 http www ti com ww en launchpad about htmlgcc arm none eabi 4 9 2015q2 为 STM32F0 进行编译 现在我想使用该集合中的 arm none eabi
  • 当端点和 PMA 地址均更改时,CubeMX 生成的 USB HID 设备发送错误数据

    我正在调试我正在创建的复合设备的问题 并在新生成的仅 CubeMX 代码中重新创建了该问题 以使其更容易解决 我添加了少量代码main 让我发送 USB HID 鼠标点击 并在按下蓝色按钮时使 LED 闪烁 uint8 t click re
  • stm32l0: 执行MI命令失败。使用 vFlashErase 数据包擦除闪存时出错

    我正在使用 Nucleo STM32L031 和 AC6 STM32 工作台 eclipse 我编写应用程序并进入调试模式 一切正常 直到我在应用程序中添加另一个功能 我注意到当我删除 评论 新函数 软件可以再次进入调试模式 但是当我添加
  • GCC 变量映射和 MISRA-C

    我主要知道两种使用 GCC 声明内存映射寄存器的方法 有许多变体 使用双字段 每个外设的数据结构等 要么使用初始化为正确地址的指针 例如volatile uint32 t pMyRegister uint32 t 0xDEADBEEFUL

随机推荐

  • 论文笔记:Tip-Adapter: Training-free CLIP-Adapter for Better Vision-Language Modeling详解

    论文 https arxiv org abs 2111 03930 代码 GitHub gaopengcuhk Tip Adapter 摘要 对比性视觉语言预训练模型 即CLIP 为使用大规模图像 文本对学习视觉表征提供了一个新的范式 它通
  • --------三种简单的程序设计模式实例

    1 题目名称 1 简单工厂模式 使用简单工厂模式模拟女娲 Nvwa 造人 Person 如果传入参数M 则返回一个Man对象 如果传入参数W 则返回一个Woman对象 请实现该场景 现需要增加一个新的Robot类 如果传入参数R 则返回一个
  • Winform无法加载基类的错误解决

    相信在vs2010进行开发的人 如果用到了继承窗体的功能 基本上都会遇到 无法加载基类 的错误 这类错误说大也不大 可说小也不小 基本上都是vs2010分析数据时遇到错误造成的 基本上解决方法有三 1 重新生成解决方案 2 删除第三方引用控
  • harbor离线安装

    1 介绍 Docker容器应用的开发和运行离不开可靠的镜像管理 虽然Docker官方也提供了公共的镜像仓库 但是从安全和效率等方面考虑 部署我们私有环境内的Registry也是非常必要的 Harbor是由VMware公司开源的企业级的Doc
  • 花里胡哨的CentOS

    花里胡哨的CentOS 文章基于如下环境 WSL2下的CentOS7 下载地址为 CentOS7 在WSL2下安装CentOS7 首先启用win10或者win11的wsl2功能 这里不过多介绍 不会的自行问度娘 把下载好的CentOS7 z
  • 电脑重置网络 解决网络异常问题

    电脑重置网络可以解决网络异常问题 修复网络链接不畅问题 步骤 1 首先在屏幕左下角的开始 单点击右键 在弹出的菜单中xz选择 Windows Power Shell 管理员 A 打开命令提示符 2 然后在弹出的命令符窗口输入 netsh w
  • 主动扫描系列文章(1):nmap的基础使用

    20201024 目录 主动扫描系列文章 1 nmap的基础使用 主动扫描系列文章 2 masscan zmap扫描主机与端口 主动扫描系列文章 3 nmap与masscan的配合使用 0 引言 关于nmap的使用 这种文章网上满天飞 本篇
  • 哈夫曼树实现文件的压缩与解压

    一 哈夫曼树的构造方法 1 首先要拿到一组数据及其权重 其中每个数据都作为一颗哈夫曼树 也可以被视为一个结点 2 在这些树中找到权重最小的两棵树 将其合并为一棵树 合并方法 将这两棵树的权重相加 权重和为一个新的结点 并且为原来两棵树的父节
  • 计算均值的95%置信区间的下限值和上限值(计算置信区间)

    计算均值的95 置信区间的下限值和上限值 计算置信区间 在统计学中 置信区间是用来估计总体参数的范围 当我们想要估计总体均值的置信区间时 可以使用R语言进行计算 下面将介绍如何使用R语言计算均值的95 置信区间的下限值和上限值 首先 我们需
  • MySQL数据库之表中的数据增删改查

    前置操作 在数据库中新建表kk2 1 增 insert into 表名 字段1 字段2 values 数据1 数据2 向表中新增数据 可以选择部分字段插入数据 注意 编写插入语句时 在前面括号内写的字段和后面括号内的数据的位置 数量必须保持
  • 第二章 软件测试策略

    第二章 软件测试策略 根据mooc课程所做的笔记 课程链接 文章目录 第二章 软件测试策略 2 1 软件开发过程及模型 2 2 软件测试过程 单元测试 2 3 软件测试过程 集成测试 2 4 静态白盒测试 2 5 静态黑盒测试 2 1 软件
  • 手把手教你做计算机网络基础大题—地址分配

    一 题目 某单位分配到一个起始地址为14 24 74 0 24的地址块 该单位需要用到三个子网 它们的三个子网地址块的具体要求是 子网N1需要120个地址 子网N2需要60个地址 子网N3需要10个地址 请给出地址的分配方案 二 解答 起始
  • 通信上的RX、TX分别表示什么?

    RX 表示接收数据 Receive rx Data 的简写形式 TX 表示发送数据 Transmit tx Data 的简写形式
  • 使用 Docker-Compose部署JavaWeb项目并运行JavaWeb项目

    一共需要两个容器 Tomcat mysql 然后需要jpress的war包 创建一个新的composeJava目录 将war包放入该目录下 并且以下操作都在 该目录下进行 创建server xml 内容如下
  • 名人名言(持续更新中)

    杰克威尔逊 他说 领导者的工作 就是每天把全世界各地最优秀的人才延揽过来 他们必须热爱自己的员工 拥抱自己的员工 激励自己的员工 作为一个过来人 韦尔奇给公司领导者传授的用人秘诀是他自创的 活力曲线 一个组织中 必有20 的人是最好的 70
  • Android 删除文件功能代码

    Hello everyone 我是鲁班 一个热衷于科研和软开的胖子 亲测有效 废话不说 直接上代码 有问题评论或私信 public static boolean deleteFoder File file if file exists 判断
  • 实用插件_《FF14》将封禁一批第三方插件 其中不乏实用插件

    SE旗下人气网游 最终幻想14 Final Fantasy 14 的最新5 2版本即将上线 正在所有光之战士准备摩拳擦掌大干一场时 官方似乎给这些玩家浇了一盆冷水 先是制作人吉田直树希望玩家们在游戏中停止使用一些色情mod 然后官方表示在此
  • 尚医通——数据字典开发

    这里写目录标题 一 数据字典介绍 二 数据字典开发 1 搭建service cmn模块 1 1 搭建service cmn模块 1 2 修改配置 1 3 启动类 2 数据字典列表 2 1 数据字典列表接口 2 1 1 model模块添加数据
  • C++中的对象初始化

    当对象在创建时获得了一个特定的值 我们说这个对象被初始化 初始化不是赋值 初始化的含义是创建变量赋予其一个初始值 而赋值的含义是把当前值擦除 而以一个新值来替代 对象初始化可以分为默认初始化 直接初始化 拷贝初始化以及值初始化 1 默认初始
  • STM32常用小驱动

    STM32常用小驱动 灯控及蜂鸣器驱动 按键消抖使用例子 蜂鸣器控制列子 数据处理校验计算类 因为疫情 最近在做红外温度检测设备 一些设备组合控制逻辑 灯控及蜂鸣器驱动 支持循环响 响多少次 响多少秒 FILE misc drv c Cre