Based on our post,
it simply explains a simple program that can be easily understood by
the flow of the script. For those who wonder about the register name
and its operator, this post explain a bit about them.
A circuit and script (from the post linked above) bellow are attached
to ease the explanation:
![]() |
Figure 1 led circuit atmega8535 |
#include <avr/io.h> //DDRA, PORTA
#include <util/delay.h> //_delay_ms()
//“main” function must exist
int main(){
//activate A register on the first bit
DDRA |= 0x01;
while(1){ //endless loop
//assign HIGH logic to its first bit of A Register, led turns on
PORTA |= 0x01;
//wait for 250 milli second
_delay_ms(250);
//assign LOW logic to its first bit of A Register, led turns off
PORTA &= ~0x01;
//wait for 250 milli second
_delay_ms(500);
}
//integer return type for our main function
return 0;
}
From the script above:
Header File
When we are working with C/C++,
firstly, we have to include somthing, here we have seen the include
syntax: #include <…>,
this is usually called by header file. the name inside the brackets
is just a file name containing configuration of the specific MCU, in
this case atmega8535. e.g.,:
#include <avr/io.h> //contains DDRA, PORTA
It’s where all register names (of atmega8535) reside, e.g., DDRA
and PORTA.
The form of the value here is an integer, with 8-bit resolution,
meaning that it can hold value of 0 to 255.
Main()
function and _delay_ms() function
Next
we have seen int main().
this is also called by function name, that must be declared in C/C++
program. This is where the program firstly starts the execution.
For the _delay_ms()
function, it's in <util/delay.h>.
as the name of the function, it
will stop the program flow for the specified time in unit of
millisecond. e.g., we pass parameter of 250 (as the above example
above), then the program flow (at where the function is called) will
be paused for 0.25 second.
For the people being
familiar with C/C++ programming language, it will be so easy.
Register Accessing
Data Direction Register A (DDRA) is used to activate or deactivate a
particular bit in it, in other words we use it to set pins labeled
PORTA on the MCU (proteus simulation) as seen on figure 1. DDRA |=
0x01, or equivalent to DDRA = DDRA | 0x01 in hexa form, or DDRA =
DDRA | 0b00000001 in binary form. It means to activate pin 0 in the
register. see figure 2 below:
As in figure 2 shows the sequence of
the bit number of 0 to 7 with the default value in each is 0. So when
we assign the 0th
bit of DDRA by 1, so the bit will be active, meaning that we can set
the logic in this bit to LOW state (0 volt) or HIGH state (5 volt)
via PORTA register.
See the figure 3 below:
Bitwise operators
- OR Bitwise Operator '|'
As the example above:
something that needs to remember is that a major number of atmega8535 register such as PORTA and DDRA have 8-bit resolution, if we try to assign it with the value that's bigger than 8-bit e.g., 0b100010001 (9-bit) then there is a big chance of your program to have undefined behavior. From the above example, we can clarify://the following code lines are equivalent: PORTA |= 0x01; PORTA = PORTA | 0x01; PORTA = PORTA | 0b00000001; //binary format (8-bit)
PORTA 00000000 //(default register value) OR 00000001 result 00000001 //(the 0th bit active, HIGH logic)
- AND Bitwise Operator '&'As the example above:
From the above example, we can clarify://the following code lines are equivalent: PORTA &= ~0x01; PORTA = PORTA & ~0x01; PORTA = PORTA & ~0b00000001; PORTA = PORTA & 0b11111110; //binary binary(8-bit)
PORTA 00000001 //(the value from the previous operation above) AND 11111110 //(the result of '~' operator) result 00000000 //(the 0th bit or the whole bit in the resiter not active; LOW logic)
- Complement Bitwise Operator '~'
This operator is usually used to invert the logic stored in a register. for example: 0b00010010, if we place '~' operator in front if it ~0b00010010, so this sequence of value becomes 0b11101101.
Note:
There might be some readers that realize and ask; "why don't we
access into the register directly?, without any bitwise operator..".
In this case, in this example above, we may do that actually, as:
PORTA = 0x01; //assign HIGH logic to the first bit and LOW to the rest of the bit
_delay_ms(250); //wait for 250 milli second
PORTA = 0x00; //assign LOW logic to the whole bit of the Register A
_delay_ms(500); //wait for 250 milli second
But
in the other cases, such accessing for example lm016L 16x2 lcd's register will endanger
the process or we would fail to access corectly the register at all,
because accessing the register directly means to reset all bit in it
and assign it with the new ones. For this reason, I recommend to use
the above way even if we just access a single bit in a single
register. Such this method is called by mask-bit so
that only specific bits that will be updated.
0 Comments
Post a Comment