C GPIO hex numbering - c

I have been given the following bit of code as an example:
Make port 0 bits 0-2 outputs, other to be inputs.
FIO0DIR = 0x00000007;
Set P0.0, P0.1, P0.2 all low (0)
FIO0CLR = 0x00000007;
I have been told that the port has 31 LED's attached to it. I cant understand why, to enable the first 3 outputs, it is 0x00000007 not 0x00000003?

These GPIO config registers are bitmaps.
Use your Windows calculator to convert the hex to binary:
0x00000007 = 111, or with 32 bits - 00000000000000000000000000000111 // three outputs
0x00000003 = 11, or with 32 bits - 00000000000000000000000000000011 // only two outputs

Because the value you write to the register is a binary bit-mask, with a bit being one meaning "this is an output". You don't write the "number of outputs I'd like to have", you are setting 8 individual flags at the same time.
The number 7 in binary is 00000111, so it has the lower-most three bits set to 1, which here seems to mean "this is an output". The decimal value 3, on the other hand, is just 00000011 in binary, thus only having two bits set to 1, which clearly is one too few.
Bits are indexed from the right, starting at 0. The decimal value of bit number n is 2n. The decimal value of a binary number with more than one bit set is simply the sum of all the values of all the set bits.
So, for instance, the decimal value of the number with bits 0, 1 and 2 set is 20 + 21 + 22 = 1 + 2 + 4 = 7.
Here is an awesome ASCII table showing the 8 bits of a byte and their individual values:
+---+---+---+---+---+---+---+---+
index | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+---+---+---+---+---+---+---+---+
value |128| 64| 32| 16| 8 | 4 | 2 | 1 |
+---+---+---+---+---+---+---+---+

Related

How to sort Hexadecimal Numbers (like 10 1 A B) in C?

I want to implement a sorting algorithm in C for sorting hexadecimal numbers like:
10 1 A B
to this:
1 A B 10
The problem that I am facing here is I didn;t understand how A & B is less than 10 as A = 10 and B = 11 in hexadecimal numbers. Im sorry if I am mistaken.
Thank you!
As mentioned in the previous comments, 10 is 0x10, so this sorting seems to be no problem: 0x1 < 0xA < 0xB < 0x10
In any base a number with two digits is always greater than a number with one digit.
In hexadecimal notation we have 6 more digits available than in decimal, but they still count as one "digit":
hexadecimal digit | value in decimal representation
A | 10
B | 11
C | 12
D | 13
E | 14
F | 15
When you get a number in hexadecimal notation, it might be that its digits happen to use none of the above extra digits, but just the well-known 0..9 digits. This can be confusing, as we still must treat them as hexadecimal. In particular, a digit in a multi-digit hexadecimal representation must be multiplied with a power of 16 (instead of 10) to be correctly interpreted. So when you get 10 as hexadecimal number, it has a value of one (1) time sixteen plus zero (0), so the hexadecimal number 10 has a (decimal) value of 16.
The hexadecimal numbers you gave should therefore be ordered as 1 < A < B < 10.
As a more elaborate example, the hexadecimal representation 1D6A can be converted to decimal like this:
1D6A
│││└─> 10 x 16⁰ = 10
││└──> 6 x 16¹ = 96
│└───> 13 x 16² = 3328
└────> 1 x 16³ = 4096
──── +
7530
Likewise
10
│└─> 0 x 16⁰ = 0
└──> 1 x 16¹ = 16
── +
16

Bitwise carry applications

Call me naive but in this area I always struggled. So I was just browsing through the code for adding two numbers without + operator and bumped into this code:
int Add(int x, int y)
{
// Iterate till there is no carry
while (y != 0)
{
// carry now contains common set bits of x and y
int carry = x & y;
// Sum of bits of x and y where at least one of the bits is not set
x = x ^ y;
// Carry is shifted by one so that adding it to x gives the
// required sum
y = carry << 1;
}
return x;
}
Now I understand, how he is calculating the carry but why y!=0 and how this code is achieving the result for adding two numbers?
Basics first. Exclusive or'ing two bits is the same as the bottom digit of their sum. And'ing two bits is the same as the top bit of their sum.
A | B | A&B | A^B | A+B
-----------------------
0 | 0 | 0 | 0 | 00
0 | 1 | 0 | 1 | 01
1 | 0 | 0 | 1 | 01
1 | 1 | 1 | 0 | 10
As you can see the exclusive-or result is the same as the last digit of the sum. You can also see that the first digit of the sum is only 1 when A is 1 and B is 1.
[If you have a circuit with two inputs and two outputs, one of which is the exclusive or of the inputs and the other is the and of the inputs, it is called a half adder - because there is no facility to also input a carry (from a previous digit).]
So, to sum two bits, you calculate the XOR to get the lowest digit of the result and the AND to get the highest digit of the result.
For each individual pair of bits in a pair of numbers, I can calculate the sum of those two bits by doing both an XOR and an AND. Using four bit numbers, for example 3 and 5
3 0011
5 0101
------
0110 3^5 = 6 (low bit)
0001 3&5 = 1 (high bit)
In order to treat the 3 and 5 as single numbers rather than collections of four bits, each of those high bits needs to be treated as a carry and added to the next low bit to the left. We can do this by shifting the 3&5 left 1 bit and adding to the 3^5 which we do by repeating the two operations
6 0110
1<<1 0010
----
0100 6^(1<<1) = 4
0010 6&(1<<1) = 2
Unfortunately, one of the additions resulted in another carry being generated. So we can just repeat the operation.
4 0100
2<<1 0100
----
0000 4^(2<<1) = 0
0100 4&(2<<1) = 4
We still have a carry, so round we go again.
0 0000
4<<1 1000
----
1000 4^(4<<1) = 8
0000 4&(4<<1) = 0
This time, all the carries are 0 so more iterations are not going to change anything. We've finished.
I will try to explain it on a simple 3 bits example (you can skip this example to the actual explanation which marked in bold font and starts at Now to the way we achieve the same flow from the posted code).
Lets say we want to add x=0b011 with y=0b101. First we add the least significant bits 1+1 = 0b10
carry: x10
x: 011
+
y: 101
-----
xx0
Then we add the second bits (and by the book we need to add also the carry from the previous stage but we can also skip it for later stage): 1+0 = 0b1
carry: 010
x: 011
+
y: 101
-----
x10
Do the same for the third bit: 0+1 = 0b1
carry: 010
x: 011
+
y: 101
-----
110
So now we have carry = 0b010 and some partial result 0b110.
Remember my comment earlier that we take care of carry at some later stage? So now is this "later stage". Now we add the carry to the partial result we got (note that it is the same if we added the carry for each bit separately at the earlier stages). LSB bits addition:
NEW carry: x00
carry: 010
+
part. res.: 110
-----
xx0
Second bits addition:
NEW carry: 100
carry: 010
+
part. res.: 110
-----
x00
Third bit addition:
NEW carry: 100
carry: 010
+
part. res.: 110
-----
new part. res. 100
Now carry = NEW carry, part. res. = new part. res. and we do the same iteration once again.
For LSB
NEW carry: x00
carry: 100
+
part. res.: 100
-----
xx0
For the second bits:
NEW carry: 000
carry: 100
+
part. res.: 100
-----
x00
Third bits:
NEW carry: 1000 --> 000 since we are working with 3 bits only
carry: 100
+
part. res.: 100
-----
000
Now NEW carry is 0 so we have finished the calculation.The final result is 0b000 (overflow).
I am sure I haven't discovered anything to here. Now to the way we achieve the same flow from the posted code:
The partial result is the result without the carry, which means when x and y have different bits at the same position, the sum of these bits will be 1. If the same bits are identical, the result will be 0 (1+1 => 0, carry 1 and 0+0 => 0, carry 0).
Thus partial result is x ^ y (see the properties of the XOR operation). In the posted code it is x = x ^ y;.
Now let's look at the carry. We will get carry from a single bit addition only if both bits are 1. So the bits which will set the carry bits to 1 are marked as 1 in the following expression: x & y (only the set bits at the same position will remain 1). But the carry should be added to the next (more significant) bit! Thus
carry = (x & y) << 1; // in the posted code it is y = carry << 1
And the iterations are performed unless carry is 0 (like in our example).

what is the function of $value & 15

I have been going over a perl book i have recently purchased, and while reading I noticed a block of code that confused me..
use integer;
$value = 257;
while($value){
unshift #digits, (0..9,a..f)[$value & 15];
$value /= 16;
}
print digits;
the book mentions the purpose was to reverse the order of digits. however, new to perl I am having trouble figuring out what [$value & 15] is doing.
It's a bitwise and operation.
What it's doing is performing a bitwise and using the value of 15 and whatever value is contained in $value.
The resulting value is the decimal value that corresponds to the result of a bitwise and with the lower 4 bits of the value.
Ex:
$value = 21
which has a binary representation of: 0b10101
Performing a bitwise and with 15 means that any bits in $value will be zeroed if they are either outside the lower 4 bit range, or contain no 1's in the lower 4 bits.
The result is:
0b10101
&
0b 1111
-------
0b00101 = 5
Looking up the truth tables for performing bitwise operations will help with stuff like this in the future, but when performing an AND with any value, the result is only true, when both bits are 1, 0 otherwise.
V1 | V2 | V1 & V2
-----------------
0 | 0 | 0
0 | 1 | 0
1 | 0 | 0
1 | 1 | 1

Need explain a code in embedded program

I am completely new to embedded programming, I'm examining the code below and trying to understand how it work, but I really got stuck.
The program is used to count and print out the numbers from 0 to 9.
So can someone please explain the line const uint8_t ? why do I need an array of heximal number here?
#include <avr/io.h>
#include <util/delay.h>
#include "debug.h"
const uint8_t segments[10] = {0xFC,0x60,0xDA,0xF2,0x66,0xB6,0xBE,0xE4,0xFE,0xF6};
int main(void) {
uint8_t i=0; //s
int g;
init_debug_uart0();
/* set PORT A pins as outputs */
DDRA = 0xFF;
for (;;) {
PORTA = segments[i];
printf("%d\n\r",i);
_delay_ms(1000);
if (i >=9) {
fprintf(stderr , "Count Overflow\n\r"); i = 0;
scanf("%d", &g);
}else
i++;
}
}
And a final question, does anyone know good sources to read about embedded programming? Currently i'm learning about the IIMatto, 8-bits processor and it has 32-registers, designed in Harvard architecture and has 1 level pipeline.
The const uint8_t segments[10] = {0xFC,0x60,0xDA, ... simple defines a constant 10-byte array of bytes.
Code does not need an array of hexadecimal, it could have been decimal.
But consider the benefit of
0xFC,0x60,0xDA,0xF2,0x66,0xB6,0xBE,0xE4,0xFE,0xF6
// versus
252,96,218,...
A casual inspection shows that the number of bits set in each byte is
6,2,5,5,...
This just happens to match the number of segments set in a 7-segment display of the digits 0,1,2,3 ...
Closer inspection of the bits set will detail which bit activate what segment.
Other methods could be employed to get this mapping of 7-segment to digit, but showing the data in hexadecimal is one step closer than decimal.
Perhaps code could be like (the proper segment mapping is TBD).
typedef enum {
LED7_a = 1 << 0,
LED7_b = 1 << 1,
LED7_c = 1 << 2,
LED7_d = 1 << 3,
LED7_e = 1 << 4,
LED7_f = 1 << 5,
LED7_g = 1 << 6,
LED7_dp = 1 << 7
} LED7_Segment_t;
/* ****************************************************************************
7 Segment Pattern
Layout
aaa
f b
f b
ggg
e c
e c
ddd dp
**************************************************************************** */
const uint8_t segments[] = {
/*'0*/ LED7_a | LED7_b | LED7_c | LED7_d | LED7_e | LED7_f ,
/*'1*/ LED7_b | LED7_c ,
/*'2*/ LED7_a | LED7_b | LED7_d | LED7_e | LED7_g,
/*'3*/ LED7_a | LED7_b | LED7_c | LED7_d | LED7_g,
/*'4*/ LED7_b | LED7_c | LED7_f | LED7_g,
/*'5*/ LED7_a | LED7_c | LED7_d | LED7_f | LED7_g,
/*'6*/ LED7_a | LED7_c | LED7_d | LED7_e | LED7_f | LED7_g,
/*'7*/ LED7_a | LED7_b | LED7_c ,
/*'8*/ LED7_a | LED7_b | LED7_c | LED7_d | LED7_e | LED7_f | LED7_g,
/*'9*/ LED7_a | LED7_b | LED7_c | LED7_d | LED7_f | LED7_g};
First of all, ask yourself where is segments used, what is it used for, how is it used?
Hints:
Where: Used to assign a value to PORTA
What: PORTA Is an output from an embedded system. Perhaps to an external device. segments is used to store outputs.
How: Each time around the loop, the value i is incremented. i is used as the index for segments when its value is assigned to PORTA.
Also: A hexadecimal number, specifically 2 digits long, is a byte which is 8 bits. Look on your microcontroller for up to 8 pins labelled "PORTA"
When writing to PORTA (an I/O port) you are concerned with the state of individual I/O lines associated with each bit.
To display a specific set of segments representing a digit on a 7-segment display, you have to write a specific bit pattern - one bit for each segment you wish to light. The segments array is indexed by the digit you want to display, and the value at that index represents the bit pattern on PORTA required to light the segments that represent that digit.
The reason hexadecimal is used is because there is a direct mapping of single hexadecimal digit to exactly four binary digits, so hex is a compact way of representing bit patterns. For an experienced embedded developer, mentally converting a bit-pattern to hex and vice versa becomes second nature. If the values were decimal, the representation would bear no direct relationship to the bit pattern, and the conversion or mental visualisation of the bit pattern less simple.
The hex digit to binary pattern conversion is as follows:
0 0000
1 0001
2 0010
3 0011
4 0100
5 0101
6 0110
7 0111
8 1000
9 1001
A 1010
B 1011
C 1100
D 1101
E 1110
F 1111
0xFC = 11111100
0x60 = 1100000
0xDA = 11011010
....
you need an array of hex numbers, most probably you have connected some sort of device to portA, and in this device
0xFC or 11111100 means display 0,(when portA pins 7,6,5,4,3,2, are high and 1,0 are low this device will display 0
0x60 or 11000000 means display 1(when PortA pins 7,6 are high and the rest low, this device will display 1.
and so on..
The memory locations in the microcontroller are 8 bits wide so 16 I/O will require two 8 bit registers called PORTA and PORTB. in your case its only 8bits wide ie. 8 I/O pins per PORTA, another 8 for PORTB and so on.
the outputs of these ports are controlled by the 8bits..
Suppose we wish to turn on an LED which we are going to connect to bit 4 on PORTB. We first of all have to instruct the microcontroller to ensure that PORTB bit 4 is an output.(the micro needs to know if ports are outputs are inputs you cant just plug stuff in)
in a pic micro you would say TRIA = 0x00010000 this tell the micro portB4 is an output.Now that we have said its an output, PORTA = 0b00010000 sets this portB4 to a high voltage, in other words this will illuminate the LED or whatever you have connected to the port.
PORTA = 0b00000000 // turns off PORTA outputs,
PORTA = 0b10000000 // turns on PORTA pin 7
The hexadecimal values its just a notation, the first letter represents the first 4 bits of your int and the other the other four bits because you are declaring a const uint8 variable wich means an unsigned integer of 8 bits, this is an integer but without sign, the bit of the sign is removed, so it can store 2^8 posibles values.
I'm just answering the first question. Hope it help!!

C - Fast conversion between binary and hex representations

Reading or writing a C code, I often have difficulties translating the numbers from the binary to the hex representations and back. Usually, different masks like 0xAAAA5555 are used very often in low-level programming, but it's difficult to recognize a special pattern of bits they represent. Is there any easy-to-remember rule how to do it fast in the mind?
Each hex digit map exactly on 4 bit, I usually keep in mind the 8421 weights of each of these bits, so it is very easy to do even an in mind conversion ie
A = 10 = 8+2 = 1010 ...
5 = 4+1 = 0101
just keep the 8-4-2-1 weights in mind.
A 5
8+4+2+1 8+4+2+1
1 0 1 0 0 1 0 1
I always find easy to map HEX to BINARY numbers. Since each hex digit can be directly mapped to a four digit binary number, you can think of:
> 0xA4
As
> b 1010 0100
> ---- ---- (4 binary digits for each part)
> A 4
The conversion is calculated by dividing the base 10 representation by 2 and stringing the remainders in reverse order. I do this in my head, seems to work.
So you say what does 0xAAAA5555 look like
I just work out what A looks like and 5 looks like by doing
A = 10
10 / 2 = 5 r 0
5 / 2 = 2 r 1
2 / 2 = 1 r 0
1 / 2 = 0 r 1
so I know the A's look like 1010 (Note that 4 fingers are a good way to remember the remainders!)
You can string blocks of 4 bits together, so A A is 1010 1010. To convert binary back to hex, I always go through base 10 again by summing up the powers of 2. You can do this by forming blocks of 4 bits (padding with 0s) and string the results.
so 111011101 is 0001 1101 1101 which is (1) (1 + 4 + 8) (1 + 4 + 8) = 1 13 13 which is 1DD

Resources