MM32F3273G8P火龙果开发板MindSDK开发教程12 -获取msa311加速器的敲击事件

news2024/11/18 9:49:49

MM32F3273G8P火龙果开发板MindSDK开发教程12 -获取msa311加速器的敲击事件

1、功能描述

msa311可以识别单击、双击事件,类似手机上的点击返回,双击截屏功能。
单击,双击都能产生中断事件。
中断事件产生后,从对应的状态寄存器读取是双击还是单击。
中断需要打开映射。
单双击可设置阈值。
对应寄存器的描述如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2、设置相关寄存器

a、设置tap_quite
b、设置tap_shock
c、设置tap_duration
在这里插入图片描述
d、设置tap_threshole
e、设置中断映射
f、设置中断使能。

对应代码:

    #if ENABLE_TAP_DETECT == 1
        Msa311_SetTapQuiteParam(MSA311_TAPQUITE_30_MS);
        Msa311_GetTapQuiteParam(&tapQuite);
        printf("Msa311_getTapQuiteParam == %s\r\n",tapQuite == MSA311_TAPQUITE_30_MS ? "MSA311_TAPQUITE_30_MS" : "MSA311_TAPQUITE_20_MS");

        Msa311_SetTapShockParam(MSA311_TAPSHOCK_50_MS);
        Msa311_GetTapShockParam(&tapShock);
        printf("Msa311_GetTapShockParam == %s\r\n",tapShock == MSA311_TAPSHOCK_50_MS ? "MSA311_TAPSHOCK_50_MS" : "MSA311_TAPSHOCK_70_MS");

        Msa311_SetTapDurationParam(MSA311_TAPDUR_250_MS);
        Msa311_GetTapDurationParam(&tapDuration);
        printf("Msa311_GetTapDurationParam == 0x%02x\r\n",tapDuration);

        Msa311_ThresholdConvertToRegister(1.0f,&reg);
        Msa311_SetTapThresholdParam(reg);
        Msa311_GetTapThresholdParam(&threshold);
        printf("Msa311_GetTapThresholdParam  == 0x%02x\r\n",threshold);

        //使能S_TAP D_TAP Int
        Msa311_SetInterruptMap0(MSA311_INTERRUPT_D_TAP,MSA311_BOOL_TRUE);
        Msa311_SetInterruptMap0(MSA311_INTERRUPT_S_TAP,MSA311_BOOL_TRUE);
        Msa311_GetInterruptMap0(MSA311_INTERRUPT_D_TAP,&enable);
        printf("Msa311_GetInterruptMap0 MSA311_INTERRUPT_D_TAP %s\r\n",enable==MSA311_BOOL_TRUE ? "enable" : "disable");
        Msa311_GetInterruptMap0(MSA311_INTERRUPT_S_TAP,&enable);
        printf("Msa311_GetInterruptMap0 MSA311_INTERRUPT_S_TAP %s\r\n",enable==MSA311_BOOL_TRUE ? "enable" : "disable");

        Msa311_SetInterrupt0Enable(MSA311_INTERRUPT_D_TAP_EN,MSA311_BOOL_TRUE);
        Msa311_GetInterrupt0Enable(MSA311_INTERRUPT_D_TAP_EN,&enable);
        printf("Msa311_GetInterrupt0Enable MSA311_INTERRUPT_D_TAP %s\r\n",enable==MSA311_BOOL_TRUE ? "enable" : "disable");
        
        Msa311_SetInterrupt0Enable(MSA311_INTERRUPT_S_TAP_EN,MSA311_BOOL_TRUE);
        Msa311_GetInterrupt0Enable(MSA311_INTERRUPT_S_TAP_EN,&enable);
        printf("Msa311_GetInterrupt0Enable MSA311_INTERRUPT_S_TAP_EN %s\r\n",enable==MSA311_BOOL_TRUE ? "enable" : "disable");
   
    #endif  

每个功能函数:

static bool Msa311_SetTapQuiteParam(msa311_tapquite_t tapQuite)
{
    uint8_t r_data;
	uint8_t w_data;
	bool bRet = 0;

	bRet = Msa311_ReadReg(MSA311_REG_TAPDUR,&r_data);
	if (bRet == false)
	{
		perror("Msa311_SetTapQuiteParam read error\n");
		return false;
	}
 	w_data = ((r_data & MSA311_TAP_QUITE_MASK) | tapQuite);
	bRet = Msa311_WirteReg(MSA311_REG_TAPDUR,w_data);
	if (bRet == false)
	{
		perror("Msa311_SetTapQuiteParam write error\n");
		return false;
	}

    return bRet;
}

static bool Msa311_GetTapQuiteParam(msa311_tapquite_t *tapQuite)
{    
    uint8_t r_data;
	bool bRet = 0;

    bRet = Msa311_ReadReg(MSA311_REG_TAPDUR,&r_data);
	if (bRet == false)
	{
		perror("Msa311_GetRange read error\n");
		return false;
	}
    *tapQuite = (r_data & ~(MSA311_TAP_QUITE_MASK));
    
    return bRet;
}

static bool Msa311_SetTapShockParam(msa311_tapshock_t tapShock)
{
    uint8_t r_data;
	uint8_t w_data;
	bool bRet = 0;

	bRet = Msa311_ReadReg(MSA311_REG_TAPDUR,&r_data);
	if (bRet == false)
	{
		perror("Msa311_SetTapShockParam read error\n");
		return false;
	}
 	w_data = ((r_data & MSA311_TAP_SHOCK_MASK) | tapShock);
	bRet = Msa311_WirteReg(MSA311_REG_TAPDUR,w_data);
	if (bRet == false)
	{
		perror("Msa311_SetTapShockParam write error\n");
		return false;
	}

    return bRet;
}

static bool Msa311_GetTapShockParam(msa311_tapshock_t *tapShock)
{    
    uint8_t r_data;
	bool bRet = 0;

    bRet = Msa311_ReadReg(MSA311_REG_TAPDUR,&r_data);
	if (bRet == false)
	{
		perror("Msa311_GetTapShockParam read error\n");
		return false;
	}
    *tapShock = (r_data & ~(MSA311_TAP_SHOCK_MASK));
    
    return bRet;
}

static bool Msa311_SetTapDurationParam(msa311_tapduration_t tapDuration)
{
    uint8_t r_data;
	uint8_t w_data;
	bool bRet = 0;

	bRet = Msa311_ReadReg(MSA311_REG_TAPDUR,&r_data);
	if (bRet == false)
	{
		perror("Msa311_SetTapDurationParam read error\n");
		return false;
	}
 	w_data = ((r_data & MSA311_TAP_DUR_MASK) | tapDuration);
	bRet = Msa311_WirteReg(MSA311_REG_TAPDUR,w_data);
	if (bRet == false)
	{
		perror("Msa311_SetTapDurationParam write error\n");
		return false;
	}

    return bRet;
}

static bool Msa311_GetTapDurationParam(msa311_tapduration_t *tapDuration)
{    
    uint8_t r_data;
	bool bRet = 0;

    bRet = Msa311_ReadReg(MSA311_REG_TAPDUR,&r_data);
	if (bRet == false)
	{
		perror("Msa311_GetTapDurationParam read error\n");
		return false;
	}
    *tapDuration = (r_data & ~(MSA311_TAP_DUR_MASK));
    
    return bRet;
}

static uint8_t Msa311_ThresholdConvertToRegister(float g, uint8_t *reg)
{
    msa311_range_t range;
    Msa311_GetRange(&range);
    switch (range)
    {
    case MSA311_RANGE_2_G/* constant-expression */:
        /* code */
        *reg = (int8_t)(g / 0.0625f);    
        break;
    case MSA311_RANGE_4_G/* constant-expression */:
        /* code */
        *reg = (int8_t)(g / 0.125f);    
        break;
    case MSA311_RANGE_8_G/* constant-expression */:
        /* code */
        *reg = (int8_t)(g / 0.250f);    
        break;
    case MSA311_RANGE_16_G/* constant-expression */:
        /* code */
        *reg = (int8_t)(g / 0.5f);    
        break;        
    default:
        printf("Msa311_ThresholdConvertToRegister error\r\n");
        break;
    }
    return 0;                                                                             
}

static uint8_t Msa311_ThresholdConvertToData(uint8_t reg, float *g)
{
    msa311_range_t range;
    Msa311_GetRange(&range);
    switch (range)
    {
    case MSA311_RANGE_2_G/* constant-expression */:
        /* code */
        *g = (float)(reg) * 0.0625f;   
        break;
    case MSA311_RANGE_4_G/* constant-expression */:
        /* code */
        *g = (float)(reg) * 0.125f;     
        break;
    case MSA311_RANGE_8_G/* constant-expression */:
        /* code */
        *g = (float)(reg) * 0.250f;     
        break;
    case MSA311_RANGE_16_G/* constant-expression */:
        /* code */
        *g = (float)(reg) * 0.500f;    
        break;        
    default:
        printf("Msa311_ThresholdConvertToData error\r\n");
        break;
    }
    
    *g = (float)(reg) * 0.0039f;    
    return 0;
}

static bool Msa311_SetTapThresholdParam(uint8_t threshold)
{
    uint8_t r_data;
	uint8_t w_data;
	bool bRet = 0;

 	w_data = threshold;
	bRet = Msa311_WirteReg(MSA311_REG_TAPTH,w_data);
	if (bRet == false)
	{
		perror("Msa311_SetTapThresholdParam write error\n");
		return false;
	}

    return bRet;
}

static bool Msa311_GetTapThresholdParam(uint8_t *threshold)
{    
    uint8_t r_data;
	bool bRet = 0;

    bRet = Msa311_ReadReg(MSA311_REG_TAPTH,&r_data);
	if (bRet == false)
	{
		perror("Msa311_SetTapThresholdParam read error\n");
		return false;
	}
    *threshold = r_data;
    
    return bRet;
}

static bool Msa311_SetInterruptMap0(msa311_interrupt_map0_t type, msa311_bool_t enable)
{
    uint8_t r_data;
	uint8_t w_data;
	bool bRet = 0;

	bRet = Msa311_ReadReg(MSA311_REG_INTMAP0,&r_data);
	if (bRet == false)
	{
		perror("Msa311_SetInterruptMap0 read error\n");
		return false;
	}
 	r_data &= ~(1 << type);                                                                   /* clear type */
    r_data |= enable << type; 

	bRet = Msa311_WirteReg(MSA311_REG_INTMAP0,r_data);
	if (bRet == false)
	{
		perror("Msa311_SetInterruptMap0 write error\n");
		return false;
	}

    return bRet;
}

static bool Msa311_GetInterruptMap0(msa311_interrupt_map0_t type, msa311_bool_t *enable)
{
    uint8_t r_data;
	bool bRet = 0;

    bRet = Msa311_ReadReg(MSA311_REG_INTMAP0,&r_data);
	if (bRet == false)
	{
		perror("Msa311_SetInterruptMap0 read error\n");
		return false;
	}
    r_data &= (1 << type);                                                                    /* clear config */
    *enable = (msa311_bool_t)(r_data >> type);   

    return 0;
}

static bool Msa311_SetInterrupt0Enable(msa311_interrupt_sw0_t type, msa311_bool_t enable)
{
    uint8_t r_data;
	uint8_t w_data;
	bool bRet = 0;

	bRet = Msa311_ReadReg(MSA311_REG_INTSET0,&r_data);
	if (bRet == false)
	{
		perror("Msa311_SetInterrupt0Enable read error\n");
		return false;
	}
 	r_data &= ~(1 << type);                                                                   /* clear type */
    r_data |= enable << type; 

	bRet = Msa311_WirteReg(MSA311_REG_INTSET0,r_data);
	if (bRet == false)
	{
		perror("Msa311_SetInterrupt0Enable write error\n");
		return false;
	}

    return bRet;
}

static bool Msa311_GetInterrupt0Enable(msa311_interrupt_sw0_t type, msa311_bool_t *enable)
{
    uint8_t r_data;
	bool bRet = 0;

    bRet = Msa311_ReadReg(MSA311_REG_INTMAP0,&r_data);
	if (bRet == false)
	{
		perror("Msa311_GetInterrupt0Enable read error\n");
		return false;
	}
    r_data &= (1 << type);                                                                    /* clear config */
    *enable = (msa311_bool_t)(r_data >> type);   

    return 0;
}

static bool Msa311_SetInterrupt1Enable(msa311_interrupt_sw1_t type, msa311_bool_t enable)
{
    uint8_t r_data;
	uint8_t w_data;
	bool bRet = 0;

	bRet = Msa311_ReadReg(MSA311_REG_INTSET1,&r_data);
	if (bRet == false)
	{
		perror("Msa311_SetInterrupt1Enable read error\n");
		return false;
	}
 	r_data &= ~(1 << type);                                                                   /* clear type */
    r_data |= enable << type; 

	bRet = Msa311_WirteReg(MSA311_REG_INTSET1,r_data);
	if (bRet == false)
	{
		perror("Msa311_SetInterrupt1Enable write error\n");
		return false;
	}

    return bRet;
}

static bool Msa311_GetInterrupt1Enable(msa311_interrupt_sw1_t type, msa311_bool_t *enable)
{
    uint8_t r_data;
	bool bRet = 0;

    bRet = Msa311_ReadReg(MSA311_REG_INTMAP1,&r_data);
	if (bRet == false)
	{
		perror("Msa311_GetInterrupt1Enable read error\n");
		return false;
	}
    r_data &= (1 << type);                                                                    /* clear config */
    *enable = (msa311_bool_t)(r_data >> type);   

    return 0;
}

static bool Msa311_GetInterruptState(msa311_int_state_t state, msa311_bool_t *enable)
{
    uint8_t r_data;
	bool bRet = 0;

    bRet = Msa311_ReadReg(MSA311_REG_MOTIONINT,&r_data);
	if (bRet == false)
	{
		perror("Msa311_GetInterrupt1Enable read error\n");
		return false;
	}
    r_data &= (1 << state);                                                                    /* clear config */
    *enable = (msa311_bool_t)(r_data >> state);   

    return 0;
}

对应头文件:

#ifndef __MSA311_H__
#define __MSA311_H__

#define MSA311_I2CADDR_DEFAULT_7 (0x62) ///< Fixed I2C address
#define MSA311_I2CADDR_DEFAULT_8 (0xC4) ///< Fixed I2C address

/*=========================================================================*/

#define MSA311_REG_RESET                    0x00    ///< Register soft reset
#define MSA311_REG_PARTID                   0x01    ///< Register that contains the part ID
#define MSA311_REG_OUT_X_L                  0x02    ///< Register address for X axis lower byte
#define MSA311_REG_OUT_X_H                  0x03    ///< Register address for X axis higher byte
#define MSA311_REG_OUT_Y_L                  0x04    ///< Register address for Y axis lower byte
#define MSA311_REG_OUT_Y_H                  0x05    ///< Register address for Y axis higher byte
#define MSA311_REG_OUT_Z_L                  0x06    ///< Register address for Z axis lower byte
#define MSA311_REG_OUT_Z_H                  0x07    ///< Register address for Z axis higher byte
#define MSA311_REG_MOTIONINT                0x09    ///< Register address for motion interrupt
#define MSA311_REG_DATAINT                  0x0A    ///< Register address for data interrupt
#define MSA311_REG_CLICKSTATUS              0x0B    ///< Register address for click/doubleclick status
#define MSA311_REG_ORIENTATION_STATUS       0x0C    ///< Register address for orientation status
#define MSA311_REG_RESRANGE                 0x0F    ///< Register address for resolution range
#define MSA311_REG_ODR                      0x10    ///< Register address for data rate setting
#define MSA311_REG_POWERMODE                0x11    ///< Register address for power mode setting
#define MSA311_REG_INTSET0                  0x16    ///< Register address for interrupt setting #0
#define MSA311_REG_INTSET1                  0x17    ///< Register address for interrupt setting #1
#define MSA311_REG_INTMAP0                  0x19    ///< Register address for interrupt map #0
#define MSA311_REG_INTMAP1                  0x1A    ///< Register address for interrupt map #1
#define MSA311_REG_TAPDUR                   0x2A    ///< Register address for tap duration
#define MSA311_REG_TAPTH                    0x2B    ///< Register address for tap threshold

#define MSA311_REG_OFFSET_X                 0x38
#define MSA311_REG_OFFSET_Y                 0x39
#define MSA311_REG_OFFSET_Z                 0x3A

#define MSA311_POWER_MODE_MSAK				0x3F
#define MSA311_POWER_MODE_SHIFT				0x05u

/** The accelerometer power mode */
typedef enum {
  	MSA311_NORMALMODE 	= 0x00,   	    ///< Normal (high speed) mode
  	MSA311_LOWPOWERMODE 	= 0x40, 	///< Low power (slow speed) mode
  	MSA311_SUSPENDMODE 	= 0xC0, 	    ///< Suspend (sleep) mode
} msa311_powermode_t;


#define MSA311_AXES_ENABLE_MSAK				0x1F
typedef enum{
	AXES_DISABLE 	= 0x00,
	AXES_ENABLE 	= 0xE0,
}msa311_axes_state_t;

#define MSA311_DATA_RATE_MASK				0xF0			
/** The accelerometer data rate */
typedef enum {
  	MSA311_DATARATE_1_HZ 			= 0x00,     	///<  1 Hz
  	MSA311_DATARATE_1_95_HZ 		= 0x01,  		///<  1.95 Hz
  	MSA311_DATARATE_3_9_HZ 			= 0x02,   		///<  3.9 Hz
	MSA311_DATARATE_7_81_HZ 		= 0x03,  		///<  7.81 Hz
	MSA311_DATARATE_15_63_HZ 		= 0x04, 		///<  15.63 Hz
	MSA311_DATARATE_31_25_HZ 		= 0x05, 		///<  31.25 Hz
	MSA311_DATARATE_62_5_HZ 		= 0x06,  		///<  62.5 Hz
	MSA311_DATARATE_125_HZ 			= 0x07,   		///<  125 Hz
	MSA311_DATARATE_250_HZ 			= 0x08,   		///<  250 Hz
	MSA311_DATARATE_500_HZ 			= 0x09,   		///<  500 Hz
	MSA311_DATARATE_1000_HZ 		= 0x0A,  		///<  1000 Hz
} msa311_dataRate_t;

#define MSA311_BAND_WIDTH_MASK				0xE1
/** The accelerometer bandwidth */
typedef enum {
	MSA301_BANDWIDTH_1_95_HZ 		= 0x00,  	///<  1.95 Hz
	MSA301_BANDWIDTH_3_9_HZ 		= 0x06,   	///<  3.9 Hz
	MSA301_BANDWIDTH_7_81_HZ 		= 0x08,  	///<  7.81 Hz
	MSA301_BANDWIDTH_15_63_HZ 	= 0x0A, 	///<  15.63 Hz
	MSA301_BANDWIDTH_31_25_HZ 	= 0x0C, 	///<  31.25 Hz
	MSA301_BANDWIDTH_62_5_HZ 		= 0x0E,  	///<  62.5 Hz
	MSA301_BANDWIDTH_125_HZ 		= 0x10,   	///<  125 Hz
	MSA301_BANDWIDTH_250_HZ 		= 0x12,   	///<  250 Hz
	MSA301_BANDWIDTH_500_HZ 		= 0x14,   	///<  500 Hz
} msa301_bandwidth_t;

#define MSA311_RANG_MASK					0xFC
/** The accelerometer ranges */
typedef enum {
	MSA311_RANGE_2_G 			= 0x00,  		///< +/- 2g (default value)
	MSA311_RANGE_4_G 			= 0x01,  		///< +/- 4g
	MSA311_RANGE_8_G 			= 0x02,  		///< +/- 8g
	MSA311_RANGE_16_G			= 0x03, 		///< +/- 16g
} msa311_range_t;

#define MSA311_TAP_DUR_MASK      			0xF8
/** Tap duration parameter */
typedef enum {
	MSA311_TAPDUR_50_MS 		= 0x00,  		///< 50 millis
	MSA311_TAPDUR_100_MS 		= 0x01, 		///< 100 millis
	MSA311_TAPDUR_150_MS 		= 0x02, 		///< 150 millis
	MSA311_TAPDUR_200_MS 		= 0x03, 		///< 200 millis
	MSA311_TAPDUR_250_MS 		= 0x04, 		///< 250 millis
	MSA311_TAPDUR_375_MS 		= 0x05, 		///< 375 millis
	MSA311_TAPDUR_500_MS 		= 0x06, 		///< 500 millis
	MSA311_TAPDUR_700_MS 		= 0x07, 		///< 50 millis700 millis
} msa311_tapduration_t;

#define MSA311_TAP_QUITE_MASK				0x7F
typedef enum{
	MSA311_TAPQUITE_20_MS		= 0x80,
	MSA311_TAPQUITE_30_MS		= 0x00,
}msa311_tapquite_t;

#define MSA311_TAP_SHOCK_MASK				0xBF	

typedef enum{
	MSA311_TAPSHOCK_50_MS   	= 0x00,
	MSA311_TAPSHOCK_70_MS		= 0x40,

}msa311_tapshock_t;

typedef enum
{
    MSA311_BOOL_FALSE = 0x00,        /**< false */
    MSA311_BOOL_TRUE  = 0x01,        /**< true */
} msa311_bool_t;

typedef enum
{
    MSA311_INTERRUPT_FREE_FALL 	= 0x00,        /**< free fall */
	MSA311_INTERRUPT_ACTIVE		= 0x02,
	MSA311_INTERRUPT_D_TAP		= 0x04,
	MSA311_INTERRUPT_S_TAP		= 0x05,
	MSA311_INTERRUPT_ORIENT		= 0x06,

} msa311_interrupt_map0_t;

typedef enum
{
    MSA311_INTERRUPT_ACTIVE_EN_X 	= 0x00, 
	MSA311_INTERRUPT_ACTIVE_EN_Y 	= 0x01,    
    MSA311_INTERRUPT_ACTIVE_EN_Z 	= 0x02,   
	MSA311_INTERRUPT_D_TAP_EN		= 0x04,
	MSA311_INTERRUPT_S_TAP_EN		= 0x05,
	MSA311_INTERRUPT_ORIENT_EN		= 0x06,
} msa311_interrupt_sw0_t;

typedef enum
{
    MSA311_INTERRUPT_FREE_FALLEN 	= 0x03, 
	MSA311_INTERRUPT_NEW_DATA_EN 	= 0x04,    
} msa311_interrupt_sw1_t;


typedef enum{
	MSA311_INT_S_TAP_MESSAGE   		= 0x00,
	MSA311_INT_D_TAP_MESSAGE   		= 0x01,

}msa311_int_message_type;

typedef enum
{
	MSA311_FREE_FALL_INT_STATE 		= 0x00,
	MSA311_ACTIVE_INT_STATE			= 0x02,
	MSA311_D_TAP_INT_STATE			= 0x04,
	MSA311_S_TAP_INT_STATE			= 0x05,
	MSA311_ORIENT_INT_STATE			= 0x06,

}msa311_int_state_t;

// golbal function
void Msa311_Init(void);
void handle_int_message(void);
#endif

这样设置好msa311的寄存器后,当我们敲击的时候,int脚会拉低。所以我们只需要连接mm32一个gpio,并且配成中断模式,就可以捕获对应的敲击事件了。

3、中断接收并处理数据

将msa311的Int脚连接至mm32 的PC8.
pc8适配中断代码如下:

void BOARD_InitPins(void)
{
    /* 调用GPIO的HAL库对象结构体声明GPIO对象 */
    GPIO_Init_Type gpio_init;

    //pc 8 for msa311 inter detect
    uint32_t prioritygroup = 0;
    RCC_EnableAPB2Periphs(RCC_APB2_PERIPH_SYSCFG, true);

    /* 设置GPIO的模式 */
    gpio_init.PinMode  = GPIO_PinMode_In_PullUp;
    gpio_init.Speed = GPIO_Speed_50MHz;
    
    /* 选择引脚初始化 */
    gpio_init.Pins  = GPIO_PIN_8;
    GPIO_Init(GPIOC, &gpio_init);

     /* 将外部中断线设置为复用模式 */
    SYSCFG_SetExtIntMux(SYSCFG_EXTIPort_GPIOC, SYSCFG_EXTILine_8);
    /* 设置外部中断线的触发方式 */
    EXTI_SetTriggerIn(EXTI, EXTI_LINE_8, EXTI_TriggerIn_FallingEdge); 
    /* 使能外部中断线 */
    EXTI_EnableLineInterrupt(EXTI, EXTI_LINE_8, true);

    prioritygroup = NVIC_GetPriorityGrouping();
    NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(prioritygroup, 0, 2));
    /* 使能对应的外部中断 */
    NVIC_EnableIRQ(EXTI9_5_IRQn);
}

对应的中断处理函数:

void EXTI9_5_IRQHandler(void)
{
	uint32_t flags = EXTI_GetLineStatus(EXTI);
    if ( 0u != ( flags & EXTI_LINE_8 ) ) /* Interrupts. */
    {
		handle_int_message();
    }
    EXTI_ClearLineStatus(EXTI, flags);
}

中断处理函数将事件处理交给handle_int_message()函数,此函数在msa311.c中定义。

void handle_int_message(void)
{
    uint8_t state;
    bool bRet;
    bRet = Msa311_ReadReg(MSA311_REG_MOTIONINT,&state);
	if (bRet == false)
	{
		perror("Msa311_GetInterrupt1Enable read error\n");
		return;
    }

    if (state & (1 << MSA311_S_TAP_INT_STATE))
    {
        printf("this is s_tap \r\n");
    }
    else if (state & (1 << MSA311_D_TAP_INT_STATE))
    {
        printf("this is d_tap \r\n");

    }
}

在中断处理函数中,我们做个一件事,就是去读一下0x09寄存器的值,当第四位为1的时候,表示双击,第五位为1的时候,表示单击。
在这里插入图片描述

4、现象

在这里插入图片描述
单击模块时候打印 this is s_tap
双击模块时候打印 this is d_tap

5、代码

代码下载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/634035.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

算法模板(4):动态规划(3) 做题积累(1)

动态规划 1. 背包 1. 1024. 装箱问题 题意&#xff1a;有一个箱子容量为 V&#xff0c;同时有 n 个物品&#xff0c;每个物品有一个体积&#xff08;正整数&#xff09;。要求 n 个物品中&#xff0c;任取若干个装入箱内&#xff0c;使箱子的剩余空间为最小。别学那么死板。…

2023夏-PAT甲级题解

目录 总结&#xff1a; A-1 Trap Input Specification: Output Specification: Sample Input: Sample Output: 题意&#xff1a; 思路&#xff1a; AC代码&#xff1a; A-2 Queue Using Two Stacks Input Specification: Output Specification: Sample Input: Sa…

SpringBoot 项目部署笔记

1. 直接通过 jar 包部署 本地直接 build package 成 jar 包&#xff0c;上传至服务器 ps -ef|grep XXX #查找项目进程sudo kill -9 19727 #杀掉项目进程nohup sudo java -jar *.jar >> app.log & #后台运行 jar &代表让该命令在后台执行 3. 通过 Jenkins …

pytorch笔记:conv2d

来自B站视频&#xff0c;API查阅&#xff0c;TORCH.NN nn.conv2d 中一般 kernel_size 是小奇数&#xff0c;padding 设置为 k − 1 2 \frac{k-1}{2} 2k−1​&#xff08;实际上padding的是 k − 1 k-1 k−1&#xff0c;因为参数的意义是左右各padding&#xff09;&#xff0c;

探索Xiotman:物联网软件架构的创新之路

文章目录 探索Xiotman&#xff1a;物联网软件架构的创新之路什么是物联网什么是XiotmanXiotman的特点Xiotman的架构Xiotman的使用安装env工具获取源代码使用其他教程 Xiotman的开源地址 总结 探索Xiotman&#xff1a;物联网软件架构的创新之路 什么是物联网 &#x1f680;&am…

高燃盛会全程回顾|鸿雁加速推进数字转型之路

6月10日&#xff0c;以“双翅齐振雁南飞”为主题的鸿雁电器数字化营销启动大会暨中山古镇鸿雁全屋智能体验中心开业庆典&#xff0c;在中山古镇华艺广场圆满落幕。 古镇镇长阮志力、华艺集团董事长区锦标、华艺广场总经理丁瑜、古镇灯饰传媒董事长曹利晖以及杭州鸿雁电器有限公…

spring boot + xxl-job 分布式任务调度

一、介绍 1、任务调度 1.1、什么是任务调度 我们可以先思考一下下面业务场景的解决方案&#xff1a; 某电商系统需要在每天上午10点&#xff0c;下午3点&#xff0c;晚上8点发放一批优惠券。某财务系统需要在每天上午10点前结算前一天的账单数据&#xff0c;统计汇总。某电…

那年我头脑发热,选择了自动化,后来我掉入计算机的世界无法自拔

首先&#xff0c;小雅兰是22届高考考生&#xff0c;而且当时填报志愿也没有填报到计算机相关的专业去&#xff0c;小雅兰是自动化专业的学生&#xff0c;是由于一次偶然的机会&#xff0c;了解到了这个行业&#xff0c;对于写代码所带来的成就感&#xff0c;总之&#xff0c;我…

Java013——常见进制以及转换

一、常见进制 十进制 数字组成&#xff1a;0-9这十个数字组成&#xff0c;不能以0开头 进位规则&#xff1a;满10进1 int num1 10;//对应的十进制为10二进制 数字组成&#xff1a;0-1这两个数字组成&#xff0c;以0b或0B开头 进位规则&#xff1a;满2进1 int num2 0b1010;…

华为存储IA篇仿真器搭建

设备清单 编号 设备名 数量 备注 01 Windows系统主机 1台 为VMware提供安装位置 02 VMware软件 1份 提供存储仿真器的部署环境 03 仿真器文件 1份 用于部署estor虚拟机 【注意】&#xff1a;暂无注意事项 一、下载安装文件并配置虚拟机设备清单 1.1…

TypeScript 自定义装饰器

&#xff08;预测未来最好的方法就是把它创造出来——尼葛洛庞帝&#xff09; 装饰器 装饰器一种更现代的代码模式&#xff0c;通过使用的形式注入在属性&#xff0c;寄存器&#xff0c;方法&#xff0c;方法参数和类中&#xff0c;比如在Angular&#xff0c;Nestjs和midway等…

大数据Doris(三十九):Spark Load 注意事项

文章目录 Spark Load 注意事项 Spark Load 注意事项 1、现在Spark load 还不支持 Doris 表字段是String类型的导入,如果你的表字段有String类型的请改成varchar类型,不然会导入失败,提示 type:ETL_QUALITY_UNSATISFIED; msg:quality not good enough to cancel 2、使用Spa…

无敌!我用【C语言】手搓出了一个体系完整的【员工管理系统】还能玩游戏听音乐?(超详细,附完整源码)

博主简介&#xff1a;Hello大家好呀&#xff0c;我是陈童学&#xff0c;一个与你一样正在慢慢前行的人。 博主主页&#xff1a;陈童学哦 所属专栏&#xff1a;C语言程序设计实验项目 如果本文对你有所帮助的话&#xff0c;还希望可以点赞&#x1f44d;收藏&#x1f4c2;支持一下…

Linux——IP协议1

目录 协议头格式 如何封装和解包 如何交付&#xff08;分用&#xff09; 报头每一个字段 分片是怎么做到的 应用层解决的是数据使用的问题。 在传输层&#xff0c;网络层&#xff0c;数据链路层&#xff1a;解决的是网络通信的细节&#xff0c;将数据可靠的从A主机跨网络发…

【深入浅出 Spring Security(八)】前后端分离-使用CSRF漏洞保护详讲

CSRF 漏洞保护 一、CSRF 概述二、CSRF 攻击演示三、CSRF 防御令牌同步模式 四、前后端分离使用 CSRFCsrfFilter 源码分析源码一些方法的细究 测试 五、总结 一、CSRF 概述 CSRF&#xff08;Cross-Site Request Forgery 跨站请求伪造&#xff09;&#xff0c;也可称为一键式攻击…

乐盟互动申请纳斯达克IPO上市,募资2000万美元

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 猛兽财经获悉&#xff0c;来自北京的程序化广告平台【乐盟互动】近期已向美国证券交易委员会&#xff08;SEC&#xff09;提交招股书&#xff0c;申请在纳斯达克IPO上市&#xff0c;股票代码&#xff08;LIAI&#xff09;&…

SpringBoot社区小区物业管理停车场系统(Java+Layui+MyBatis+Python+Mysql)

wx供重浩&#xff1a;创享日记 对话框发送&#xff1a;69小区 获取完整源码源文件说明文档数据库文件 项目特色 本项目使用现行主流技术与架构模式&#xff08;控制层、服务层、数据层&#xff09;代码结构清晰&#xff0c;严格遵循模块化、组件化、接口化思想&#xff1b;关…

mysq在RR级别怎么解决不可重复读和幻读

1、定义 不可重复读&#xff1a; 事务1读取一行&#xff0c;事务2然后修改或删除该行数据并且提交事务&#xff0c;事务1再次读取结果不一样&#xff1b; 幻读&#xff1a;事务1按条件读取查询数据&#xff0c;事务2按照同样的条件新增一条或多条数据并且提交事务&#xff0c…

mysql8查看大事务

文章目录 1、查看大事务的原因2、构建测试数据3、模拟大事务场景4、查询mysql的事务5、查询大事务的详情 1、查看大事务的原因 大事务的特点是执行时间长&#xff0c;长期占有锁不释放&#xff0c;导致其他想操作同一行数据的线程阻塞&#xff0c;如果客户端设置了超时时间&am…

单正态总体和双正态总体的假设检验

1.单正态总体和双正态总体的假设检验 笔者之前的相关笔记&#xff1a; 1.正态总体下常见的抽样分布 2.假设检验&#xff08;Hypothesis Testing&#xff09; 个人理解假设检验&#xff1a;先对总体参数提出一个假设值&#xff0c;利用样本信息判断这一假设是采取拒绝该假设还是…