Microcontroller reverse engineer
Microcontroller reverse engineer
Everything they make, We can break! 
  HOME COMPANY PCB COPY MCU HACK FAQ CONTACT US
Disassembler Software   
WHY US ?
World first mcu hack company
In business since 1998
Reversed tens of thousands of chips
Copied thousands of pcbs
Foreseen all pertential problems
Integrity with payments
crack ic
 
 
Microcontroller Beginners' Guide

Chapter 3

 

Part 6 - Revising the First Program to Make the LED Blink and an Introduction to Bitwise Operations

You've written the first program, which turned on an LED. Yeah, that was spectacular! Well, not really, but let's introduce a little bit of craziness to the LED. We'll give it a "bi-polar" personality by making it blink. Then we'll step it up a notch and make it blink really fast. The program is surprisingly concise and easy to implement.

 

See for yourself:

#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
DDRB |= 1 << PINB0;
while (1)
{
PORTB ^= 1 << PINB0;
_delay_ms(100);
}
}

HEY!! What are those crazy symbols!! Crazy seems to be a common theme here. Well, I'll explain. But, I promise, it's pretty easy. You just need to memorize a few things. I will get into a little bit of detail, but if you don't get it, don't worry, just memorize what the entire statement accomplishes and you will be fine. I will give you a hint along the way. Here comes the detail of bitwise operations:

 

There are logical operators called AND, OR, NOT and XOR that we are concerned with at this point. They really do mean what they say. This is all for the sake of comparing two bits, "1" and "0". See? How can just comparing two numbers be difficult! "1" AND "1" is True or "1". And yes, you guessed it, "0" AND "0" is False or "0". But what is "0" AND "1" and vice versa? Well, False or "0", obviously. Those guys are different, so, truely, they are false.

Example AND binary number operation (the "&" is used in C programming for AND):

01001011 &
10001101
equals
00001001

Easy, right? Well, OR is even easier! "1" OR "1" is "1", obviously. "0" OR "0" is also "0". It's starting to look very similar to AND, but here is the difference. If the two numbers are different, it will result in "1". So, "1" OR "0" is "1".

 

Let's use the same binary number for the example (that funny character "|" is the OR, sometimes located above the "\" onthe keyboard):

01001011 |
10001101
equals
11001111

Hmm, that turned on all of the places where there were missing ones! This is where the magic happens. Yes, it kept the ones in the first number and where there are ones in the second binary number, but not the first, it changed those to ones. Very simple. NOT simply takes all of the bits and flips them. For example, for this binary number: 01001101 will turn into 10110010. It turned the 0's into 1's and 1's into 0's, but don't get this confused with the XOR.

XOR is similar to OR but the "1" XOR "1" is actually "0". I'll just show the example and you can figure out what happenes.

01001011 ^
10001101
equals
11000110

Yep, you guessed it, the "^" that is above the "6" is the XOR symbol. Hmmm... The "|" and the "^" are in the program. Cool. Well, since we are thinking program, let's disect the stuff we don't know yet!

#include <util/delay.h>

You already know what the <avr/io.h> does, so I won't waste your time with that one, but there is a new #include statement. The delay.h will provide us a couple of convenient methods for us to use. Just like the name implies, the delay.h will provide us with a way to create delays in our program.

 

Skipping over the "main" since we know that already, we see the DDRB changed. Don't be scared! Here is the process from where we were to where we are:

 

This is what we had before. This is not a very good way of minipulating the pins because we just changed all of the pins from 1 to 7 as input, but "what if" we had a larger program that used those pins for other things, like for instance, pin 2 allpies brake pressure control for the anti-lock braking system. You wouldn't want to just arbitrarily set that as an input. That would render your brakes useless (which would be REALLY bad).

DDRB = 0b00000001;

We need a way to ONLY affect one bit, the pin 0 bit. Well, if you look above at the "OR", we can do this with a mask (not the carnival mask you are thinking, but a binary mask.

DDRB = DDRB | 0b00000001;

This will takes it's former self and "OR" it to a mask. The mask is: 0b00000001. Yes this looks like the actual binary number, but if the previous DDRB was, say, 0b01001010, then doing an OR to that with our mask would be: 0b01001010 | 0b00000001 = 0b01001011. What is different in the result. That's right, only the pin 0 bit is changed!

This statememt can be further compressed in C++:

DDRB |= 0b00000001;

But that is not what is in the program. Even though this is perfectly valid, why don't we take advantage of some of the definitions in the io.h header file. I mean, it's there for our convenience, isn't it? Notice my use of contractions! This is the same in C++: "it's" is really "it is", just like "DDRB |= 0b00000001" is the same as "DDRB = DDRB | 0b00000001". I sink in my chair with that bad analogy. Whataver, helps!

So why "DDRB |= 1 << PINB0

1 << PINB0 is the act of creating the mask. The "1" represents what will be inserted into the mask, the << is a left shift operator. It does EXACTLY microcontroller pins blown with focused ion beam modification what it says, and PINB0 is a number of positions that the "1" will shift left. In essence, PINB0 is just equal to 0. So, you start with a 0b00000000, and you add a "1" to make 0b00000001 and then you shift it left 0 positions. So you are left with 0b00000001, the same number from above. So, what if it was PINB4? The statement would be: 1 << PINB4. The "1" would be left shifted 4 times resulting in: 0b00010000. Remember, we are using a zero index, so there is four 0s after the 1.

 

Let's move on to the While loop. You're right, we didn't have anything in the "infinite loop" before. Well, now we need the microcontroller to show some action. This is only possible within the loop. The loop is where the action is repeated over and over. If the action was located before snaileye the loop, then the action would only happen once, like setting the direction of the pin, which is appropriate for this program. But to create forever blinking, we need to turn the PINB0 on and off within the loop. Here is also where the delays come in. If we didn't have delays, we would not see the LED blinking at all, it would look like it is just on, since the blinking would occur faster than the eye could perceive, so we need to slow it down.

 

We know how to set a specific bit in the binary number, but we don't know how to make a specific bit "0" if it is a "1" yet. The following code does just this, but you will notice that it is not what the program shows. The first couple of lines turns the bit to "1" (5 volts, light), and pauses for 100 miliseconds (by the way, you can use microseconds by changing the "ms" to "us"). The second two lines turns the PINB0 bit to "0" (0 volts, no light). No, the AND comparison cannot just make a "0" from the bit, but if you NOT "~" the binary number mask, it will turn all of the 0s to 1s and all of the 1s to 0s. This will permit you to only affect the PINB0 bit and turn it into a "0". I added the parenthesis just to contain the masking operation so the NOT could NOT the whole maks and not just the "1" before the left shift "<<".

PORTB |= 1 << PINB0;
_delay_ms(100);
PORTB &= ~(1 << PINB0);
_delay_ms(100);

If the delay is going to be the same for on and off, we could shorten the previous four lines to only two and take advantage of the XOR operation. Remember, the XOR will turn our specific pin to a 1 if it is 0 and vice versa. This instruction will only affect the PINB0. Every time that the instruction is executed, it will flip the bit to the opposite.

PORTB ^= 1 << PINB0;
_delay_ms(100);

That's it. See that was not painfull at all.

 

 

Part 7 - Adding a Button to the Microcontroller and Making it Do Something

A very simple and easy way to provide for human interaction with the microcontroller is to insert a button into the circuit. We communicate with computers using two main input devices: the mouse and the keyboard. A keyboard is nothing more mcu dump than a bunch of buttons laid-out to allow the user to input (ASCII) characters to the computer. If you're scratching your head on the ASCII part, don't worry--it just represents the code for each character.

 

By this point in our journey, you should have already setup your computer with WINAVR (or AVR-GCC for Linux), and be able to program your microcontroller. You should also have a circuit built with an LED plugged into the microcontroller. You also made the LED blink in the previous tutorial.

 

Adding a button or switch to the circuit enables the microcontroller to receive human input. Other forms of input for microcontrollers include (but are not limited to) a keyboard or a mouse, buttons, switches, audio (through microphones), touch screen displays and digitizers. There are of course many other devices that can provide input to a microcontroller, but these may not all be activated by voluntary human action. I place these other devices into the "sensing" category, as these devices typically sense conditions or events and react accordingly. A few such examples include sensors for tilt (accelerometers), detecting infrared energy or monitoring temperature.

 

So, here's the skinny on buttons and mechanical switches: they're imperfect! The two families of mechanics and electronics go together like the Montagues and Capulets. That is, they don't! When you push a button, you might expect a clean response electronically. Well, sorry to be the bearer of bad news 聚焦离子束FIB, but the signal often bounces quite a bit before it settles to its correct voltage level. In this image, I show this phenomenon. If the voltage is set at 5 volts before the button is pressed and then goes to zero volts when the button is pressed, there will be a "bouncing" effect of the voltage between these two values. So then why don't all of our kitchen appliances or our cars exhibit this problem?

 

As you should be able to see in the image, I have inserted a capacitor between the two pins. This will smooth out the signal. The effect of this capacitor can be seen on an oscilloscope, as demonstrated in the video. But if you don't have an oscilloscope of your own, then you will just have to trust me. Another way we could alleviate this problem is to add a time delay into the program, just after the microcontroller senses the first button press event. However adding a discrete component to a circuit to solve such an electronics problem, is often a better way than adding code to cause a delay--as that code will introduce another potential source of a bug into the program, and will also require more processor time to execute. In additional, this code can also result in the development of other problems as the rest of the code continues to execute.

 

But what value capacitor should we select? This will ultimately depend on how poorly the button performs regarding this particular problem. Some buttons can display a tremendous bouncing behavior, yet others will have very little. A low capacitor value like 1.0nF (nanofarads) will react very quickly, with little or no effect on the bouncing. Conversely, a higher capacitor value such as 220nF (which is still pretty small in terms of capacitors) will provide a slow transition from the starting to the ending voltage (i.e. 5v to 0v). The transition seen with a 220nF capacity is still pretty fast in a real-world sense however, and thus can be used on poorly performing buttons.

 

You might have noticed by now that the breadboard has changed somewhat, to give the circuit a cleaner look. The previous wires were too long, and the build environment started getting messy as I added further components to the circuit. Therefore a re-design of the breadboard was in order, so I snapped a second breadboard to the end of the first. But you might be asking--why did I do this if there were sufficient ties remaining at the other end? Well, I did it for neatness, and I also liked where the microcontroller was positioned. You may be able to tell that I've aligned it with the numbers so that I don't need to count pins all the time--I simply let the breadboard numbering tell me where each pin is on the MCU. I also tied all of the positive (+) rails on both boards together, and did the same to all of the negative (-) rails as well. This will allow me to have VCC or GND close by, anywhere on the breadboard.

 

So then, how do we program the ATmega32 microcontroller (or other MCU that you may be applying to this experiment) to make use of the new button? Well it's really quite straightforward! We only have to add two initializing lines just prior to the infinite loop, and a single condition block within the loop. The two initialization lines added before the loop include one statement to set PINB1 for input by assigning it a "0" like this:

DDRB &= ~(1 << PINB1);

We will also set pin B1 "high," meaning the pin will read 5 volts until the button is pressed; at which time the pin will read zero volts. To set the pin at a high voltage of 5 volts, we add this line of code:

PORTB |= 1 << PINB1;

Within the program, there must be a decision: a decision to run some code when the button is pressed, or run some other code if the button is not pressed. This task is in the form of a conditional statement called an "if else" statement. It does EXACTLY what is says. Just like the English equivalent... if (the button is pressed), jump up and down, else stand on your head. the action "jump up and down" will happen while the button is pressed. But while the button is not pressed, the other action "stand on your head" will happen. The if statement code:

if (bit_is_clear(PINB, 1))

specifies a test for a condition specified inside the parentheses. The name "bit_is_clear" represents a function that takes two arguments. In this case the first argument is PINB, which describes the set of pins we are specifying. The second argument represents which pin we are checking, and in this case we are concerned with pin #1 in the set.

You might be wondering what sorts of things can we put into the code block controlled by the "if" condition? That all depends on what you want your program (and circuit) to do. In this case, as a way to show that this button does something and works, I have the LED blinking slowly (every 100 ms) while the button is not pressed, and blinking faster (every 10ms) while pressed.

Here are the changes made to the previous LED blinking program:

#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
DDRB |= 1 << PINB0;
DDRB &= ~(1 << PINB1);
PORTB |= 1 << PINB1;


while (1)
{
PORTB ^= 1 << PINB0;
if (bit_is_clear(PINB, 1))
{
_delay_ms(10); //Fast
}
else
{

_delay_ms(100); //Slow, from previous
}
}
}

That is it!! There is very little programming required to use a button, LED and make things blink!

 

 

Part 8 - Understanding Button Debouncing

Let's study button debouncing in a little more detail. The importance of button debouncing should not be overlooked. Button switches are one of the many ways that humans can provide input to the microcontroller. When a button is pressed, the human will expect a reaction in some form, say an LED toggling, a menu on an LCD (moving from one menu item to another), a motion controlled device (moving and stopping), etc. If a button is not debounced in some way, the human may get quite maker together club frustrated.

 

Button debouncing can cause multiple false button presses. Imagine using a button in the selection of a menu item. The button not being debounced, one click can cause the menu to skip one or more menu items. Even worse, when trying to select a particular item, and it continually skips when either button is toggled, making a particular selection to be made.

 

To demonstrate this phenomenon, this project will contain two LEDs. When a button is pressed, the LEDs will toggle between each other. A button press will turn one off, and the other on. When the button is released, it can start this process again and cause the LEDs to toggle again, once the button is pressed. You will notice that the LEDs will toggle twice, or even more times with only one button press.

 

I will show two ways to eliminate debouncing. The in-circuit method (hardware) using a capacitor, and software debouncing. The hardware will simply use a capacitor to eliminate debouncing, and the software will introduce a variable that measures the confidence level of the button stream of ones, or zeros. Disclaimer: the method that I use for hardware debouncing is a very simple and poor mans method. The main problem with this method is that the voltage climbs from 0 to 5v rather than an immediate, or instantaneous change. This can put the signal in a range that the microcontroller does not know how to deal with the voltage. This range is the area between the thresholds of high and low signals, which is between 2 and 3 volts. With this said, I have not personally seen any problem with this with my button debouncing. If you would like to eliminate this climbing, use a schmitt trigger.

 

In the video, the circuit is connected together on the breadboard without the hardware debouncing, so the problem can be experienced. Two LEDs are connected to the microcontroller, both on port B, one on pin 0 and the other on pin 2. both of these pins will be set to output and since the LEDs are green, a 330 ohm resistor is used for each LED. The button switch is connected to pin 1, on port B. This pin will be set for input and set to read high (pin set to a "1"). for the first "bounce" test, we will not use a capacitor across the two leads of the button.

 

The program to make two LEDs toggle when the push button is pressed is very simple. First, the pins are initialized: Pins outputting to the LEDs are set to output in the DDR (Data Direction Register). One of the LEDs are toggled high, so at the start, one is on and one is off. Then, the never ending loop is started and the code within that block gets executed until the microcontroller loses power. Withing this loop, the pin that is connected to the push button is constantly checked to determine if it is on. If it is pressed, and exhibits a 1, then it checks if the button was firsts released. This is important, because if we don't have this check, the button will just toggle continuously while the button is pressed. We only want the button to toggle if the button is pressed and then released.

#include <avr/io.h>
int main(void)
{
DDRB |= 1 << PINB0; //Set Direction for output on PINB0
PORTB ^= 1 << PINB0; //Toggling only Pin 0 on port b
DDRB |= 1 << PINB2; //Set Direction for Output on PINB2
DDRB &= ~(1 << PINB1); //Data Direction Register input PINB1
PORTB |= 1 << PINB1; //Set PINB1 to a high reading
int Pressed = 0; //Initialize/Declare the Pressed variable

while (1)
{
if (bit_is_clear(PINB, 1)) //Check is the button is pressed
{
//Make sure that the button was released first
if (Pressed == 0)
{
PORTB ^= 1 << PINB0; //Toggle LED in pin 0
PORTB ^= 1 << PINB2; //Toggle LED on pin 2
Pressed = 1;
}
}
else
{
//This code executes when the button is not pressed.
Pressed = 0;
}
}
}

So, when the microcontroller is programmed, and the button is pressed several times, it is evident that the LEDs will toggle, sometimes correctly, and sometimes will toggle multiple times with only one button press. Add the capacitor and check the button pressing and LED toggling again. On the ocilliscope, with the capacitor installed, a gradual rise of the voltage is created when the button is pressed, opposed to a bunch of up and down voltages resulting from a bounce from the mechanical parts of the button. But when the button is released, it shows that the voltage is a direct change. This is because another capacitor is not installed between the button and the microcontroller.

 

Next, the software debounce method is investigated.

 

 

Chapter 1 | Chapter 2 | Chapter 3 | Chapter 4 | Chapter 5 | Chapter 6 | Chapter 7 | Chapter 8 | Chapter 9

 

 

 
 
     
 
PCB Copying Service
PCB Projects Overview
PCB Clone
PCB Reverse Engineering
PCB Prototype
PCB Assembly Production
 
 
 
Mcu Hacking Service
Atmel / Analog Mcu Hack
Actel Mcu Attack
Altera Microcontroller Crack
Cygnal Mcu Unlock
Cypress IC Reverse Engineer
Dallas / Elan Mcu Code Extract
Fujitsu Microprocessor Decryption
Freescale IC Code Extraction
Giga Device circuit Hack
Hitachi Mcu Code Extract
Holtek Chip Reverse Engineer
Infineon Microcontroller Dump
Intel Mcu Read Code Protection
ICT Microcontroller Duplication
Lattice Microcontroller Clone
Microchip Source Code Recovery
Motorola Microcontroller Crack
Maxim Mcu Attack
MDT Controller Hack
Megawin Microcontroller Unlock
NEC Mcu Reverse Engineer
NTK Microcontroller Code Extract
Nuvoton Chip Decryption
NXP Semiconductor Code Extraction
Philips integrated circuit Crack
Renesas Microcontroller Dump
ST Processor Reverse Engineer
Silicon Labs Mcu Read Protection
Samsung Mcu Duplication
SST Mcu Clone
Sinowealth Source Code Recovery
SyncMOS Mcu Unlock
Sonix Mcu Read Source Code
STC Microprocessor Code Extract
Tenx Microcontroller Decryption
Texas Instruments MCU Hack
Winbond MCU Code Extraction
Xilinx integrated circuit Crack
Zilog MCU Reverse Engineer
 
     
 
 
More MCU brands we can reverse engineer below, please contact us if yours not listed here:
AMD Feeling LG / Hyundai Myson STK
ChipON Hynix Mitsubishi National Semi Temic
Coreriver ICSI Mosel Vitelic Portek Toshiba
Dallas ISSI MXIC SSSC Gal / Pal / Palce
Copyright © 2013 Mikatech. All rights reserved. Full dedicated reverse engineering company