Anda di halaman 1dari 107

List of Experiments (STM32F407VG)

1. Study of ARM Evaluation System


2. Interfacing ADC and DAC
3. Interfacing PWM and LED
4. Interfacing Real-time clock and Serial Port
5. Interfacing Keypad and LCD
6. Interfacing EEPROM and Interrupt
7. Mailbox
8. Interrupt performance characteristics of ARM and FPGA
9. Flashing of LED
10. Interfacing Stepper motor and Temperature sensor
11. Interfacing Zig-bee Protocol and ARM

Experiment 1
Study of ARM Evaluation System
Aim
To learn about the evolution, core features, general characteristics and applications of
ARM processors.
Theory
The VSK STM4 syllabus board is a demonstration and development platform for the
STM32F4 series and includes an embedded STM32F407VG high-performance ARM Cortex-M4 32bit microcontroller. The full range of hardware features on the board is provided to help you
evaluate all peripherals (Ethernet, motor control, CAN, USART etc.) and develop your own
applications. Extension headers make it possible to easily connect a daughterboard or wrapping board
for your specific application.
Features

Core: ARM 32-bit Cortex-M4 CPU with FPU, Adaptive real-time accelerator

(ART Accelerator)

allowing 0-wait state execution from Flash memory, frequency

up to 168 MHz, memory protection unit, 210 DMIPS/ 1.25


DMIPS/MHz (Dhrystone 2.1), and DSP instructions

Memories

Up to 1 Mbyte of Flash memory

Up to 192+4 Kbytes of SRAM including 64- Kbyte of CCM (core coupled memory)

data RAM
Flexible static memory controller supporting Compact Flash, SRAM, PSRAM,

NOR and NAND memories


LCD parallel interface, 8080/6800 modes

Low-power operation

Sleep, Stop and Standby modes

VBAT supply for RTC, 2032 bit backup registers + optional 4 KB backup

Clock, reset and supply management

1.8 V to 3.6 V application supply and I/Os

POR, PDR, PVD and BOR

4-to-26 MHz crystal oscillator

Internal 16 MHz factory-trimmed RC (1% accuracy)

32 kHz oscillator for RTC with calibration

Internal 32 kHz RC with calibration

SRAM

312-bit, 2.4 MSPS A/D converters: up to 24 channels and 7.2 MSPS in triple interleaved

mode
212-bit D/A converters

General-purpose DMA: 16-stream DMA controller with FIFOs and burst support

Up to 17 timers: up to twelve 16-bit and two 32- bit timers up to 168 MHz, each with up to

4 IC/OC/PWM or pulse counter and quadrature (incremental) encoder input


Debug mode

Serial wire debug (SWD) & JTAG interfaces

Cortex-M4 Embedded Trace Macrocell

Up to 140 I/O ports with interrupt capability

Up to 136 fast I/Os up to 84 MHz

Up to 138 5 V-tolerant I/Os

Up to 15 communication interfaces

Up to 3 I2C interfaces (SMBus/PMBus)

Up to 4 USARTs/2 UARTs (10.5 Mbit/s, ISO 7816 interface, LIN, IrDA, modem

control)
Up to 3 SPIs (42 Mbits/s), 2 with muxed full-duplex I2S to achieve audio class

accuracy via internal audio PLL or external clock


2 CAN interfaces (2.0B Active)

SDIO interface

Advanced connectivity

USB 2.0 full-speed device/host/OTG controller with on-chip PHY

USB 2.0 high-speed/full-speed device/host/OTG controller with dedicated

DMA, on-chip full-speed PHY and ULPI

10/100 Ethernet MAC with dedicated DMA: supports IEEE 1588v2 hardware,

MII/RMII
8- to 14-bit parallel camera interface up to 54 Mbytes/s

True random number generator

CRC calculation unit

96-bit unique ID

RTC: subsecond accuracy, hardware calendar.

ARCHITECTURAL OVERVIEW
In STM32F405xx/07xx and STM32F415xx/17xx, the main system consists of 32-bit multilayer
AHB bus matrix that interconnects: The main system consists of 32-bit multilayer AHB bus
matrix that interconnects:

Eight masters:

Cortex -M4 with FPU core I-bus, D-bus and S-bus

DMA1 memory bus

DMA2 memory bus

DMA2 peripheral bus

Ethernet DMA bus

USB OTG HS DMA bus

Seven slaves:

Internal Flash memory ICode bus

Internal Flash memory DCode bus

Main internal SRAM1 (112 KB)

Auxiliary internal SRAM2 (16 KB)

AHB1 peripherals including AHB to APB bridges and APB peripherals

AHB2 peripherals
FSMC

The bus matrix provides access from a master to a slave, enabling concurrent access and

efficient operation even when several high-speed peripherals work simultaneously. The
64- Kbyte CCM (core coupled memory) data RAM is not part of the bus matrix and can be
accessed only through the CPU.

BLOCK DIAGRAM

4
04

Result
The evolution, core features, general characteristics and the applications of ARM
processors has been studied and is evaluated.

Experiment 2
Interfacing ADC and DAC
Aim
To develop a C-Language program for reading an on-chip ADC, convert into decimal and to
display it in PC and to generate a square wave depending on this ADC reading. The ADC input is
connected to any analog sensor/ on board potentiometer.

Apparatus & Software Required


1. VSK-SCM4 Development board.
2. IAR IDE software.
3. Flash Loader Demonstrator. .
4. CRO
Theory
ADC
Three 12-bit analog-to-digital converters are embedded and each ADC shares up to 16 external
channels, performing conversions in the single-shot or scan mode. In scan mode, automatic
conversion is performed on a selected group of analog inputs.
Additional logic functions embedded in the ADC interface allow:

Simultaneous sample and hold

Interleaved sample and hold

Procedure
1. Follow the steps 1 of How to create a New project
2. Type the below code and save it with the name (anyname.c)
3. Follow the steps 2 to 6 of How to create a New Project to add the necessary file, compile and build
the program
4.

Follow the procedures in How to Download a Code to Our Controller to download


your code.

Program
#include "stm32f4xx.h"
#include <stdio.h>
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_adc.h"
int ConvertedValue = 0;

/* Converted value read from ADC1 */

void adc_configure()
{
/* Clock configuration */
RCC->APB2ENR |= 1<<10;
will use its clock source */

/*The ADC3 is connected the APB2 peripheral bus thus we

RCC->AHB1ENR |= 1<<0;

/* Clock for the ADC port!! Do not forget about this one ;) */

/* Analog pin configuration */


GPIOA->MODER |=0x0000000F;

/* analog mode PA1,PA2 */ GPIOA->OSPEEDR =

0xFFFFFFFF;
GPIOA->PUPDR = 0x00000000;
/* ADC configuration */

ADC3->CR1 = 0x00000000;

/* scan mode disable,12-bit resolution. */

ADC3->CR2 = 0x00000002;

/* data right alignment,continuous conversion mode. */

ADC3->SQR1 = 0x00000000;

/* single mode conversion */

ADC3->CR2 |= 0x00000001;

/* ADC enable */

ADC3->SMPR2 = 0x00000030;

/*ADC3 channel-1 with 144 cycles */ ADC3->SQR3

= 0x00000001;

/* rank1 to ADC3 channel-1 */

int adc_convert()
{
ADC_SoftwareStartConv(ADC3);

/* Start the conversion */ while(!

ADC_GetFlagStatus(ADC3, ADC_FLAG_EOC));

/* Processing the conversion */ return

ADC_GetConversionValue(ADC3);

/* Return the converted data */

}
void USART2_config()
{
RCC->AHB1ENR |= 1 << 0;

/* clock to portA */ RCC->APB1ENR |= 1 <<17;

/* clock to USART2 */

GPIOA->MODER |= 0x000000A0;
>AFR[0] |= 0x00007700;
USART2->BRR = 0x16D;

/* alternate function mode(PA2,PA3) */ GPIOA/* USART2 AF */


/*115200 baud rate */ USART2->CR3 = 0x0000;

USART2->CR2 = 0x000; USART2->CR1 = 0x200C;


}

int main(void)
{
USART2_config();
adc_configure();

/*Start configuration */

while(1)
{
ConvertedValue = adc_convert();

/*Read the ADC converted value */

printf("\n ADC value => %d",ConvertedValue); /*print the ADC value */

}
}

int putchar(int data)


{
USART2->DR = (data & 0x01FF);
/* Loop until the end of transmission */
while((USART2->SR & 0x40) ==0)
{}
return data;
}

DAC
The two 12-bit buffered DAC channels can be used to convert two digital signals into two analog
voltage signal outputs.
This dual digital Interface supports the following features:
two DAC converters: one for each output channel
8-bit or 12-bit monotonic output
left or right data alignment in 12-bit mode
synchronized update capability
noise-wave generation
triangular-wave generation
dual DAC channel independent or simultaneous conversions
DMA capability for each channel
external triggers for conversion
input voltage reference VREF+
Eight DAC trigger inputs are used in the device. The DAC channels are triggered through the timer
update outputs that are also connected to different DMA streams.

Procedure
1. Follow the steps 1 of How to create a New project
2. Type the above code and save it with the name (anyname.c)
3. Follow the steps 2 to 6 of How to create a New Project to add the necessary file, compile and build
the program
4.

Follow the procedures in How to Download a Code to Our Controller to download


your code.

PROGRAM
#include "stm32f4xx.h"
#include "stm32f4xx_dac.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_tim.h"
#include "stm32f4xx_syscfg.h"

static void TIM6_Config(void)


{
TIM_TimeBaseInitTypeDef

TIM_TimeBaseStructure;

/* TIM6 Periph clock enable */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);


/* Time base configuration */ TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Period = 0xFF; TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode =
TIM_CounterMode_Up; TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);
/* TIM6 TRGO selection */

TIM_SelectOutputTrigger(TIM6, TIM_TRGOSource_Update);
/* TIM6 enable counter */ TIM_Cmd(TIM6, ENABLE);
}
static void DAC_Ch2_TriangleConfig(void)
{
DAC_InitTypeDef DAC_InitStructure;
/* DAC channel2 Configuration */ DAC_InitStructure.DAC_Trigger = DAC_Trigger_T6_TRGO;
DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_Triangle;
DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_TriangleAmplitude_1023;
DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable; DAC_Init(DAC_Channel_1,
&DAC_InitStructure);

/* Enable DAC Channel2 */ DAC_Cmd(DAC_Channel_1, ENABLE);

/* Set DAC channel2 DHR12RD register */ DAC_SetChannel2Data(DAC_Align_12b_R, 0x100);


}

int main(void)
{
GPIO_InitTypeDef GPIO_InitStructure;

5
05

/* DMA1 clock enable */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);


/* GPIOA clock enable (to be used with DAC) */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
/* DAC Periph clock enable */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
/* DAC channel 1 & 2 (DAC_OUT1 = PA.4)(DAC_OUT2 = PA.5) configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; //DAC pin A5 as analog mode
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOA,
&GPIO_InitStructure);

TIM6_Config();
while (1)
{
DAC_Ch2_TriangleConfig();
}
}

Experiment 3
Interfacing LED and PWM
Aim
To write a C program to generate a PWM and to vary the brightness of the LED
depending on the duty cycle.
Apparatus & Software Required
1. VSK-SCM4 Development board.
2. IAR IDE software.
3. Flash Loader Demonstrator. .
4. CRO
5. LED board Setup
Theory
The PWM is based on the standard timer block and inherits all of its features,. The timer is designed
to count cycles of the peripheral clock (PCLK) and optionally generate interrupts or perform other
actions when specified timer values occur, based on seven match registers. The PWM function is also
based on match register events

Procedure
1. Follow the steps 1 of How to create a New project
2. Type the below code and save it with the name (anyname.c)
3. Follow the steps 2 to 6 of How to create a New Project to add the necessary file, compile and build
the program
4.

Follow the procedures in How to Download a Code to Our Controller to download


your code.

Program
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx.h"
#include <stdio.h>
uint16_t PrescalerValue = 0;
static int duty_cycle =1 ;
int duty;
/* Private function prototypes -----------------------------------------------*/
void TIM10_Config(void); void TIM11_Config(void); void TIM3_Config(void); void delay(int
delay);
int switch_read();
void mx_pinout_config(void);
void USART2_config();
/* main functions ---------------------------------------------------------*/

int main(void)
{
USART2_config(); TIM3_Config(); while(1)
{

duty = switch_read();

/* receive switch value */

/* for debug purpose */


// printf("\n duty =%d",duty);

/* Compute the prescaler value */


PrescalerValue = (uint16_t) ((SystemCoreClock /2) / 21000000) - 1;
clock */

TIM3->ARR =0x348;

/* 21MHZ timer/counter

/* 25khz */ TIM3->PSC =PrescalerValue;

TIM3->CR1 = 0<<8|0<<9;

TIM3->CCMR1 = 1<<4|1<<5|1<<6;

TIM3->CCER |= 1<<0|1<<1;

duty;
TIM3->CCMR1 = 1<<3;

/*enable capture/compare2*/ TIM3->CCR1 =

/* apply duty cycle */


/* enable channel1 preload register */ TIM3-

>CCMR1 = 1<<12|1<<13|1<<14;
TIM3->CCER |= 1<<4|1<<5;
= duty;
TIM3->CCMR1 = 1<<11;

/* enable capture/compare2 */ TIM3->CCR2


/* apply duty cycle */
/* enable channel2 preload register */

/* TIM10 enable counter */


TIM3->CR1 =1<<0;
}
}
void TIM3_Config(void)
{
RCC->APB1ENR |=1<<1; RCC->AHB1ENR |=1<<2;
GPIOC->MODER |=0x0000A000; GPIOC->AFR[0]|=0x22000000;
}
int switch_read()
{
int val;
mx_pinout_config();
val = ((GPIOE->IDR)&0x14);
if(val == 0x04)
{
if(duty_cycle <= 0)
{
duty_cycle =1;
}

duty_cycle--;

/* variable decrement */

delay(250);
}
else if(val == 0x10)
{
duty_cycle++;

/* variable increment */
delay(250);

if(duty >= 1500)


{
duty =1500;
}
}

return(duty_cycle);
}
int putchar(int data)
{
USART2->DR = (data & 0x01FF);
/* Loop until the end of transmission */
while((USART2->SR & 0x40) ==0)
{}
return data;
}

void mx_pinout_config(void)
{
/*Enable or disable the AHB1 peripheral clock */
RCC->AHB1ENR |= 1<<3;
1<<4;

/* enable the clock to portD */ RCC->AHB1ENR |=

/*enable clock to portE */

GPIOE->MODER |=0x00000000;

/*set portE as i/p mode, other pins are input mode */

GPIOE->OTYPER =0x00000000;
GPIOE->PUPDR = 0x00000000; GPIOE->OSPEEDR =0xAAAAAAAA;
}
void USART2_config()
{
RCC->AHB1ENR |= 1 << 0;

/* clock to PORTA */ RCC->APB1ENR |= 1 <<17;

/* clock to USART2 */ GPIOA->MODER |= 0x000000A0;


GPIOA->AFR[0] |= 0x00007700;

/* USART2 AF */ USART2->BRR = 0x16D;

/* 115200 baud rate */ USART2->CR3 = 0x0000;


USART2->CR2 = 0x000; USART2->CR1 = 0x200C;
}

/* AF mode */

void delay(int delay)


{
int d1,d2; for(d1=0;d1<delay;d1++) for(d2=0;d2<delay;d2++);
}

Result
The C program to vary the intensity of the LED depending on the duty cycle of the
PWM has been developed and is verified.

5
95

Experiment 4
Interfacing Real Time Clock and Serial Port
Aim
To develop a C-Language program for reading the RTC, convert into decimal and to display it.

Apparatus & Software Required


1. VSK-SCM4 Development board.
2. IAR IDE software.
3. Flash Loader Demonstrator. .
Theory
RTC
The real-time clock (RTC) is an independent BCD timer/counter. Dedicated registers contain the
second, minute, hour (in 12/24 hour), week day, date, month, year, in BCD (binary coded decimal)
format. Correction for 28, 29 (leap year), 30, and 31 day of the month are performed automatically.
The RTC provides a programmable alarm and programmable periodic interrupts with wakeup
from Stop and Standby modes. The sub- seconds value is also available in binary format.
It is clocked by a 32.768 kHz external crystal, resonator or oscillator, the internal low- power RC
oscillator or the high-speed external clock divided by 128. The internal low- speed RC has a typical
frequency of 32 kHz. The RTC can be calibrated using an external
512 Hz output to compensate for any natural quartz deviation.

Two alarm registers are used to generate an alarm at a specific time and calendar fields can be
independently masked for alarm comparison. To generate a periodic interrupt, a
16-bit programmable binary auto-reload down counter with programmable resolution is
available and allows automatic wakeup and periodic alarms from every 120 s to e very
36 hours

Serial Communication
Serial communication takes a byte of data and transmits the 8 bits in the byte one at a time. The
advantage is that a serial port needs only one wire to transmit the 8 bits (while a parallel port needs
8). The disadvantage is that it takes 8 times longer to transmit the data than it would if there were 8
wires. Serial ports lower cable costs and make cables smaller.

Procedure
1. Follow the steps 1 of How to create a New project
2. Type the below code and save it with the name (anyname.c)
3. Follow the steps 2 to 6 of How to create a New Project to add the necessary file, compile and build
the program
4.

Follow the procedures in How to Download a Code to Our Controller to download


your code.

Program
#include "stm32f4xx.h"
#include "stm32f4xx_i2c.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_usart.h"
#include "misc.h"
#include "stdio.h"

//uint8_t GK[64] = "ABCD";

#define SLAVE_ADDRESS1 0xD0


#define SLAVE_ADDRESS2 0xD1

// the slave address for write


// the slave address for read

/* prototype functions */
void I2C_stop(I2C_TypeDef* I2Cx);
void I2C_write(I2C_TypeDef* I2Cx, uint8_t data);
void I2C_start(I2C_TypeDef* I2Cx, uint8_t address, uint8_t direction);
void init_I2C1();
void Delay(int t);
void USART2_config();
int BCD_to_DECIMAL(int bcd);
int RTC_read(I2C_TypeDef* I2Cx,uint8_t address);

int main(void)
{
USART2_config();

printf("\n welcome to RTC");


init_I2C1();
int gk_sec,gk_min,gk_hrr;

I2C_start(I2C1, SLAVE_ADDRESS1, I2C_Direction_Transmitter);


/* start a transmission in Master transmitter mode */

I2C_write(I2C1,0x00);

/*send RTC second address */

I2C_write(I2C1,0x00);

/* send RTC second data */ I2C_write(I2C1,0x00);

send RTC min data */ I2C_write(I2C1,0x08);

/*

/* send RTC hour data */ I2C_stop(I2C1);

Delay(500);
while(1)
{
gk_sec = RTC_read(I2C1,0x00);

/*read RTC second */ gk_min = RTC_read(I2C1,0x01);

/*read RTC minute */ gk_hrr = RTC_read(I2C1,0x02);

/*read RTC hour */

printf("\n\t RTC_TIME => %d:%d:%d",gk_hrr,gk_min,gk_sec);


}
}
void Delay(int t)
{
int y,u; for(y=0;y<t;y++) for(u=0;u<t;u++);
}

int RTC_read(I2C_TypeDef* I2Cx,uint8_t address)


{
int r_value,gj;
I2C_start(I2Cx, SLAVE_ADDRESS1, I2C_Direction_Transmitter);
/* start a transmission in Master transmitter mode */

I2C_write(I2Cx,address);

/* send EEPROM MSB address */ Delay(200);

I2C_stop(I2Cx); Delay(200);
I2C_start(I2Cx, SLAVE_ADDRESS2, I2C_Direction_Receiver);
/* start a transmission in Master transmitter mode */
Delay(200);

gj = I2C_ReceiveData(I2Cx);
r_value = BCD_to_DECIMAL(gj);

I2C_stop(I2Cx); Delay(3700); return(r_value);


}
int BCD_to_DECIMAL(int bcd)
{
int gk_MSB,gk_LSB,decimal; gk_MSB = (bcd&0xF0)>>4; gk_LSB = (bcd&0x0F);
decimal =(gk_MSB*10)+gk_LSB;
return(decimal);
}
void USART2_config()
{
RCC->AHB1ENR |= 1 << 0; RCC->APB1ENR |= 1 <<17;

GPIOA->MODER |= 0x000000A0; GPIOA->AFR[0] |= 0x00007700;

USART2->BRR = 0x16D;//115200 baud rate


USART2->CR3 = 0x0000; USART2->CR2 = 0x000; USART2->CR1 = 0x200C;
}
int putchar(int data)
{
USART2->DR = (data & 0x01FF);
/* Loop until the end of transmission */
while((USART2->SR & 0x40) ==0)
{}
return data;
}
void init_I2C1()
{
I2C_InitTypeDef I2C_InitStruct;
/* setup SCL and SDA pins
* You can connect I2C1 to two different
* pairs of pins:
* 1. SCL on PB6 and SDA on PB9
*/
RCC->AHB1ENR |= 1<<1; //CLK to port B RCC->APB1ENR |= 1<<21; // CLK to I2C1

GPIOB->MODER = 0x00082000;

/* PB6 & PB9 =>i2c pins (SDA,SCL) */

GPIOB->AFR[0] = 0x04000000;
GPIOB->AFR[1] = 0x00000040;
GPIOB->OTYPER = 0xFFFFFFFF;
=0xAAAAAAAA;

/*open drain */ GPIOB->OSPEEDR

/* 50 MHZ */ GPIOB->PUPDR = 0x55555555;

/* pull up */
/* configure I2C1 */

I2C_InitStruct.I2C_ClockSpeed = 100000;
I2C_Mode_I2C;

/* 100kHz */ I2C_InitStruct.I2C_Mode =

/* I2C mode */ I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2; /*

50% duty cycle --> standard*/


I2C_InitStruct.I2C_OwnAddress1 = 0x00;

/* own address, not relevant in master mode*/

I2C_InitStruct.I2C_Ack = I2C_Ack_Disable;
/* disable acknowledge when reading (can be changed later on) */
I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
/* set address length to 7 bit addresses */ I2C_Init(I2C1, &I2C_InitStruct);
/* init I2C1 */

/* enable I2C1 */ I2C_Cmd(I2C1, ENABLE);


}
void I2C_start(I2C_TypeDef* I2Cx, uint8_t address, uint8_t direction)
{
/* wait until I2C1 is not busy anymore */
7
07

while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));

/* Send I2C1 START condition */ I2C_GenerateSTART(I2Cx, ENABLE);


/* wait for I2C1 EV5 --> Slave has acknowledged start condition */
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
/* Send slave Address for write */ I2C_Send7bitAddress(I2Cx, address, direction);

/* wait for I2C1 EV6, check if


* either Slave has acknowledged Master transmitter or
* Master receiver mode, depending on the transmission
* direction
*/
if(direction == I2C_Direction_Transmitter)
{
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
}
else if(direction == I2C_Direction_Receiver)
{
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
}
}

void I2C_write(I2C_TypeDef* I2Cx, uint8_t data)


{
I2C_SendData(I2Cx, data);
/* wait for I2C1 EV8_2 --> byte has been transmitted */
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
}

uint8_t I2C_read_ack(I2C_TypeDef* I2Cx)


{
/* enable acknowledge of received data */ I2C_AcknowledgeConfig(I2Cx, ENABLE);
// wait until one byte has been received
while( !I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED) );
// read data from I2C data register and return data byte uint8_t data = I2C_ReceiveData(I2Cx);
return data;
}
uint8_t I2C_read_nack(I2C_TypeDef* I2Cx)
{
// disabe acknowledge of received data
// nack also generates stop condition after last byte received
// see reference manual for more info

I2C_AcknowledgeConfig(I2Cx, DISABLE); I2C_GenerateSTOP(I2Cx, ENABLE);


// wait until one byte has been received
while( !I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED) );
// read data from I2C data register and return data byte uint8_t data = I2C_ReceiveData(I2Cx);
return data;
}

void I2C_stop(I2C_TypeDef* I2Cx)


{
// Send I2C1 STOP Condition
I2C_GenerateSTOP(I2Cx, ENABLE);
}

Result
The C-Language program for reading RTC and displaying it in PC was written &
output is verified with running the RTC from a default/specified time.

Experiment 5
Interfacing Keyboard and LCD
Aim
To develop a C-Language program for displaying the Key pressed in the Keypad in the
LCD module. The display should come in the desired line and column.
Apparatus & Software Required
1. VSK-SCM4 Development board.
2. IAR IDE software.
3. Flash Loader Demonstrator. .
Theory
Keypad
The Matrix keyboard is used to minimize the number of I/O lines. Normally it is possible to connect
only one key or switch with an I/O line. If the number of keys in the system exceeds the more I/O
lines are required. To reduce the number of I/O lines the keys are connected in the matrix circuit.
Keyboards use a matrix with the rows and columns made up of wires. Each key acts like a switch.
When a key is pressed a column wire makes contact with row wire and completes a circuit.
For example 16 keys arranged in a matrix circuit uses only 8 I/O lines

LCD
Liquid crystals are a phase of matter whose order is intermediate between that of a liquid and that of
a crystal. The molecules are typically rod-shaped organic matters about 25
Angstroms in length and their ordering is a function of temperature. The molecular orientation
can be controlled with applied electric fields.

CHARACTER BASED LCD

A standard character LCD is probably the most widely used data Visualization component.
Character LCDs are available in various kinds of models.
1. No. Of characters x Lines: 8x1, 16x1, 16x2, 16x4, 20x4, 40x4
2. Color: Yellow, Green, Gray, Blue
The Character LCD communicates with the microcontroller via 8 bit data bus. The pin description
for character LCD is given below.

VCC, GND AND V0 - While VCC and VSS provide +5V and ground, respectively; V0 is used for
controlling LCD contrast.
RS (Register Select) - If RS = 0, the instruction command code 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.
RW (Read/Write) - RW allows the user to write information to the LCD or read information
from it. RW=1 when reading; RW=0 when writing.
EN (Enable) - The LCD to latch information presented to its data pins uses the enable pin. When
data is supplied to data pins, a high to low pulse must be applied to this pin in order for the LCD to
latch in the data present at the data pins.
D0 D7 - The 8-bit data pins, are used to send information to the LCD or read the contents of the
LCDs internal registers. To display letters and numbers, we send ASCII codes for the letters A-Z, a-z,
and numbers 0-9 to these pins while making RS = 1

Procedure
1. Follow the steps 1 of How to create a New project
2. Type the below code and save it with the name (anyname.c)
3. Follow the steps 2 to 6 of How to create a New Project to add the necessary file, compile and build
the program
4.

Follow the procedures in How to Download a Code to Our Controller to download


your code.

Program
#include "stm32f4xx.h"
#include "stm32f4xx_gpio.h"

unsigned char d1[] = {"

WELCOME "}; unsigned char d2[] = {" Press any Key"}; unsigned char i;

/*ptototype functions */
void delay(int a);
void mx_pinout_config(void);
void busy_check();
void command_write(int comm);
void lcd_init();
void lcd_out(unsigned char a);
void lcd_stringout(unsigned char *gk);
void mx_pinout_config(void);
void Row1_check(); void Row2_check(); void Row3_check(); void Row4_check(); int val;

void main(void)
{
mx_pinout_config();
lcd_init();

/* send initial commands */

command_write(0x80); lcd_stringout(d1); command_write(0xC0); lcd_stringout(d2);


while (1)
{
Row1_check(); Row2_check(); Row3_check(); Row4_check();

}
void Row1_check()
{
/*1 st row */
GPIOD->BSRRH = 0x0001;
= 0x000E;

/* high PD0 */ GPIOD->BSRRL


/* low PD1 to PD3 */

8
08

val = (GPIOD->IDR)&0xF0;
if(val == 0xE0)

/* status of D4 to D7 */
/* 1st column */

{
command_write(0x01); command_write(0x80); lcd_stringout("You Pressed =>C"); delay(100);
}
else if(val== 0xD0)

/*2nd column */

{
command_write(0x01); command_write(0x80); lcd_stringout("You Pressed =>D"); delay(100);
}
else if(val== 0xB0)

/* 3rd column */

{
command_write(0x01); command_write(0x80); lcd_stringout("You Pressed =>E"); delay(100);
}

else if(val== 0x70)

/*4th column */

{
command_write(0x01); command_write(0x80); lcd_stringout("You Pressed =>F"); delay(100);
}
}

void Row2_check()
{
/*2nd row */
GPIOD->BSRRH = 0x0002;

/* low PD0 */ GPIOD->BSRRL = 0x000D;

/* low PD0 */

val = (GPIOD->IDR)&0xF0;

/* status of D4 to D7 */

if(val == 0xE0)

/* 1st column */

{
command_write(0x01); command_write(0x80); lcd_stringout("You Pressed =>8"); delay(100);
}

else if(val== 0xD0)

/* 2nd column */

{
command_write(0x01); command_write(0x80); lcd_stringout("You Pressed =>9"); delay(100);
}
else if(val== 0xB0)

/* 3rd column */

{
command_write(0x01); command_write(0x80); lcd_stringout("You Pressed =>A"); delay(100);
}
else if(val== 0x70)

/* 4th column */

{
command_write(0x01); command_write(0x80); lcd_stringout("You Pressed =>B"); delay(100);
}
/* GPIOD->BSRRH = 0x000E; //low PD0 */
}

void Row3_check()
{
/*3rd row */
GPIOD->BSRRH = 0x0004;

/* low PD0 */ GPIOD->BSRRL = 0x000B;


/* low PD0 */

val = (GPIOD->IDR)&0xF0;

/* status of D4 to D7 */

if(val == 0xE0)

/*1st column */

command_write(0x01); command_write(0x80); lcd_stringout("You Pressed =>4"); delay(100);


}
else if(val== 0xD0)

/* 2nd column */

{
command_write(0x01); command_write(0x80); lcd_stringout("You Pressed =>5"); delay(100);
}

else if(val== 0xB0)

/* 3rd column */
{

command_write(0x01); command_write(0x80); lcd_stringout("You Pressed =>6"); delay(100);


}
else if(val== 0x70)

/* 4th column */
{

command_write(0x01); command_write(0x80); lcd_stringout("You Pressed =>7"); delay(100);


}
}
void Row4_check()
{
/*4th row*/
GPIOD->BSRRH = 0x0008;

/*low PD0 */ GPIOD->BSRRL = 0x0007;

/* low PD0 */

val = (GPIOD->IDR)&0xF0;

/* status of D4 to D7 */

if(val == 0xE0)

/*1st column */

{
command_write(0x01); command_write(0x80); lcd_stringout("You Pressed =>0"); delay(100);
}
else if(val== 0xD0)

/* 2nd column*/

{
command_write(0x01); command_write(0x80); lcd_stringout("You Pressed =>1"); delay(100);
}
else if(val== 0xB0)

/*3rd column */

{
command_write(0x01); command_write(0x80); lcd_stringout("You Pressed =>2"); delay(100);
}
else if(val== 0x70)
{
command_write(0x01);

/*4th column */

command_write(0x80);
lcd_stringout("You Pressed =>3");
delay(100);
}
}
void delay(int a)
{
int i,j; for(i=0;i<a;i++) for(j=0;j<a;j++);
}

void busy_check()
{
delay(200);
GPIOE->BSRRH = 0x0020;

/*low the RS pin */ GPIOE->BSRRH = 0x0040;

/*low RW pin */
}
void command_write(int comm)
{
busy_check();
GPIOE->BSRRH = 0x0020;
GPIOE->ODR = (comm<<8)|(0<<5);
PG15*/

/* low RS pin */
/*write the data from 8th bit.(i.E) PG8 to

GPIOE->BSRRL = 0x0080;

/*enable pin high */

delay(200);
GPIOE->BSRRH = 0x0080;

/*enable pin low */

/*LCD initial commands */


void lcd_init()
{
command_write(0x38);

command_write(0x01);

command_write(0x0f);

command_write(0xC0);

command_write(0x06);
}
void lcd_out(unsigned char a)
{
busy_check();
GPIOE->BSRRL = 0x0020;

/* high RS pin

GPIOE->ODR = (a<<8)|(1<<5);

/*write the data from 8th bit.(i.E) PG8 to PG15*/

GPIOE->BSRRL = 0x0080;

/*enable pin high*/

delay(200);
GPIOE->BSRRH = 0x0080;
}

/* enable pin low */

void lcd_stringout(unsigned char *gk)


{
int i;
busy_check();

GPIOE->BSRRL = 0x0020;

/* high RS pin */

for(i=0;gk[i] !='\0';i++)
{
GPIOE->ODR =( gk[i]<<8)|(1<<5);

/*write the data from 8th bit.(i.E) PG8 to PG15 */

GPIOE->BSRRL = 0x0080;

/* enable pin high */

delay(200);
GPIOE->BSRRH = 0x0080;

/*enable pin low */

}
}
void mx_pinout_config(void)
{
/* GPIO_InitTypeDef GPIO_InitStruct; */
/*Enable or disable the AHB1 peripheral clock */
RCC->AHB1ENR |= 1<<3;
1<<4;

/* enable the clock to portF */ RCC->AHB1ENR |=

/*enable clock to portB,C,G */

GPIOD->MODER |=0x00000055;

/* set port D0-D3 as o/p mode, other pins are input mode */

GPIOD->OTYPER =0x00000000;
GPIOD->PUPDR = 0x00000000; GPIOD->OSPEEDR =0xAAAAAAAA;

/*Enable pin */
GPIOE->MODER = 0X55555555;

/* lcd_pins OUTPUT MODE SELECT */ GPIOE-

>OTYPER = 0x00000000;
GPIOE->PUPDR = 0x00000000; GPIOE->OSPEEDR = 0xAAAAAAAA; GPIOE->ODR

0x00000000;

9
09

Procedure to View the Result


1. Set your board to the execution mode and reset it.
2. The switches SW2, SW3, SW5 and SW6 are interfaced as keypad.
3. Each switch is programmed to have a defined function. SW2 is to Clear the display, SW3 is to get the
user data, SW5 and SW6 is to shift the cursor to the left and right respectively.
4. We can type up to 32 datas with these keys.

Result
The C-Language program for displaying the Key pressed in the Keyboard is displayed in the LCD
module and the output was verified on the LCD on the desires line and column/address.

Experiment 6
Interfacing EEPROM and Interrupt
Aim
To develop a C-Language program to write and read a data in EEPROM and also to analyze its
performance with the interrupt
Apparatus & Software Required
1. VSK-SCM4 Development board.
2. IAR IDE software.
3. Flash Loader Demonstrator. .
Theory
Serial-interface EEPROMs are

used in

broad spectrum of

consumer, automotive,

telecommunication, medical, industrial and PC related markets. Primarily used to store personal
preference data and configuration/setup data, Serial EEPROMs are the most flexible type of
nonvolatile memory utilized today. Compared to other NVM solutions, Serial EEPROM devices
offer a lower pin count, smaller packages, lower voltages, as well as lower power consumption

Procedure
1. Follow the steps 1 of How to create a New project
2. Type the below code and save it with the name (anyname.c)
3. Follow the steps 2 to 5 of How to create a New Project to add the necessary file, compile and build
the program
4. Copy the INC_EEPROM and SRC_EEPROM folders from the existing
EEPROM project and paste it in the current working.
5. Add that folders path into your preprocessor directory.
6. Then add all files from SRC_EEPROM folder
7. Now build the project.
8.

Follow the procedures in How to Download a Code to Our Controller to download


your code.

Program
#include "stm32f4xx.h"
#include "stm32f4xx_i2c.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_usart.h"
#include "misc.h"
#include "stdio.h"

/* uint8_t GK[64] = "ABCD"; */

#define SLAVE_ADDRESS1 0xA6

/* the slave address (example) */

#define SLAVE_ADDRESS2 0xA7

/* the slave address (example) */

/* prototype functions */

void I2C_stop(I2C_TypeDef* I2Cx);


void I2C_write(I2C_TypeDef* I2Cx, uint8_t data);
void I2C_start(I2C_TypeDef* I2Cx, uint8_t address, uint8_t direction); int I2C_read(I2C_TypeDef*
I2Cx,uint8_t MSB_addr,uint8_t LSB_addr); void init_I2C1();
void Delay(int t);
void USART2_config();

int main(void)
{
USART2_config();
printf("\n welcome to EEPROM");
init_I2C1();
int i,gk;
/*EEPROM read operation */

printf("\n\n EEPROM EEPROM "); printf("\nAddress Data "); for(i=0;i<64;i++)


{
gk = I2C_read(I2C1,0x00,i);
printf("\n 0x%x------->%d ",0x00+i,gk);
}
}
void Delay(int t)
{
int y,u; for(y=0;y<t;y++) for(u=0;u<t;u++);
}

void USART2_config()
{
RCC->AHB1ENR |= 1 << 0; RCC->APB1ENR |= 1 <<17;

GPIOA->MODER |= 0x000000A0; GPIOA->AFR[0] |= 0x00007700;

USART2->BRR = 0x16D;
0x0000;
USART2->CR2 = 0x000; USART2->CR1 = 0x200C;

}
int putchar(int data)
{
USART2->DR = (data & 0x01FF);
/* Loop until the end of transmission */
while((USART2->SR & 0x40) ==0)
{}
return data;
}

/* 115200 baud rate */ USART2->CR3 =

void init_I2C1()
{
GPIO_InitTypeDef GPIO_InitStruct; I2C_InitTypeDef I2C_InitStruct;
/* enable APB1 peripheral clock for I2C1 */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,
ENABLE);
/* enable clock for SCL and SDA pins */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,
ENABLE);
/* setup SCL and SDA pins
* You can connect I2C1 to two different
* pairs of pins:
* 1. SCL on PB6 and SDA on PB9
*/
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_9;

/* we are going to use PB6 and PB7*/

GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;

/* set pins to alternate function */

GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;

/* set GPIO speed */

GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;
/* set output to open drain --> the
line has to be only pulled low, not driven high */
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;

/* enable pull up resistors */

GPIO_Init(GPIOB, &GPIO_InitStruct);

/* init GPIOB */

/* Connect I2C1 pins to AF */

GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);

/* SCL*/

/* configure I2C1 */
I2C_InitStruct.I2C_ClockSpeed = 100000;
I2C_Mode_I2C;

/* 100kHz */ I2C_InitStruct.I2C_Mode =

/* I2C mode */ I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2; /*

50% duty cycle --> standard */ I2C_InitStruct.I2C_OwnAddress1 = 0x00;

/* own address, not

relevant in master mode */

Disable;

/* disable acknowledge when reading (can be changed later on) */


I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
/* set address length to 7 bit addresses*/
I2C_Init(I2C1, &I2C_InitStruct);

/* init I2C1 */

/* enable I2C1 */ I2C_Cmd(I2C1, ENABLE);


}
void I2C_start(I2C_TypeDef* I2Cx, uint8_t address, uint8_t direction)
{
/* wait until I2C1 is not busy anymore */
while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));
/* Send I2C1 START condition */ I2C_GenerateSTART(I2Cx, ENABLE);
/* wait for I2C1 EV5 --> Slave has acknowledged start condition */
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
/* Send slave Address for write */ I2C_Send7bitAddress(I2Cx, address, direction);

/* wait for I2C1 EV6, check if


* either Slave has acknowledged Master transmitter or
* Master receiver mode, depending on the transmission
* direction
*/
if(direction == I2C_Direction_Transmitter)
{
while(!I2C_CheckEvent(I2Cx,
I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
}

else if(direction == I2C_Direction_Receiver)


{
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
}
}
void I2C_write(I2C_TypeDef* I2Cx, uint8_t data)
{
I2C_SendData(I2Cx, data);
/* wait for I2C1 EV8_2 --> byte has been transmitted */
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
}

uint8_t I2C_read_ack(I2C_TypeDef* I2Cx)


{
/* enable acknowledge of received data */ I2C_AcknowledgeConfig(I2Cx, ENABLE);
/* wait until one byte has been received */
while( !I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED) );
/* read data from I2C data register and return data byte */
uint8_t data = I2C_ReceiveData(I2Cx);
return data;
}
uint8_t I2C_read_nack(I2C_TypeDef* I2Cx)
{
/* disabe acknowledge of received data
// nack also generates stop condition after last byte received
// see reference manual for more info */ I2C_AcknowledgeConfig(I2Cx, DISABLE);
I2C_GenerateSTOP(I2Cx, ENABLE);
/* wait until one byte has been received */
while( !I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED) );
/* read data from I2C data register and return data byte */
uint8_t data = I2C_ReceiveData(I2Cx);
return data;
}

10
01

void I2C_stop(I2C_TypeDef* I2Cx)


{
/* Send I2C1 STOP Condition */ I2C_GenerateSTOP(I2Cx, ENABLE);
}
int I2C_read(I2C_TypeDef* I2Cx,uint8_t MSB_addr,uint8_t LSB_addr)
{
int j;
I2C_start(I2Cx, SLAVE_ADDRESS1, I2C_Direction_Transmitter);
/* start a transmission in Master transmitter mode*/
Delay(200);
I2C_write(I2C1,MSB_addr); I2C_write(I2C1,LSB_addr); I2C_stop(I2C1);
Delay(200);
I2C_start(I2Cx, SLAVE_ADDRESS2, I2C_Direction_Receiver);
/* start a transmission in Master transmitter mode */
Delay(200);
j = I2C_ReceiveData(I2C1);
//printf("\n %d",j); I2C_stop(I2C1); Delay(200); return(j);
}

Program EEPROM Write


#include "stm32f4xx.h"
#include "stm32f4xx_i2c.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_usart.h"
#include "misc.h"
#include "stdio.h"

#define SLAVE_ADDRESS1 0xA6

/* the slave address (example) */

#define SLAVE_ADDRESS2 0xA7

/* the slave address (example) */

/* prototype functions */
void I2C_stop(I2C_TypeDef* I2Cx);
void I2C_write(I2C_TypeDef* I2Cx, uint8_t data);
void I2C_start(I2C_TypeDef* I2Cx, uint8_t address, uint8_t direction);
void init_I2C1();
void Delay(int t);
void USART2_config();

int main(void)
{
USART2_config();
printf("\n welcome to EEPROM");
init_I2C1();
int i;
I2C_start(I2C1, SLAVE_ADDRESS1, I2C_Direction_Transmitter);
/* start a transmission in Master transmitter mode*/
I2C_write(I2C1,0x00);

/* send EEPROM MSB address */ I2C_write(I2C1,0x00);

/* send EEPROM LSB address */


/*write data upto 63 */
for(i=10;i<74;i++)

/* modify your data here. Here data is 10 to 73 */

{ I2C_write(I2C1,i); Delay(200);
}
I2C_stop(I2C1);

/*stop write operation */ Delay(2000);

}
void Delay(int t)
{
int y,u; for(y=0;y<t;y++) for(u=0;u<t;u++);
}

void USART2_config()
{
RCC->AHB1ENR |= 1 << 0; RCC->APB1ENR |= 1 <<17; GPIOA->MODER |= 0x000000A0;
GPIOA->AFR[0] |= 0x00007700;
USART2->BRR = 0x16D;
0x0000;
USART2->CR2 = 0x000; USART2->CR1 = 0x200C;
}

int putchar(int data)


{
USART2->DR = (data & 0x01FF);
/* Loop until the end of transmission */
while((USART2->SR & 0x40) ==0)
{}
return data;
}

/* 115200 baud rate */ USART2->CR3 =

void init_I2C1()
{
GPIO_InitTypeDef GPIO_InitStruct; I2C_InitTypeDef I2C_InitStruct;

/* enable APB1 peripheral clock for I2C1 */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,


ENABLE);

/* enable clock for SCL and SDA pins */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,


ENABLE);

/* setup SCL and SDA pins


* You can connect I2C1 to two different
* pairs of pins:
* 1. SCL on PB6 and SDA on PB9
*/
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_9;

/* we are going to use PB6 and PB7 */

GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;

/* set pins to alternate function*/

GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;

/* set GPIO speed */

GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;
/* set output to open drain --> the line has to be only pulled low, not driven high */
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;

/* enable pull up resistors */

GPIO_Init(GPIOB, &GPIO_InitStruct);

/* init GPIOB */

/* Connect I2C1 pins to AF */

GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);

/* SCL */

GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_I2C1);

/* SDA */

/* configure I2C1 */
I2C_InitStruct.I2C_ClockSpeed = 100000;
I2C_Mode_I2C;

/* 100kHz */ I2C_InitStruct.I2C_Mode =

/* I2C mode */ I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2; /*

50% duty cycle --> standard */ I2C_InitStruct.I2C_OwnAddress1 = 0x00;

/* own address,

not relevant in master mode*/

Disable;

/* disable acknowledge when reading (can be changed later on) */


I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
/* set address length to 7 bit addresses */
I2C_Init(I2C1, &I2C_InitStruct);

/* init I2C1 */
/* enable I2C1 */

I2C_Cmd(I2C1, ENABLE);
}
void I2C_start(I2C_TypeDef* I2Cx, uint8_t address, uint8_t direction)
{
/* wait until I2C1 is not busy anymore */
while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));
/* Send I2C1 START condition */ I2C_GenerateSTART(I2Cx, ENABLE);

/* wait for I2C1 EV5 --> Slave has acknowledged start condition */
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));

/* Send slave Address for write */ I2C_Send7bitAddress(I2Cx, address, direction);

/* wait for I2C1 EV6, check if


* either Slave has acknowledged Master transmitter or
* Master receiver mode, depending on the transmission
* direction
*/
if(direction == I2C_Direction_Transmitter)
{
while(!I2C_CheckEvent(I2Cx,
I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
}
else if(direction == I2C_Direction_Receiver)
{
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
}
}

void I2C_write(I2C_TypeDef* I2Cx, uint8_t data)


{
I2C_SendData(I2Cx, data);
/* wait for I2C1 EV8_2 --> byte has been transmitted */
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
}

uint8_t I2C_read_ack(I2C_TypeDef* I2Cx)


{
/* enable acknowledge of recieved data */ I2C_AcknowledgeConfig(I2Cx, ENABLE);
/* wait until one byte has been received */
while( !I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED) );
/* read data from I2C data register and return data byte */
uint8_t data = I2C_ReceiveData(I2Cx);
return data;
}
void I2C_stop(I2C_TypeDef* I2Cx)
{
/* Send I2C1 STOP Condition */ I2C_GenerateSTOP(I2Cx, ENABLE);
}

int I2C_read(I2C_TypeDef* I2Cx,uint8_t MSB_addr,uint8_t LSB_addr)


{
int j;
I2C_start(I2Cx, SLAVE_ADDRESS1, I2C_Direction_Transmitter);
/* start a transmission in Master transmitter mode */ Delay(200);
I2C_write(I2C1,MSB_addr); I2C_write(I2C1,LSB_addr); I2C_stop(I2C1);
Delay(200);
I2C_start(I2Cx, SLAVE_ADDRESS2, I2C_Direction_Receiver);
/* start a transmission in Master transmitter mode */ Delay(200);
j = I2C_ReceiveData(I2C1);
//printf("\n %d",j); I2C_stop(I2C1);
Delay(200);
return(j);

Procedure to View the Result


1. Follow the steps of How to view the result in Win X Talk.
2. Set your board to the execution mode and reset it.
3. In first step, some data will be written in EEPROM at the starting address
0x01.
4. Then read the data from that memory location. The read data will be displayed in the terminal
window.

Result

The C-Language program to write and read a data in EEPROM and also to analyze its performance
with the interrupt is developed and is verified.

11
01

Experiment 7
Mailbox
Aim
To develop a C code to create a mailbox and to understand the RTOS functions.
Apparatus & Software Required
1. VSK-SCM4 Development board.
2. IAR IDE software.
3. Flash Loader Demonstrator. .
Theory
Real-time and embedded systems operate in constrained environments in which computer memory
and processing power are limited. They often need to provide their services within strict time
deadlines to their users and to the surrounding world. It is these memory, speed and timing
constraints that dictate the use of real-time operating systems in embedded software.
The "kernel" of a real-time operating system ("RTOS") provides an "abstraction layer" that hides
from application software the hardware details of the processor (or set of processors) upon which the
application software will run.

In providing this "abstraction layer" the RTOS kernel supplies five main categories of basic services
to application software
The most basic category of kernel services is Task Management. This set of services allows
application software developers to design their software as a number of separate "chunks" of software
-- each handling a distinct topic, a distinct goal, and perhaps its own real-time deadline. Each separate
"chunk" of software is called a "task." The main RTOS service in this category is the scheduling of
tasks as the embedded system is in operation.
The second category of kernel services is Intertask Communication and Synchronization. These
services make it possible for tasks to pass information from one to another, without danger of that
information ever being damaged. They also make it possible for tasks to coordinate, so that they can
productively cooperate with one another. Without the help of these RTOS services, tasks might well
communicate corrupted information or otherwise interfere with each other.
Since many embedded systems have stringent timing requirements, most RTOS kernels also provide
some basic Timer services, such as task delays and time-outs.

Many (but not all) RTOS kernels provide Dynamic Memory Allocation services. This category of
services allows tasks to "borrow" chunks of RAM memory for temporary use in application software.
Often these chunks of memory are then passed from task to task, as a means of quickly
communicating large amounts of data between tasks. Some very small RTOS kernels that are
intended for tightly memory-limited environments, do not offer Dynamic memory allocation.
Many (but not all) RTOS kernels also provide a "Device I/O Supervisor" category of services. These
services, if available, provide a uniform framework for organizing and accessing the many hardware
device drivers that are typical of an embedded system.

Procedure
1. Follow the steps 1 of How to create a New project
2. Type the below code and save it with the name (anyname.c)
3. Follow the steps 2 to 6 of How to create a New Project to add the necessary file, compile and build
the program.
4. Follow the procedures in How to Download a Code to Our Controller to download your code

Program
#include "ucos_ii.h"
#include "bsp.h"

#define TASK_STK_SIZE

128

OS_STK AppStk_send[TASK_STK_SIZE]; OS_STK AppStk_recv[TASK_STK_SIZE]; static void


Mailbox_App_Tx(void *p_arg);
static void Mailbox_App_Rx(void *p_arg);

OS_EVENT *pmailbox;
int main(void)
{
BSP_IntDisAll();
/* Disable all interrupts until we are ready to accept them */ RCC_ClocksTypeDef rcc_clocks;
RCC_GetClocksFreq(&rcc_clocks);
SysTick_Config(rcc_clocks.HCLK_Frequency/OS_TICKS_PER_SEC);

OSInit();

/*ucosii initialization */

BSP_Init();

/*board support package initialization */ OSStatInit();

/*DetermineCPUcapacity.*/

/*TODO:create application tasks here*/


OSTaskCreate(Mailbox_App_Tx,NULL,(OS_STK *)&AppStk_send[TASK_STK_SIZE1],(INT8U)10);
/*sending task */
OSTaskCreate(Mailbox_App_Rx,NULL,(OS_STK *)&AppStk_recv[TASK_STK_SIZE1],(INT8U)30);
/*receiving task */

OSStart();

/*start os here */

printf("\n\r Never Arrives here");


return 0;
}
/* post data to mailbox */
void Mailbox_App_Tx(void *p_arg)
{
INT8U i,err, *buffer[5]; buffer[0] = "1.RCC"; buffer[1] = "2.DMA"; buffer[2] = "3.NVIC"; buffer[3]
= "4.FPU";
//buffer[4] = "5.FSMC"; p_arg = p_arg; pmailbox=OSMboxCreate(NULL);

for (i=0;i<=5;)
{
if((err=OSMboxPost(pmailbox,buffer[i]))==NO_ERROR_GK)

/* if success */

{
printf("\n\rThis is sender \n\t post data to Mailbox,data is-->%s",buffer[i]);
i++;
}
else if(err== MAILBOX_FULL_GK)

/* if mailbox full */

printf("\n\rThis is sender \n\t the Mailbox has data,data is-->%s",pmailbox->OSEventPtr);


else

/*other errors occurred */

printf("\n\r Other err"); OSTimeDlyHMSM(0, 0, 5, 0);


}
OSTimeDlyHMSM(0, 0, 5, 0);
OSMboxDel (pmailbox,OS_DEL_NO_PEND, &err);
if(err==OS_ERR_TASK_WAITING_GK)
*/
printf("\n\rSome task wait for this Mailbox");
}
/*Get data from mailbox */
void Mailbox_App_Rx(void *p_arg)
{
INT8U err;
INT16U timeout=100;

/*another task waiting error

INT8U *buffer;
p_arg = p_arg;

for (;;)
{
buffer=OSMboxPend(pmailbox,timeout,&err); OSTimeDly(200);

if(err==OS_ERR_NONE) //if no error


printf("\n\rThis is receiver \n\t get data from Mailbox data is-->%s",buffer);

else if(err==TIMEOUT_ERROR_GK)

/* if timeout error occurred */

printf("\n\rTimeout");
else if(err==EVENT_TYPE_ERROR_GK)

/* if unmatched event occurred */

{
printf("\n\rThis is receiver \n\t err is OS_ERR_EVENT_TYPE");
break;
} else break;
OSTimeDlyHMSM(0,0,6, 0);
}
}

Procedure to View the Result


1. Follow the steps of How to view the result in Win X Talk.
2. Set your board to the execution mode and reset it.
3. The data that is transmitted from the task 1 is received by the task 2 and is displayed.

Result
The C-Language program to create a mailbox and to understand the about the RTOS
functions is developed and is verified.

Experiment 9
Flashing of LEDS
Aim
To develop a C program to make the LED blink (including delay routine). Upon change in the delay
program the speed should vary.
Apparatus & Software Required
1. VSK-SCM4 Development board.
2. IAR IDE software.
3. Flash Loader Demonstrator. .
Theory
LEDs are based on the semiconductor diode. When the diode is forward biased (switched on),
electrons are able to recombine with holes and energy is released in the form of light. This effect is
called electroluminescence and the color of the light is determined by the energy gap of the
semiconductor

11
91

Procedure
5. Follow the steps 1 of How to create a New project
6. Type the below code and save it with the name (anyname.c)
7. Follow the steps 2 to 6 of How to create a New Project to add the necessary file, compile and build
the program
8.

Follow the procedures in How to Download a Code to Our Controller to download


your code.

Program
#include "stm32f4xx.h"
#include <stdio.h>
#include "stm32f4xx_rcc.h" void LED_init();
/* delay function */
void delay(long int a)
{
long int b,c; for(b=0;b<a;b++) for(c=0;c<a;c++);
}
/*main function starts here */
void main()
{
LED_init();

/* LED initialization */

while(1)
{
GPIOD->ODR =0x00000F00;

/*

leds turns ON */

delay(3000);

/*

delay */

GPIOD->ODR =0x00000000;

/*

leds turns OFF */

delay(3000);

/*

delay */

}
}

void LED_init()
{
RCC->AHB1ENR = 1 <<3;

/*enable the clock to port D */

GPIOD->MODER = 0x55555555;

/* select all pins as output mode */ GPIOD-

>OTYPER =0x00000000;

/* push-pull type */

GPIOD->OSPEEDR =0xAAAAAAAA;
=0x00000000;
}

/* 50MHz speed */ GPIOD->PUPDR

/* no pull-up no pull down*/

Procedure to View the Result


1. Set your board to the execution mode and reset it.
2. The four LEDs on the board will toggle with a delay.

Result:
The C-Language program to make the LED blink was developed and output was verified. Upon
change in the delay program the speed variation was verified.

Experiment 10
Interfacing Stepper Motor and Temperature Sensor
Aim
To write C Programs for running stepper motor either in clock-wise or counter-clock- wise and the
direction of the rotation of the stepper motor depends on the variation in the temperature sensor.

Apparatus & Software Required


1. VSK-SCM4 Development board.
2. IAR IDE software.
3. Flash Loader Demonstrator. .
4. Stepper motor
Theory
Stepper Motor
Stepper motors, effectively have multiple "toothed" electromagnets arranged around a central metal
gear. To make the motor shaft turn, first one electromagnet is given power, which makes the gear's
teeth magnetically attracted to the electromagnet's teeth. When the gear's teeth are thus aligned to
the first electromagnet, they are slightly offset from the next electromagnet.
So when the next electromagnet is turned on and the first will turn off, the gear rotates slightly to
align with the next one and from there the process is repeated. Each of those slight rotations is called a
"step." In that way, the motor can be turned to a precised angle. There are two basic arrangements for
the electromagnetic coils: bipolar and unipolar.

Procedure
1. Follow the steps 1 of How to create a New project
2. Type the below code and save it with the name (anyname.c)
3. Follow the steps 2 to 6 of How to create a New Project to add the necessary file, compile and build
the program
4.

Follow the procedures in How to Download a Code to Our Controller to download


your code.

Programs
#include "stm32f4xx.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h" static int i=0;

void anticlock_wise(); void clock_wise(); void delay()


{
for(int i=0;i<0xFF;i++)
for(int j=0;j<0xFF;j++);
}
void mx_pinout_config(void)
{
RCC->AHB1ENR |= 1<<1;

GPIOB->MODER = 0x55555555; GPIOB->OTYPER =0x00000000; GPIOB->PUPDR =


0x00000000; GPIOB->OSPEEDR = 0xFFFFFFFF;
}

148

int main(void)
{
mx_pinout_config();

while (1)
{

anticlock_wise(); delay(); clock_wise(); delay();

}
}
void anticlock_wise()
{
for(i=0;i<52;i++)
{
GPIOB->ODR = 0xA000;
delay(); delay(); delay();delay(); delay(); GPIOB->ODR = 0x6000;
delay(); delay(); delay();delay(); delay(); GPIOB->ODR = 0x5000;

14
91

delay(); delay(); delay();delay(); delay(); GPIOB->ODR = 0x9000;


delay(); delay(); delay();delay(); delay();
}
}

void clock_wise()
{
for(i=0;i<52;i++)
{
GPIOB->ODR = 0x9000;
delay(); delay(); delay();delay(); delay(); GPIOB->ODR = 0x5000;
delay(); delay(); delay();delay(); delay(); GPIOB->ODR = 0x6000;
delay(); delay(); delay();delay(); delay(); GPIOB->ODR = 0xA000;
delay(); delay(); delay();delay(); delay();
}
}

15
01

Procedure to see OUTPUT:


1. Set your board to the execution mode and reset it.
2. The stepper motor will start rotating.

Temperature Sensor
The temperature sensor has to generate a voltage that varies linearly with temperature. The
conversion range is between 1.8 V and 3.6 V. The temperature sensor is internally connected to the
ADC1_IN16 input channel which is used to convert the sensor output voltage into a digital value.
As the offset of the temperature sensor varies from chip to chip due to process variation, the internal
temperature sensor is mainly suitable for applications that detect temperature changes instead of
absolute temperatures. If an accurate temperature reading is needed, then an external temperature
sensor part should be used.

Procedure
1. Follow the steps 1 of How to create a New project
2. Type the below code and save it with the name (anyname.c)
3. Follow the steps 2 to 6 of How to create a New Project to add the necessary file, compile and build
the program
4.

Follow the procedures in How to Download a Code to Our Controller to download


your code.

Program
#include "stm32f4xx.h"
#include <stdio.h>
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_adc.h"
#include "stm32f4xx_gpio.h" static int i=0;

/* private prototype functions*/


void anticlock_wise();
void clock_wise();
void USART2_config();
void adc_configure(); int adc_convert(); uint32_t temp;
static float gk;
void delay()
{
for(int i=0;i<0xFF;i++)
for(int j=0;j<0xFF;j++);
}

IO uint32_t uhADCxConvertedValue = 0;

void USART2_config()
{
RCC->AHB1ENR |= 0x01; RCC->APB1ENR |= 0x20000;

GPIOA->MODER |= 0x000000A0; GPIOA->AFR[0] |= 0x00007700;

USART2->BRR = 0x16D; USART2->CR3 = 0x0000; USART2->CR2 = 0x000; USART2->CR1 =


0x200C;

}
void adc_configure()
{
//Clock configuration
/*The ADC1 is connected the APB2 peripheral bus thus we will use its clock source */
/*Clock for the ADC port!! Do not forget about this one ;) */

//Analog pin configuration


GPIOA->MODER |=0x0000000F; GPIOA->OSPEEDR = 0xFFFFFFFF; GPIOA->PUPDR =
0x00000000;

/* ADC configuration */

ADC3->CR1 = 0x00000000;

/*scan mode disable,12-bit resolution.*/

ADC3->CR2 = 0x00000002;
conversion mode. */

/*data right alignment, continuous

ADC3->SQR1 = 0x00000000;

/* single mode conversion */ ADC3->CR2 |=

0x00000001;

ADC3->SMPR2 = 0x00000030;
>SQR3 = 0x00000001;

/*ADC enable */

/*ADC3 channel-1 with 144 cycles */ ADC3/* rank1 to ADC3 channel-1 */

}
int adc_convert()
{
ADC_SoftwareStartConv(ADC3);

/*Start the conversion */ while(!

ADC_GetFlagStatus(ADC3, ADC_FLAG_EOC));/* Processing the conversion */ return


ADC_GetConversionValue(ADC3);
}

/*Return the converted data */

int putchar(int data)


{
USART2->DR = (data & 0x01FF);
/* Loop until the end of transmission */
while((USART2->SR & 0x40) ==0)
{}
return data;
}
void motor_PIN_config(void)
{
RCC->AHB1ENR |= 1<<1;

GPIOB->MODER = 0x55555555; GPIOB->OTYPER =0x00000000; GPIOB->PUPDR =


0x00000000; GPIOB->OSPEEDR = 0xFFFFFFFF;
}
void main(void)
{
static int ConvertedValue;
motor_PIN_config(); USART2_config();
adc_configure();

/* ADC configuration */

while(1)
{

ConvertedValue = adc_convert();

/* Read the ADC converted value */

temp =ConvertedValue;
gk =temp*3.3; gk /=4095; gk *=100;
printf("\n Temperature = %3.2fC",gk);

if(gk >40)

/* if temperature > 40 */

{ anticlock_wise(); delay();
}
else if(gk <40)
{ clock_wise(); delay();
}
}
}

/* if temperature < 40 */

void anticlock_wise()
{
for(i=0;i<52;i++)
{
GPIOB->ODR = 0xA000;
delay(); delay(); delay();delay(); delay(); GPIOB->ODR = 0x6000;
delay(); delay(); delay();delay(); delay(); GPIOB->ODR = 0x5000;
delay(); delay(); delay();delay(); delay(); GPIOB->ODR = 0x9000;
delay(); delay(); delay();delay(); delay();
}
}
void clock_wise()
{
for(i=0;i<52;i++)
{
GPIOB->ODR = 0x9000;
delay(); delay(); delay();delay(); delay();

GPIOB->ODR = 0x5000;
delay(); delay(); delay();delay(); delay(); GPIOB->ODR = 0x6000;
delay(); delay(); delay();delay(); delay(); GPIOB->ODR = 0xA000;
delay(); delay(); delay();delay(); delay();
}
}

Procedure to View the Result


1. Follow the steps of How to view the result in Win X Talk.
2. Set your board to the execution mode and reset it.
3. The room Temperature will be displayed on the Terminal Window
4. Place a soldering iron or any substance that will dissipate some amount of heat near U12 IC, to have a
variation in the temperature readings.

16
01

Experiment 11
Implementing Zigbee Protocol with ARM
Theory
The X Bee/X Bee-PRO ZNet 2.5 (formerly known as Series 2 and Series 2 PRO) RF Modules were
directed to operate within the ZigBee protocol. The modules provide reliable delivery of data between
remote devices. Zigbee is the communication protocol like wifi and Bluetooth. Xbee is the module
using Zigbee protocol
Some of its features are:
ZigBee is targeted at radio-frequency (RF) applications
Low data rate, long battery life, and secure networking
Transmission range is between 10 and 75 meters (33~246 feet)
The

addressing

space

allows

of

extreme

node

densityup

to

18,450,000,000,000,000,000 devices (64 bit IEEE address)


using local addressing, simple networks of more than 65,000 nodes can be configured, with
reduced address overhead
The radios use direct-sequence spread spectrum coding, which is managed by the digital stream into
the modulator.
To ensure reliable data transmission
Binary phase shift keying (BPSK) in the 868/915 MHz

Offset quadrature phase shift keying (O-QPSK) at 2.4 GHz

Xbee interfacing with PC

Xbee interfacing with microcontroller


Aim
To transmit the data via Xbee and view the output data in the PC.
Apparatus & Software Required
1. VSK STM4 syllabus board.
2. IAR IDE software.
3. Flash Loader Demonstrator.
4. Xbee modules 2 Nos.

Procedure
1. Follow the steps 1 of How to create a New project
2. Type the below code and save it with the name (anyname.c)
3. Follow the steps 2 to 6 of How to create a New Project to add the necessary file, compile and build
the program.
4. Follow the procedures in How to Download a Code to Our Controller to download your code

EC6711 Embedded Systems


Laboratory
User Manual

Program

#include "stm32f4xx.h"
#include <stdio.h>

void USART2_config(); void send_data(char data); char gk[8] = "VSK-SCM4"; void delay(int j)
{
int g,k; for(g=0;g<j;g++) for(k=0;k<j;k++);
}
void main()
{
int i; USART2_config(); while(1)
{
for(i=0;gk[i] != '\0';i++)
{

164

send_data(gk[i]);
} send_data(0x0d); send_data(0x0A);
}
}
void USART2_config()
{
RCC->AHB1ENR |= 1 << 0; RCC->APB1ENR |= 1 <<17;

GPIOA->MODER |= 0x000000A0; GPIOA->AFR[0] |= 0x00007700;

USART2->BRR = 0x1117; USART2->CR3 = 0x0000; USART2->CR2 = 0x000; USART2->CR1 =


0x200C;

165

void send_data(char data)


{
USART2->DR = (data & 0x01FF);
/* Loop until the end of transmission */
while((USART2->SR & 0x40) ==0)
{}
}

int putchar(int data)


{
USART2->DR = (data & 0x01FF);
/* Loop until the end of transmission */
while((USART2->SR & 0x40) ==0)
{}
return data;
}

16
61

Procedure to see OUTPUT:


Compile, Debug & Simulate the above code in IAR.
Connect the RS232 cable / USB cable provided to the PC / Laptop and the VSK STM4 Boards,
and Power on the Board.
For seeing the output in real-time, select the PROG mode, reset the board and download the code
in the board using Flash Loader Demonstrator through UART0.
Connect 1 Xbee module with VSK-STM4 board and the other module to the PC.
Open Win X Talk with a baud rate of 115200.
Now change the Mode-Selection-Switch to EXEC position and reset the board.
The data that is transmitted from the controller can be viewed in PC.

Anda mungkin juga menyukai