EP - Unit - V - Real World Interfacing With Cortex M4 Based Microcontroller
EP - Unit - V - Real World Interfacing With Cortex M4 Based Microcontroller
GPIO Programming, Interfacing seven segment LED, LDR and MQ3 sensor with STM32F4xx, STM32F4xx:
Counters and Timers: Timer and Delay Generation, UART Programming, on chip ADC and Onchip DAC for
waveform generation.
Unit Objectives
1. To get Peripheral insights of STM32F407VG microcontroller.
2. To enhance the capabilities of students to interface various I/O devices and communication protocol
3. To interface sensors using ADC
T3: 3. Shujen Chen, Muhammad Ali Mazidi, Eshragh Ghaemi, “STM32 Arm Programming for Embedded Systems: Using C Language with STM32”, Nucleo, Micro
DigitalEd., Illustrated Edition,2018.
These bits are written by software to configure the I/O direction mode. For eg:- pins 0 and 1 of PORT A as OUTPUT
AFRLy Selection:
0000: AF0 (Alternate Function 0) 1000: AF8 (Alternate Function 8)
0001: AF1 (Alternate Function 1) 1001: AF9 (Alternate Function 9)
0010: AF2 (Alternate Function 2) 1010: AF10 (Alternate Function 10)
0011: AF3 (Alternate Function 3) 1011: AF11 (Alternate Function 11)
0100: AF4 (Alternate Function 4) 1100: AF12 (Alternate Function 12)
0101: AF5 (Alternate Function 5) 1101: AF13 (Alternate Function 13)
0110: AF6 (Alternate Function 6) 1110: AF14 (Alternate Function 14)
0111: AF7 (Alternate Function 7) 1111: AF15 (Alternate Function 15)
Bits [31:0] – AFRHy : Alternate function selection for port X and bit Y, (y = 0 … 7)
AFRHy Selection:
0000: AF0 (Alternate Function 0) 1000: AF8 (Alternate Function 8)
0001: AF1 (Alternate Function 1) 1001: AF9 (Alternate Function 9)
0010: AF2 (Alternate Function 2) 1010: AF10 (Alternate Function 10)
0011: AF3 (Alternate Function 3) 1011: AF11 (Alternate Function 11)
0100: AF4 (Alternate Function 4) 1100: AF12 (Alternate Function 12)
0101: AF5 (Alternate Function 5) 1101: AF13 (Alternate Function 13)
0110: AF6 (Alternate Function 6) 1110: AF14 (Alternate Function 14)
0111: AF7 (Alternate Function 7) 1111: AF15 (Alternate Function 15)
GPIO- Port Output Register (GPIOx_ODR)
• The output register in STM Arm is called GPIO port output data register (GPIOx_ODR)
GPIO port input data register (GPIOx_IDR)
If the pin is high, it returns a ‘1’ and if the pin is low, it returns a ‘0’.
GPIO port bit set/reset register (GPIOx_BSRR)
GPIO port output speed register (GPIOx_OSPEEDR)
GPIO: Clock Enable of the Peripheral Registers (RCC_AHB1ENR)
• To conserve power, Arm microcontrollers have ways of either slowing down the peripheral circuit clock or stopping the
clock altogether.
Ref: [1]
Reading an Input from Push Button using STM32 ARM
C Code:
Q.Draw an interfacing diagram and write a C program to blink LEDs connected to Pin
numbers PC0,2,3,PE3,PB0,1,2,10 using STM32F4xx Controller.
Interfacing Diagram
#include "main.h"
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
while (1)
{
HAL_GPIO_WritePin(Led4_GPIO_Port, Led4_Pin, 0);
HAL_GPIO_WritePin(GPIOC, Led1_Pin|Led2_Pin|Led3_Pin, 0);
HAL_GPIO_WritePin(GPIOB, Led5_Pin|Led66_Pin|Led7_Pin|Led8_Pin,0);
HAL_Delay(1000);
HAL_GPIO_WritePin(Led4_GPIO_Port, Led4_Pin, 1);
HAL_GPIO_WritePin(GPIOC, Led1_Pin|Led2_Pin|Led3_Pin, 1);
HAL_GPIO_WritePin(GPIOB, Led5_Pin|Led66_Pin|Led7_Pin|Led8_Pin,1);
HAL_Delay(1000);
}
}
Q. Draw an interfacing diagram and write a C program to interface “7-Segment” with
STM32F4xx controller and display the count digit “0” to “F” on Segment1.
Interfacing with Seven Segment Display
#include "main.h"
void SSInit()
{
//enable the clock to the GPIOA,GPIOB,GPIOE and GPIOC
RCC->AHB1ENR |= (1<<0)|(1<<1)|(1<<2)|(1<<4); //ENABLE GPIOA,GPIOB,GPIOC,GPIOE
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
SSInit();
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
GPIOA->ODR |= (1<<4); //enable segment 1
for(i=0;i<16;i++)
{
SSDisplay(ssCode[i]);
HAL_Delay(1000);
}
}
/* USER CODE END 3 */
}
Interfacing with Seven Segment Display
C Program to turn on two 7-seg digits alternatively.
Algorithm:-
int main(void)
{
unsigned char buf[16];
unsigned int val;
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
lcd_clear();
lcd_displayString(1,1,"LDR");
HAL_ADC_Start(&hadc1);
if (HAL_ADC_PollForConversion(&hadc1,10)== HAL_OK)
{
val = HAL_ADC_GetValue(&hadc1);
val = val*3.3;
sprintf(buf,"%4.0d mv",val);
lcd_displayString(2,1,buf);
}
//HAL_ADC_Stop(&hadc1);
HAL_Delay(2000);
}
/* USER CODE END 3 */
}
Q.Draw an interfacing diagram and write a C program to interface MQ3 sensor with
STM32F4xx Controller.
Interfacing with MQ3 (Alcohol Gas Sensor )
• Gas Sensor(MQ3) module is useful for gas leakage detection (in home and industry).
• It is suitable for detecting Alcohol, Benzine, CH4, Hexane, LPG, CO.
• It is a low cost semiconductor sensor which can detect the presence of alcohol
gases at concentrations from 0.05 mg/L to 10 mg/L
• Due to its high sensitivity and fast response time, measurements can be taken as soon as
possible.
• The sensitivity of the sensor can be adjusted by using the potentiometer
MQ3 Alcohol Sensor
● MQ3 is one of the most commonly used sensors
in the MQ sensor series.
● It is a Metal Oxide Semiconductor (MOS) type of
sensor.
● Metal oxide sensors are also known as
Chemiresistors, because sensing is based on the
change of resistance of the sensing material
when exposed to alcohol.
Operating voltage 5V ● So by placing it in a simple voltage divider
Load resistance 200 KΩ
network, alcohol concentrations can be detected.
● MQ3 alcohol sensor works on 5V DC and draws
Heater resistance 33Ω ± 5%
around 800mW. It can detect Alcohol
Heating consumption <800mw concentrations anywhere from 25 to 500 ppm.
Sensing Resistance 1 MΩ – 8 MΩ
● The Nickel-Chromium coil and Aluminum Oxide based ceramic forms a Heating
System; while Platinum wires and coating of Tin Dioxide forms a Sensing System.
How MQ3 Alcohol Sensor Works?
● When SnO2 semiconductor layer is heated at high temperature, oxygen is adsorbed
on the surface.
● In clean air, electrons from the conduction band in tin dioxide are attracted to oxygen
molecules. This form an electron depletion layer just below the surface of SnO2
particles and forms a potential barrier.
● As a result, the SnO2 film becomes highly resistive and prevents electric current flow.
● In the presence of alcohol, however, the surface density of adsorbed oxygen decreases
as it reacts with the alcohols; which lowers the potential barrier.
● Electrons are then released into the tin dioxide, allowing current to flow freely
through the sensor.
MQ3 Alcohol Sensor Module Pinout
The main block of the programmable timer is a 16-bit/32-bit counter with its related auto-reload register
• Without the clock enabled, the CPU will not be able to communicate with the timer.
RCC_APB1ENR
RCC_APB2ENR
For example, we can use the following code to enable the clock to TIM2: RCC->APB1ENR |= 1; /* enable TIM2 clock */
Timers in STM32F4xx:- Basic Registers
• There are 14
Registers
DIR (Direction, D4): This bit configures the Timer/Counter as an up or down counter.
• If the DIR bit is 0, the timer counts up.
• If the DIR bit is 1, the counter counts down.
Eg:- Find the value for CR1 register, to enable the TIM2 for up counter.
UIF (D0): This is like overflow flag in other microcontrollers. When the timer counts down from a starting value and
reaches 0, the UIF is set high.
STM32F407 Programmable Timers
Timers in STM32F4xx :- Delay Generation
Example:- Using TIM2, show the code that makes a delay of 20 ms.
Assume SYSCLK =16 MHz.
Given Data:-
SYSCLK =16 MHz
Delay = 20 ms
Solution:-
• delay = N × M / SYSCLK
• N = delay × SYSCLK / M = 0.020 sec × 16 MHz / M = 320,000 / M
Initialization Code:
• If we choose the prescaler (PSC) to divide by 64, RCC->APB1ENR |= 1; /* enable TIM2 clock */
TIM2->PSC = 64 - 1; /*divided by 64 */
• N = 320,000 / 64 = 5,000
TIM2->ARR = 5000 - 1; /* divided by 5000*/
TIM2->CNT = 0;
TIM2->CR1 = 1; /* enable timer2 */
#include "stm32f4xx.h" // Device header
int main()
{
//Configure PA5 as ouput to drive LED
RCC->AHB1ENR |=0x00000008;// Enable GPIOD Clock
GPIOD->MODER &=0x55000000;//Set pin to OUTPUT Mode
GPIOD->MODER |=0x55000000;
The Synchronous type of transmitters generates the data clock and sends it to the receiver
which works accordingly in a synchronized manner. On the other hand, the Asynchronous
type of transmitter generates the data clock internally. There is no incoming serial clock signal,
so in order to achieve proper communication between the two ends, both of them must be
using the same baud rate.
UART in STM32F4xx
The universal synchronous asynchronous receiver transmitter (USART) offers a
flexible means of full-duplex
data exchange with external equipment requiring an industry standard
Bits 1:0 SW: System clock switch Bits 7:4 HPRE: AHB prescaler
00: HSI oscillator selected as system clock 0xxx: system clock not divided
01: HSE oscillator selected as system clock 1000: system clock divided by 2
10: PLL selected as system clock 1001: system clock divided by 4
11: not allowed 1010: system clock divided by 8
1011: system clock divided by 16
1100: system clock divided by 64
1101: system clock divided by 128
1110: system clock divided by 256
1111: system clock divided by 512
UART: RCC_CR (RCC Control Register)
The HSI clock signal is generated from an internal 16 MHz RC oscillator and can be used directly as a system clock
RCC_CR is used to set the clock for UART
Bit 5 RXNE: Read data register not empty: 0: Data is not received, 1: Received data is ready to be
read.
UART: Data register (USART_DR)
• Contains the Received or Transmitted data character, depending on whether it is read from or written to.
UART :- Baud Rate Generation
The baud rate for the receiver and transmitter (Rx and Tx) are both set to the same value as programmed in
the Mantissa and Fraction values of USARTDIV
Baud Rate =
Example 2:- For SYSCLK = 16MHZ, And for Baud Rate = 19200 with OVER8 = 0 ?
Soln:-
USARTDIV = Fck / 16 x Baud
16MHz / 16 x 19,200 = 52.08.
Now, 52 = 0x034 for upper 12-bits.
For fraction part, 0.08 x 16 = 1.28 and we use 1 for lower 4-bits.
Steps to configure USART2 for transmitting data
• 6) Configure the CR2 (Control 2) register for number of stop bit(s) and so on.
• 7) Configure the CR3 (Control 3) register for no hardware flow control and so on.
• 8) Enable USART2 after configuration complete
• 9) Wait until the TXE (Transmit Empty) bit of the USART_SR register is set.
C Code to configure USART2 for transmitting data
#include "stm32F4xx.h"
void USART2_init(void);
void USART2_write(int c);
int main (void) { /* Write a character to USART2 */
USART2_init(); /* initialize USART2 */ void USART2_write (int ch) {
while(1) { /* Loop forever */ while (!(USART2->SR & 0x0080)) {} // wait until Tx
USART2_write('Y’); //Transmit Character buffer empty
USART2_write('e'); USART2->DR = (ch & 0xFF);
USART2_write('s'); }
}}
void USART2_init (void) {
RCC->AHB1ENR |= 1; /* Enable GPIOA clock */
RCC->APB1ENR |= 0x20000; /* Enable USART2 clock */
conversion time
• A sample and hold circuit is added between the input signal and the converter.
The number of clock cycles for sampling time can be programmed using ADC_SMPRx (Sample Time Register)
register. We have two ADC_SMPRx registers to covers all the 18 ADC channels.
• For example, if we use the default of 3 clock cycle for sample time with the 8-bit ADC resolution, the total
number of clocks needed for ADC conversion is 11 clocks.
Analog input pin assignment (GPIO_MODER Register)
GPIO_MODER
ADC-H/W Pins
Channel Allocation
ADC_DR (ADC Data Register)
• Upon the completion of a conversion, the result is placed in the DATA registers.
• Its 32 bit, only the lower 12 bits are used and upper 18 bits are unused.
Control 1 (ADC_CR1) Register
• RES bits (D25-D24) of ADC_CR1 register to select 6, 8, 10, or 12- bit ADC resolution.
• Bit 5 EOCIE: Interrupt enable for EOC
• ALIGN bit in CR2 register allows the binary output result of ADC conversion to be moved to the left
ADC regular sequence register 3 (ADC_SQR3)
Bit 5: OVR Overrun This bit is set by hardware when data are lost.
This happens if we do not read the result of the last conversion from the Data Register (ADC_DR).
We can use EOCIE (EOC Interrupt enable) bit in ADC_CR1 register to enable the interrupt option
Algorithm:- Configuring ADC and reading ADC channel
3. Using ADC_CR1 register, select the resolution and the analog input channel.
4. Use GPIOx_MODER register to configure input pin for analog input channel.
5. Using ADC_CR2 register Enable the ADC (ADON) and START (SWSTART) to start the conversion.
6. Monitor the EOC flag in the ADC_SR register for end-of-conversion.
7. When the EOC flag goes HIGH, read the ADC data result from the ADC_DR register and save it.
8. Repeat steps 6 through 7 for the next conversion.
C Program to Read ADC
#include "stm32f4xx.h"
int main (void) {
int result;
/* set up pin PA5 for LED */
RCC->AHB1ENR |= 1; /* enable GPIOA clock */
GPIOA->MODER &=~0x00000C00; /* clear pin mode */
GPIOA->MODER |= 0x00000400; /* set pin to output mode */
/* set up pin PA1 for analog input */
RCC->AHB1ENR |= 1; /* enable GPIOA clock */
GPIOA->MODER |= 0xC; /*PA1 analog */
while (1) {
/* setup ADC1 */
ADC1->CR2 |= 0x40000000; /* start a conversion */
RCC->APB2ENR |= 0x00000100; /* enable ADC1 clock */
while(!(ADC1->SR & 2)) {} /* wait for conv complete */
ADC1->CR2 = 0; /* SW trigger */ result = ADC1->DR; /* read conversion result */
ADC1->SQR3 = 1; /* conversion sequence starts at ch 1 */ if (result & 0x100)
ADC1->SQR1= 0; /* conversion sequence length 1 */ GPIOA->BSRR = 0x00000020; /* turn on LED */
ADC1->CR2 |= 1; /* enable ADC1 */ else
GPIOA->BSRR = 0x00200000; /* turn off LED */ }
}
DAC
Features of DAC
• Two DAC converters: one output channel each as DAC1 and DAC2.
• They are available at the analog out pins “PA4 and PA5” for chan1 and chan2
• Left or right data alignment in 12-bit mode
• Synchronized update capability
• Noise-wave generation
• Triangular-wave generation
• Dual DAC channel for independent or simultaneous conversions
• DMA capability for each channel
• DMA underrun error detection
STM32F4xx DAC Block Diagram
The DAC integrates two output buffers that can be used to reduce the output impedance, and to drive external loads
directly without having to add an external operational amplifier.
Vref should be at 1.8 V ≤ VREF+ ≤ VDDA
The output voltage from the DAC can be calculated using the following formula:
DAC_CR (DAC Control Register)
Bit 0 EN1: DAC channel1 enable ; where 0: DAC channel1 disabled, 1: DAC channel1 enabled
Bit 1 BOFF1: DAC channel1 output buffer disable
Bits 5:3 TSEL1[2:0]: DAC channel1 trigger selection
DAC Data Holding Registers (DAC_DHR)
• There are 8 registers according to Data Holding Position
• For eg: - DAC channel1 12-bit right-aligned data holding register (DAC_DHR12R1)
• Solution:- The loop counter i is incremented every iteration and written into the DAC_DHR register to create
the 4 steps.
void delay(void)
{
volatile int i;
for(i=0;i<5000;i++);
}
int main(void)
{
uint32_t DAC_OUT[4]={0,1241,2482,3723};
uint8_t i=0;
int data;
RCC->AHB1ENR|=1;
GPIOA->MODER |=0x00000300;
RCC->APB1ENR |=1<<29;/*Enable DAC Clock*/
DAC->CR|=1;;/*Enable DAC */
while(1)
{
DAC->DHR12R1=DAC_OUT[i++];
if(i==4)
{
i=0;
}
delay();
}
}
REFERENCES
• [1] https://ezcontents.org/stm32f4-discovery-blink-led-osx
• [2] https://deepbluembedded.com/
THANK YOU