In the last post https://whileinthisloop.blogspot.com/2016/04/c-in-arduino-interrupted-adc-with-free.html I showed you how to run the ADC in free-running mode. In this post I am going to show you how to wrap up the ISR() in a Class
I don't know if you have tried it or not but implementing ISR() in a class is a bit tricky ;)
Handling interrupts is not only a job for C or assembly language actually C++ can also handle it. In a later post, I will show how to wrap up the ISR() with the help of some advanced concepts of c++ like virtual function.
But in this post, I am going to show you a quick & simple way that may help you if you don't understand advanced concepts of C++. So if you are willing to design and maintain OOP concepts and want to implement your ISR() in a class in a simple way then this post may help you.
Note: The way I am going to show is kind of mixing C & C++ concepts.
To keep our embedded context relevant, we are going to make a Sensor Class from the last post's codes,
First Let us make the declaration file (sensor.h)
you can see that there is no ISR(ADC_vect) function declaration in the header file.
now let's make the implementation file (sensor.cpp)
Note: The way I am going to show is kind of mixing C & C++ concepts.
To keep our embedded context relevant, we are going to make a Sensor Class from the last post's codes,
First Let us make the declaration file (sensor.h)
#ifndef SENSOR_H_ //tells compiler to compile this class only once
#define SENSOR_H_
#include <Arduino.h>
#include <avr/interrupt.h>
class Sensor
{
//variables
public:
private:
//functions
public:
Sensor();
~Sensor();
void init(void);
unsigned int readAdcValue(void);
};
#endif
you can see that there is no ISR(ADC_vect) function declaration in the header file.
now let's make the implementation file (sensor.cpp)
#include "Sensor.h"
static unsigned int adcValue; //this variable's scope is only this file
//constructor
Sensor::Sensor()
{}
//destructor
Sensor::~Sensor()
{}
void Sensor::init(void)
{
//initiating variables
adcValue = 0;
//initiating registers
ADMUX |= (1 << REFS0); //AVCC with external capacitor at AREF pin
ADMUX |= (1 << MUX2) | (1 << MUX0); //0101adc channel 5 selected for adc input
ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); //prescalar 128 selected ADC clk = 125KHz
ADCSRA |= (1 << ADEN); //adc enabled
ADCSRA |= (1 << ADATE); // ADC Auto Trigger Enable
ADCSRA |= (1 << ADIE); //adc interrupt enable such that interrupt will happen after each conversion
ADCSRA |= (1 << ADSC); //conversion process begins
sei(); //global interrupt enabled
}
unsigned int Sensor::readAdcValue(void)
{
return adcValue;
}
ISR(ADC_vect) //adc interrupt service routine /tasks which will be executed by microprocessor after each conversion
{
adcValue = ADCL; //ADCL data register read
adcValue += (ADCH << 8); //ADCH data register read
}
Note that the adcValue variable is a static unsigned int type global variable & this variable gets updated in the interrupt service routine but why I have not declared this variable as a Class member variable? the answer is as the ISR() function is not a Class member function you won't be able to access any Class member variable in the ISR() .
Also, note that the adcValue is a static variable which means its scope is limited to the cpp implementation file only. This pattern provides a data abstraction like private variables in a class. This is kind of implementing a C++ feature in C.
As per language pattern One may argue on the above approach but I found this simple solution working without any runtime / compile time issue but obvisously there may be better ways to implement.
All the sources are available in this link https://github.com/hassin23ayz/ArduinoCpp/tree/master/T37_inheritance
This comment has been removed by a blog administrator.
ReplyDelete