
I have explained how to define a peripheral registers adreses in another content. I would like to show you how to declare a function for identical peripherals on this content. It helps if you use multiple identical peripherals. Lets start by defining the problem.
Assume that we use 3 identical timers with different frequencies in our project. We need to configure them one by one. First basic method is that preparing 3 different init function for each of them and invoke these function. Sounds easy but lets try to figure out problems on this method;
-We use code memory inefficiently
-We write more codes this may mean more time
-We will end up with less flexible code
In stead of this method, we can prepare only one init function and make it usable for identical peripherals. This function should take frequency and timer as input. Then, it will set corresponding timer with desired frequency.
I would like to show an example with Atmega328p IO ports. We have 3 ports which are B, C and D. We will prepare an init function which will work for all IO ports.
Definition of registers.
//Definition of Registers
typedef struct
{
volatile uint8_t PIN; // first register, offset: 0x00
volatile uint8_t DDR; // second register, offset: 0x01
volatile uint8_t PORT; // third register, offset: 0x02
} IO_type;
#define IOB ((volatile IO_type*) 0x23)
#define IOC ((volatile IO_type*) 0x26)
#define IOD ((volatile IO_type*) 0x29)
Init function
int8_t pin_init(IO_type *IOx, uint8_t pin_number, uint8_t mode)
{
if(mode==1) //output
{
IOx->DDR |= (1<<pin_number);
return 0;
}
else if(mode==0) //input
{
IOx->DDR &= ~(1<<pin_number);
return 0;
}
else //error
{
return -1;
}
}
Calling pin_init function properly.
pin_init(IOC,5,1); // 5th pin of C port is output
pin_init(IOB,3,0); // 3th pin of B port is input
I made a simple example then it may look non sense. However, when we have multiple registers and parameters to set, this method will make code readable and more efficient in terms of storage.