Вы находитесь на странице: 1из 38

K. S.

SCHOOL OF ENGINEERING & MANAGEMENT


# 15, Mallasandra, Off Kanakapura Road, Bangalore-560109,
Karnataka, India.

DEPARTMENT OF ELECTRONICS & COMMUNICATION


ENGINEERING

Embedded Controllers Lab Manual


Sub Code: 15ECL67

Sem : VI

Prepared by

Mr. Ravikiran B. A.
Asst. Professor, Dept of ECE
Table of Contents

About the STM32F103RB microcontroller. ..............................................1

Part A: Experiments written using Embedded C


1. Display of Message using Internal UART .................................................5

2. DC Motor Interface ............................................................................7

3. Stepper Motor Interface.......................................................................9

4. Waveform Generation using DAC ........................................................11

5. Keypad and LCD Interface .................................................................17

6. PWM Generation using Internal PWM .................................................21


7. LED control using External Interrupts ..................................................24

8. 7-Segment LED Display .....................................................................27

9. Switch Control of Buzzer, Relay and LED ..............................................30

10. Temperature Measurement using ADC .................................................32

Part B: Exercises with Programs written using ALP Code

11. ALP to Find the Sum of First 10 Numbers ..............................................35

12. ALP to Find the Product of two 16-bit Numbers ......................................36


Embedded Controller Lab (15ECL67) 6th Sem ECE KSSEM, Bangalore

About the STM32F103RB microcontroller.

The kit used in our lab experiments is built around the STM32 Nucleo-64 board, which is based
on the STM32 Microcontroller, manufactured by ST Microelectronics. We use a ARM Cortex-M3
72 MHz, 128-KB Flash, 20-KB SRAM. STM32 Nucleo-64 development board with
STM32F103RB MCU, supports Arduino and ST morpho connectivity.

STM32 Key Features


• STM32 microcontroller in LQFP64 package
• External SMPS to generate Vcore logic supply (only available on '-P' suffixed boards)
• 1 user LED shared with Arduino™
• 1 user and 1 reset push-buttons
• 32.768 kHz LSE crystal oscillator
 Board expansion connectors:
 Arduino™ Uno V3
 ST Morpho extension pin headers for full access to all STM32 I/O's
 External SMPS experimentation dedicated connector
 Flexible power-supply options: ST-LINK USB VBUS or external sources
 On-board ST-LINK/V2-1 debugger/programmer with USB re-enumeration capability.

STM32F103RB Features:
• ARM® 32-bit Cortex®-M3
• CPU Core – 72 MHz maximum frequency,
Single-cycle multiplication and hardware division
• Memories
64 or 128 Kbytes of Flash memory
20 Kbytes of SRAM
• Clock, reset and supply management:
2.0 to 3.6 V application supply and I/Os
4-to-16 MHz crystal oscillator
Internal 8 MHz factory-trimmed RC
Internal 40 kHz RC
32 kHz oscillator for RTC with calibration
• 2 x 12-bit, 1 μs A/D converters (up to 16 channels)
Conversion range: 0 to 3.6 V
Dual-sample and hold capability
Temperature sensor
• Peripherals supported: timers, ADC, SPIs, I2Cs and USARTs
• Up to 80 fast I/O ports – 26/37/51/80 I/Os, all mappable on 16 external interrupt vectors and almost
all 5 V-tolerant
• 7 timers – Three 16-bit timers, each with up to 4 IC/OC/PWM or pulse counter and quadrature
(incremental) encoder input, 16-bit, motor control PWM timer, 2 watchdog
• Up to 9 communication interfaces
Up to 2 x I2C interfaces (SMBus/PMBus)
Up to 3 USARTs (ISO 7816 interface, LIN, IrDA capability, modem control)
Up to 2 SPIs (18 Mbit/s)
CAN interface (2.0B Active)
USB 2.0 full-speed interface

Dept of ECE, KSSEM 1


Embedded Controller Lab (15ECL67) 6th Sem ECE KSSEM, Bangalore

The STM32F103RB has 51 GPIO pins available to the user, in 4 groups – Port A (16 pins), Port
B (16 Pins), Port C (16 Pins) and Port D (3 Pins).

The general workflow for creating and downloading a complete project on Keil are as follows:
1. Create a New uVision Project
2. Set up the Target configuration by choosing the right device (STM32F103RB)
3. Choose the appropriate Device libraries necessary for that particular project.
4. Create a new Source File in the relevant file format (.c, .cpp, etc)
5. Write the program into the source file.
6. Translate and Build the Program once debugging is done.
7. Download the compiled program onto the target hardware and run.

The basic GPIO setup procedure is as follows:

Step 1: Configure the Clock Register for the Port to be Used


In this step, we are configuring the clock registers, and enabling the clock registers for the
specific GPIO ports that we will be using. The Register structure is as shown:

APB2 Peripheral Clock Control Register: (RCC_APB2ENR):

Dept of ECE, KSSEM 2


Embedded Controller Lab (15ECL67) 6th Sem ECE KSSEM, Bangalore

Step 2: Configure the Port Configuration Registers.


Once the Port has been enabled, and the clock registers configured for the same, the next step is
to specify the particular pins that would be used, and also indicate the mode and configuration for
each of the pins. This is done by setting or resetting the corresponding bits in the Port
configuration Register.
The Port Configuration Register consists of two 32-bit registers – GPIOx_CRL (Pin 0 – Pin 7)
and GPIOx_CRH (Pin 8 – Pin 15). Each pin in the register is configured using 4 consecutive bits.

The structure of the CRH and CRL registers is as shown:

For each pin in the CRL or CRH register, there are 4 bits, which have to be set or reset depending
on the mode and speed of operation of the pins as shown:

For instance, consider Pin 0 in CRL (bits 0 to 3):

The Pin configuration and Mode selection bits are as shown:

Dept of ECE, KSSEM 3


Embedded Controller Lab (15ECL67) 6th Sem ECE KSSEM, Bangalore

Step 3: Write data into the Data Register (ODR)


Once the ports and pins have been configured, we now can read data into the microcontroller
through the input pins, or write data from the microcontroller through the output data pins, by
making use of the Data Register.
The Data Register is 32 bits long, out of which the lower 16 bits are usable. Each of these bits (15-
0) indicate the status of the signal on the corresponding GPIO pins in the selected port.
An Example of the Port Output Data Register (GPIOx_ODR) is as shown:

In our kit, there are some pre-connected peripherals, whose port and pin connections are given:
(NOTE: These numbers are specific to the kit used in our lab only)

Dept of ECE, KSSEM 4


Embedded Controller Lab (15ECL67) 6th Sem ECE KSSEM, Bangalore

PROGRAM 1
Display of Message using Internal UART

Aim: To Display “Hello World” message using Internal UART


Theory:
A universal asynchronous receiver-transmitter (UART) is a computer hardware device
for asynchronous serial communication in which the data format and transmission speeds are
configurable. The electric signaling levels and methods are handled by a driver circuit external to the
UART.
In UART communication, two UARTs communicate directly with each other. The transmitting
UART converts parallel data from a controlling device like a CPU into serial form, transmits it in serial
to the receiving UART, which then converts the serial data back into parallel data for the receiving
device. Only two wires are needed to transmit data between two UARTs. Data flows from the Tx pin
of the transmitting UART to the Rx pin of the receiving UART.
UARTs transmit data asynchronously, which means there is no clock signal to synchronize the
output of bits from the transmitting UART to the sampling of bits by the receiving UART. Instead of a
clock signal, the transmitting UART adds start and stop bits to the data packet being transferred. These
bits define the beginning and end of the data packet so the receiving UART knows when to start reading
the bits.
When the receiving UART detects a start bit, it starts to read the incoming bits at a specific frequency
known as the baud rate. Baud rate is a measure of the speed of data transfer, expressed in bits per second
(bps). Both UARTs must operate at about the same baud rate. The baud rate between the transmitting
and receiving UARTs can only differ by about 10% before the timing of bits gets too far off.
Both UARTs must be configured to transmit and receive the same data packet structure.

The UART that is going to transmit data receives the data from a data bus. The data bus is used to
send data to the UART by another device like a CPU, memory, or microcontroller. Data is transferred
from the data bus to the transmitting UART in parallel form. After the transmitting UART gets the
parallel data from the data bus, it adds a start bit, a parity bit, and a stop bit, creating the data packet.
Next, the data packet is output serially, bit by bit at the Tx pin. The receiving UART reads the data
packet bit by bit at its Rx pin. The receiving UART then converts the data back into parallel form and
removes the start bit, parity bit, and stop bits. Finally, the receiving UART transfers the data packet in
parallel to the data bus on the receiving end.
NOTE: In our experiment, we start PuTTY on the computer, set the communication mode to Serial,
include the right COM port number (as seen from the Device Manager), and run the program.

Dept of ECE, KSSEM 5


Embedded Controller Lab (15ECL67) 6th Sem ECE KSSEM, Bangalore

C - CODE:
#include <stdio.h>
#include "stm32f10x.h"
uint8_t text [] = "Hello World \n\r\n\r"; // Text to be displayed
void delay(int time);
void USART_PutChar(uint8_t ch) //USART Print Subroutine
{
while(!(USART2->SR & USART_SR_TXE));
USART2->DR = ch; // Write text to USART Data Register
}
void USART_PutString(uint8_t * str)
{
while(*str != 0)
{
USART_PutChar(*str); //Send string
str++;
}
}
int main(void)
{
RCC->APB2ENR = RCC_APB2ENR_IOPAEN ; //IO port declaration
RCC->APB1ENR = RCC_APB1ENR_USART2EN; //USART declaration
GPIOA->CRL = 0x00004B00; //0100 ->3 1011 ->2 0000->1 0000->0
USART2->CR1 = USART_CR1_UE | USART_CR1_TE;
USART2->BRR = (SystemCoreClock / (9600*2)); // baud rate change
while (1)
{
USART_PutString(text);
delay(10);
}
}

void delay(int time)


{
int i,j;
for(i=0;i<=time;i++)
{
for(j=0;j<=72000;j++);
}
}

OUTPUT:

Hello World

RESULT:
We see that upon executing this code, the text defined in the program is sent from the
Microcontroller via UART, and the message can then be viewed on a serial window using a program
such as PuTTy or TeraTerm.

Dept of ECE, KSSEM 6


Embedded Controller Lab (15ECL67) 6th Sem ECE KSSEM, Bangalore

PROGRAM 2

DC Motor Interface

Aim: To write a program to Interface and Control a DC Motor with the ARM controller
Theory:
A DC motor is any of a class of rotary electrical machines that converts direct current electrical
energy into mechanical energy. DC motors were the first type widely used, since they could be powered
from existing direct-current lighting power distribution systems. A DC motor's speed can be controlled
over a wide range, using either a variable supply voltage or by changing the strength of current in its
field windings. Small DC motors are used in tools, toys, and appliances.

The very basic construction of a DC motor contains a current carrying armature which is connected
to the supply end through commutator segments and brushes. The armature is placed in between north
south poles of a permanent or an electromagnet as shown in the diagram above.
As soon as we supply direct current in the armature, a mechanical force acts on it due to
electromagnetic effect of the magnet. If a current carrying conductor is placed in a magnetic field
perpendicularly, then the conductor experiences a force in the direction mutually perpendicular to both
the direction of field and the current carrying conductor. In a typical DC motor, there are
permanent magnets on the outside and a spinning armature on the inside. The permanent magnets are
stationary, so they are called the stator. The armature rotates, so it is called the rotor.

The armature contains an electromagnet. When electricity flows into this electromagnet, it creates
a magnetic field in the armature that attracts and repels the magnets in the stator. So the armature spins
through 180 degrees. To keep it spinning, we have to change the poles of the electromagnet. The brushes
handle this change in polarity. They make contact with two spinning electrodes attached to the armature
and flip the magnetic polarity of the electromagnet as it spins.

Motor Driver L293D

A motor driver is an integrated circuit chip which is usually used to control motors. L293D is
a dual H-bridge motor driver integrated circuit (IC). Motor drivers act as current amplifiers since
they take a low-current control signal and provide a higher-current signal. This higher current signal
is used to drive the motors. L293D contains two inbuilt H-bridge driver circuits. In its common
mode of operation, two DC motors can be driven simultaneously, both in forward and reverse
direction. The motor operations of two motors can be controlled by input logic at pins 2 & 7 and
10 & 15. Input logic 00 or 11 will stop the corresponding motor. Logic 01 and 10 will rotate it in
clockwise and anticlockwise directions, respectively.

Dept of ECE, KSSEM 7


Embedded Controller Lab (15ECL67) 6th Sem ECE KSSEM, Bangalore

NOTE: In the kit used in our experiment, we first need to ensure that the jumpers are connected to
the first 4 pins at the DC Motor side. The DC Motor is to be connected to the M1 port.

C - CODE:

#include "stm32f10x.h"

void delay(int time) //Delay Subroutine


{
int i,j;
for(i=0;i<=time;i++)
{
for(j=0;j<=72000;j++);
}
}

int main(void)
{
RCC ->APB2ENR |= 0x10; // Port C
GPIOC ->CRH = 0x1111; // Enable Pin 8-11 as O/P
GPIOC->ODR = 0x0000; // Clear ODR

// Use DC Motor Control on Pins 10-11


while (1)
{
GPIOC->ODR = 0x0100; // Rotate
delay(300);
GPIOC->ODR = 0x0000; // stop
delay(30);
GPIOC->ODR = 0x0200; // Reverse Direction
delay(300);
GPIOC->ODR = 0x0000; // Stop
delay(30);
}
}

RESULT:
Upon execution of the program the DC motor connected to the kit is seen to rotate in both clockwise
and anticlockwise directions alternatively.

Dept of ECE, KSSEM 8


Embedded Controller Lab (15ECL67) 6th Sem ECE KSSEM, Bangalore

PROGRAM 3

Stepper Motor Interface

Aim: To write a program to Interface a Stepper motor and rotate it in clockwise and anti-clockwise
directions.

Theory:
A stepper motor or step motor or stepping motor is a brushless DC electric motor that divides a
full rotation into a number of equal steps. Unlike a brushless DC motor which rotates continuously
when a fixed DC voltage is applied to it, a step motor rotates in discrete step angles. The Stepper Motors
therefore are manufactured with steps per revolution of 12, 24, 72, 144, 180, and 200, resulting in
stepping angles of 30, 15, 5, 2.5, 2, and 1.8 degrees per step. The stepper motor can be controlled with
or without feedback.

Stepper motors work on the principle of electromagnetism. There is a soft iron or magnetic rotor
shaft surrounded by the electromagnetic stators. The rotor and stator have poles which may be teethed
or not depending upon the type of stepper. When the stators are energized the rotor moves to align itself
along with the stator (in case of a permanent magnet type stepper) or moves to have a minimum gap
with the stator (in case of a variable reluctance stepper). This way the stators are energized in a sequence
to rotate the stepper motor.
Stepper motors are used in a number of applications where precise control of rotation angles are
required, for instance, in robotics, 3D printers, disk drives, etc. They are also very commonly used in
speed control applications in automation and robotics applications.
Despite their applications, they have a few limitations including reduced efficiency, limited high
speed torque and no feedback (unlike servo motors).

NOTE: In our kit, the Stepper Motor is connected to Pins 8-11 of Port C as Output. The jumper pins
should be on the Stepper Motor side of the pins.

C - CODE:
#include "stm32f10x.h"
void delay(int time) // Delay Subroutine
{
int i,j;
for(i=0;i<=time;i++)
{
for(j=0;j<=72000;j++);
}
}

Dept of ECE, KSSEM 9


Embedded Controller Lab (15ECL67) 6th Sem ECE KSSEM, Bangalore

int main(void)
{
RCC ->APB2ENR |= 0x10; // Port C
GPIOC ->CRH = 0x1111; //Enable Pins 8-11
GPIOC->ODR = 0x0000; // Clear ODR
while (1)
{
// Clockwise Rotation
GPIOC->ODR = 0x0100;
delay(50);
GPIOC->ODR = 0x0200;
delay(50);
GPIOC->ODR = 0x0400;
delay(50);
GPIOC->ODR = 0x0800;
delay(50);

// Anticlockwise Rotation
GPIOC->ODR = 0x0800;
delay(50);
GPIOC->ODR = 0x0400;
delay(50);
GPIOC->ODR = 0x0200;
delay(50);
GPIOC->ODR = 0x0100;
delay(50);
}
}

RESULT:
Upon execution of the program, it is observed that the Stepper motor connected to the microcontroller
rotates in the clockwise direction for one cycle, and then rotates in the anticlockwise direction in the
next cycle.

Dept of ECE, KSSEM 10


Embedded Controller Lab (15ECL67) 6th Sem ECE KSSEM, Bangalore

PROGRAM 4
Waveform Generation using DAC

Aim: To write a program to Interface a DAC and generate Triangular and Square waveforms

Theory:

In electronics, a digital-to-analog converter (DAC, D/A, D2A, or D-to-A) is a system that converts
a digital signal into an analog signal. There are several DAC architectures; the suitability of a DAC for
a particular application is determined by figures of merit including: resolution, maximum sampling
frequency and others. Digital-to-analog conversion can degrade a signal, so a DAC should be specified
that has insignificant errors in terms of the application.

DACs are commonly used in music players to convert digital data streams into analog audio
signals. They are also used in televisions and mobile phones to convert digital video data into analog
video signals which connect to the screen drivers to display monochrome or color images.

ST32F103RB used in our kit does not have a built-in DAC module. So, we use an external DAC
chip, MCP4921, a 12-bit DAC with SPI Interface in Slave Mode, for this experiment. The MCP4921
DAC can be used in single or dual channel mode. However, we will be using a single channel. It also
provides an option of using unity or 2x gain output. The MCP4921 provides a high accuracy and low
noise performance.

The connections to the STM32F103RB is as shown:

MOSI MOSI

MISO MISO

𝐶𝑆 𝐶𝑆

SCK SCK

STM32F103RB MCP4921

The STM32F103RB communicates with the MCP4921 DAC through SPI protocol, which involves
4 logical signal lines:
1. Master Output Slave Input (MOSI) – Data flows from Master to Slave
2. Master Input Slave Output (MISO) – Data flows from Slave to Master
3. Chip Select (CS) – Low on this pin selects a particular chip
4. SCK – Serial Clock – Used to synchronize data transfer

In the Kit, the connections to the DAC IC are as follows:


Vcc – 3.3 V of the Arduino Header
GND – GND of Arduino Header
MOSI – MOSI pin (Arduino Header D11 pin)
CS – Analog I/O pin A2 of Arduino Header
SCK – SCK Pin of Arduino Header (D13)

Dept of ECE, KSSEM 11


Embedded Controller Lab (15ECL67) 6th Sem ECE KSSEM, Bangalore

The Output is taken from Vout and GND pins of the DAC Chip, which are connected to the
leads of the CRO unit.

The Write Command Register of the DAC chip is as shown:

We see that the first 4 bits (15-12) are the control bits, while the last 12 bits (D11-D0) are the
data bits.
Bit 15 = 0, since we are writing to DACA.
Bit 14 = 1, since we are using VREF Input Buffer
Bit 13 = 1 since we are selecting unity output gain
Bit 12 = 1 since we are using the DAC in output power down mode.

During our program the first 4 bits are kept as 0111 (Hex 0x7), while the data is written to the
rest of the 12 bits.

C - CODE:

1. Triangular Waveform:

#include "stm32f10x.h"
void select(); // Select DAC
void deselect(); // Deselect DAC
void DelayMs(int time);
uint8_t SPI1_Transfer(uint8_t data); //8-bit SPI data
uint16_t DAC_write(uint16_t); //16-bit value to DAC

void int_spi() //SPI Configuration


{
//Configure SPI:Enable AFIO | SPI1 | IOPA
RCC->APB2ENR = 0x0001 | 0x1000 | 0x0004; //0x1005
GPIOA->CRL= 0xB4B30000;
// DAC Pinouts
//PA4 -> CS (Analog O/P) = 0011 (3)
//PA5 -> SCK (Alt Fn O/P) = 1011 (B)
//PA6 -> MISO (Floating Input) = 0100 (4)
//PA7 -> MOSI (Alt Fn O/P) = 1011 (B)
SPI1->CR1=0x00000374;
}

Dept of ECE, KSSEM 12


Embedded Controller Lab (15ECL67) 6th Sem ECE KSSEM, Bangalore

int main()
{
int i,j;
int_spi();
deselect();
while(1)
{
// Code to generate Triangular Waveform
i = 0;
while ( i != 4000 )
{
DAC_write(i);
i= i+100;
}
while ( i != 0 )
{
DAC_write(i);
i= i-100;
}

}
}

uint8_t SPI1_Transfer(uint8_t data) //SPI1 Data Transfer Subroutine


{
SPI1->DR = data; // Write data to be transmitted to the SPI data register
while (!(SPI1->SR & (0x0002))); // Wait until transmit complete
while (!(SPI1->SR & (0x0001))); // Wait until receive complete
while (SPI1->SR & (0x0080)); // Wait until SPI is not busy anymore
return SPI1->DR; // Return received data from SPI data register
}

void DelayMs(int time) //Delay Subroutine


{
int i,j;
for(i=0;i<=time;i++)
{
for(j=0;j<=3900;j++);
}

}
void select() {
GPIOA->BRR = 0x0010;
}
void deselect() {
GPIOA->BSRR = 0x0010;
}

uint16_t DAC_write(uint16_t valueDAC) //DAC Write Subroutine


{

Dept of ECE, KSSEM 13


Embedded Controller Lab (15ECL67) 6th Sem ECE KSSEM, Bangalore

uint16_t temp; //Declare 16-bit Value temp


uint8_t t; //Declare 8-bit value t

// Send Higher order Byte


temp = valueDAC; // Data to be written
temp = temp|0x7000; // Prepend 4 control bits to data
select(); // select MCP4921
t = ((temp >> 8) & 0xff); //Shift MS bytes to LS bytes
SPI1_Transfer(t); // Write MS byte to DAC via SPI

// Send Lower Order Byte


t = valueDAC; //Load only LSB 8 bits to value
SPI1_Transfer(t); //Write LSB byte to DAC
deselect(); // Deselect MCP4921
}

2. Square Waveform

#include "stm32f10x.h"
void select(); // Select DAC
void deselect(); // Deselect DAC
void DelayMs(int time);
uint8_t SPI1_Transfer(uint8_t data); //8-bit SPI data
uint16_t DAC_write(uint16_t); //16-bit value to DAC

void int_spi() //SPI Configuration


{
//Configure SPI:Enable AFIO | SPI1 | IOPA
RCC->APB2ENR = 0x0001 | 0x1000 | 0x0004; //0x1005
GPIOA->CRL= 0xB4B30000;
// DAC Pinouts
//PA4 -> CS (Analog O/P) = 0011 (3)
//PA5 -> SCK (Alt Fn O/P) = 1011 (B)
//PA6 -> MISO (Floating Input) = 0100 (4)
//PA7 -> MOSI (Alt Fn O/P) = 1011 (B)
SPI1->CR1=0x00000374;
}

int main()
{
int i,j;
int_spi();
deselect();
while(1)
{
// Code to generate Square Waveform
DAC_write(4095);
DelayMs(2);
DAC_write(0);

Dept of ECE, KSSEM 14


Embedded Controller Lab (15ECL67) 6th Sem ECE KSSEM, Bangalore

DelayMs(2);
}
}

uint8_t SPI1_Transfer(uint8_t data) //SPI1 Data Transfer Subroutine


{
SPI1->DR = data; // Write data to be transmitted to the SPI data register
while (!(SPI1->SR & (0x0002))); // Wait until transmit complete
while (!(SPI1->SR & (0x0001))); // Wait until receive complete
while (SPI1->SR & (0x0080)); // Wait until SPI is not busy anymore
return SPI1->DR; // Return received data from SPI data register
}

void DelayMs(int time) //Delay Subroutine


{
int i,j;
for(i=0;i<=time;i++)
{
for(j=0;j<=3900;j++);
}

}
void select() {
GPIOA->BRR = 0x0010;
}
void deselect(){
GPIOA->BSRR = 0x0010;
}

uint16_t DAC_write(uint16_t valueDAC) //DAC Write Subroutine


{
uint16_t temp; //Declare 16-bit Value temp
uint8_t t; //Declare 8-bit value t

// Send Higher order Byte


temp = valueDAC; // Data to be written
temp = temp|0x7000; // Prepend 4 control bits to data
select(); // select MCP4921
t = ((temp >> 8) & 0xff); //Shift MS bytes to LS bytes
SPI1_Transfer(t); // Write MS byte to DAC via SPI

// Send Lower Order Byte


t = valueDAC; //Load only LSB 8 bits to value
SPI1_Transfer(t); //Write LSB byte to DAC
deselect(); // Deselect MCP4921
}

Dept of ECE, KSSEM 15


Embedded Controller Lab (15ECL67) 6th Sem ECE KSSEM, Bangalore

OUTPUT WAVEFORMS:

1. Triangular Waveform:

2. Square Waveform:

OUTPUT: We observe that, upon execution of the program, triangular and square waveforms are
displayed on the CRO, which is connected to the output of the DAC unit.

Dept of ECE, KSSEM 16


Embedded Controller Lab (15ECL67) 6th Sem ECE KSSEM, Bangalore

PROGRAM 5
Keypad and LCD Interface

Aim: To write a program to Interface a 4x4 keyboard and display the key code on an LCD.

Theory:
A liquid crystal display (LCD) is a flat panel display, electronic visual display, or video display that uses the
light modulating properties of liquid crystals (LCs). LCs does not emit light directly.
The STM library allows a controller board to control Liquid Crystal displays (LCDs) based on the Hitachi
HD44780 (or a compatible) chipset, which is found on most text-based LCDs. The library works with in either
4- or 8-bit mode (i.e. using 4 or 8 data lines in addition to the RS, enable, and, optionally, the RW control lines).
The LCDs have a parallel interface, meaning that the microcontroller has to manipulate several interface pins at
once to control the display. The interface consists of the following pins:
• A register selects (RS) pin that controls where in the LCD's memory you're writing data to. You can
select either the data register, which holds what goes on the screen, or an instruction register, which is
where the LCD's controller looks for instructions on what to do next.
• A Read/Write (R/W) pin that selects reading mode or writing mode
• An Enable pin that enables writing to the registers
• 8 data pins (D0 -D7). The states of these pins (high or low) are the bits that you're writing to a register
when you write, or the values you're reading when you read.
• There's also a display contrast pin (Vo), power supply pins (+5V and Gnd) and LED Backlight
(Bklt+ and BKlt-) pins that you can use to power the LCD, control the display contrast, and
turn on and off the LED backlight, respectively.

4x4 Matrix Keypad


Typically one port pin is required to read a digital input into the controller. When there are a lot of digital
inputs that have to be read, it is not feasible to allocate one pin for each of them. This is when a matrix keypad
arrangement is used to reduce the pin count. Therefore, the number of pins that are required to interface a given
number of inputs decreases with increase in the order of the matrix.

Initially all switches are assumed to be released. So there is no connection between the rows and columns.
When any one of the switches are pressed, the corresponding row and column are connected (short circuited).
This will drive that column pin (initially high) low. Using this logic, the button press can be detected.

Dept of ECE, KSSEM 17


Embedded Controller Lab (15ECL67) 6th Sem ECE KSSEM, Bangalore

The first step involved in interfacing the matrix keypad is to write all logic 0’s to the rows and all logic 1’s
to the columns. Now the software has to scan the pins connected to columns of the keypad. If it detects a logic 0
in any one of the columns, then a key press was made in that column. Once the column corresponding to the key
pressed is located, the next thing that the software has to do is to start writing logic 1’s to the rows sequentially
(one after the other) and check if those columns becomes high. The logic is that if a button in that row was pressed,
then the value written to that row will be reflected in the corresponding column as they are short circuited.

Once the pressed key is detected, the software sends a couple of values indicating the corresponding row and
column number, indicating the button pressed.

In our kit:
LCD connections are as follows:
VSS & K -> Gnd VDD & A -> VCC 5V V0 -> 10k pot center terminal
RS -> PC.12 EN -> PC.13
D0-> PB.8 D1-> PB.9 D2-> PB.10 D3-> PB.11
D4-> PB.12 D5-> PB.13 D6-> PB.14 D7-> PB.15

Keypad Connections are as follows:


Keypad Columns:
KEYPAD_PIN_COL0 -> PC.7 KEYPAD_PIN_COL1 -> PC.6
KEYPAD_PIN_COL2 -> PC.5 KEYPAD_PIN_COL3 -> PC.4
Keypad Rows:
KEYPAD_PIN_ROW0 ->PC.3 KEYPAD_PIN_ROW1 ->PC.2
KEYPAD_PIN_ROW2 ->PC.1 KEYPAD_PIN_ROW3 ->PC.0

NOTE:
 In the kit, ensure that the jumpers are connecting the 4x4 keypad side, as well as the 16x2 LCD Display
side. This is important to ensure that both the keypad and LCD Display are being used in the
experiment.
 While writing the code, do not forget to include the extra libraries – the libraries “keypad4x4-
simultaneous-scanning.h” and “keypad4x4-simultaneous-scanning.c” which maps the keypad buttons to
the pins, and a library “delay.c” to include delay subroutines.

Dept of ECE, KSSEM 18


Embedded Controller Lab (15ECL67) 6th Sem ECE KSSEM, Bangalore

C - CODE:
#include <stdio.h>
#include "stm32f10x.h"
#include "keypad4x4-simultaneous-scanning.h"
int i,j,t;
static int ini_lcd=0;
uint8_t key;

void delay(int time)


{
for(i=0;i<=time;i++)
{
int j;
for(j=0;j<=64000;j++);
}
}

void command_lcd(unsigned char cmd)


{
GPIOC->ODR = 0x2000; // rs=0 en=1 0010 0000 0000 0000
t=(cmd<<8)& (0xFF00);
GPIOB->ODR = t;
delay(10);
GPIOC->ODR = 0x0000; // rs=0 rw=0 en=0
}

void data_lcd(unsigned char data)


{
GPIOC->ODR = 0x3000; // rs=1 rw=0 en=1 0011 0000 0000 0000
t=(data<<8)& (0xFF00);
GPIOB->ODR = t;
delay(10);
GPIOC->ODR = 0x1000; // rs=1 rw=0 en=0 0001 0000 0000 0000
delay(10);
}

void lcd_ini() //Function to prepare the LCD and get it ready


{
command_lcd(0x38); // for using 2 lines and 16x2 matrix of LCD
delay(20);
command_lcd(0x0F); // turn display ON, cursor blinking
delay(20);
command_lcd(0x01); //clear screen
delay(20);
command_lcd(0x80); // bring cursor to position 1 of line 1
delay(20);
}
void string_lcd(unsigned char* t)
{
while(*t != '\0')

Dept of ECE, KSSEM 19


Embedded Controller Lab (15ECL67) 6th Sem ECE KSSEM, Bangalore

{
data_lcd(*t);
t++;
}
}
int main(void)
{

//RCC - Reset and Clock Control


// 0x14 in binary = 00010100 = [0001][0100] = [IOPF IOPE IOPD IOPC IOPB IOPA Res. AFIO]
RCC ->APB2ENR |= 0x10 | 0x08;
//CRH - Port Configuration Register High *pins 8-15
GPIOC ->CRH= 0x00110000; //for RS and ES
//CRL- Port Configuration Register High *pins 8-15
GPIOB ->CRH = 0x11111111; //for LCD
KeypadInit();
if(ini_lcd==0)
lcd_ini();
ini_lcd++;
command_lcd(0x80);
string_lcd("Tenet Tech");
command_lcd(0xC0);
string_lcd("Press Key-> ");
while(1)
{
key = KeypadGetKey();
// Display pressed char to LCD
if (key != KEYPAD_NO_PRESSED)
{
command_lcd(0xCC);
data_lcd(key);
delay(5);
command_lcd(0x01); //clear screen
}
}
}

OUTPUT:
We see that, upon execution, the 16x2 LCD Display indicates the button pressed, on the 4x4 pushbutton
grid. Whenever a button is pressed in the keypad, the corresponding button number is displayed on the LCD
display.

Dept of ECE, KSSEM 20


Embedded Controller Lab (15ECL67) 6th Sem ECE KSSEM, Bangalore

PROGRAM 6

PWM Generation using Internal PWM

Aim: To generate PWM waveform using the Internal PWM module of ARM controller and vary its
duty cycle.

Theory:
Pulse-width modulation (PWM), or pulse-duration modulation (PDM), is a modulation technique
used to encode a message into a pulsing signal. Although this modulation technique can be used to
encode information for transmission, its main use is to allow the control of the power supplied to
electrical devices, especially to inertial loads such as motors.

A PWM signal consists of two main components that define its behavior: a duty cycle and a
frequency. The duty cycle describes the amount of time the signal is in a high (on) state as a percentage
of the total time of it takes to complete one cycle. The frequency determines how fast the PWM
completes a cycle, and therefore how fast it switches between high and low states. By cycling a digital
signal off and on at a fast enough rate, and with a certain duty cycle, the output will appear to behave
like a constant voltage analog signal when providing power to devices.

PWM signals are used for a wide variety of control applications. Their main use is for controlling
DC motors but it can also be used to control valves, pumps, hydraulics, and other mechanical parts.

The STM32 Family processors include general purpose timers with PWM function that can handle
four channels of independently controlled duty cycles. There are three general purpose 16-bit Timers,
each with up to 4 PWM inputs, and a 16-bit motor control PWM timer. Here, we use the General
Purpose timer, TIM2 to generate PWM pulse.

TIM2 is connected to APB1 bus that has default system clock of 72MHz. So, the frequency of TIM2
is 72MHz. If we use a prescaler value of 10 (To be specified in TIM2 Configuration), the clock timer
will have a frequency of 72 MHz/10 = 7.2 MHz.

The PWM frequency can be calculated by:


𝐶𝑙𝑜𝑐𝑘 𝑇𝑖𝑚𝑒𝑟
𝑃𝑊𝑀 𝑓𝑟𝑒𝑞𝑢𝑒𝑛𝑐𝑦 =
(𝑇𝐼𝑀𝐸_𝑃𝑒𝑟𝑖𝑜𝑑 + 1)
Hence, the total time period of the pulse (Ton + Toff) is calculated as:
𝐶𝑙𝑜𝑐𝑘 𝑇𝑖𝑚𝑒𝑟
𝑇𝐼𝑀𝐸_𝑃𝑒𝑟𝑖𝑜𝑑 = –1
𝑃𝑊𝑀 𝑓𝑟𝑒𝑞𝑢𝑒𝑛𝑐𝑦
Where Timer Clock = 7.2 MHz.
If PWM frequency = 1 kHz, we get: 𝑻𝑰𝑴𝑬_𝑷𝒆𝒓𝒊𝒐𝒅 = 𝟕𝟏𝟗𝟗 (To be specified in TIM2 Config).

Dept of ECE, KSSEM 21


Embedded Controller Lab (15ECL67) 6th Sem ECE KSSEM, Bangalore

In order to calculate the On_Time for generating the PWM pulse with the given duty cycle, we use
the equation:
(𝑇𝐼𝑀𝐸_𝑃𝑒𝑟𝑖𝑜𝑑 + 1) ∗ 𝑑𝑢𝑡𝑦_𝑐𝑦𝑐𝑙𝑒
𝑇𝐼𝑀𝐸_𝑃𝑢𝑙𝑠𝑒_𝑂𝑛 = ( ) − 1
100

So, for 25% duty cycle, we get:


(7199 + 1) ∗ 25
𝑇𝐼𝑀𝐸_𝑃𝑢𝑙𝑠𝑒_𝑂𝑛 = ( ) − 1 = 𝟏𝟕𝟗𝟗
100
So, for 50% duty cycle, we get:
(7199 + 1) ∗ 50
𝑇𝐼𝑀𝐸_𝑃𝑢𝑙𝑠𝑒_𝑂𝑛 = ( ) − 1 = 𝟑𝟓𝟗𝟗
100

So, for 75% duty cycle, we get:


(7199 + 1) ∗ 25
𝑇𝐼𝑀𝐸_𝑃𝑢𝑙𝑠𝑒_𝑂𝑛 = ( ) − 1 = 𝟓𝟑𝟗𝟗
100

NOTE: In our Kit, the PWM Output is taken at PA0, where the CRO leads are connected. This
experiment has a code which varies the duty cycle of the PWM wave from 0-75%.
If a constant Duty Cycle has to be maintained, replace the while loop with a single value of i
corresponding to the required duty cycle as calculated above.

C - CODE:

#include "stm32f10x.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_tim.h"

void PWM_Init(void);

void Delay(int time) //Delay Subroutine


{
int i,j;
for(i=0;i<=time;i++)
{
for(j=0;j<=72000;j++);
}
}

int main(void)
{
PWM_Init(); // Initialize PWM
int i = 0;
while (1)
{
while(i<=5399) //Cycle On-Time from 0-75%
{
TIM2->CCR1 = i; //Write On-Time value to TIM2 CCR
i+=100; //Increment On-Time by 100
Delay(10);
}

Dept of ECE, KSSEM 22


Embedded Controller Lab (15ECL67) 6th Sem ECE KSSEM, Bangalore

i=0; //Reset to 0
}
}
void PWM_Init() //PWM Initialization Subroutine
{
// Initialization Structure
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
TIM_OCInitTypeDef TIM_OCInitStruct;
GPIO_InitTypeDef GPIO_InitStruct;

// Step 1: Initialize TIM2


RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_TimeBaseInitStruct.TIM_Prescaler = 10;
TIM_TimeBaseInitStruct.TIM_Period = 7199;
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);
TIM_Cmd(TIM2, ENABLE); // Start TIM2

// Step 2: Initialize PWM


// Common PWM settings
TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;

// Initialize PWM value with duty cycle of 0%


TIM_OCInitStruct.TIM_Pulse = 0;
TIM_OC1Init(TIM2, &TIM_OCInitStruct);
TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable);

// Step 3: Initialize GPIOA (PA0)


// Initialize PA0 as push-pull alternate function (PWM output) for LED
RCC->APB2ENR=0x04; // Use LED brightness as indicator
GPIOA->CRL=0x0A;
}

OUTPUT:

Upon Execution of the program, it is observed that the CRO displays a PWM pulse train. The Duty
Cycle of the PWM pulse train varies from 0% to 75%, and this process repeats.

Dept of ECE, KSSEM 23


Embedded Controller Lab (15ECL67) 6th Sem ECE KSSEM, Bangalore

PROGRAM 7

LED control using External Interrupts

Aim: To write a program to demonstrate the use of an external interrupt to toggle an LED
On/Off.
Theory:

In system programming, an interrupt is a signal to the processor emitted by hardware or software


indicating an event that needs immediate attention. An interrupt alerts the processor to a high-priority
condition requiring the interruption of the current code the processor is executing. The processor
responds by suspending its current activities, saving its state, and executing a function called an interrupt
handler (or an interrupt service routine, ISR) to deal with the event. This interruption is temporary, and,
after the interrupt handler finishes, the processor resumes normal activities. The act of initiating a
hardware interrupt is referred to as an interrupt request (IRQ).

There are two types of interrupts: hardware interrupts and software interrupts. Hardware interrupts
are used by devices to communicate that they require attention from the operating system. Unlike the
software type, hardware interrupts are asynchronous and can occur in the middle of instruction
execution. A software interrupt is caused either by an exceptional condition in the processor itself, or a
special instruction in the instruction set which causes an interrupt when it is executed. Software interrupt
instructions can function similarly to subroutine calls and are used for a variety of purposes, such as to
request services from device drivers, like interrupts sent to and from a disk controller to request reading
or writing of data to and from the disk.

The STM32F103xx performance line embeds a nested vectored interrupt controller able to handle
up to 43 maskable interrupt channels (not including the 16 interrupt lines of Cortex®-M3) and 16
priority levels. The external interrupt/event controller consists of 19 edge detector lines used to generate
interrupt/event requests. Each line can be independently configured to select the trigger event (rising
edge, falling edge, both) and can be masked independently. A pending register maintains the status of
the interrupt requests. The EXTI can detect an external line with a pulse width shorter than the Internal
APB2 clock period. Up to 80 GPIOs can be connected to the 16 external interrupt lines.

C - CODE:
#include "stm32f10x.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_exti.h"

void DelayMs(int time) //Delay Subroutine


{
int i,j;
for(i=0;i<=time;i++)
{
for(j=0;j<=64000;j++);
}
}

void EXTI9_5_Init(void);
void wait(unsigned int nCount);

Dept of ECE, KSSEM 24


Embedded Controller Lab (15ECL67) 6th Sem ECE KSSEM, Bangalore

void EXTI9_5_IRQHandler(void) //Interrupt Handler


{
// Checks whether the interrupt is from EXTI12 or not
if (EXTI_GetITStatus(EXTI_Line6))
{
// Blink LED on PA9 5 times
int i;
for (i = 0; i < 5; i++)
{
GPIOA->BSRR = GPIO_Pin_9;
DelayMs(30);
GPIOA->BRR = GPIO_Pin_9;
DelayMs(30);
}
EXTI_ClearITPendingBit(EXTI_Line6);
}
}

int main(void)
{
EXTI9_5_Init(); // Initialize exernal interrupt
RCC ->APB2ENR |= 0x04;
GPIOA ->CRH = 0x00000011;
while (1)
{
GPIOA->BRR = GPIO_Pin_8; //Default Blink LED
DelayMs(50);
GPIOA->BSRR = GPIO_Pin_8;
DelayMs(50);
}
}

void EXTI9_5_Init()
{
// Initalization struct
GPIO_InitTypeDef GPIO_InitStruct;
EXTI_InitTypeDef EXTI_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;

// Initialize PB6 as input with pull-up resistor


RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOC, &GPIO_InitStruct);

// Initialize PB6 to EXTI


RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource6);

Dept of ECE, KSSEM 25


Embedded Controller Lab (15ECL67) 6th Sem ECE KSSEM, Bangalore

// Initialize EXTI line 6 for PB6


EXTI_InitStruct.EXTI_Line = EXTI_Line6;
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStruct.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStruct);

// Initialize NVIC for EXTI9_5 IRQ channel


NVIC_InitStruct.NVIC_IRQChannel = EXTI9_5_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
}

OUTPUT:
We see that upon execution, the LED 1 keeps blinking by default, indicating normal operation. When
Pushbutton 2 is pressed, the LED 1 stops blinking, and LED 2 blinks 5 times, denoting interrupt
operation. Once this is done, LED 1 resumes blinking.

Dept of ECE, KSSEM 26


Embedded Controller Lab (15ECL67) 6th Sem ECE KSSEM, Bangalore

PROGRAM 8

7-Segment LED Display

Aim: To write a program to display the Hex digits 0 to F on a 7-segment LED interface, with
an appropriate delay in between.

Theory:
A seven-segment display (SSD), or seven-segment indicator, is a form of electronic display device
for displaying decimal numerals that is an alternative to the more complex dot-matrix displays. Seven-
segment displays are widely used in digital clocks, electronic meters, and other electronic devices for
displaying numerical information.

The 7-segment display, consists of seven LEDs arranged in a rectangular fashion as shown. Each of
the seven LEDs is called a segment because when illuminated the segment forms part of a numerical
digit (both Decimal and Hex) to be displayed. An additional 8th LED is sometimes used within the
same package thus allowing the indication of a decimal point, (DP) when two or more 7-segment
displays are connected together to display numbers greater than ten.

Each one of the seven LEDs in the display is given a positional segment with one of its connection
pins being brought straight out of the rectangular plastic package. These individually LED pins are
labelled from a through to g representing each individual LED. The other LED pins are connected
together and wired to form a common pin.

So, by forward biasing the appropriate pins of the LED segments in a particular order, some
segments will be light and others will be dark allowing the desired character pattern of the number to
be generated on the display. This then allows us to display each of the ten decimal digits 0 through to 9
on the same 7-segment display.

7-segement LED displays are of two types:


 Common Anode (CA), where all the anode connections of the LED segments are joined
together to logic “1”. The individual segments are illuminated by applying a ground, logic “0”
or “LOW” signal via a suitable current limiting resistor to the Cathode of the particular segment.
This is the type used in our kit.
 Common Cathode (CC), where all the cathode connections of the LED segments are joined
together to logic “0” or ground. The individual segments are illuminated by application of a
“HIGH”, or logic “1” signal via a current limiting resistor to forward bias the individual Anode
terminals

Dept of ECE, KSSEM 27


Embedded Controller Lab (15ECL67) 6th Sem ECE KSSEM, Bangalore

Depending upon the decimal digit to be displayed, the particular set of LEDs is forward biased. For
instance, to display the numerical digit 0, we will need to light up six of the LED segments
corresponding to a, b, c, d, e and f. Thus the various digits from 0 through 9 can be displayed using a
7-segment display as shown.

Then for a 7-segment display, we can produce a truth table giving the individual segments that need
to be illuminated in order to produce the required decimal digit from 0 through 9 as shown below.

Digit DP G F E D C B A Hex
0 1 1 1 0 0 0 0 0 C0
1 1 1 1 1 1 0 0 1 F9
2 1 0 1 0 0 1 0 0 A4
3 1 0 1 1 0 0 0 0 B0
4 1 0 0 1 1 0 0 1 99
5 1 0 0 1 0 0 1 0 92
6 1 0 0 0 0 0 1 0 82
7 1 1 1 1 1 0 0 0 F8
8 1 0 0 0 0 0 0 0 80
9 1 0 0 1 0 0 0 0 90
A 1 0 0 0 1 0 0 0 88
B 1 0 0 0 0 0 1 1 83
C 1 1 0 0 0 1 1 0 C6
D 1 0 1 0 0 0 0 1 A1
E 1 0 0 0 0 1 1 0 86
F 1 0 0 0 1 1 1 0 8E

NOTE: In our kit, in order to ensure that the 7-Segment LEDs are operational, jumpers should be
switched to the 7-Segment side, rather than the 16x2 LCD side.

C - CODE:

#include <stm32f10x.h>

void delay(int time) //Delay Subroutine


{
int i,j;
for(j=0;j<=time;j++)
{
for(i=0;i<=72000;i++);
}
}

int main()
{
RCC->APB2ENR = 0x08; //Port B

Dept of ECE, KSSEM 28


Embedded Controller Lab (15ECL67) 6th Sem ECE KSSEM, Bangalore

GPIOB->CRH=0X11111111; //Enable all pins


GPIOB->ODR = 0x00000000; //Clear LED Display
delay(100);
while(1)
{
GPIOB->ODR = 0xC000; //Hex for displaying 0
delay(100);
GPIOB->ODR = 0xF900; // Hex for displaying 1
delay(100);
GPIOB->ODR = 0xA400; // Hex for displaying 2
delay(100);
GPIOB->ODR = 0xB000; // Hex for displaying 3
delay(100);
GPIOB->ODR = 0x9900; // Hex for displaying 4
delay(100);
GPIOB->ODR = 0x9200; // Hex for displaying 5
delay(100);
GPIOB->ODR = 0x8200; // Hex for displaying 6
delay(100);
GPIOB->ODR = 0xf800; // Hex for displaying 7
delay(100);
GPIOB->ODR = 0x8000; // Hex for displaying 8
delay(100);
GPIOB->ODR = 0x9000; // Hex for displaying 9
delay(100);
GPIOB->ODR = 0x8800; // Hex for displaying A
delay(100);
GPIOB->ODR = 0x8300; // Hex for displaying B
delay(100);
GPIOB->ODR = 0xC600; // Hex for displaying C
delay(100);
GPIOB->ODR = 0xa100; // Hex for displaying D
delay(100);
GPIOB->ODR = 0x8600; // Hex for displaying E
delay(100);
GPIOB->ODR = 0x8e00; // Hex for displaying F
delay(100);
}
}

Result:
Upon execution of the program, the 7-Segment LED Display indicates hexadecimal numbers
from 0-F and cycles through them with a small delay in between.

Dept of ECE, KSSEM 29


Embedded Controller Lab (15ECL67) 6th Sem ECE KSSEM, Bangalore

PROGRAM 9

Switch Control of Buzzer, Relay and LED

AIM: To write a program to Interface a simple Switch and display its status through Relay,
Buzzer and LED.

Theory:
BUZZER
Piezo buzzer is an electronic device commonly used to produce sound. Light weight, simple
construction and low price make it usable in various applications like car/truck reversing indicator,
computers, call bells etc. Piezo buzzer is based on the inverse principle of piezo electricity discovered
in 1880 by Jacques and Pierre Curie. It is the phenomena of generating electricity when mechanical
pressure is applied to certain materials and the vice versa is also true. Such materials are called piezo
electric materials. Piezo electric materials are either naturally available or manmade. Piezo ceramic is
class of manmade material, which poses piezo electric effect and is widely used to make disc, the heart
of piezo buzzer. When subjected to an alternating electric field they stretch or compress, in accordance
with the frequency of the signal thereby producing sound.

RELAY
A relay is an electrically operated switch. Many relays use an electromagnet to mechanically operate
a switch, but other operating principles are also used, such as solid-state relays. Relays are used where
it is necessary to control a circuit by a separate low-power signal, or where several circuits must be
controlled by one signal.
A type of relay that can handle the high power required to directly control an electric motor or other
loads is called a contactor. Solid-state relays control power circuits with no moving parts, instead using
a semiconductor device to perform switching. Relays with calibrated operating characteristics and
sometimes multiple operating coils are used to protect electrical circuits from overload or faults.
Magnetic latching relays require one pulse of coil power to move their contacts in one direction, and
another, redirected pulse to move them back. Repeated pulses from the same input have no effect.
Magnetic latching relays are useful in applications where interrupted power should not be able to
transition the contacts.

NOTE: In our kit, the Relay is connected to Pin 2 of Port C, Buzzer to Pin 3 of Port C, Push Button 1
is connected to Pin 4 of Port C, and Push Button 2 is connected to Pin 5 of Port C.
Hence, PC2 and PC3 have to be configured as outputs and PC4 and PC5 have to be configured as
Inputs.

C - CODE:

1. Relay Control

#include "stm32f10x.h" // device header file

int main(void)
{
RCC ->APB2ENR |= 0x10 ; // PORT-C peripheral clock selected
// Set PC2 (Relay) as Output, and PC5 (Push Button 2) as Input
GPIOC ->CRL = 0x00400100;

Dept of ECE, KSSEM 30


Embedded Controller Lab (15ECL67) 6th Sem ECE KSSEM, Bangalore

while (1)
{
if((GPIOC ->IDR & (1<<5)) == 0 ) // Read the Push button data register
{
GPIOC ->BSRR = ~(1<<2); // Turn Relay On
}
else
{
GPIOC ->BSRR = (1<<2); // Turn Relay Off
}

}
}

2. Buzzer Control

#include "stm32f10x.h" // device header file

int main(void)
{
RCC ->APB2ENR |= 0x10 ; // PORT-C peripheral clock selected
// Set PC3 (Buzzer) as Output, and PC4 (Push Button 1) as Input
GPIOC ->CRL = 0x00041000;

while (1)
{
if(GPIOC->IDR & GPIO_IDR_IDR4 )
{
GPIOC ->BSRR = (1<<3); //Turn Buzzer ON
}
else
{
GPIOC ->BSRR = ~(1<<3); //Turn Buzzer OFF
}

}
}

OUTPUT:
We observe that when Pushbutton 1 is pressed, the Buzzer is turned on, and when the button is
released, the buzzer turns off. When Push button 2 is pressed, the Relay is turned on, and the LED
glows. When the push button 2 is released, the Relay and LED are turned off.

Dept of ECE, KSSEM 31


Embedded Controller Lab (15ECL67) 6th Sem ECE KSSEM, Bangalore

PROGRAM 10

Temperature Measurement using ADC

Aim: To write a program to measure Ambient temperature using a sensor and SPI ADC IC.
Theory:
Analog to Digital Converters (ADCs) are electronic devices that convert continuous analog signals such as
electric current into digital values. Two 12-bit analog-to-digital converters are embedded into STM32F103xx
performance line devices and each ADC shares up to 16 external channels, performing conversions in single-shot
or scan modes. An analog watchdog feature allows very precise monitoring of the converted voltage of one, some
or all selected channels. An interrupt is generated when the converted voltage is outside the programmed
thresholds. The Maximum ADC conversion rate is 1MHz and more than 2MHz in some STM32 families. It has
an A/D conversion range of 0 – 3.6V DC, and the ADC power supply operating range is 2.4V – 3.6V DC.
In the STM32 line of controllers, there are two modes of operation primarily. These are:
 Independent mode. It is just as the typical ADC use. Each ADC unit is operating on its own and without any
mutual dependency.
 Dual mode. In this mode two ADCs are converted simultaneously or with some (literally negligible) delay.
Two ADC units mutually working together as if they are a single unit.

A/D conversion can be:


 Single Conversion. One sample conversion at a given instant.
 Continuous Conversion. Non-stop sample collection and conversion.
 Discontinuous Conversion. Sequential conversion of some channels in a group.
 Scan Conversion. Sequential sampling and converting of an array of channels one after another.

To start A/D conversion, an ADC unit needs to be stimulated with a trigger signal:
 Software Trigger. A/D conversion as per demand from coded program.
 Hardware Trigger. A/D conversion as per hardware events like external interrupts or timer events.

In our code, we use our ADC 1 in independent mode, with continuous conversion occurring, with a software
trigger.
Since the analog signal can take values from 0-3.3 V, and since the ADC resolution is 12 bits (4096 intervals), the
corresponding digital value for the measured analog input is by:
3.3 𝑉
𝐷𝑖𝑔𝑖𝑡𝑎𝑙 𝑉𝑎𝑙𝑢𝑒 = 𝐴𝑛𝑎𝑙𝑜𝑔 𝑉𝑎𝑙𝑢𝑒 ∗ 4095

NOTE: In our kit, the LM35 Temperature Sensor Module has to be connected to the Temp section. UART
protocol is used to transmit the data to the serial window, and as a result, a serial window monitoring application
like PuTTy has to be used.

Dept of ECE, KSSEM 32


Embedded Controller Lab (15ECL67) 6th Sem ECE KSSEM, Bangalore

C - CODE:

#include <stdio.h>
#include "stm32f10x.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_adc.h"

int USART_PutChar(int ch);


void delay(int time);
struct __FILE { int handle;};
FILE __stdout;
FILE __stdin;

int fputc(int c, FILE *f) //USART Character Write subroutine


{
return (USART_PutChar(c));
}

void _ttywrch(int c) //This function writes a character to the console


{
USART_PutChar(c);
}

// Creating GPIO and ADC objects


GPIO_InitTypeDef myGPIO;
ADC_InitTypeDef myADC;

int USART_PutChar(int ch) //Send Character to USART


{
while(!(USART2->SR & USART_SR_TXE));
USART2->DR = ch;
}

void adc_config() //ADC Configuration Subroutine


{
//ADC1 setup
myGPIO.GPIO_Pin = GPIO_Pin_0; //Set to pin 0 for Temperature
myGPIO.GPIO_Mode = GPIO_Mode_AIN; //GPIO Analog Input
GPIO_Init(GPIOA, &myGPIO); //Set to A0

RCC_ADCCLKConfig (RCC_PCLK2_Div6); //clock for ADC (max 14MHz, 72/6=12MHz)


RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //enable ADC clock
myADC.ADC_ContinuousConvMode = ENABLE;
myADC.ADC_NbrOfChannel = 1;
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5); //PA0 as Input
ADC_Init(ADC1, &myADC);

Dept of ECE, KSSEM 33


Embedded Controller Lab (15ECL67) 6th Sem ECE KSSEM, Bangalore

ADC_Cmd(ADC1, ENABLE); //Enable ADC

//Calibrate ADC
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
ADC_Cmd(ADC1, ENABLE); //Enable ADC to work

int getADC(void) //Acquire Analog Value at pin


{
return ADC_GetConversionValue(ADC1); //Return Converted Value
}

int main(void)
{
float x;
RCC->APB2ENR = RCC_APB2ENR_IOPAEN ;
RCC->APB1ENR = RCC_APB1ENR_USART2EN;
GPIOA->CRL = 0x00004B00; // 0100 ->3 1011 ->2 0000->1 0000->0
USART2->CR1 = USART_CR1_UE | USART_CR1_TE;
USART2->BRR = (SystemCoreClock / (9600*2)); // baud rate change
adc_config(); //configure ADC

while(1)
{
x = getADC()*3.3/4095.0; //Get analog value and convert to volts, 12bit ADC
float temp= x/0.01; // Convert to Temperature
printf("Temperature Value-> %.2f\n\r",temp);
delay(40);
}
}

void delay(int time) //Delay Subroutine


{
int i,j;
for(i=0;i<=time;i++)
{
for(j=0;j<=72000;j++);
}
}

RESULTS:
Upon execution of the program, it is observed that the temperature value sensed by the LM35 unit is displayed
continuously in the Serial Monitoring window, which can be viewed using a suitable application like PuTTY.

Dept of ECE, KSSEM 34


Embedded Controller Lab (15ECL67) 6th Sem ECE KSSEM, Bangalore

ALP to Find the Sum of First 10 Numbers

CODE:
AREA RESET, DATA, READONLY
EXPORT __Vectors
__Vectors
DCD 0x20001000 ; stack pointer value when stack is empty
DCD Reset_Handler ; reset vector
ALIGN
AREA MYCODE, CODE, READONLY
ENTRY
EXPORT Reset_Handler
Reset_Handler
MOV R0, #0 ; R0 accumulates total
MOV R1, #10 ; R1 counts from 10 down to 1
again ADD R0, R0, R1
SUBS R1, R1, #1
BNE again
halt B halt ; infinite loop to stop computation

Dept of ECE, KSSEM 35


Embedded Controller Lab (15ECL67) 6th Sem ECE KSSEM, Bangalore

ALP to Find the Product of two 16-bit Numbers

CODE:
AREA RESET, DATA, READONLY
EXPORT __Vectors
__Vectors
DCD 0x20001000 ; stack pointer value when stack is empty
DCD Reset_Handler ; reset vector
ALIGN
AREA MYCODE, CODE, READONLY
ENTRY
EXPORT Reset_Handler
Reset_Handler
MOV R0, 0x4 ; R0 accumulates total
MOV R1, 0x1
again MUL R3, R0, R1
halt B halt ; infinite loop to stop computation

Dept of ECE, KSSEM 36