Professional Documents
Culture Documents
INTORDUCTION to MICROCONTOLLERS
A microcontroller is a small computer on a single integrated circuit containing a
processor core, memory, and programmable input/output peripherals. Program memory is
in the form of NOR flash or OTP ROM is also often included on chip, as well as a
typically small amount of RAM. Microcontrollers are designed for embedded
applications, in contrast to the microprocessors used in personal computers or other
general purpose applications.
Microcontrollers are used in automatically controlled products and devices, such as
automobile engine control systems, implantable medical devices, remote controls, office
machines, appliances, power tools, and toys. By reducing the size and cost compared to a
design that uses a separate microprocessor, memory, and input/output devices,
microcontrollers make it economical to digitally control even more devices and
processes. Mixed signal microcontrollers are common, integrating analog components
needed to control non-digital electronic systems.
Some microcontrollers may use Four-bit words and operate at clock rate frequencies as
low as 4 kHz, for low power consumption (mill watts or microwatts). They will generally
have the ability to retain functionality while waiting for an event such as a button press or
other interrupt; power consumption while sleeping (CPU clock and most peripherals off)
may be just nanowatts, making many of them well suited for long lasting battery
applications. Other microcontrollers may serve performance-critical roles, where they
may need to act more like a digital signal processor (DSP), with higher clock speeds and
power consumption.
EMBEDDED DESIGN
The Intel MCS-51 is a Harvard architecture, single chip microcontroller (µC) series
which was developed by Intel in 1980 for use in embedded systems.[1][2] Intel's original
versions were popular in the 1980s and early 1990s, but has today largely been
superseded by a vast range of faster and/or functionally enhanced 8051-compatible
devices manufactured by more than 20 independent manufacturers
including Atmel,Infineon Technologies (formerly Siemens AG), Maxim Integrated
Products (via its Dallas
Semiconductor subsidiary), NXP (formerly PhilipsSemiconductor), Nuvoton
(formerly Winbond), ST Microelectronics, Silicon Laboratories (formerly Cygnal), Texas
Instruments, Ramtron International, Silicon Storage Technology, and Cypress
Semiconductor.
Intel's original MCS-51 family was developed using NMOS technology, but later
versions, identified by a letter C in their name (e.g., 80C51) used CMOS technology and
were less power-hungry than their NMOS predecessors. This made them more suitable
for battery-powered devices.
Interfacing refers to the ability or capacity of two objects or items to be brought together
to form a function together or a surface forming a common boundary between two
adjacent regions, forms, bodies, etc.
In the computer science and technology fields, interfacing refers to the point of
interaction or communication between two devices or a user and a device.
Whenever a key is pressed, a row and a column gets shorted through that pressed key and
all the other keys are left open. When a key is pressed only a bit in the port goes high
which indicates microcontroller that the key is pressed. By this high on the bit key in the
corresponding column is identified.
Once we are sure that one of key in the key board is pressed next our aim is to identify
that key. To do this we first check for a particular row and then we check the
corresponding column the key board.
To check the row of the pressed key in the keyboard, one of the rows is made high by
making one of bit in the output port of 8051 high. This is done until the row is found
out. Once we get the row next job is to find out the column of the pressed key. The
column is detected by contents in the input ports with the help of a counter. The content
of the input port is rotated with carry until the carry bit is set.
The contents of the counter is then compared and displayed in the display. This display is
designed using a seven segment display and a BCD to seven segment decoder IC
7447.The BCD equivalent number of counter is sent through output part of 8051 displays
the number of pressed key.
MICRO
KEYPAD DISPLAY
CONTROLLER
1. The 8051 has 4 I/O ports P0 to P3 each with 8 I/O pins, P0.0 to P0.7,P1.0 to P1.7,
P2.0 to P2.7, P3.0 to P3.7. The one of the port P1 (it understood that P1 means
P1.0 to P1.7) as an I/P port for microcontroller 8051, port P0 as an O/P port of
microcontroller 8051 and port P2 is used for displaying the number of pressed
key.
2. Make all rows of port P0 high so that it gives high signal when key is pressed.
3. See if any key is pressed by scanning the port P1 by checking all columns for non
zero condition.
4. If any key is pressed, to identify which key is pressed make one row high at a
time.
5. Initiate a counter to hold the count so that each key is counted.
6. Check port P1 for nonzero condition. If any nonzero number is there in
[accumulator], start column scanning by following step 9.
7. Otherwise make next row high in port P1.
8. Add a count of 08h to the counter to move to the next row by repeating steps
from step 6.
9. If any key pressed is found, the [accumulator] content is rotated right through the
carry until carry bit sets, while doing this increment the count in the counter till
carry is found.
10. Move the content in the counter to display in data field or to memory location
11. To repeat the procedures go to step 2.
INTERFACING THE LCD TO 8051
PINOUT
Display data RAM (DDRAM) is where you send the characters (ASCII code) you want
to see on the LCD screen. It stores display data represented in 8-bit character codes. Its
capacity is 80 characters (bytes). Below you see DD RAM address layout of a 2*16
LCD.
In the above memory map, the area shaded in black is the visible display (For 16x2
display) .
For first line addresses for first 15 characters is from 00h to 0Fh. But for second line
address of first character is 40h and so on up to 4Fh for the 16th character.
So if you want to display the text at specific positions of LCD , we require to manipulate
address and then to set cursor position accordingly .
In the character generator RAM, we can define our own character patterns by program.
CG RAM is 64 bytes, allowing for eight 5*8 pixel, character patterns to be defined.
However how to define this and use it is out of scope of this tutorial. So I will not talk
any more about CGRAM
Registers
The HD44780 has two 8-bit registers, an instruction register (IR) and a data register
(DR). The IR stores instruction codes. The DR temporarily stores data to be written into
DDRAM or CGRAM and temporarily stores data to be read from DDRAM or CGRAM.
Data written into the DR is automatically written into DDRAM or CGRAM by an
internal operation. . These two registers can be selected by the register selector (RS)
signal. See the table below:
Register Selection
RS R/WOperation
0 0 IR write as an internal operation (display clear, etc.)
0 1 Read busy flag (DB7) and address counter (DB0 to DB6)
1 0 DR write as an internal operation (DR to DDRAM or CGRAM)
1 1 DR read as an internal operation (DDRAM or CGRAM to DR)
When the busy flag is 1, the LCD is in the internal operation mode, and the next
instruction will not be accepted. When RS = 0 and R/W = 1 (see the table above), the
busy flag is output to DB7 (MSB of LCD data bus). The next instruction must be written
after ensuring that the busy flag is 0.
LCD Commands
The LCD’s internal controller accepts several commands and modifies the display
accordingly. These commands would be things like:
– Clear screen
– Return home
– Shift display right/left
The 44780 standard requires 3 control lines as well as either 4 or 8 I/O lines for the data
bus. The user may select whether the LCD is to operate with a 4-bit data bus or an 8-bit
data bus.
If a 4-bit data bus is used, the LCD will require a total of 7 data lines.
If an 8-bit data bus is used, the LCD will require a total of 11 data lines.
Note that the EN line must be raised/lowered before/after each instruction sent to the
LCD regardless of whether that instruction is read or write text or instruction. In short,
you must always manipulate EN when communicating with the LCD. EN is the LCD's
way of knowing that you are talking to it. If you don't raise/lower EN, the LCD doesn't
know you're talking to it on the other lines.
Analog signals are very common inputs to embedded systems .Most transducers and
sensors such as temperature ,pressure ,velocity ,humidity are analog. Therefore we need
to convert these analog signals in to digital so that 8051 can read it.
ABOUT IC
PinOut
• CS – Chip Select , active low
• RD – Read Digital data from ADC, H-L edge triggered
• WR -- Start conversion, L-H pulse edge triggered
• INTR -- end of conversion, Goes low to indicate conversion done
• Data bits -- D0-D7
• CLK IN & CLK R
– CLK IN is an input pin connected to an external clock source when an external clock is
used for timing. However, ADC804 has an internal clock
generator.
To use the internal clock generator of the ADC804, the CLK IN and CLK R pins are
connected to a capacitor and a resistor. In that case, the
clock frequency is determined by the equation.
f = 1/1.1RC
R=10K and C=150pF f=606Hz
the conversion time is 110us. Vref/2 Vin
Step size (mV)
Input Voltage range (Volts) (Volts)
• Default 0-5V. Can be changed by setting Open (2.5) 0 to 5 5/256 = 19.53
different value for Vref/2 pin. 2.56 0 to 5.12 5.12/256 =20
Vin=Vin(+) – Vin (-) 1.28 0 to 2.56 2.56/256 = 10
0.5 0 to 1 1/256=3.90
• Range = 0 to 2x Vref/2.
for Vin = 2x Vref/2. we get 256 as a digital output on D0-D7. (Refer Table)
for input vtg. of 2.56 volts (Vref=1.28 volts) and stepsize of 10mv Dout =2560/10 =256
or FF that is full scale output.
Conversion Time
Greater than 110us for ADC804
Resolution
8 bits for ADC804
Algorithm
• Make CS=0 and send a low-to-high to pin WR to start the conversion.
• Keep monitoring INTR
– If INTR =0, the conversion is finished and we can go to the next step.
– If INTR=1, keep polling until it goes low.
• After INTR=0, we make CS=0 and send a high-to-low pulse to RD to get the data out of
the ADC804 chip.
ASSEMBLY LANGUEGE (A51)
ADC_IO:
mov P1, #0xff ; To configure as input
AGAIN
clr p3.7 ;Chip select
setb P3.6 ;RD=1
clr P3.5 ;WR=0
setb P3.5 ;WR=1- low to high transition
WAIT:
jb P3.4, WAIT ;wait for INTR
clr p3.7 ;generate cs to ADC
clr P3.6 ;RD=0 -High to low transition
mov A, P1 ;read digital o/p
sjmp AGAIN
ADC808/809 Chip with 8 analog channel. This means this kind of chip allows to monitor
8 different transducers.
• ADC804 has only ONE analog input: Vin(+).
• ALE: Latch in the address
• Start : Start of conversion (same as WR in
804)
• OE: output enable (same as RD in 804)
• EOC: End of Conversion (same as INTR in
804)
Channel CBA
IN0 000
IN1 001
IN2 010
IN3 011
IN4 100
IN5 101
IN6 110
IN7 111
Algorithm
Notice that the ADC808/809 that there is no self-clocking and the clock must be provided
from an external source to the CLK pin. (you can use programmable clock oscillator to
enable or disable clock by programmable bit. )
PinOut
– D0-D7 à Connected to the Processor’s IO port
– Vref+, Vref-, Vee
Usage:
– Just write a byte to the IO port and the DAC converts it to an
analog value
Some 8051 clones have ADCs and DACs in built
EXPERIMENT NO. 2
#include <Philips\8xC31-51-80C51Fx-80C51Rx+.h>
#include <stdio.h>
#include <standard.h>
void main ()
{
delay_ms(5);
sl1=1;
sl2=0; //select display2
sl3=1;
sl4=1;
ds2=0xda; //1101 1010b pattern for 2
P0=ds2;
delay_ms(5);
sl1=1;
sl2=1;
sl3=0; //select display3
sl4=1;
delay_ms(5);
sl1=1;
sl2=1;
sl3=1;
sl4=0; //select display4
delay_ms(5);
}
EXPERIMENT NO. 3
#include <REG51F.H>
unsigned int k;
void MSDelay(unsigned int);
void main(void)
{
P0=0X00;
while(1)
{
P0=0X01;
MSDelay(50000);
P0=0X02;
MSDelay(50000);
P0=0X04;
MSDelay(50000);
P0=0X08;
MSDelay(50000);
P0=0X10;
MSDelay(50000);
P0=0X20;
MSDelay(50000);
P0=0X40;
MSDelay(50000);
P0=0X80;
MSDelay(50000);
}// end of while
}//end of main
void MSDelay(unsigned int itime)
{
unsigned int i,j;
for(i=0;i<itime;i++)
{
j++;
}
// for(j=0;j<1275;j++);
}
EXPERIMENT NO. 4
#include <Philips\8xC31-51-80C51Fx-80C51Rx+.h>
#include <stdio.h>
#include <standard.h>
unsigned int scount;
void main()
{
scount=25;
while(1)
{ stm1=1;
stm2=0;
stm3=0;
stm4=0;
delay_ms(scount);
stm1=0;
stm2=1;
stm3=0;
stm4=0;
delay_ms(scount);
stm1=0;
stm2=0;
stm3=1;
stm4=0;
delay_ms(scount);
stm1=0;
stm2=0;
stm3=0;
stm4=1;
delay_ms(scount);
}}
EXPERIMENT NO. 5
#include <p18xxxx.h>
#include <delays.h>
#include "lcd.h"
#include <string.h>
temp2 = cmd;
temp2 = temp2 >> 4;
PORTD = temp2 & 0x0F;
Delay1KTCYx(1);
lcd_strobe();
Delay1KTCYx(1);
temp2 = cmd;
PORTD = temp2 & 0x0F;
Delay1KTCYx(1);
lcd_strobe();
Delay1KTCYx(1);
void lcd_clear(void)
{
lcd_write_cmd(0x01);
Delay1KTCYx(2);
LCD_RS = 1;
Delay10TCYx(4);
temp1 = data;
temp1 = temp1 >> 4;
PORTD = temp1 & 0x0F;
Delay1KTCYx(1);
lcd_strobe();
Delay1KTCYx(1);
temp1 = data;
PORTD = temp1 & 0x0F;
Delay1KTCYx(1);
lcd_strobe();
Delay1KTCYx(1);
void lcd_strobe(void)
{
LCD_EN = 1;
Delay10TCYx(4);
LCD_EN = 0;
Delay10TCYx(4);
}
void lcd_init(void)
{
LCD_RS = 0;
LCD_WR = 0;
Delay1KTCYx(250);
Delay1KTCYx(250);
Delay1KTCYx(250);
Delay1KTCYx(250);
PORTD = 0x03;
lcd_strobe();
Delay1KTCYx(250);
PORTD = 0x03;
lcd_strobe();
Delay1KTCYx(250);
PORTD = 0x03;
lcd_strobe();
Delay1KTCYx(250);
PORTD = 0x02;
lcd_strobe();
Delay1KTCYx(250);
Delay1KTCYx(250);
lcd_write_cmd(0x2);
lcd_write_cmd(0x01);
Delay1KTCYx(20);
Delay1KTCYx(20);
lcd_write_cmd(0x0F);
Delay1KTCYx(20);
lcd_write_cmd(0x06);
Delay1KTCYx(20);
}
main(void)
{
char outchar;
unsigned char Sizevalue1, Sizevalue2, Sizevalue3;
unsigned char index;
#define constant 0x01
#define constant2 0x05
TRISA = 0x00;
TRISD = 0x00;
PORTD = 0x00;
ADCON0 = 0b11000001;
ADCON1 = 0b00001110;
for(;;)
{
ADCON0bits.GO = 1;
(PIR1bits.ADIF == 0);
PORTD = ADRESH;
lcd_goto(set_dd_line1_pos1);
for (index = 0; index < Sizevalue1; index++)
{
outchar = value1[index];
lcd_write_data(outchar);
}
Delay1KTCYx(250);
Delay1KTCYx(250);
Delay1KTCYx(250);
lcd_goto(set_dd_line1_pos1);
PIR1bits.ADIF = 0;
lcd_clear();
}
lcd_goto(set_dd_line1_pos1);
for (index = 0; index < Sizevalue1; index++)
{
outchar = value2[index];
lcd_write_data(outchar);
}
Delay1KTCYx(250);
Delay1KTCYx(250);
Delay1KTCYx(250);
lcd_goto(set_dd_line1_pos1);
PIR1bits.ADIF = 0;
lcd_clear();
}
}
}
EXPERIMENT NO. 6
#include <Philips\8xC31-51-80C51Fx-80C51Rx+.h>
Sfr ldata= 0x90; // P1= LCD data pins
Sbit rs – P2.0;
Sbit rw = P2.1;
Sbit en=P2.2;
void main ()
{
Lcdcmd(0x38);
MSDelay(250);
Lcdcmd(0x0E);
MSDelay(250);
Lcdcmd(0x01);
MSDelay(250);
Lcdcmd(0x06);
MSDelay(250);
Lcdcmd(0x86);
MSDelay(250);
Lcddata(‘A’);
}
#include <dos.h>
#include <string.h>
#include <conio.h>
#include <time.h>
void lcd_init(void);
void lcd_write(char char2write);
void lcd_putch(char char2write);
void lcd_puts(char * str2write);
void lcd_goto(int row, int column);
void lcd_clear(void);
void lcd_home(void);
void lcd_cursor(int cursor);
void lcd_entry_mode(int mode);
void main(void)
{
struct time t;
struct date d;
char strtime[17];
textbackground(0);
clrscr();
textcolor(0);
textbackground(10);
gotoxy(8,5);
cputs(" ");
gotoxy(8,4);
cputs(" ");
lcd_init();
lcd_cursor(0);
while(!kbhit())
{
gettime(&t);
getdate(&d);
lcd_goto(0,4);
sprintf(strtime,"%02d:%02d:%02d", t.ti_hour%12, t.ti_min, t.ti_sec);
lcd_puts(strtime);
gotoxy(12,4);
cputs(strtime);
lcd_goto(1,3);
sprintf(strtime,"%02d:%02d:%4d", d.da_day, d.da_mon, d.da_year);
lcd_puts(strtime);
gotoxy(11,5);
cputs(strtime);
delay(200);
}
textbackground(0);
textcolor(7);
void lcd_init()
{
lcd_write(0x0f);
delay(20);
lcd_write( 0x01);
delay(20);
lcd_write( 0x38);
delay(20);
outportb(DATA, char2write);
outportb(CONTROL,inportb(CONTROL) | 0x01); /* Set Strobe */
delay(2);
outportb(CONTROL,inportb(CONTROL) & 0xFE); /* Reset Strobe */
delay(2);
void lcd_clear()
{
void lcd_home()
{
outportb(CONTROL, inportb(CONTROL) | 0x08);
lcd_write(0x02);
/*
if you dont call this function, entry mode sets to 2 by default.
mode: 0 - cursor left shift, no text shift
1 - no cursor shift, text right shift
2 - cursor right shift, no text shift
3 - no cursor shift, text left shift
*/
outportb(CONTROL, inportb(CONTROL) | 0x08);
lcd_write(0x04 + (mode%4));
/*
set cursor: 0 - no cursor, no blink
1 - only blink, no cursor
2 - only cursor, no blink
3 - both cursor and blink
*/
}
EXPERIMENT NO. 8
#include <Philips\8xC31-51-80C51Fx-80C51Rx+.h>
#include <stdio.h>
#include <standard.h>
#include <macros31.h>
#include <stdlib.h>
/*----------------------Function declaration---------------------------------*/
void init_timer0();
void init_ex0();
void init_ex1();
void motor_drive();
}
/* ISR for ex0--------------------*/
interrupt(INT_EXT1) isr_ex1() using 2
{
job=0x04; //right
}
void main()
{
init_timer0();
enable_t0(); //enable timer0 int
init_ex0();
init_ex1();
void init_timer0()
{
TMOD|=0x01; //Timer0 in mode 1
}
void init_ex0()
{
ex0_edge();
enable_ex0()
count1=50;
count2=50;
}
void init_ex1()
{
ex1_edge();
enable_ex1()
count1=50;
count2=50;
}
void motor_drive()
{ if(job!=job_old)
{
count1=50;
count2=50;
count3=200;
}
job_old=job;
switch(job)
{
case 00: //forward
left_speed=1; //full speed
right_speed=1; //full speed
count1--;
break;
}
if(count2!=0)
{
l_en=1; //
r_en=1;
count2--;
break;
}
job=00;
count1=50;
count2=50;
break;
count1--;
break;
}
if(count2!=0)
{
l_en=1; //
r_en=1;
count2--;
break;
}
job=00;
count1=50;
count2=50;
break;
count1--;
break;
}
if(count2!=0)
{
l_en=1; //
r_en=1;
count2--;
break;
}
job=00;
count1=50;
count2=50;
break;
count1--;
break;
}
if(count2!=0)
{
l_en=1; //
r_en=1;
count2--;
break;
}
job=00;
count1=50;
count2=50;
break;
count3--;
break;
}
job=00;
count3=200;
break;
count3--;
break;
}
job=00;
count3=200;
break;
default:
l_en=1; //default action
r_en=1;
if(right_speed)
{
r_en=1;
}
else
{
r_en=!r_en;
}
}
EXPERIMENT NO. 9
void init_timer0();
void init_keypad();
void test_display();
void scanner();
void k();
void get_key();
void key_process();
void key_release();
void buzzer();
void main()
{
ds1=ds2=ds3=ds4='9'+3;
while(1)
{
get_key();
key_process();
}
}
void init_timer0()
{
TMOD|=0x01; //Timer0 in mode 1
start_timer0();
}
void init_keypad()
{
sl1=sl2=sl3=sl4=1;
krl1=krl2=krl3=krl4=1;
}
void test_display()
{
delay_ms(1000);
delay_ms(1000);
delay_ms(1000);
}
void scanner()
{
switch(scan_no)
{
case 0:
krl=krl1;
k();
scan_no=1;
break;
case 1:
krl=krl2;
k();
scan_no=2;
break;
case 2:
krl=krl3;
k();
scan_no=3;
break;
case 3:
krl=krl4;
k();
scan_no=4;
P0=0x00; //clears the display
break;
case 4:
sl1=1;
sl2=0; //select display2/Row2
sl3=1;
sl4=1;
krl=krl1;
k();
scan_no=5;
break;
case 5:
krl=krl2;
k();
scan_no=6;
break;
case 6:
krl=krl3;
k();
scan_no=7;
break;
case 7:
krl=krl4;
k();
scan_no=8;
P0=0x00; //clears the display
break;
case 8:
sl1=1;
sl2=1;
sl3=0; //select display3/Row3
sl4=1;
krl=krl1;
k();
scan_no=9;
break;
case 9:
krl=krl2;
k();
scan_no=10;
break;
case 10:
krl=krl3;
k();
scan_no=11;
break;
case 11:
krl=krl4;
k();
scan_no=12;
P0=0x00; //clears the display
break;
case 12:
sl1=1;
sl2=1;
sl3=1;
sl4=0; //select display4/Row4
krl=krl1;
k();
scan_no=13;
break;
case 13:
krl=krl2;
k();
scan_no=14;
break;
case 14:
krl=krl3;
k();
scan_no=15;
break;
case 15:
krl=krl4;
k();
scan_no=0;
P0=0x00; //clears the display
break;
default:
scan_no=0;
break;
}
if(dcount==32)
{
if(krl) //checks for
first time key press
goto out_k;
key_code=scan_no;
dcount--;
goto out_k;
}
else
{
if(dcount!=0)
{
dcount--;
goto out_k;
//debounces for 32ms
}
else
{
if(krl)
//checks for key press after debounce
{
dcount=32;
goto out_k;
//spurious key
}
else
{
key_ready=1; //
indicates confirms key press
start_buzzer=1; //puts
buzzer on
dcount=32;
goto out_k;
}
}
}
}
else //key
release part
{
if(krl)
//checks for key release
{
krcount--;
if(krcount!=0)
{
goto out_k;
}
else
{
nkp=1;
//indicates confirm key release
start_buzzer=0; //puts buzzer
off
krcount=31;
goto out_k;
}
}
else
{
krcount=31;
goto out_k;
}
}
out_k:
}
void get_key()
{
void key_process()
{
ds1=key_code;
key_release();
}
void key_release()
{
while(!nkp) //waits for all key release
{
}
key_ready=0; //starts scanning key pad again by clearing flags
nkp=0;
}
void buzzer()
{
if(start_buzzer) //buzzer starts if flag set
{
P1^=0x20; //generates square wave on P1.5
}
}