0% found this document useful (0 votes)
78 views

Microcontroller and

Uploaded by

rahulsinha8591
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
78 views

Microcontroller and

Uploaded by

rahulsinha8591
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 91

MICROCONTROLLER

AND
APPLICATION

(ELECTRONICS ENGG)
Programming 8051 MICROCONTROLLER ASM and
c and implement in flash 8051 micro controller 1.
The assembly language is a low-level programming language used to write program code in terms of
mnemonics. Even though there are many high-level languages that are currently in demand, assembly
programming language is popularly used in many applications .It can be used for direct hardware
manipulations. It is also used to write the 8051 programming code efficiently with less number of clock
cycles by consuming less memory compared to the other high-level languages.

8051 Programming in Assembly Language

The assembly language is a fully hardware related programming language. The embedded designers
must have sufficient knowledge on hardware of particular processor or controllers before writing the
program. The assembly language is developed by mnemonics; therefore, users cannot understand it
easily to modify the program.
Assembly programming language is developed by various compilers and the “keiluvison” is best
suitable for microcontroller programming development. Microcontrollers or processors can
understand only binary language in the form of ‘0s or 1s’; An assembler converts the assembly language
to binary language, and then stores it in the microcontroller memory to perform the specific task.

8051 Microcontroller Architecuture

The 8051 microcontroller is the CISC based Harvard architecture, and it has peripherals like 32 I/O,
timers/counters, serial communication and memories. The microcontroller requires a program to
perform the operations that require a memory for saving and to read the functions. The
8051 microcontroller consists of RAM and ROM memories to store instructions.

8051 Microcontroller Architecuture

A Register is the main part in the processors and microcontrollers which is contained in the memory
that provides a faster way of collecting and storing the data. The 8051 assembly language
programming is based on the memory registers. If we want to manipulate data to a processor or
controller by performing subtraction, addition, etc., we cannot do that directly in the memory, but it
needs registers to process and to store the data. Microcontrollers contain several types of registers that
can be classified according to their instructions or content that operate in them.
8051 Microcontroller Programs in Assembly Language

The assembly language is made up of elements which all are used to write the program in sequential
manner. Follow the given rules to write programming in assembly language.
Rules of Assembly Language

• The assembly code must be written in upper case letters


• The labels must be followed by a colon (label:)
• All symbols and labels must begin with a letter
• All comments are typed in lower case
• The last line of the program must be the END directive

The assembly language mnemonics are in the form of op-code, such as MOV, ADD, JMP, and so on,
which are used to perform the operations.
USING C
Flash 8051 microcontroller
3. Flash/EEPROM Programming
The AT89LP51xx2 microcontroller does not support high-voltage parallel programming. Instead an
SPI-based interface compatible with other AT89LP devices is provided. Users with third-party
parallel programmers will need to update their programmer with the appropriate AT89LP51xx2 serial
driver if available. However, the serial bootloader protocol is compatible with the existing
AT89C51xx2. Existing bootloader-based programmers will be able to program the AT89LP51xx2
with an AT89C51xx2 driver, although it is recommended that drivers be updated to make use of the
new features on the AT89LP51xx2. The flash programming differences are summarized in
Table 3-1
Note: 1
The device signature is stored in the Atmel Signature Array on AT89LP51xx2 and in the XROW on
AT89C51xx2. Locations 30-31H and 60-61H have the same signature value in both AT89C51xx2 and
AT89LP51xx2. Locations 00-02H are provided for compatibility with other AT89LP devices
Users migrating from AT89C51xx2 to AT89LP51xx2 devices will notice the following changes to the
programming interface:
the programming interface:
1. The Hardware Security Byte (HSB) is accessible only through the Bootloader interface. The SPI-
based interface accesses these bits individually
. 2. The Bootloader configuration bytes (BSB, SSB and SBV) are located in the User Signature
space at different addresses than AT89C51xx2. This affects only the SPI-based interface and not
the Bootloader.

3. The AT89LP51xx2 has a half-page buffer of 64 bytes. Therefore Page mode commands accept
only 64 bytes of data. However, Bootloader programming still allows a full 128 bytes to be sent.

4. Individual reprogramming of bytes is not possible. On AT89LP51xx2 one page is the smallest
erasable quantity whereas on AT89C51xx2 it was one byte. Programming algorithms must erase
and write an entire page when even only a single byte needs to change. This affects only the SPI-
based interface and not the Bootloader; however, the bootloader is most efficient when working
with full pages. Table 3-1. Summary of Programming Differences on AT89LP51xx2 Feature
AT89C51xx2 AT89LP51xx2 High-Voltage Parallel Interface YES NO 4-wire SPI Interface NO
YES Serial UART Bootloader YES YES Reset Polarity Active-High Selectable Flash Page Size
128 128 Flash Page Buffer Size 128 64 Flash Auto-Erase Programming Byte-Level Page-Level
Device Signature Locations(1) 30H, 31H, 60H, 61H 00H, 01H, 02H, 30H, 31H, 60H, 61H User
Signature Array 0 512 bytes EEPROM Data Memory 2KB 4KB EEPROM Page Size 1 32 User
Configuration Fuses 4 19 4 3716A–MICRO–10/11 Migrating from 89C51xx2 to 89LP51xx2

5. The Data[1] byte of the Program OSC Fuse command is changed from 20h on
AT89C51IC2/ID2 to 10h on AT89LP51IC2/ID2.
6. The AT89LP51xx2 has a selectable polarity RST pin. Existing AT89C51xx2 drivers expect the
reset to have active-high polarity. In most existing applications the EA pin is tied high, so dropping
in an AT89LP51xx2 will result in an active-high reset. See Section
“Reset” on page 12.
In addition to the above changes, the AT89LP51xx2 also supports the following new features:

1. The AT89LP51xx2 includes a User Signature Array for storing up to 512 bytes of user ID,
revision, configuration or other nonvolatile information. This information can be read/written
from the application code. The BSB, SBV and SSB bytes are stored in this array. The full array
is accessible to the SPI interface; however, only the first 256 bytes can be programmed through
the Bootloader.

2. The AT89LP51xx2 supports 19 User Configuration Fuses for configuring the default behavior
of the device. See Section 3.1 for more information. The fuses beyond the 4 used by the
AT89C51xx2 are not accessible by the Bootloader. These fuses may require configuration
before placing the device in system.

3. SPI-programming can be disabled during warm resets by clearing the ISP Enable Fuse. When
this fuse is disabled, programming is only available by asserting RST at powerup (cold reset).
This
4. The AT89LP51ED2/ID2 supports page programming of the EEPROM with up to 32 bytes
written per operation0

Programming with Arithmetic logic


instructions (Assembly) 2.
he INC Instruction
The INC instruction is used for incrementing an operand by one. It works on a single operand
that can be either in a register or in memory.
Syntax
The INC instruction has the following syntax −
INC destination
The operand destination could be an 8-bit, 16-bit or 32-bit operand.
Example
INC EBX ; Increments 32-bit register
INC DL ; Increments 8-bit register
INC [count] ; Increments the count variable

The DEC Instruction


The DEC instruction is used for decrementing an operand by one. It works on a single operand
that can be either in a register or in memory.
Syntax
The DEC instruction has the following syntax −
DEC destination
The operand destination could be an 8-bit, 16-bit or 32-bit operand.
Example
segment .data
count dw 0
value db 15

segment .text
inc [count]
dec [value]

mov ebx, count


inc word [ebx]

mov esi, value


dec byte [esi]

The ADD and SUB Instructions


The ADD and SUB instructions are used for performing simple addition/subtraction of binary
data in byte, word and doubleword size, i.e., for adding or subtracting 8-bit, 16-bit or 32-bit
operands, respectively.
Syntax
The ADD and SUB instructions have the following syntax −
ADD/SUB destination, source
The ADD/SUB instruction can take place between −

• Register to register
• Memory to register
• Register to memory
• Register to constant data
• Memory to constant data
However, like other instructions, memory-to-memory operations are not possible using
ADD/SUB instructions. An ADD or SUB operation sets or clears the overflow and carry flags.
Example
The ADD/SUB instruction can take place between −

• Register to register
• Memory to register
• Register to memory
• Register to constant data
• Memory to constant data
However, like other instructions, memory-to-memory operations are not possible using
ADD/SUB instructions. An ADD or SUB operation sets or clears the overflow and carry flags.
Example
SYS_EXIT equ 1
SYS_READ equ 3
SYS_WRITE equ 4
STDIN equ 0
STDOUT equ 1

segment .data

msg1 db "Enter a digit ", 0xA,0xD


len1 equ $- msg1

msg2 db "Please enter a second digit", 0xA,0xD


len2 equ $- msg2

msg3 db "The sum is: "


len3 equ $- msg3

segment .bss

num1 resb 2
num2 resb 2
res resb 1

section .text
global _start ;must be declared for using gcc

_start: ;tell linker entry point


mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, msg1
mov edx, len1
int 0x80

mov eax, SYS_READ


mov ebx, STDIN
mov ecx, num1
mov edx, 2
int 0x80

mov eax, SYS_WRITE


mov ebx, STDOUT
mov ecx, msg2
mov edx, len2
int 0x80

mov eax, SYS_READ


mov ebx, STDIN
mov ecx, num2
mov edx, 2
int 0x80

mov eax, SYS_WRITE


mov ebx, STDOUT
mov ecx, msg3
mov edx, len3
int 0x80

; moving the first number to eax register and second number to ebx
; and subtracting ascii '0' to convert it into a decimal number

mov eax, [num1]


sub eax, '0'

mov ebx, [num2]


sub ebx, '0'

; add eax and ebx


add eax, ebx
; add '0' to to convert the sum from decimal to ASCII
add eax, '0'

; storing the sum in memory location res


mov [res], eax
; print the sum
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, res
mov edx, 1
int 0x80

exit:

mov eax, SYS_EXIT


xor ebx, ebx
int 0x80

The MUL/IMUL Instruction


There are two instructions for multiplying binary data. The MUL (Multiply) instruction handles
unsigned data and the IMUL (Integer Multiply) handles signed data. Both instructions affect
the Carry and Overflow flag.
Syntax
The syntax for the MUL/IMUL instructions is as follows −
MUL/IMUL multiplier
Multiplicand in both cases will be in an accumulator, depending upon the size of the
multiplicand and the multiplier and the generated product is also stored in two registers
depending upon the size of the operands. Following section explains MUL instructions with
three different cases −

The DIV/IDIV Instructions


The division operation generates two elements - a quotient and a remainder. In case of
multiplication, overflow does not occur because double-length registers are used to keep the
product. However, in case of division, overflow may occur. The processor generates an
interrupt if overflow occurs.
The DIV (Divide) instruction is used for unsigned data and the IDIV (Integer Divide) is used
for signed data.
Syntax
The format for the DIV/IDIV instruction −
DIV/IDIV divisor
The dividend is in an accumulator. Both the instructions can work with 8-bit, 16-bit or 32-bit
operands. The operation affects all six status flags. Following section explains three cases of
division with different operand size −

Assembly - Logical Instructions


Previous Page
Next Page
The processor instruction set provides the instructions AND, OR, XOR, TEST, and NOT
Boolean logic, which tests, sets, and clears the bits according to the need of the program.
The format for these instructions −

The first operand in all the cases could be either in register or in memory. The second operand
could be either in register/memory or an immediate (constant) value. However, memory-to-
memory operations are not possible. These instructions compare or match bits of the operands
and set the CF, OF, PF, SF and ZF flags.

The AND Instruction


The AND instruction is used for supporting logical expressions by performing bitwise AND
operation. The bitwise AND operation returns 1, if the matching bits from both the operands
are 1, otherwise it returns 0. For example −
Operand1: 0101
Operand2: 0011
----------------------------
After AND -> Operand1: 0001
The AND operation can be used for clearing one or more bits. For example, say the BL register
contains 0011 1010. If you need to clear the high-order bits to zero, you AND it with 0FH.
AND BL, 0FH ; This sets BL to 0000 1010
Let's take up another example. If you want to check whether a given number is odd or even, a
simple test would be to check the least significant bit of the number. If this is 1, the number is
odd, else the number is even.
Assuming the number is in AL register, we can write −
AND AL, 01H ; ANDing with 0000 0001
JZ EVEN_NUMBER
The following program illustrates this −
The OR Instruction
The OR instruction is used for supporting logical expression by performing bitwise OR
operation. The bitwise OR operator returns 1, if the matching bits from either or both operands
are one. It returns 0, if both the bits are zero.
For example,
Operand1: 0101
Operand2: 0011
----------------------------
After OR -> Operand1: 0111
The OR operation can be used for setting one or more bits. For example, let us assume the AL
register contains 0011 1010, you need to set the four low-order bits, you can OR it with a value
0000 1111, i.e., FH.
OR BL, 0FH ; This sets BL to 0011 1111

The XOR Instruction


The XOR instruction implements the bitwise XOR operation. The XOR operation sets the
resultant bit to 1, if and only if the bits from the operands are different. If the bits from the
operands are same (both 0 or both 1), the resultant bit is cleared to 0.
For example,
Operand1: 0101
Operand2: 0011
----------------------------
After XOR -> Operand1: 0110
XORing an operand with itself changes the operand to 0. This is used to clear a register.
XOR EAX, EAX

The TEST Instruction


The TEST instruction works same as the AND operation, but unlike AND instruction, it does
not change the first operand. So, if we need to check whether a number in a register is even or
odd, we can also do this using the TEST instruction without changing the original number.
TEST AL, 01H
JZ EVEN_NUMBER

The NOT Instruction


The NOT instruction implements the bitwise NOT operation. NOT operation reverses the bits
in an operand. The operand could be either in a register or in the memory.
For example,
Operand1: 0101 0011
After NOT -> Operand1: 1010 1100
Program using constructs (sorting an array) 3.
All programming language utilise program constructs. In imperative languages
they are used to control the order (flow) in which statements are executed (or not
executed). There are a number of recognised basic programming constructs that
can be classified as follows:

• Sequences (First Floor)


• Selection (Second Floor)
• Repetition (Third Floor)
To which we can also add routine invocation (Fourth Floor). Note also that each of
the above constructs are all also program statements in their own right.

A sequence construct tells the processor which statement is to be executed next. By


default, in imperative languages, this is the statement following the current
statement (or the first statement in the program). If we wish to "jump" to some
other statement we can use a goto statement. This was popular in the early days of
computer programming (1950's to early 1960's). Example BASIC go to statement:
GOTO 400

This tells the processor to "jump" to line 400 and to then continue processing from
this point in the program. The use of go to statements was also encouraged by
languages such as Fortran and Cabo

A selection statement provides for selection between alternatives. We can identify


three types of selection construct:

1. If statements
2. Case statements
3. Pattern matching

However, imperative languages do not generally make much use of pattern


matching (logic and some modern functional languages do), thus we will limit the
following discussion to the "if" and "case" forms of selection.

IF STATEMENT
An if statement, sometimes referred to as a conditional, can be used in two forms:

1. If condition then action1


2. If condition then action1 else action2

Where X is a Boolean expression (or a sequence of Boolean expression),


and Y and Z are program statements of some description. We can also identify a
number of variations of the above which are particular to individual programming
languages. For example the Ada:
if X1 then Y1 elsif X2 then Y2 ... elsif Xn then Yn else Yn+1 end if

Case Statement
Generally speaking an "if ... then ... else ..." statement supports selection from only two
alternatives; we can of course nest such statements, but it is usually more succinct to use
a case statement. Case statements allow selection from many alternatives where each
alternative is linked to a predicate, referred to as a selector, which when evaluated to true
causes an associated program statement (or statements) to be executed. Selections may be
made according to:

1. A distinct value of a given selector.


2. An expression involving the selector.
3. A default value.

Selectors must be of a discrete type (typically an integer, a character or an enumerated type).


C only supports selection by distinct value or default (default). Ada also supports selection by
distinct value and default (others), as well as selection according to:

1. A number of Alternatives (each separated by a bar |).


2. Ranges expressed using the .. operator.
3. Selection by condition *e.g. <, =, >).

Also note that where selection is by distinct value, in some cases, these must be
presented in the correct numeric order (this is the case in C).
Note that C requires that selectors are presented according to their numeric order.
Note also that neither Ada nor C support selection using expressions involving
selectors, e.g. a conditional expression or an arithmetic expression. This is
supported by languages such as Pascal.
Program using Ports 4.
Delay generation using timer (Assembly
and c) 5.

8051 Timer Programming in Assembly and C

Delay using 8051 Timers


• April 5, 2018
• By Administrator

In this project, I will discuss a little bit about Timers in 8051 Microcontroller and also
how to Generate a Delay using 8051 Timers.

Generation of time delay is most important concept in embedded systems. Most of the
times, we need to generate precise time delay between two actions in any
microcontroller applications. We can generate the time delay using the techniques like
LOOPs or by using in built delay functions.

But these are not precise methods for generating time delay so that we will go for
timers to produce accurate time delay. This concept is similar to Time Delay Relay
concept.

Outline

• Principle behind the Project


• Circuit Diagram
• Components Required
• Circuit Design
• 8051 Timers Register Description
o TMOD Register
o TCON Register
• Steps for generating precise Delay using 8051 Timers
• Delay Function to Generate 1 ms Delay
• Code for LED Blinking using Timers
• Circuit Simulation Video
• How to Operate?
• Circuit Applications
• Output Video

Principle behind the Project


Most of the controllers have inbuilt timers. These timers are not only used for
generating time delay but also used for counting purpose. The value of the counter is
incremented by 1 when an action or an event occurs.

Timers on the other hand are used to generate delays. Timers in a microcontroller are
controlled by the SFRs (Special Function Registers). Timers in different mode of
operations are configured by special function registers.

The main principle behind this project is to generate a Delay using 8051 Timers with
the help of its Special Function Registers.

Get an idea about How to Interface DC Motor with 8051 Microcontroller?


Circuit Diagram
Even though external components (except the oscillator) do not have much in
generating delay, I have made a simple circuit, where I will be Blinking an LED ON
and OFF with a Delay of 1 second and this delay will be generated with the help of
8051 Timers.
Components Required
• AT89C51 Microcontroller
• 8051 Programmer
• Programming Cable
• LED
• 330Ω Resistor
• 2 – 10KΩ Resistor
• 10μF/16V Capacitor
• 2 – 33pF Capacitors
• 11.0592MHz Crystal
• Push Button

Circuit Design
The major component in this circuit is AT89C51 controller. A reset circuit for 8051
Microcontroller is made up of a Push Button, a 10KΩ Resistor and a 10μF Capacitor.

A 11.0592MHz uartz Crystal and two 33pF Ceramic Capacitors form the oscillator
circuit of the 8051 Microcontroller and are connected to Pins 18 and 19.

Finally, an LED is connected to the P2.0 through a 330Ω resistor to indicate the time
delay.

8051 Timers Register Description


TMOD Register

The upper nibble (TMOD.7 to TMOD.4) is used to configure timer1 and the lower
nibble (TMOD.3 to TMOD.0) is used to configure timer0.

GATE: If this pin is high, then corresponding timer is enabled when there is an
interrupt at corresponding INT pin of the microcontroller.

C/T: This pin is used to select timer or counter. If this pin is high, then used as a
counter to count the external event. If this pin is low, then used as a timer to produce
time delay.

M1 and M0: These bits are used to select the different timer modes.
13 Bit Timer: This mode uses 8 bits from high byte and remaining 5 bits from low
byte. The value of the timer in this mode is from 0000H to 1FFFH

16 Bit Timer: This mode is most commonly used for producing the time delay. In this
mode all the 16 bits are used for timer and values vary from 0000H to FFFFH.

If the value XXXXH is loaded into the timer register, then the produced time delay is
equal to the [(FFFFH – XXXXH+1)*(period of one clock pulse)].

The time period of one clock pulse is equal to the 1.085μs 11.0592 MHz frequency.

8-bit Auto Reload: In this mode, initial value is loaded in to the high byte and the
same value is loaded into the low byte. Timer value is from 00H to FFH. This mode is
used to set the baud rates for serial communication.

Split Mode: In this mode timer is divided in to two 8 bit timers. These 8 bit timers
can count from 00H to FFH. This mode is used in the applications where we require
an additional 8 bit timer or counter.

TCON Register
It is a special function register used to control the timer operation. In this register only
upper nibble is used to control the timer and remaining bits are used for interrupt
control.
• TF1: This bit is set to 1 automatically on the timer 1 overflow.
• TR1: This bit is used to enable the timer 1. This pin must be high to enable the
timer1.
• TF0: set to one automatically when timer0 overflows.
• TR0: place 1 in this bit to enable the timer 0.

Steps for generating precise Delay using 8051 Timers


In order to produce time delay accurately,

1. Divide the time delay with timer clock period.


NNNN=time delay/1.085μs

2. Subtract the resultant value from 65536.


MMMM=65536-NNNN

3. Convert the difference value to the hexa decimal form.


MMMMd = XXYYh

4. Load this value to the timer register.


TH=XXh

TL=YYh

Delay Function to Generate 1 ms Delay


In order to generate a delay of 1ms, the calculations using above steps are as follows.
1. NNNN = 1ms/1.085μs ≈ 922.
2. MMMM = 65536-922 = 64614
3. 64614 in Hexadecimal = FC66h
4. Load TH with 0xFC and TL with 0x66
The following function will generate a delay of 1 ms using 8051 Timer 0.

Void delay ()

TMOD = 0x01; // Timer 0 Mode 1

TH0= 0xFC; //initial value for 1ms

TL0 = 0x66;

TR0 = 1; // timer start

while (TF0 == 0); // check overflow condition

TR0 = 0; // Stop Timer

TF0 = 0; // Clear flag

view raw8051_Delay_using_Timer_1ms.c hosted with ❤ by GitHub

Code for LED Blinking using Timers


To demonstrate the functioning of the delay using 8051 Timers, I will blink an LED
with a period of 2 seconds i.e. LED will be ON for 1 second and OFF for 1 second.
/* The delay function will generate a delay of 1mS.

For the purpose of demonstration, I've called it a 1000 times using

for loop so that I get a delay of 1 second.

*/

#include<reg51.h>

#define ON 1

#define OFF 0

sbit led=P2^0;

unsigned int i=0;

void delay();

void delay()

TMOD = 0x01; // Timer0 mode1

TH0 = 0xFC; //initial value for 1ms

TL0 = 0x66;

TR0 = 1; // timer start

while(TF0==0); // check overflow condition

TR0 = 0; // Stop Timer

TF0 = 0; // Clear flag

void main()
{

while(1)

led = ON;

for(i=0;i<1000;i++)

delay();

led = OFF;

for(i=0;i<1000;i++)

delay();

view raw8051_Delay_using_Timer.c hosted with ❤ by GitHub

Circuit Simulation Video


How to Operate?
1. Initially burn the program to the AT89C51 controller
2. Give the connections as per the circuit diagram
3. Switch on the supply, now you can observe the toggling of LED with some
time delay.
4. If you connect the output to an oscilloscope you can observe the square wave.

Circuit Applications
• Used in embedded system applications where we want precise time Delay.
• This system used to generate square wave.
• Used in Ultrasonic module applications.
Programming Interrupts (Assembly and c) 6.
what-when-how
In Depth Tutorials and Information
INTERRUPT PROGRAMMING IN C
SECTION 11.6: INTERRUPT PROGRAMMING IN C

So far all the programs in this chapter have been written in Assembly. In this section we show how to
program the 8051/52′s interrupts in 8051 C language. In reading this section, it is assumed that you
already know the material in the first two sections of this chapter.

8051 C interrupt numbers

The 8051 C compilers have extensive support for the 8051 interrupts with two major features as follows:

1. They assign a unique number to each of the 8051 interrupts, as shown in Table
11-4.
2. It can also assign a register bank to an ISR. This avoids code overhead due to
the pushes and pops of the RO – R7 registers.
Table 11-4: 8051/52 Interrupt Numbers in C

Example 11-14 shows how a simple interrupt is written in 8051 C.

Example 11-14

Write a C program that continuously gets a single bit of data from PI. 7 and sends it to Pl.O, while
simultanepusly creating a square wave of 200 (as period on pin P2.5. Use timer 0 to create the square
wave. Assume that XTAL = 11.0592 MHz.
Solution:

Example 11-15
Write a C program that continuously gets a single bit of data from PI. 7 and sends it to Pl.O in the main,
while simultaneously (a) creating a square wave of 200 us period on pin P2.5, and (b) sending letter ‘A’
to the serial port. Use Timer 0 to create the square wave. Assume that XTAL = 11.0592 MHz. Use the
9600 baud rate.

Solution:
Example 11-16

Write a C program using interrupts to do the following:

1. Receive data serially and send it to PO,


2. Read port PI, transmit data serially, and give a copy to P2,
3. Make timer 0 generate a square wave of 5 kHz frequency on PO.l.
Assume that XTAL = 11.0592 MHz. Set the baud rate at 4800.
Solution:
Example 11-17

Write a C program using interrupts to do the following:

1. Generate a 10000 Hz frequency on P2.1 using TO 8-bit auto-reload,


Use timer 1 as an event counter to count up a 1-Hz pulse and display it on PO. The
pulse is connected to EX1.
Assume that XTAL = 11.0592 MHz. Set the baud rate at 9600.

SUMMARY

An interrupt is an external or internal event that interrupts the microcontroller to inform it that a device
needs its service. Every interrupt has a program associated with it called the ISR, or interrupt service
routine. The 8051 has 6 interrupts, 5 of which are user-accessible. The interrupts- are for reset: two for
the timers, two for external hardware interrupts, and a serial communication interrupt. The 8052 has an
additional interrupt for Timer 2.

The 8051 can be programmed to enable or disable an interrupt, and the interrupt priority can be altered.
This chapter showed how to program 8051/52 interrupts in both Assembly and C languages.
Implementation of standard UART
communication (using hyper terminal) 7.
In this tutorial we learn to Enable UART communication with PIC Microcontroller
and how to transfer data to and from your Computer. So far, we have covered all
basic modules like ADC, Timers, PWM and also have learnt how to interface
LCDs and 7-Segment displays. Now, we will equip our self with a new communication
tool called UART which widely used in most of the Microcontroller projects. Check
here our complete PIC Microcontroller Tutorials using MPLAB and XC8.

Here we have used PIC16F877A MCU, it has a module called “Addressable


Universal Synchronous Asynchronous Receiver and Transmitter” shortly known
as USART. USART is a two wire communication system in which the data flow
serially. USART is also a full-duplex communication, means you can send and receive
data at the same time which can be used to communicate with peripheral devices, such
as CRT terminals and personal computers.

The USART can be configured in the following modes:

• Asynchronous (full-duplex)
• Synchronous – Master (half-duplex)
• Synchronous – Slave (half-duplex)

There are also two different modes namely the 8-bit and 9-bit mode, in this tutorial we
will configure the USART module to work in Asynchronous mode with 8-bit
communication system, since it is the most used type of communication. As it is
asynchronous it doesn't need to send clock signal along with the data signals. UART
uses two data lines for sending (Tx) and receiving (Rx) data. The ground of both devices
should also be made common. This type of communication does not share a common
clock hence a common ground is very important for the system to work.

At the end of this tutorial you will be able establish a communication (UART)
between your computer and your PIC Microcontroller and toggle an LED on the
PIC board from your laptop. The status of the LED will be sent to your laptop from the
PIC MCU. We will test the output using Hyper Terminal in computer. Detailed Video
is also given at the end of this tutorial.

Requirements:
Hardware:

• PIC16F877A Perf Board


• RS232 to USB converter Module
• Computer
• PICkit 3 Programmer

Software:

• MPLABX
• HyperTerminal

A RS232 to USB converter is required to convert the serial data into computer readable
form. There are ways to design your own circuit instead of buying your own module
but they are not reliable as they are subjected noise. The one which we are using is
shown below

Note: Each RS232 to USB converter would require a special driver to be installed; most
of them should get installed automatically as soon as you plug in the device. But, if it
doesn’t relax!!! Use the comment section and I will help you out.

Programming PIC Microcontroller for UART Communication:


Like all modules (ADC, Timer, PWM) we should also initialize our USART module of
our PIC16F877A MCU and instruct it to work in UART 8-bit communication
mode. Let’s define the configuration bits and start with the UART initialization
function.

Initializing the UART module of the PIC Microcontroller:


The Tx and Rx pins are physically present at the pins RC6 and RC7. According
to datasheet let’s declare TX as output and RX as input.

//****Setting I/O pins for UART****//


TRISC6 = 0; // TX Pin set as output
TRISC7 = 1; // RX Pin set as input
//________I/O pins set __________//

Now the baud rate has to be set. The baud rate is the rate at which information is
transferred in a communication channel. This can be one of the many default values,
but in this program we are using 9600 since its the most used baud rate.

/**Initialize SPBRG register for required


baud rate and set BRGH for fast baud_rate**/
SPBRG = ((_XTAL_FREQ/16)/Baud_rate) - 1;
BRGH = 1; // for high baud_rate
//_________End of baud_rate setting_________//

The value of the baud rate has to be set using the register SPBRG, the value depends
on the value of the External crystal frequency, the formulae to calculate the baud rate is
shown below:

SPBRG = ( ( _XTAL_FREQ/16 ) / Baud_rate) – 1;

The bit BRGH has to be made high to enable high speed bit rate. According to datasheet
(page 13) it is always advantageous to enable it, as it can eliminate errors during
communication.

As said earlier we will be working in Asynchronous mode, hence the bit SYNC should
be made zero and bit SPEM must be made high to enable serial pins (TRISC6 and
TRICSC5)

//****Enable Asynchronous serial port*******//


SYNC = 0; // Asynchronous
SPEN = 1; // Enable serial port pins
//_____Asynchronous serial port enabled_______//

In this tutorial we will be both sending and receiving data between MCU and computer
hence we have to enable both TXEN and CREN bits.

//**Lets prepare for transmission & reception**//


TXEN = 1; // enable transmission
CREN = 1; // enable reception
//__UART module up and ready for transmission and reception__//

The bits TX9 and RX9 have to be made zero so that we operate in 8-bit mode. If there
has to be high reliability need to be established then 9-bit mode can be selected.

//**Select 8-bit mode**//


TX9 = 0; // 8-bit reception selected
RX9 = 0; // 8-bit reception mode selected
//__8-bit mode selected__//

With this we complete our initialization setup. Now the Module is configured as
UART and is ready for operation.

Transmitting data using UART:

The below function can be used to transmit data through the UART module:

//**Function to send one byte of date to UART**//


void UART_send_char(char bt)
{
while(!TXIF); // hold the program till TX buffer is free
TXREG = bt; //Load the transmitter buffer with the received value
}
//_____________End of function________________//

Once the module is initialized whatever value is loaded into the register TXREG will
be transmitted through UART, but transmission might overlap. Hence we should always
check for the Transmission Interrupt flag TXIF. Only if this bit is low we can proceed
with the next bit for transmission else we should wait for this flag to get low.

However, above function can be used only to send only one byte of data, to send a
complete a string the below function should be used

//**Function to convert string to byte**//


void UART_send_string(char* st_pt)
{
while(*st_pt) //if there is a char
UART_send_char(*st_pt++); //process it as a byte data
}
//___________End of function______________//
This function might be a bit tricky to understand since it has pointers, but trust me
pointers are wonderful and they make programming more easy and this is one good
example of the same.

As you can notice we have again called the UART_send_char() but now inside the while
loop. We have split the string into individual characters, each time this function is
called, one char will be sent to the TXREG and it will get transmitted.

Receiving data using UART:

The following function can be used to receive data from the UART module:

//**Function to get one byte of date from UART**//


char UART_get_char()
{
if(OERR) // check for Error
{
CREN = 0; //If error -> Reset
CREN = 1; //If error -> Reset
}

while(!RCIF); // hold the program till RX buffer is free

return RCREG; //receive the value and send it to main function


}
//_____________End of function________________//

When a data is received by the UART module it picks it up and stores it up in


the RCREG register. We can simply transfer the value to any variable and use it. But
there might be overlap error or the user might be sending data continuously and we have
not yet transferred them to a variable.

In that case the Receive flag bit RCIF comes to rescue. This bit will go low whenever
a data is received and is not yet processed. Hence we use it in the while loop creating a
delay to hold the program till we deal with that value.

Toggling LED using the UART module of PIC Microcontroller:

Now let us come to the final part of the Program, the void main(void) function, where
we will be toggling a LED through the computer using the UART communication
between PIC and computer.
When we send a character “1” (from computer) the LED will be turned ON and the
status message “RED LED -> ON” will be sent back (from PIC MCU) to the computer.

Similarly we send a character “0” (from computer) the LED will be turned OFF and the
status message “RED LED -> OFF” will be sent back (from PIC MCU) to the
computer.

while(1) //Infinite loop


{
get_value = UART_get_char();

if (get_value == '1') //If the user sends "1"


{
RB3=1; //Turn on LED
UART_send_string("RED LED -> ON"); //Send notification to the computer
UART_send_char(10);//ASCII value 10 is used for carriage return (to print in new line)
}

if (get_value == '0') //If the user sends "0"


{
RB3=0; //Turn off LED
UART_send_string("RED -> OFF"); //Send notification to the computer
UART_send_char(10);//ASCII value 10 is used for carriage return (to print in new line)
}
}

Simulating our program:


As usual let’s simulate our program using proteus and find out if it works as expected.
The above image shows a virtual terminal in which one it shows a welcome message
and status of the LED. The Red Color LED can be noticed to be connected to the pin
RB3. The detailed working of the simulation can be found in the Video at the end.
Interfacing LCD Display 8.
16×2 Character LCD is a very basic LCD module which is commonly used in electronics
projects and products. It contains 2 rows that can display 16 characters. Each character is
displayed using 5×8 or 5×10 dot matrix. It can be easily interfaced with a microcontroller. In
this tutorial we will see how to write data to an LCD with PIC Microcontroller using Hi-Tech
C Compiler. Hi-Tech C has no built in LCD libraries so we require the hardware knowledge of
LCD to control it. Commonly used LCD Displays uses HD44780 compliant controllers.

16×2 LCD
Pin Diagram

This is the pin diagram of a 16×2 Character LCD display. As in all devices it also has two
inputs to give power Vcc and GND. Voltage at VEE determines the Contrast of the display. A
10K potentiometer whose fixed ends are connected to Vcc, GND and variable end is connected
to VEE can be used to adjust contrast. A microcontroller needs to send two informations to
operate this LCD module, Data and Commands. Data represents the ASCII value (8 bits) of
the character to be displayed and Command determines the other operations of LCD such as
position to be displayed. Data and Commands are send through the same data lines, which are
multiplexed using the RS (Register Select) input of LCD. When it is HIGH, LCD takes it as
data to be displayed and when it is LOW, LCD takes it as a command. Data Strobe is given
using E (Enable) input of the LCD. When the E (Enable) is HIGH, LCD takes it as valid data
or command. The input signal R/W (Read or Write) determines whether data is written to or
read from the LCD. In normal cases we need only writing hence it is tied to GROUND in
circuits shown below.

The interface between this LCD and Microcontroller can be 8 bit or 4 bit and the difference
between them is in how the data or commands are send to LCD. In the 8 bit mode, 8 bit data
and commands are send through the data lines DB0 – DB7 and data strobe is given through E
input of the LCD. But 4 bit mode uses only 4 data lines. In this 8 bit data and commands are
splitted into 2 parts (4 bits each) and are sent sequentially through data lines DB4 – DB7 with
its own data strobe through E input. The idea of 4 bit communication is introduced to save pins
of a microcontroller. You may think that 4 bit mode will be slower than 8 bit. But the speed
difference is only minimal. As LCDs are slow speed devices, the tiny speed difference between
these modes is not significant. Just remember that microcontroller is operating at high speed in
the range of MHz and we are viewing LCD with our eyes. Due to Persistence of Vision of our
eyes we will not even feel the speed difference.
Hope that you got rough idea about how this LCD Module works. Actually you need to read
the datasheet of HD44780 LCD driver used in this LCD Module to write a Hi-Tech C program
for PIC. But we solved this problem by creating a header file lcd.h which includes all the
commonly used functions. Just include it and enjoy.

Functions in lcd.h

Lcd8_Init() & Lcd4_Init() : These functions will initialize the LCD Module connected to the
following defined pins in 8 bit and 4 bit mode respectively.

8 Bit Mode :

#define RS RB6
#define EN RB7
#define D0 RC0
#define D1 RC1
#define D2 RC2
#define D3 RC3
#define D4 RC4
#define D5 RC5
#define D6 RC6
#define D7 RC7

4 Bit Mode :

#define RS RB2
#define EN RB3
#define D4 RB4
#define D5 RB5
#define D6 RB6
#define D7 RB7

These connections must be defined for the working of LCD library.

Lcd8_Clear() & Lcd4_Clear() : Calling these functions will clear the LCD Display when
interfaced in 8 Bit and 4 Bit mode respectively.

Lcd8_Set_Cursor() & Lcd4_Set_Cursor() : These functions set the row and column of the
cursor on the LCD Screen. By using this we can change the position of the character being
displayed by the following functions.

Lcd8_Write_Char() & Lcd4_Write_Char() : These functions will write a character to the


LCD Screen when interfaced through 8 Bit and 4 Bit mode respectively.
Lcd8_Write_String() & Lcd4_Write_String() : These functions are used to write strings to
the LCD Screen.

Lcd8_Shift_Left() & Lcd4_Shift_Left() : These functions are used to shift the content on the
LCD Display left without changing the data in the display RAM.

Lcd8_Shift_Right() & Lcd4_Shift_Right() : Similar to above functions, these are used to


shift the content on the LCD Display right without changing the data in the display RAM.

8 Bit Mode

Circuit Diagram

Interfacing LCD with PIC Microcontroller – 8 Bit Mode

Hi-Tech C Code

#include<htc.h>
#include<pic.h>

#define RS RB6
#define EN RB7
#define D0 RC0
#define D1 RC1
#define D2 RC2
#define D3 RC3
#define D4 RC4
#define D5 RC5
#define D6 RC6
#define D7 RC7

#define _XTAL_FREQ 8000000

#include "lcd.h"

void main()
{
int i;
TRISB = 0x00;
TRISC = 0x00;
Lcd8_Init();
while(1)
{
Lcd8_Set_Cursor(1,1);
Lcd8_Write_String("electroSome LCD Hello World");
for(i=0;i<15;i++)
{
__delay_ms(1000);
Lcd8_Shift_Left();
}
for(i=0;i<15;i++)
{
__delay_ms(1000);
Lcd8_Shift_Right();
}
Lcd8_Clear();
Lcd8_Set_Cursor(2,1);
Lcd8_Write_Char('e');
Lcd8_Write_Char('S');
__delay_ms(2000);
}
}
4 Bit Mode

Circuit Diagram

Interfacing LCD with PIC Microcontroller – 4 Bit Mode

Hi-Tech C Code

#include<htc.h>
#include<pic.h>

#define RS RB2
#define EN RB3
#define D4 RB4
#define D5 RB5
#define D6 RB6
#define D7 RB7
#define _XTAL_FREQ 8000000
#include "lcd.h"
void main()
{
int i;
TRISB = 0x00;
Lcd4_Init();
while(1)
{
Lcd4_Set_Cursor(1,1);
Lcd4_Write_String("electroSome LCD Hello World");
for(i=0;i<15;i++)
{
__delay_ms(1000);
Lcd4_Shift_Left();
}
for(i=0;i<15;i++)
{
__delay_ms(1000);
Lcd4_Shift_Right();
}
Lcd4_Clear();
Lcd4_Set_Cursor(2,1);
Lcd4_Write_Char('e');
Lcd4_Write_Char('S');
__delay_ms(2000);
}
}
Interfacing LCD Keypad 9.
LCD (LIQUID CRYSTAL DISPLAY) INTERFAC

LCDs can display numbers, characters, and graphics. To produce a proper display, the information
has to be periodically refreshed. This can be done by the CPU or internally by the LCD device itself.
Incorporating a refreshing controller into the LCD, relieves the CPU of this task and hence many
LCDs have built-in controllers. These controllers also facilitate flexible programming for characters
and graphics. Table 5.1 shows the pin description of an LCD. from Optrex.

• Vss and VDD provide +5v and ground, V0 is used for controlling LCD contrast.

• If RS=0, the instruction command register is selected, allowing the user to send a command such as
clear display, cursor at home, etc.

• If RS=1 the data register is selected, allowing the user to send data to be displayed on the LCD.

• R/W input allows the user to Read/ Write the information to the LCD.

• The enable pin is used by the LCD to latch information presented to its data pins.

• The 8-bit data pins are used to send information to LCD.

• Section 5.1 discusses about command codes for writing the instructions on the LCD register.
Section 5.2 gives an example program for displaying a character on the LCD.
LCD COMMAND CODES
The LCD’s internal controller can accept several commands and modify the display accordingly.
These commands would be things like:

✓ Clear screen

✓ Return home

✓ Decrement/Increment cursor
After writing to the LCD, it takes some time for it to complete its internal operations. During this
time, it will not accept any new commands or data. Figure 5.4.1 shows the command codes of LCD
and Figure 5.4.2 shows the LCD interfacing. We need to insert a time delay between any two
commands or data sent to LCD.

PROGRAM TO DISPLAY CHARACTERS ON LCD


To send any of the commands to the LCD, make pin RS=0. For data, make RS=1. Then send a high-
to-low pulse to the E pin to enable the internal latch of the LCD. This is shown in the code below.
;calls a time delay before sending next data/command
;P1.0-P1.7 are connected to LCD data pins D0-D7
;P2.0 is connected to RS pin of LCD
;P2.1 is connected to R/W pin of LCD
;P2.2 is connected to E pin of LCD
KEYBOARD INTERFACING WITH 8051
Keys in a keyboard are arranged in a matrix of rows and columns. The controller access both rows
and columns through ports. Using two ports, we can connect to an 8x8 or a 4x4 matrix keyboard.
When a key is pressed, a row and column make a contact, otherwise there is no contact. We will look
at the details using a 4x4 keyboard.
4X 4 KEYBOARD Figure 5.4.31 shows a 4 x4 matrix connected to two ports.

• The rows are connected to an output port(Port 1) and the columns are connected to an input port.
(Port 2)

• If no key has been pressed, reading the input port will yield 1s for all columns since they are all
connected to high (Vcc).
• If all the rows are grounded and a key is pressed, one of the columns will have 0 since the key
pressed provides the path to ground.

• It is the function of the microcontroller to scan the keyboard continuously to detect and identify the
key pressed.

KEY
SCAN To find out the key pressed , the controller grounds a row by sending a ‘0’ on the
corresponding line of the output port. It then reads the data at the columns using the input port. If data
from columns is D3-D0=1111, then no key is pressed. If any bit of the column is ‘0’, it indicates that
a key is pressed in that column. In this example, the column is identified by the following values:
1110 – key pressed in column
0 1101 – key pressed in column
1 1011 – key pressed in column
2 0111 – key pressed in column 3
STEPS TO FIND OUT KEY PRESSED
Beginning with the row 0, the microcontroller grounds it by providing a low to row D0 only. It then
reads the columns (port2). If the data read is all 1s, then no key in that row is activated and the process
is moved to the next row. It then grounds the next row, reads the columns, and checks for any zero.
This process continues until a row with a zero is identified. After identification of the row in which
the key has been pressed, the column to which the pressed key belongs is identified as discussed
above - by looking for a zero in the input values read. Example:
(a) D3 – D0 = 1101 for the row, D3 – D0 = 1011 for the column, indicate row 1 and column 3 are
selected. This indicates that key 6 is pressed.
(b) D3 – D0 = 1011 for the row, D3 – D0 = 0111 for the column, indicate row 2 and column 3 are
selected. Then key ‘B’ is pressed.
PROGRAM:
The program used for detection and identification of the key activated goes through the following
stages:
1. To make sure that the preceding key has been released, 0s are output to all rows at once, and the
columns are read and checked repeatedly until all the columns are high.
● When all columns are found to be high, the program waits for a short amount of time before it goes
to the next stage of waiting for a key to be pressed. ROHINI COLLEGE OF ENGINEERING &
TECHNOLOGY EC 8691 MICROPROCESSORS AND MICROCONTROLLERS 2. To see if any
key is pressed, the columns are scanned over and over in an infinite loop until one of them has a 0 on
it.
● Remember that the output latch is connected to rows, still have their initial zeros (in stage 1),
making them grounded.
● After the key press detection, it waits for 20-ms for the bounce and then scans the columns again.
i) It ensures that the first key press detection was not an erroneous one due to spike noise.
ii) After the 20-ms delay, if the key is still pressed, then it goes to the loop (step 3) to detect the actual
key pressed.
3. To detect which row the key pressed belongs to, it grounds one row at a time, reading the columns
each time.
• If it finds that all columns are high, this means that the key press does not belong to that row.
Therefore, it grounds the next row and continues until it finds the row, that the key pressed belongs to.
• Upon finding the row that the key pressed belongs to, it sets up the starting address for the lookup
table holding the scan codes for that row.
4 To identify the key pressed, it rotates the column bits, one bit at a time, into the carry flag and
checks to see if it is low.
• Upon finding the zero, it pulls out the ASCII code for that key from the look-up table.

• Otherwise, it increments the pointer to point to the next element of the look-up table. Figure 5.4.4
provides the flowchart for keyboard interfacing Program for scanning and identifying the pressed key.
Programming ADC/DAC 10.
Description
Analog-to-digital conversion (ADC) is necessary because, while embedded
systems deal with digital values, their surroundings typically involve many
analog signals such as, temperature, speed, pressure, the output of a
microphone, etc. They all need to be converted into digital data before being
processed by the microcontroller. Today, we will see how to read an external
analog signal using a PIC16F688 microcontroller, and display the conversion
output (a digital number) on a LCD. The input analog signal will be a varying
voltage between 0-5V derived using a potentiometer.

Required Theory
The PIC16F688 microcontroller has a built-in 10-bit ADC with eight input
channels. The eight channels are available at RA0, RA1, RA2, RA4, RC0, RC1,
RC2, and RC3. They have alternate labels, AN0-AN7, for this function, and are
multiplexed into a single Sample and Hold circuit. The output of the Sample
and Hold is connected to the input of the A/D converter. The 10-bit conversion
result is stored into the ADC result registers ADRESH (A/D Result Higher
byte) and ADRESL (A/D Result Lower byte). Each of these registers is 8-bit.
The functionality of the A/D module is controlled by three registers: ANSEL,
ADCON0, and ADCON1. The details of these control registers are discussed
in ADC channels in PIC16F688.

Circuit Diagram
The test circuit to demonstrate the 10-bit A/D conversion using PIC16F688 is
shown below. The test input voltage for ADC is derived from a 5K
potentiometer connected across the +5V power supply, and is connected to
RA2/AN2 pin of PIC16F688. The supply voltage (+5V) is chosen as the
reference voltage for A/D conversion. Therefore, the 10-bit ADC will convert
any analog voltage between 0-5V to a digital number ranging from 0-1023. The
number will be displayed on the LCD.

This circuit diagram is not much different from the one for our previous lab
(Lab 4: Interfacing a character LCD), except it has a 5K potentiometer for
generating test analog voltage for ADC operation.
The MC1408 DAC (or DAC0808)
In this chip the digital inputs are converted to current. The output current is known as Iout by
connecting a resistor to the output to convert into voltage. The total current provided by
the Iout pin is basically a function of the binary numbers at the input pins D0 - D7 (D0 is the LSB
and D7 is the MSB) of DAC0808 and the reference current Iref. The following formula is
showing the function of Iout

IOut=Iref⟮D72+D64+D58+D416+D332+D264+D1128+D0256⟯IOut=Iref⟮D72+D6
4+D58+D416+D332+D264+D1128+D0256⟯

The Iref is the input current. This must be provided into the pin 14. Generally 2.0mA is used as
Iref
We connect the Iout pin to the resistor to convert the current to voltage. But in real life it may
cause inaccuracy since the input resistance of the load will also affect the output voltage. So
practically Iref current input is isolated by connecting it to an Op-Amp with Rf = 5KΩ as
feedback resistor. The feedback resistor value can be changed as per requirement.

Generating Sinewave using DAC and 8051 Microcontroller


Angle(in θ ) sinθ Vout (Voltage Magnitude) Values sent to DAC

0 0 5 128

30 0.5 7.5 192

60 0.866 9.33 238

90 1.0 10 255

120 0.866 9.33 238

150 0.5 7.5 192

180 0 5 128

210 -0.5 2.5 64

240 -0.866 0.669 17

270 -1.0 0 0

300 -0.866 0.669 17

330 -0.5 2.5 64

360 0 5 128

For generating sinewave, at first we need a look-up table to represent the magnitude of the
sine value of angles between 0° to 360°. The sine function varies from -1 to +1. In the table
only integer values are applicable for DAC input. In this example we will consider 30°
increments and calculate the values from degree to DAC input. We are assuming full-scale
voltage of 10V for DAC output. We can follow this formula to get the voltage ranges.
Vout = 5V + (5 ×sinθ)
Let us see the lookup table according to the angle and other parameters for DAC.
Circuit Diagram −
Source Code
#include<reg51.h>
sfr DAC = 0x80; //Port P0 address
void main(){
int sin_value[12] = {128,192,238,255,238,192,128,64,17,0,17,64};
int i;
while(1){
//infinite loop for LED blinking
for(i = 0; i<12; i++){
DAC = sin_value[i];
}
}
}

Output
The output will look like this −
Interfacing with stepper motor 11.

How to Interface Stepper motor with 8051 Lab Trainer

Kit

8051 – TRAINER BOARD


PS-TRAINER-8051 trainer kit is proposed to smooth the progress of learning
and developing designs of MCU from Intel and NXP. It has the facility to connect
PC’s 101/104 Keyboard, to enter user programs in Assembly languages. Serial
communication achieved using 8051. It also supports C & assembly language in
standalone kit (P89V51RD2). It’s designed as to facilitate On-board Programmer
for NXP 8051 MCU through ISP on serial port.

STEPPER MOTOR
A stepper motor is a brushless, synchronous electric motor that converts digital
pulses into mechanical shaft rotation. Every revolution of the stepper motor is
divided into a discrete number of steps, and the motor must be sent a separate pulse
for each step.

INTERFACING STEPPER MOTOR


Fig. 1 shows how to interface the Stepper Motor to microcontroller. As you can
see the stepper motor is connected with Microcontroller output port pins through
a ULN2803A array. So when the microcontroller is giving pulses with particular
frequency to ls293A, the motor is rotated in clockwise or anticlockwise.

Fig. 1
Interfacing Stepper Motor to Microcontroller

INTERFACING STEPPER MOTOR WITH 8051


We now want to control a stepper motor in 8051 trainer kit. It works by turning
ON & OFF a four I/O port lines generating at a particular frequency.

The 8051 trainer kit has three numbers of I/O port connectors, connected with I/O
Port lines (P1.0 – P1.7),(p3.0 – p3.7) to rotate the stepper motor. Ls293d is used
as a driver for port I/O lines, drivers output connected to stepper motor, connector
provided for external power supply if needed.

PIN ASSIGNMENT WITH 8051

CIRCUIT DIAGRAM TO INTERFACE STEPPER MOTOR


WITH 8051
ADDRESS OP CODE MNEMONICS COM

8500 74 80 MOV A, #80H Initialize 80HEX v

8502 90 40 03 MOV DPTR, #4003 Move 4003

8505 F0 MOVX @DPTR, A Store ACC valu

8506 90 40 00 MOV DPTR, #4000 Move 4000

8509 74 66 MOV A, #66H Move 66HEX val

850 AGAIN:MOVX@DPTR,
F0 In AGAIN, Store
B A

850
03 RR A Rotate sequen
C

850
B1 11 ACALL DELAY w
D

850F 80 FA SJMP AGAIN Short Jump

8511 7D 05 DELAY: MOV R5, #5 In DELAY, Loa

8513 7C 0F H3: MOV R4, #0F In H3, Load 0F va

8515 7B 43 H2: MOV R3, #43 In H2, Load 43 va


8517 DB FE H1 : DJNZ R3, H1 H1, Decrement R0

8519 DC FA DJNZ R4, H2 Decrement R4&

851
DD F6 DJNZ R5, H3 Decrement R5&
B

851
22 RET Re
D

ASSEMBLY PROGRAM TO RUN THE


STEPPER MOTOR USING 8051
NOTE: To turn the motor in the reverse direction enter as (Rl A instead of RR A).
The schematics sections given is, stepper motor connected to port 1 and the
sample program is given based on 8255.
Pulse Width Modulation 12.
In this lab you will DO the following:

• Recreate Part 4 of Lab 1 using assembly instead of C.

• Control the brightness of an LED using a hardware PWM (Pulse-width modulation) module.
In this lab you will LEARN the following:

• The native (assembly) instruction set of the MSP430.

• How to configure a timer peripheral for PWM output.

• How to operate an oscilloscope.


At the beginning of the next lab period you will demo your working system to the TA. Be prepared to
demonstrate any and all functionality developed throughout the lab assignment. Prior to the beginning
of your next lab period, each group should turn in the following to the course dropbox (one set per
group):

• A PDF containing answers to all questions posed in this lab prompt, as well as a description of any
extra functionality you added in your implementation.

• Your fully commented and neatly presented code, in a zipped format. NOTE: Only source files
(*.c, *.h, etc) are necessary. Make it obvious which files were used in which portion of the lab.
These documents and web resources will be useful in completion of the lab and/or in answering the
questions posed.

• MSP430F2013 Datasheet

• MSP430x2xx Family User’s Guide

• MSP430 Code Examples

• MSP430 Software Coding Techniques

• eZ430-F2013 User’s Guide

• Code Composer Wiki

• Code Composer v5 User’s Guide for MSP430

• MSP430 Optimizing C/C++ Compiler User’s Guide


GOAL:

• Implement Part 4 from Lab 1 using assembly code. HINTS:

• Reference the following MSP430 assembly code examples from TI : o msp430x20x3_ta_02.asm o


msp430x20x3_sd16A_01.asm

• Be sure to select “Treat as an assembly-only project” when creating the project in CCS. Question
1.1: How many lines of Assembly did this program require? How many lines of C? Question 1.2:
What was the resulting binary size (program memory utilization) for assembly and C versions
(Hint: one of the compiler output files will give you this information).
We will now take a brief interlude to introduce (or hopefully re-introduce) you to the
oscilloscope. This is an important tool for the embedded systems engineer, and will be useful
for Part 3 of this lab. For this section, please go through the Oscilloscope Tutorial on the
course website and answer the questions below. Reference the oscilloscope manual if needed.
Question
2.1: Which parameters of circuit operation (current, voltage, resistance, frequency , etc) is
your oscilloscope capable of directly measuring or calculating? Question
2.2: TRUE or FALSE: It’s OK to connect two oscilloscope probe ground clips to different
nodes (justify your answer).
3: PWM GENERATION WITH TIMER_A A pulse-width modulated (PWM) waveform is a
rectangular wave with a variable ON time. The ON time of the waveform relative to its
period is known as its duty cycle. PWM signals are used when there is a need to vary the
effective power of a signal, such as in a motor or lighting controller. Figure 1.
The green waveform is a PWM signal with varying duty cycle. Red represents the average
signal level. The TIMER_A peripheral of the MSP430 may be configured to produce a PWM
waveform directly on an output pin. Like many hardware peripherals of the MSP430, the
timer may be configured in a “set-and-forget” manner if desired, and will run continuously
until reconfigured.
The file “msp430x20x3_ta_16.c” configures the timer to produce a PWM signal, routes this
PWM signal to a physical output port, and then switches off the CPU entirely. The PWM
operation will run independent of the CPU and other subsystems of the microcontroller.
HINTS:
• Review the TIMER_A section in the MSP430F2013 datasheet.

• Only certain pins may be configured to produce the PWM signal. PROCEDURE:
1. Create a new project and import “msp430x20x3_ta_16.c”.
2. Connect the LED to the PWM output port of the MSP.
3. Connect an oscilloscope probe between the PWM output port and ground.
4. Run the application and observe the LED and oscilloscope waveform.
5. Change the duty cycle of the PWM waveform and reprogram the target. Observe changes.
6. Change the period of the PWM waveform and reprogram the target. Observe changes.
7. Produce an automatic LED fade effect by adjusting the PWM duty cycle in an ISR. The
LED should smoothly fade between low- and high-brightness states. Question
3.1: What are two advantages of direct hardware control of the PWM output, rather than
toggling the pin in a timer ISR? Question
3.2: How did changing the PWM period affect operation of the device?
GOALS: • Use the PWM module as a musical tone generator. Connect the PWM output to a
piezoelectric speaker element using the filter shown. • Select which musical tone (from the
table below) to play back based on light intensity. You should be able to “play” the optical
theremin by waving your hand over the light sensor
Programming ARM micro controller using
asm and c using simulator 13.
A micro-controller is a single Integrated Circuit (IC) which is comparable to
little stand alone computer and it is designed to perform the specific tasks of
embedded systems. 8051 and ARM comes under the family of micro-
controller. 8051 micro-controller and ARM micro-controller differs from
each other in terms of different architecture and different sets of instruction,
speed, cast, Memory, Power Consumption, Bus Width etc. Now let’s
understand in detail what actually they are and how they differs from each
other.
1. 8051 micro-controller :
It is a 8 bit family of micro-controller. It is an entry level micro-controller
used for most basic applications all across the world and it consumes low
power and available with low budget. It was developed by the Intel in the
year 1981. 8051 micro-controller has many features like Serial
Communication, Timers, Interrupts, etc. This micro-controller is used in
various devices and the major areas includes automobiles, medical
devices and energy management. Now a days 8051 Micro-controller
might seem little bit out of fashion but still it is recommended as best
platform to start work on the concept of Micro-controllers with 8051 Micro-
controller although this trend seems to be changed with the introduction of
Arduino of AVR community.

2. ARM micro-controller :
ARM micro-controller was introduced by Acron computer organization and is
manufactured by Apple, Nvidia, Qualcomm, Motorola, ST Microelectronics,
Samsung Electronics, and TI etc. ARM processor belongs to the family of
CPUs which are based on Reduced Instruction Set Computer (RISC) and
ARM microprocessor with RAM, ROM and other peripherals in one single
chip, we get an ARM micro-controller, for example, LPC2148. It is based on

RISC Instruction set Architecture (ISA)


and also called as Advanced RISC machine. It is most popular micro
controller and most industries use it for embedded systems as it provides
large set of features and is good to produce devices with excellent
appearances.

Difference between 8051 and ARM :


No. 8051 ARM
8 bit for standard core bus width is present in Mostly 32 bit bus width is present in ARM micro-controller a
8051 micro-controller. also 64-bit is available.

Its speed is 12 clock cycles per machine cycle. Its speed is 1 clock cycle per machine cycle.

UART, USART, Ethernet, I2S, DSP, SPI, CAN, LIN


UART, USART, I2C, SPI, communication
protocols are used. , I2C communication protocols are used.

Flash, ROM, SRAM memory is used in 8051 Flash, EEPROM, SDRAM memory is used in ARM micro-
micro-controller. controller.

It is based on CISC Instruction set Architecture. It is based on RISC Instruction Set Architecture.

8051 micro-controller is a Harvard-based


architecture, but it allows us to connect external
memory and simulate von Neumann’s
architecture. PIC micro-controller is based on Havard architecture.

Power consumption of 8051 micro-controller is


average. Power consumption of ARM micro-controller is low.

Its families include 8051 variants. Its families include ARMv4, 5, 6, 7 and cortex series.

Its manufacturers are Atmel, NXP, Silicon Labs, Its manufacturers are Nvidia, Qualcomm, Apple, Samsung
Dallas, Cyprus, Infineon, etc. Electronics, and TI etc.

8051 micro-controller costs very low as ARM micro-controller costs low as compared to features
compared to features provided. provided.

Popular micro-controllers include AT89C51, Popular micro-controllers include ARM Cortex-M0 to ARM
P89v51, etc. Cortex-M7, etc.
Programming with Arithmetic logic
instruction 14.
Arithmetic Instructions are the instructions which perform basic arithmetic
operations such as addition, subtraction and a few more. In 8085
microprocessor, the destination operand is generally the accumulator.
Following is the table showing the list of arithmetic instructions:

Opcode Operand Explanation Example

ADD R A=A+R ADD B

ADD M A = A + Mc ADD 2050

ADI 8-bit data A = A + 8-bit data ADI 50

ADC R A = A + R + prev. carry ADC B

ADC M A = A + Mc + prev. carry ADC 2050

ACI 8-bit data A = A + 8-bit data + prev. carry ACI 50

SUB R A=A–R SUB B

SUB M A = A – Mc SUB 2050

SUI 8-bit data A = A – 8-bit data SUI 50

SBB R A = A – R – prev. carry SBB B

SBB M A = A – Mc -prev. carry SBB 2050

SBI 8-bit data A = A – 8-bit data – prev. carry SBI 50

INR R R=R+1 INR B


Opcode Operand Explanation Example

INR M M = Mc + 1 INR 2050

INX r.p. r.p. = r.p. + 1 INX H

DCR R R=R–1 DCR B

DCR M M = Mc – 1 DCR 2050

DCX r.p. r.p. = r.p. – 1 DCX H

DAD r.p. HL = HL + r.p. DAD H

In the table, R stands for register M stands for memory Mc stands for
memory contents r.p. stands for register pair
GPIO programming in arm microcontroller 15.
Introduction
General-purpose input/output (GPIO) is a pin on an IC (Integrated Circuit). It can be
either input pin or output pin, whose behaviour can be controlled at the run time. A
group of these pins is called a port (Example, Port 0 of LPC2148 has 32 pins).

LPC2148 has two 32-bit General Purpose I/O ports.

1. PORT0

2. PORT1

PORT0 is a 32-bit port

• Out of these 32 pins, 28 pins can be configured as either general purpose input or
output.
• 1 of these 32 pins (P0.31) can be configured as general-purpose output only.
• 3 of these 32 pins (P0.24, P0.26 and P0.27) are reserved. Hence, they are not available
for use. Also, these pins are not mentioned in pin diagram.

PORT1 is also a 32-bit port. Only 16 of these 32 pins (P1.16 – P1.31) are available for
use as general-purpose input or output.
LPC2148 Pin Diagram

Almost every pin of these two ports has some alternate function available. For
example, P0.0 can be configured as the TXD pin for UART0 or as PWM1 pin as well.
The functionality of each pin can be selected using the Pin Function Select Registers.

Note : The Port 0 pins do not have built-in pull-up or pull-down resistors. Hence, while
using GPIOs on Port 0, in some cases, we need to connect pull-up or pull-down
resistors externally.

Pin Function Select Registers


Pin Function Select Registers are 32-bit registers. These registers are used to select
or configure specific pin functionality.

There are 3 Pin Function Select Registers in LPC2148:

1. PINSEL0 : - PINSEL0 is used to configure PORT0 pins P0.0 to P0.15.

2. PINSEL1 : - PINSEL1 is used to configure PORT0 pins P0.16 to P0.31.


3. PINSEL2 : - PINSEL2 is used to configure PORT1 pins P1.16 to P1.31.

Let’s see GPIO registers that control the GPIO operations.

Fast and Slow GPIO Registers


There are 5 Fast (also called Enhanced GPIO Features Registers) GPIO Registers and
4 Slow (also called Legacy GPIO Registers) GPIO Registers available to control PORT0
and PORT1.

The Slow Registers allow backward compatibility with earlier family devices using the
existing codes.

Slow GPIO Registers

There are 4 Slow GPIO registers :

1. IOxPIN (GPIO Port Pin value register): This is a 32-bit wide register. This register
is used to read/write the value on Port (PORT0/PORT1). But care should be taken
while writing. Masking should be used to ensure write to the desired pin.

Examples :

a) Writing 1 to P0.4 using IO0PIN

IO0PIN = IO0PIN | (1<<4)

b) Writing 0 to P0.4 using IO0PIN

IO0PIN = IO0PIN & (~(1<<4) )

c) Writing F to P0.7-P0.4

IO0PIN = IO0PIN | (0x000000F0)

2. IOxSET (GPIO Port Output Set register) : This is a 32-bit wide register. This register
is used to make pins of Port (PORT0/PORT1) HIGH. Writing one to specific bit makes
that pin HIGH. Writing zero has no effect.

3. IOxDIR (GPIO Port Direction control register) : This is a 32-bit wide register. This
register individually controls the direction of each port pin. Setting a bit to ‘1’
configures the corresponding pin as an output pin. Setting a bit to ‘0’ configures the
corresponding pin as an input pin.

4. IOxCLR (GPIO Port Output Clear register) : This is a 32-bit wide register. This
register is used to make pins of Port LOW. Writing one to specific bit makes that pin
LOW. Writing zeroes has no effect.

Examples :

a) Configure pin P0.0 to P0.3 as input pins and P0.4 to P0.7 as output pins.

IO0DIR = 0x000000F0;

b) Configure pin P0.4 as an output. Then set that pin HIGH.

IO0DIR = 0x00000010; OR IO0DIR = (1<<4);

IO0SET = (1<<4);

c) Configure pin P0.4 as an output. Then set that pin LOW.

IO0DIR = 0x00000010; OR IO0DIR = (1<<4);

IO0CLR = (1<<4);

Fast GPIO Registers

There are 5 fast GPIO registers :

1. FIOxDIR (Fast GPIO Port Direction control register) : This is a 32-bit wide
register.This register individually controls the direction of each port pin. Setting a bit
to ‘1’ configures the corresponding pin as an output pin. Setting a bit to ‘0’ configures
the corresponding pin as an input pin.

2. FIOxMASK (Fast Mask register for port) : This is a 32-bit wide register. This register
controls the effect of fast registers (FIOxPIN, FIOxSET, FIOxCLR) on port pins. Setting
a bit to ‘0’ configures the corresponding pin access to the fast registers i.e. we can
write/read the corresponding pin in fast mode using fast registers. Setting a bit to ‘1’
configures the corresponding pin unaffected by fast registers.
3. FIOxPIN (Fast Port Pin value register using FIOMASK) : This is a 32-bit wide
register. This register is used to read/write the value on port pins, only if that
corresponding port pins have access to fast registers (Access to port pins using fast
registers is enabled using Zeroes in FIOxMASK register).

4. FIOxSET (Fast Port Output Set register using FIOMASK) : This is a 32-bit wide
register. This register is used to make pins of Port HIGH. Writing one to specific bit
makes that pin HIGH. Writing zero has no effect. Reading this register returns the
current contents of the port output register. Only bits enabled by ZEROES in FIOMASK
can be altered.

5. FIOxCLR (Fast Port Output Clear register using FIOMASK) : This is a 32-bit wide
register.This register is used to make pins of Port LOW. Writing one to specific bit
makes that pin LOW. Writing zeroes has no effect. Only bits enabled by ZEROES in
FIOMASK can be altered.

Aside from the 32-bit long and word only accessible registers mentioned above, every
fast GPIO port can also be controlled via several byte and half-word accessible
registers. Refer chapter 8 (Page 83) on GPIO in the datasheet of LPC2148 provided in
the attachments section for their use.

Examples :

a) Configure pin P0.0 to P0.3 as input pins and P0.4 to P0.7 as output pins.

FIO0DIR = 0x000000F0;

b) Configure pin P0.4 as an output. Then set that pin HIGH.

FIO0DIR = 0x00000010; OR FIO0DIR = (1<<4);

FIO0SET = (1<<4);

c) Configure pin P0.4 as an output. Then set that pin LOW.

FIO0DIR = 0x00000010; OR FIO0DIR = (1<<4);

FIO0CLR = (1<<4);
Why this is called Fast GPIO :

Fast GPIO registers are relocated to the ARM local bus. This makes software access
to GPIO pins 3.5 times faster than access through Slow GPIO registers. This effect will
not always be visible when a program is written in c code. It may be more evident in
an assembly code than in a c code.

Example
Now, let’s write a simple program for turning LED ON or OFF depending on the status
of the pin.

Here, LED is interfaced to P0.0.

A switch is interfaced to P0.1 to change the status of the pin.

Program
/*
Input-Output Pin Programming to Drive LED through switch
-ports-and-registers
http://www.electronicwings.com/arm7/lpc2148-32-bit-arm7tdmi-s-processor-gpio
*/

#include <lpc214x.h>

#include <stdint.h>

int main(void)
{
//PINSEL0 = 0x00000000; /* Configuring P0.0 to P0.15 as GPIO */
/* No need for this as PINSEL0 reset value is 0x00000000 */
IO0DIR = 0x00000001; /* Make P0.0 bit as output bit, P0.1 b
it as an input pin */
while(1)
{
if ( IO0PIN & (1<<1) ) /* If switch is open, pin is HIGH */
{
IO0CLR = 0x00000001; /* Turn on LED */
}
else /* If switch is closed, pin is LOW */
{
IO0SET = 0x00000001; /* Turn off LED */
}
}
}

Timer’s programming in arm


microcontroller 16.
Timers in LPC2148 ARM7 Microcontroller
In this tutorial we’ll explore the use timers in LPC2148 ARM7 Microcontroller. In general, timer means
exactly how it sounds. Timer and counter is very important feature which allows us to provide time
variable to our microcontroller based project. Most microcontrollers comes with built-in timer
peripheral. The LPC2148 has two functionally identical general purpose timers: Timer0 and Timer1.
These both timers are 32-bit along with 32-bit prescaler. Timer allows us to generate precise time delay.
For Example: In our blink LED example project, we’ve generated random delay of approximate 1 Sec. but
using Timers we can generate accurate time delay. We’ll get into that while discussing example project of
Timer. Apart from this we can use timers as pulse width modulator and also as free running timer.
Timers in LPC2148 ARM7 Microcontroller enable us to do really cool stuffs. Also timer enhances the use
of microcontroller in many different ways. We may need to dedicate one more post to understand Match
and Capture registers and its uses in real world application. Let’s first understand free running counter
and related fundamentals.

How Timers in LPC2148 ARM7 Microcontroller Works?


The heart of timers of the LPC2148 Microcontroller is a 32-bit free running counter, which is designed to
count cycles of the Peripheral Clock (PCLK) or an external clock, this counter is programmable with 32-bit
prescaler.
32 bit Timer Counter with 32 bit Prescaler

The tick rate of the Timer Counter (TC) is controlled by the 32-bit number written in the Prescaler
Register (PR) in the following way. There is a Prescale Counter (PC) which increments on each tick of the
PCLK. When it reaches the value in the prescaler register, the timer count is incremented and the
Prescaler Counter (PC) is reset, on the next PCLK. This cause the timer counters to increment on every
PCLK when PR=0, every 2 PCLKs when PR=1, etc.

TIMER REGISTERS in LPC2147 ARM7


This is quick introduction. You’ll use datasheet for your reference [Page No: 247-248]
Prescale Counter: The 32-bit PC is a counter which is incremented to the value stored in PR
PC (Prescale Register) when value in PR is reached, The TC (Timer Counter) is incremented and
PC is cleared. The PC is observable and controllable through bus interface

Prescale Register: The 32-bit register which hold the maximum value of prescale counter
PR
after which it reset

Timer Counter: This is 32-bit Timer Counter which gets incremented whenever PC Prescale
TC
Counter value reaches to its maximum value as specified in PR

Timer Control Register: Timer Control register used to control the timer control functions.
TCR
We’ll enable, disable and reset Timer Counter (TC) through this register

Count Control Register: This register selects Timer Counter Mode. In our example we have
used Timer Mode. This can be done by setting CTCR to 0x0. [In Timer Mode every rising PCLK
CTCR
edge can increment Timer’s Prescale Counter (PC) or clear PC and increment Timer Counter
(TC)]

EXAMPLE PROJECT: In this example project we’ll generate precise 1 Sec. of delay using Timer0. The
Timer uses PCLK (Peripheral Clock) as a clock source. From previous post we’ve seen how to set up PLL
in LPC2148 ARM7. The Peripheral Clock (PCLK) has to be initialized before using Timer. Here in this
example: we have used 12 MHz external clock to be tick at 60 MHz.
Circuit Timers in ARM7 LPC2148

Before we jump start on writing program. We have to understand setting up of Timer Registers or
you can say sequence of operations. We’ll be following along:
▪ Setup Timer T0 into Timer Mode (T0CTCR = 0x0)
▪ Setup Prescale value in T0PR (in our case 59999)
▪ Reset Timer by setting (T0TCR = 0x02)
▪ Setup T0TCR to 0x01 to Enable Timer when needed
▪ Reset T0TCR to 0x00 to Disable Timer when needed
You may be wondering, why we have set Prescale Value to 59,999. Let’s calculate prescale count value:
Required Time 1 Second = 1/1000 milliseconds = 0.001 seconds (Resolution=1 ms)

PRESCALE COUNT= (60 MHz x Required Time Delay) – 1


= (60000000 x 0.001) – 1
= 59999
Hence the delay required for TC to increment by 1 will be 1 ms.

#include <lpc214x.h>

void initClocks(void); // Setup PLL and Clock Frequency

void initTimer0(void); // Setup and Initialize Timer0

void delay_ms(unsigned int counts); // Generate delay

int main(void)

initClocks(); //Initialize CPU and Peripheral Clocks @ 60Mhz

initTimer0(); //Initialize Timer0

IO0DIR = (1<<10); //Configure Pin P0.10 as Output

while(1)

IO0SET = (1<<10); //Turn ON LED


delay_ms(1000);

IO0CLR = (1<<10); //Turn LED OFF

delay_ms(1000);

//return 0;

void initTimer0(void)

T0CTCR = 0x0; //Set Timer 0 into Timer Mode

T0PR = 59999; //Increment T0TC at every 60000 clock cycles

//Count begins from zero hence subtracting 1

//60000 clock cycles @60Mhz = 1 mS

T0TCR = 0x02; //Reset Timer

void delay_ms(unsigned int counts) //Using Timer0

T0TCR = 0x02; //Reset Timer

T0TCR = 0x01; //Enable timer

while(T0TC < counts);//wait until TC reaches the desired delay

T0TCR = 0x00; //Disable timer

void initClocks(void)

PLL0CON = 0x01; //Enable PLL

PLL0CFG = 0x24; //Multiplier and divider setup

PLL0FEED = 0xAA; //Feed sequence

PLL0FEED = 0x55;

while(!(PLL0STAT & 0x00000400)); //is locked?

PLL0CON = 0x03; //Connect PLL after PLL is locked


PLL0FEED = 0xAA; //Feed sequence

PLL0FEED = 0x55;

VPBDIV = 0x01; // PCLK is same as CCLK i.e.60 MHz

You might also like