How to Create a Library for sensors Part 3: Adding Interrupt capability

In the third part of creating a library for ADXL345, we shall study the interrupt capabilities of ADXl345 and improve the driver to utilitize the usage of the interrupt of STM32.

In this guide, we shall cover the following:

  • Interrupts of ADXL345.
  • Header file development.
  • Source file development.
  • Enabling interrupt in STM32CubeMX.
  • Connection.
  • Main code.
  • Code download.
  • Results.

8. Interrupts of ADXL345:

ADXL345 features multiple interrupt source such as:

  • Data ready.
  • Single and double tap.
  • Activity and inactivity.
  • Freefall.
  • Watermark.
  • Overrun.

In this guide, we shall focus on using data ready interrupt generation.

The interrupts can be enabled using INT Enable register (0x2E) as following:

When a specific bit is set to, the corespondent interrupt shall be enabled. Since this guide is focused on data ready interrupt, we shall use set D7 (DATA_Ready) to 1.

Also, the ADXL345 features two interrupt pins INT1 and INT2 as following:

The selection of which pin can be done INT_MAP (0x2F) register as following:

For the state, either high or low can be used by setting INT_INVERT bit in data format register as following:

This guide shall use high state which means the bit shall remain zero.

Next, we shall start with developing the library

9. Header File Development:

In adxl345.h header file, in the ADXL345_InitParam structure, we shall include the following two parameters:

	uint8_t InterruptEnable;
	uint8_t DataReadyInterrupt;

Hence, the updated data structure as following:

typedef struct
{
	uint8_t Accel_Range;
	uint8_t InterruptEnable;
	uint8_t DataReadyInterrupt;
	/*rest of the interrupt shall be implement by the user*/
}ADXL345_InitParam;

Since the guide focuses on data ready, the rest the can be implemented by the user.

Declare the following enum to handle the interrupt enabling as following:

typedef enum
{
	Interrupt_Disabled=0,
	Interrupt_Enabled=1
}adxl345InterruptsEnable;

Also, declare the following enumeration to handle the interrupt sources as following:

typedef enum
{
	Int_DataReady=(1<<7),
	Int_SingleTap=(1<<6),
	Int_DoubleTap=(1<<5),
	Int_Activity=(1<<4),
	Int_Inactivity=(1<<3),
	Int_FreeFall=(1<<2),
	Int_Watermark=(1<<1),
	Int_Overrun=(1<<0)
}adxl345InterruptsSource;

Also, declare the following function:

adxl345InterruptsSource adxl345_ReadInterrupt(void);

This function shall read the interrupt register returns which interrupt is triggered.

Save the header file since thats all for the header file.

10. Source File Development:

In adxl345.c source file, in the adxl345_Init function, we shall enable the interrupt as following:

After entering the measurement mode, check if the interrupt is enabled or not as following:

if(Param->InterruptEnable==Interrupt_Enabled)

If the interrupt is enabled, set the interrupt as the user requirement as following:

		temp[0]=0x00;
		if(Param->DataReadyInterrupt==Int_DataReady)
		{
			temp[0]|=Int_DataReady;

		}
		/*The rest shall be implement by the user
		 * temp[0]|=Int_SingleTap
		 * */
		adxl345_write(ADXL345_INT_ENABLE,temp,1);

reset the temp variable which holds the data to be written. Then check which interrupts are needed by oring the temp variable with the interrupt source.

Hence, the update initialization function as following:

void adxl345_Init(ADXL345_InitParam *Param)
{
	/*Get the acceleration range */
	acc_range=Param->Accel_Range;

	uint8_t temp[1];

	/*Set the acceleration range*/
	temp[0]=acc_range;
	adxl345_write(ADXL345_DATA_FORMAT, temp, 1);

	/*Reset Power Control register*/
	temp[0]=PWR_RST;
	adxl345_write(ADXL345_POWER_CTL, temp, 1);

	/*Set ADXL345 into measure mode*/
	temp[0]=MEASUREMODE;
	adxl345_write(ADXL345_POWER_CTL, temp, 1);

	if(Param->InterruptEnable==Interrupt_Enabled)
	{
		temp[0]=0x00;
		if(Param->DataReadyInterrupt==Int_DataReady)
		{
			temp[0]|=Int_DataReady;

		}
		/*The rest shall be implement by the user
		 * temp[0]|=Int_SingleTap
		 * */
		adxl345_write(ADXL345_INT_ENABLE,temp,1);


	}

}

In order to read the interrupt source, we need to read the INT_Source register and return which interrupt being triggered as following:

adxl345InterruptsSource adxl345_ReadInterrupt(void)
{
	uint8_t temp[1];
	adxl345_read(ADXL345_INT_SOURCE,temp,1);

	if((temp[0]&Int_DataReady)==Int_DataReady){return Int_DataReady;}

	/*rest shall be implement by the user*/
	return 0;
}

First, declare a temp variable to store the data, then read the interrupt source register then check the interrupt source and return correct one. Here, we are focusing on the data ready one.

Save the source file since thats all.

11. Enabling External Interrupt in STM32CubeMX:

Open ADXL345_Library.ioc file and select PA0 as interrupt source as following:

Note: You can select any other pin as you wish.

12. Connection:

The connection as following:

12. Main Code:

In main.c, in user code begin 4, we shall handle the interrupt as following:

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  if(GPIO_Pin == GPIO_PIN_0)
  {
	  interrupt=1;
  }

}

Note: in if condition, replace pin number with the pin number set by your, pin 0 in this case.

The interrupt variable is defined as volatile in user code begin PV as following:

volatile uint8_t interrupt=0;

In the main function, for the initialization of adxl345 structure, include the following:

  InitParm.InterruptEnable=Interrupt_Enabled;
  InitParm.DataReadyInterrupt=Int_DataReady;

This will enable the interrupt of adxl345.

After the intialization, read the interrupt source and the acceleration data as following:

  /*clear the interrupt by reading the source register and acceleration data */
  adxl345_ReadInterrupt();
  adxl345_update(&AccData);

This will start the interrupt sequence.

In the while loop in user code begin 3:

Check if the interrupt is generated by check if the interrupt variable is set to 1 as following:

If yes, reset the interrupt variable, read the interrupt source, if it is data read, the acceleration data print them.

if(interrupt==1)
	  {
		  interrupt=0;
		  if(adxl345_ReadInterrupt()==Int_DataReady)
		  {
		  adxl345_update(&AccData);
		  printf("Ax =%0.3f \t Ay =%0.3f \t Az =%0.3f\r\n",AccData.ax,AccData.ay,AccData.az);
		  }
	  }

Thats all for the code.

Save the project, build and run it as following:

13. Source Code Download:

You may download the source code from here:

14. Results:

Open your favourite serial terminal application, set the baudrate to be 115200 and you should get the following:

Note that we are getting the correct ID and the results are correct.

Happy coding 😉

Add Comment

Your email address will not be published. Required fields are marked *