You are on page 1of 23

Table of Contents

1 SUMMARY ERROR! BOOKMARK NOT DEFINED.

2 OBJECTIVE ERROR! BOOKMARK NOT DEFINED.

3 INTRODUCTION ERROR! BOOKMARK NOT DEFINED.

4 HARDWARE DISCUSSION ERROR! BOOKMARK NOT DEFINED.

5 SOFTWARE DISCUSSION ERROR! BOOKMARK NOT DEFINED.

6 PROBLEM DISCUSSION ERROR! BOOKMARK NOT DEFINED.

7 CONCLUSION ERROR! BOOKMARK NOT DEFINED.

8 REFERENCES ERROR! BOOKMARK NOT DEFINED.

9 APPENDIX ERROR! BOOKMARK NOT DEFINED.


FIG1. Bill Of Materials BOM
Reference:

1. USB3075-30-A. USB Connectors

https://www.mouser.com/ProductDetail/GCT/USB3075-30-
A?qs=KUoIvG%2F9IlbGMJplbp1ybA%3D%3D

2. Multilayer Ceramic Capacitors


https://www.mouser.com/ProductDetail/KYOCERA-
AVX/04025C104KAT4A?qs=vLWxofP3U2xkC715MLOzpQ%3D%3D

3. LDO Voltage Regulators


https://www.mouser.com/ProductDetail/Torex-Semiconductor/XC6210A332MR-
G?qs=AsjdqWjXhJ%252BGZM2kyDkSFw%3D%3D

4. Tactile Switches
https://www.mouser.com/ProductDetail/CK/KSR221GLFS?qs=vOd3edNlRKBvF0VngmgZ
kw%3D%3D

5. Thick Film Resistors


https://www.mouser.com/ProductDetail/YAGEO/RC0402FR-
071KL?qs=V1yeUXFNrknDEmWLmm5v6g%3D%3D

6. Wi-Fi Modules - 802.11 Wi-Fi Modules


https://www.mouser.com/ProductDetail/Espressif-Systems/ESP-WROOM-02D-
N4?qs=Li%252BoUPsLEnuNxdYYhsYiqw%3D%3D

7. Thick Film Resistors - SMD Thick Film Resistors - SMD 1/16watt 4.7Koh
https://www.mouser.com/ProductDetail/Vishay-
Dale/CRCW04024K70JNEDHP?qs=k2%2FDWSARqgGhgirK%2FulFyA%3D%3D

8. Thick Film Resistors - SMD Thick Film Resistors - SMD 10 kOhms 62.5m
https://www.mouser.com/ProductDetail/YAGEO/RC0402FR-
0710KL?qs=I1mnnYJTTsxUoNwrUsQExA%3D%3D

9. Standard LEDs
https://www.mouser.com/ProductDetail/Bivar/SM0805UBWC?qs=hWDdE2Pc5RAgQGa
mDSfd%252BQ%3D%3D

10. Slide Switches 1PDT


https://www.mouser.com/ProductDetail/CK/JS102011SAQN?qs=LgMIjt8LuD%252B69b
NM9a%2FozQ%3D%3D

11. DC Power Connectors Power Jacks


https://www.mouser.com/ProductDetail/CUI-Devices/PJ-036AH-SMT-
TR?qs=WyjlAZoYn52SyDl2EH3QRQ%3D%3D

12. Multilayer Ceramic Capacitors MLCC - SMD/SMT Multilayer Ceramic C


https://www.mouser.com/ProductDetail/YAGEO/CC0402FRNPO9BN470?qs=5q%252Bql
K8CmJSNhzsn%252BFTicg%3D%3D

13. Proximity Sensors


https://www.mouser.com/ProductDetail/Vishay-
Semiconductors/VCNL3040?qs=bZr6mbWTK5m90GodUNdcvA%3D%3D

14. USB Interface IC USB to Full Serial UART IC SSOP-20


https://www.mouser.com/ProductDetail/FTDI/FT231XS-
R?qs=Gp1Yz1mis3WduRPsgrTbtg%3D%3D

15. Thick Film Resistors - SMD Thick Film Resistors - SMD 27 OHM 1%
https://www.mouser.com/ProductDetail/Bourns/CR0402-FX-
27R0GLF?qs=SFHnMgm9IsxG%252BvpJZf0h2g%3D%3D

16. Multilayer Ceramic Capacitors MLCC - SMD/SMT Multilayer Ceramic


https://www.mouser.com/ProductDetail/YAGEO/CC0402KRX5R6BB474?qs=57cj7OiSijkc
9vhOdS3kSg%3D%3D

17. SRAM 2Mb 256Kx8 45MHz 2.2-3.6V Serial SRAM


https://www.mouser.com/ProductDetail/ISSI/IS62WVS2568GBLL-45NLI-
TR?qs=F5EMLAvA7IDi1b3lWvG69A%3D%3D

18. Multilayer Ceramic Capacitors MLCC - SMD/SMT Multilayer Ceramic C


https://www.mouser.com/ProductDetail/YAGEO/CC0402KRX5R6BB105?qs=BKNoF%2F0
xMNu0TvpE6ze2Iw%3D%3D

19. Arducam Mini Module Camera Shield OV2640 2 Megapixels


https://www.amazon.com/Arducam-Module-Megapixels-Arduino-
Mega2560/dp/B012UXNDOY/ref=sr_
I2C: Inter-Integrated Circuit

I2C Pinout GPIO PINS Configuration GPIO Configuration

I2C1_SCL PB6 I2C Clock Alternate Function AF1 (Open Drain)

I2C1_SDA PB7 I2C Data I/O Alternate Function AF1 (Open Drain)

Addressing Mode 7 bit Addressing Mode

Fast Mode 300 KHz

Table 1.0. I2C GPIO Configuration

The I2C is a synchronous serial protocol. It uses only 2 bidirectional open drain pins for data

transmission. The serial Clock (SCL) role is to synchronize the data transfer between different
chips, and the Serial Data for data transfer. The implementation of the I2C protocol requires

two pull-up resistors (4.7Kohm for our design) on each line. In this project, only one master was

used to interface with at least 2 I2C devices. The master device generates the clock and initiates

and terminates the transmission. The slave receives the clock. The master and slave devices can

both receive or transmit data. Two slave devices (Proximity sensor and GPS MAX-8C) were used

in our system and both slave devices can only write to the master (the Microcontroller). In the

I2C protocol, the data line (SDA) changes only when the clock line (SCK) is LOW. SDA cannot

change when the clock line is HIGH. Notice that the START and STOP conditions are an

exception to the above rule. The START and STOP conditions are generated by setting the SCL

and SDA lines HIGH. With the SCL line HIGH, the START condition is generated by a HIGH-to-

LOW change in the SDA line and the STOP condition is generated by a LOW-to-HIGH change on

the SDA line.

What is the address byte format in I2C?

In I2C the address byte must be framed in 9-bit long with the first 8-bit put on the SDA line and

the 9th for acknowledging or not-acknowledge. If the receiver pulls the SDA line LOW, it

indicates the acknowledgment, but when the receiver does not pull the SDA line LOW it is

considered as not-acknowledge. A complete data transfer is made as follows: START + Slave

address + one / multiple data bytes + STOP.

How to determine the READ/WRITE conditions?

We said previously that the address frame is 9 bits long and 8 bits are put on the SDA line by

the transmitter. The 8th bit is the READ/WRITE control bit. Master (the Microcontroller) can
read from slave (Proximity sensor/GPS) only if the 8th bit is HIGH. Master writes to a slave only

when the 8th bit is LOW. Only the 8th bit can define the status of the 9th bit (acknowledge for

SDA line low or not-acknowledge for SDA line high)

What is the data byte format in I2C?

Same as the address byte, the data byte format is 9 bits long. The first 8 bits are the data to be

transmitted and the 9th bit is for acknowledge or not acknowledge

• The transactions are always initiated and completed by the Master


• All messages have an address frame and the data frame
• Data is placed on the SDA line after the SCL line goes LOW and it is sampled after the
SCL line goes HIGH.
• All transactions begin with START and are terminated by STOP
• A HIGH to LOW transition on the SDA line, while the SCL is HIGH, defines a START
condition
• A LOW to HIGH transition on the SDA line, while SCL is HIGH, defines a STOP
condition.
• START and STOP conditions are always generated by the MASTER
• The bus can be free again at a certain time after the STOP condition
• The bus stays busy if a repeated START is generated instead of a STOP condition.

ACK/
START Slave Address R/W Data ACK STOP
NACK
R 0

1 1

START Slave Address R/W ACK Data ACK STOP

Read (R) 1, Write (W) 0

• Any information transmitted on the SDA line must be EIGHT bits long.
• The number of bytes that can be transmitted per transfer is UNRESTRICTED.
• Each byte must be followed by an acknowledge (ACK) bit.
• Data is transferred with the MSB (Most Significant Bit) first.
• The address frame is first in any new communication sequence
• For a 7-bit address, the address is sent out a significant bit (MSB) first, followed by an
R/W bit indicating whether this is a Read (1) or Write (0) operation.
• The data frame begins transmission after the address frame is sent
• The master will simply continue generating clock pulses on SCL at regular intervals, and
the data will be placed on SDA by either the master or the slave, depending on whether
the R/W bit indicated a Read or Write operation.
• This is the speed of the I2C interface and should correspond with the bus speeds defined
in the I2C specification
• The specification defines the following modes:
Standard-Mode 100 kHz max

Fast-Mode 400 kHz max

Fast-Mode plus 1 MHz

High-Speed Mode 3.4 MHz

How to find what resistor to use for the I2C bus?

Freq<100kHz⟹Rmin = (Vcc−0.4V) / 3mA, Rmax = 1000ns / Cbus


Freq>100kHz⟹Rmin = (Vcc−0.4V) / 3mA, Rmax=300ns / Cbus
Cbus = maximum bus capacitance in microfarad (100pF).

• Specifies the ratio between the low and tHIGH of the I2C SCL line.
• Possible values:

I2C_DUTYCYCLE_2 2:1

I2C_DUTYCYCLE_2 16:9

• By choosing the appropriate duty cycle we can pre-scale the peripheral clock to
achieve the desired I2C speed.

I2C implementation with DMA


This code is written for STM32L0xx (STM32L031K6T7)
The code is written using no internal library. It is a bare metal programming utilizing the
following documentation:

Datasheet:
Access line ultra-low-power 32-bit MCU Arm®-based Cortex®-M0+, up to 32KB Flash, 8KB SRAM, 1KB
EEPROM, ADC (mouser.com)
Reference Manual:
Ultra-low-power STM32L0x3 advanced ARM®-based 32-bit MCUs (mouser.com)

On the datasheet, I2C1 is connected to APB1 Bus. We need to go to the APB1EN register to
enable clock access to I2C1. We need to configure GPIO pins to work as an Alternate Function
(AF). The GPIO pins associated with I2C1 are (see datasheet page 46):

• PB6 (I2C1_SCL),
• PB7 (I2C1_SDA)
For these pins, the Alternate function 1 (AF1) is used.

We will be using DMA to implement I2C1 and the DMA request channel that needs to be used is
Channel 6 (I2C1_Tx), and channel 7 (I2C1_Rx). This information can be found on the RM0367
Reference manual on page 266.

I2C Implementation Procedures.


PB6→ I2C1_SCL
PB7→ I2C1_SDA
DMA_Channel6→ I2C1_Tx
DMA_Channel7→ I2C1_Rx

I2C Initialization:

• GPIO pin Configuration for I2C1



#define DMA_CSELR (*(volatile unsigned int *)(0x400200a8))
void i2c_init (uint32_t timing)
{
➔ Enable clock access to GPIOB
RCC→IOPENR |= RCC_IOPENR_IOPBEN

➔ Set PB6 and PB7 to alternate function mode. Page 246 MODER6[1:0]
PB6:
GPIOB→MODER &= ~(1U<<12) = GPIO_MODER_MODE6_0
PB7 :
GPIOB→MODER |= (1U<<13) = GPIO_MODER_MODE6_1

➔ Set output type of PB6 and PB7. (GPIOx_OTYPER) Set to open drain
GPIOB→ OTYPER |= (1<<6)
GPIOB→ OTYPER |= (1<<7)

➔ GPIO port output speed register (GPIOx_OSPEEDR)


Bits 31:0 OSPEED [15:0][1:0]: Port x configuration I/O pin y (y = 15 to 0) These bits are
written by software to configure the I/O output speed. 00: Low speed 01: Medium speed
10: High speed 11: Very high speed
PB6
GPIOB→ OSPEEDR |= (1U<<12) or |= GPIO_OSPEEDER_OSPEED6_0
GPIOB→ OSPEEDR |= (1U<<13) or |= GPIO_OSPEEDER_OSPEED6_1
PB7
GPIOB→ OSPEEDR |= (1U<<14) or |= GPIO_OSPEEDER_OSPEED7_0
GPIOB→ OSPEEDR |= (1U<<15 or |= GPIO_OSPEEDER_OSPEED7_1

➔ Select PB6 and PB7 alternate function types for I2C. GPIOx_AFRL
PB6: AF1 = 0001
GPIOB→AFR [0] |= (1<<24)
GPIOB→AFR [0] &= ~ (1<<25)
GPIOB→AFR [0] &= ~ (1<<26)
GPIOB→AFR [0] &= ~ (1<<27)

PB7: AF1 = 0001


GPIOB→AFR [0] |= (1<<28)
GPIOB→AFR [0] &= ~ (1<<29)
GPIOB→AFR [0] &= ~ (1<<30)
GPIOB→AFR [0] &= ~ (1<<31)

• I2C configuration. I2C is connected to the APB1 bus.


➔ Enable clock access to I2C1
RCC→APB1ENR |= (1<<21) or |= RCC_APB1ENR_I2C1EN

➔ Reset the I2C module (Software reset)


A software reset can be performed by clearing the PE bit in the I2C_CR1 register. In that
case, I2C lines SCL and SDA are released. Internal states machines are reset and
communication control bits, as well as status bits, come back to their reset value. The
configuration registers are not impacted. See page 703 for details.

0: Peripheral disable
I2C1→CR1 &= ~(1U<<0) or = ~I2C_CR1_PE

➔ I2C timing register (I2C_TIMINGR)


I2C1→TIMINGR = timing

➔ Enable the peripheral clock on DMA


RCC→AHBENR |= RCC_AHBENR_DMA1EN

➔ DMA channel x configuration register (DMA_CCRx)

DMA1_Channel6→CCR |= DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TCIE


DMA1_Channel7→CCR |= DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TCIE

➔ DMA channel x peripheral address register (DMA_CCRx)


DMA1_Channel6→CPAR= (uint32_t)&I2C1→TXDR
DMA1_Channel6→CPAR= (uint32_t)&I2C1→RXDR;

DMA1_Channel7→CPAR= (uint32_t)&I2C1→TXDR
DMA1_Channel7→CPAR= (uint32_t)&I2C1→RXDR

➔ Enable Interrupt on DMA Channel


NVIC_EnableIRQ (DMA1_Channel4_5_6_7_IRQn)

➔ DMA channel selection register (DMA_CSELR)


DMA_CSELR |= (0x06<<20)

➔ Enable clock stretching. NOSTRETCH = 0.


0: Clock stretching enabled
1: Clock stretching disabled

I2C→CR1 &= ~(1U<<17) or &= ~I2C_CR1_NOSTRETCH

➔ Enable the I2C1 module. Release the reset

1: Peripheral enable
I2C1→CR1 |= (1U<<0) or |= I2C_CR1_PE
➔ Disable “General call enable”: Bit 19 GCEN
0: General call disabled. Address 0b00000000 is NACKed.
1: General call enabled. Address 0b00000000 is ACKed.

I2C→CR1 &= ~(1U<<19) or &= ~I2C_CR1_GCEN

➔ Select to use DMA

➔ Set source clock speed

➔ Enable I2C1 module


}

Send a byte of data to a slave device pge 336

1. Monitor the BUSY bit of I2C_SR2 (Status 2) register until the bus is idle
2. Write to START bit (bit 8) of I2C_CR1 (Control 1) register to generate a START condition on
the bus
3. Wait until the START condition is complete, the SB bit (bit 0) of I2C_SR1 register is set
4. Write the slave address with the R/W bit (bit 0) cleared (for a write) to I2C_DR (Data Register),
this will transmit the slave address
5. Wait until ADDR bit (bit 1) of I2C_SR1 register is set signaling that the slave address is sent
6. Read I2C_SR1 and I2C_SR2 to clear the ADDR bit
7. Wait until TxE bit of I2C_SR1 register is set signaling that the transmit data register is empty
8. Write the register/memory address to I2C_DR register
9. Wait until TxE bit of I2C_SR1 register is set signaling that the transmit data register is empty
10. Write the data to I2C_DR register
11. Wait until BTF (Byte Transfer Finished) bit of I2C_SR1 register is set signaling that the data is
sent
12. Write to STOP bit (bit 9) of I2C_CR1 register to generate a STOP condition on the bus The
procedure listed above is a simplified version

Read a byte of data from a slave device pge 337


1. Monitor the BUSY bit of I2C_SR2 (Status 2) register until the bus is idle
2. Write to START bit (bit 8) of I2C_CR1 (Control 1) register to generate a START condition on
the bus
3. Wait until the START condition is complete, the SB bit (bit 0) of I2C_SR1 register is set
4. Write the slave address with the R/W bit (bit 0) cleared (for a write) to I2C_DR (Data Register),
this will transmit the slave address
5. Wait until ADDR bit (bit 1) of I2C_SR1 register is set signaling that the slave address is sent
6. Read I2C_SR1 and I2C_SR2 to clear the ADDR bit
7. Wait until TxE bit of I2C_SR1 register is set signaling that the transmit data register is empty
8. Write the register/memory address to I2C_DR register
9. Wait until TxE bit of I2C_SR1 register is set signaling that the transmit data register is empty
10. Write to START bit (bit 8) of I2C_CR1 (Control 1) register to generate a RESTART condition
11. Wait until the RESTART condition is complete, the SB bit (bit 0) of I2C_SR1 register is set
12. Write the slave address with the R/W bit (bit 0) set (for a read) to I2C_DR (Data Register), this
will transmit the slave address with read
13. Wait until ADDR bit (bit 1) of I2C_SR1 register is set signaling that the slave address is sent
14. Clear ACK bit (bit 10) of I2C_CR1 register, preparing to return a NACK
15. Read I2C_SR1 and I2C_SR2 to clear the ADDR bit
16. Write to STOP bit (bit 9) of I2C_CR1 register to generate a STOP condition on the bus
17. Wait until RxNE bit of I2C_SR1 register is set signaling that the receive data register is not
empty
18. Read I2C_DR register to retrieve the data

Above are all the steps we need to implement I2C1 DMA.

Wrong behaviors in Stop mode when waking up from Stop mode is disabled in the I2C

peripheral

See→ STM32L031x4/6 device limitations (octopart.com)

Description

When wakeup from Stop mode is disabled in the I2C interface (WUPEN = 0) and the

microcontroller enters Stop mode while a transfer is ongoing on the bus, some wrong

behavior may happen:


1. The BUSY flag can be wrongly set when the microcontroller exits Stop mode. This

prevents initiating a transfer in master mode, as the START condition cannot be sent when

BUSY is set.

2. If clock stretching is enabled (NOSTRETCH = 0), the I2C clock SCL may be kept low by the

I2C as long as the microcontroller remains in Stop mode. This limitation may occur when

Stop mode is entered during the address phase of an I2C bus transfer while SCL = 0.

Therefore, the transfer may be stalled as long as the microcontroller is in Stop mode. The

probability that this issue occurs depends also on the timing’s configuration, the peripheral

clock frequency, and the I2C bus frequency.

These behaviors can occur in Slave mode and Master mode in a multi-master topology.

Workaround
Disable the I2C interface (PE=0) before entering Stop mode and enable it again in Run
mode.

SPI Implementation:

SPI stands for Serial Peripheral Interface.


SPI is a Synchronous and full-duplex communication between a master and several slave
devices.
SPI protocol uses 2 pins for data transfer: MOSI and MISO.
MOSI stands for Master Out Slave In. MOSI pin is used to send data from the master to the
slave device.
MISO stands for Master Input Slave Output. MISO is used to send data from the slave to the
master device.

There is a third pin, an SCK pin to synchronize the data transfer between two devices.
SCK stands for Serial Clock. SCK is used to generate a clock to synchronize data transfer
between master and slave. The clock is generated by the master.

The Slave Select (SS) pin is used to initiate and terminate the data transfer between slave
devices and the master. SS pin is used to select a particular slave when interfacing with
multiple slave devices. A total of 4 pins are implicated in the SPI operation. Unlike I2C, SPI
slaves have no addresses. The selection is simply made with the slave select line. In SPI, the
shift register is 8 bits long. So, after 8 clock pulses, the contents of the two shift registers are
interchanged. Suppose that master wants to send data to the slave device. Master will place
the data on its shift register and generates 8 clock pulses and after the generation of 8 clock
pulses, the byte is transmitted to the slave shift register. Now suppose the master would
like to receive data from the slave. The slave will place data on its shift register and after 8
clock pulses generated by the master, a byte of data will be received by the master shift
register. In SPI mode, data can be sent and received at the same time because SPI protocol
is a full duplex. In the USART implementation, we mentioned that the transmitter and
receiver must agree on a clock frequency known as the baud rate. It is different in SPI mode.
In SPI, the master and slave devices use the same clock. As only the master generates the
clock, the master and slave must agree on clock polarity and clock phase with respect to
data. In the SPI implementation for this project, we will set the clock polarity and phase.
Notice that the combination of CPOL and CPHA is referred to as the SPI bus. During our
implementation, CPOL and CPHA are set to 1. This means that the active state of the clock is
0, the Idle state of the clock is 1, and data is captured on the rising edge and the output
data is done on the falling edge.

SPI DMA driver


Initialization:

GPIO configuration
1. Enable clock access to port of SPI pins
2. Set SPI pins mode to alternate function mode AF0
3. Set alternate type AF0

SPI configuration
1. Enable clock access to SPI module
2. Set software slave management
3. Set SPI to master mode
4. Set CPHA and CPOL
5. Set Clock Divider: Baud Rate Control
6. Select to use DMA
7. Enable SPI module

SPI DMA Tx initialization


DMA channel 3 (Tx)

DMA Configuration

1. Enable clock access to DMA


2. Disable DMA channel 3
3. Wait until DMA is disabled

Configure DMA channel parameters.

1. Enable memory address increment


2. Set transfer direction
3. Enable transfer complete interrupt: TCIE
4. Enable transfer error interrupt: TEIE
5. Disable direct mode
6. Set DMA FIFO threshold
7. Enable DMA interrupt in NVIC

SPI DMA Tx initialization


DMA channel 2 (Rx)
1. Transmission mode: Full-Duplex data can be transmitted in both ways at a time.

USART overview:

USART is a serial data communication that uses two methods: Synchronous and
Asynchronous. During synchronous communication, the clock is transmitted with the data,
and during asynchronous communication, there is no clock transmitted. The transmitter
and the receiver agree on the clock speed for the data transmission which is known as the
Baud rate. To implement the USART we will set up the Baud rate for both the transmitter
and receiver.
The transmission mode used for this project is a Full Duplex. In a Full Duplex mode, the data
can be transmitted in both directions at the same time. In Asynchronous transmission, the
byte to be transmitted is packed between START and STOP bits and the START bit value is a
single bit which is always 0. The stop bit value can be a single or 2 bit which is always 1. So,
transmitting a character “A” (0100 0001 in binary) will become

Stop bit Data frame Start bit


1 1 0 1 0 0 0 0 0 1 0

Table1: Example of transmitting an ASCII character “A” through USART protocol.

In the USART communication system, connection speed is very important. The baud rate is
known as the rate at which the change to the signal occurs every second when the
transmission occurs. This setup is important for USART communication. Another important
setup is Stop bit and Parity. The stop bit can be 1 bit or two bits, and the parity is either odd
or even. It is important in the USART communication system to check parity. Parity is used
for error checking. For this project, we also configure the mode of communication that
specifies whether the transmission mode is Rx mode or Tx mode. The number of the data
bit to be transmitted or received is known as Word Length and can be 8 or 9 bits. Lastly, the
Hardware Flow Control configuration to specify whether it is enabled or not.

Implementation:

- DMA Channel 4 (USART2_TX)


- DMA Channel 5 (USART2_RX)
- AF4 Alternate Function 4
- PA9 →USART2_TX
- PA10 →USART2_RX

A. USART2 initialization

I. Configure USART2 GPIO pin


a. Enable clock access to GPIOA
Bit 0 of the GPIO clock enable register is I/O port A serves to enable the clock.
The bit 0 is set and cleared by the software. Writing 0 to this bit will disable port
A clock and writing 1 to this bit will enable the clock access to port A. in this
configuration bit 0 must be set to 1 to enable the clock access to PA as follow:
RCC->IOPENR |= RCC_IOPENR_GPIOAEN.

b. Set PA9 mode to alternate function mode


This bit is set through the GPIO port mode register. In this case, we are concerned
about the Alternate Function mode for PA9 and PA10. Bits 18 and 19 are set to 0
and 1 respectively for PA9, and bits 20 and 21 to 0 and 1 respectively for PA10.
GPIOA->MODER &= ! (1U<<18)
GPIOA->MODER |= (1U<<19)
c. Set PA10 mode to alternate function mode
GPIOA->MODER &= ! (1U<<20)
GPIOA->MODER |= (1U<<21).

d. Set PA9 to alternate function type AF4 (USART2_TX)


There are two types of alternate function registers. Alternate function high register
and alternate function low register. As we are using PA9 and PA10 we are
required to use GPIO alternate function High register. We are concerned about
alternate function 4 AF4 and to set the PA9 and PA10 we write these bits 0100 to
the register bits 4, 5, 6, 7 and 8, 9, 10, 11.

GPIOA->AFR [1] &=! (1U<<4)


GPIOA->AFR [1] &=! (1U<<5)
GPIOA->AFR [1] |= (1U<<6)
GPIOA->AFR [1] &=! (1U<<7)

e. Set PA10 mode to alternate function mode AF4 (USART2_RX)


GPIOA->AFR [1] &=! (1U<<8)
GPIOA->AFR [1] &=! (1U<<9)
GPIOA->AFR [1] |= (1U<<10)
GPIOA->AFR [1] &=! (1U<<11)
II. Configure USART2 module
a. Enable clock access to USART2
USART2 is connected to the APB1 bus. To enable clock access to USART2 this
must be done through the APB1 register. Bit 17 of the APB1 peripheral clock
enable register is the USART2 clock enable bit. Writing 0 to this bit will disable
the clock and writing 1 to this bit will enable the clock to access USART2. For
this project we set bit 17 to 1 as follows:
RCC->APB1ENR |= RCC_APB1ENR_USART2EN.

b. Set Baud Rate


To set the baud rate, two static functions were created. these functions take two
parameters such as peripheral_clock and baud Rate. The baud rate for both the
receiver and transmitter is set to the same value. These two functions can be
found in the appendix of this report.

c. Enable DMA TX and RX for USART2


This bit is enabled through USART control register 3. The DMA enable
transmitter DMAT is bit 7. This bit is enabled by writing 1 to the DMAT register.
The DMA enable receiver DMAR is bit 6 and it is enabled by writing 1 to the
DMAR register.
USART2->CR3 = USART_CR3_DMAT | USART_CR3_DMAR.

d. Set transfer direction


The transfer direction bit is set through the USART control register 1. Bit 2 is for
the receiver to enable the register. Writing 1 to this bit will enable RE to register.
Bit 3 is for the transmitter enable register. Writing 1 to the bit will enable the TE
register.
USART2->CR1 = USART_CR1_TE | USART_CR1_RE.

e. Clear Transfer Complete (TC) flag


This bit is set through USART interrupt and status register. The transfer complete
flag is bit 6. When this bit is set to 0, it means the transfer is not completed.
Setting the bit to 1 will complete the transfer. In our case, this bit must be cleared
USART2->ISR &= ~USART_ISR_TC.

f. Enable TCIE
Bit 6 is the transmission complete interrupt bit. This bit must be set to 1 so the
USART interrupt is generated in the USART_ISR register.
USART2->CR1 |= USART_CR1_TCIE.

g. Enable USART2 module.


This is the final action that needs to be taken for the USART2 initialization. This
bit is set through the USART control register 1 of bit 0. Writing 0 to the bit will
disable the USART Prescaler and outputs. To enable the bit, we must write 1 to it.
USART2->CR1 |= USART_CR1_UE.
As we use Direct Memory Access DMA for this project, we will proceed to the DMA initialization
in the following section.

B. DMA initialization
DMA is connected to the AHB bus. To enable clock access to DMA1 this must be done
through the AHB register. Bit 0 is the DMA clock enable bit (DMAEN). Writing 1 to this
bit will enable the clock access to DMA.
RCC->AHBENR |= RCC_AHBENR_DMAEN.
The global interrupt in NVIC also must be enabled. This will allow channels 4 and 5 to
access global interrupt.
NVIC_EnableIRQ (DMA1_Channel4_5_6_7_IRQn).

C. Configure USART2_Rx DMA1 Channel5

1. Disable DMA channel5


DMA1_Channel5->CCR &= ~DMA_CCR_EN;

2. Wait until the DMA channel is disabled


while ((DMA1_Channel5->CCR & DMA_CCR_EN)){}

3. Enable memory address Increment


DMA1_Channel5->CCR |= DMA_CCR_MINC

4. Enable Circular Mode


DMA1_Channel5->CCR |= DMA_CCR_CIRC

5. Enable Transfer complete Interrupt


DMA1_Channel5->CCR |= DMA_CCR_TCIE

6. Enable DMA channel4_5 Global Interrupt in NVIC


NVIC_EnableIRQ(DMA1_Channel4_5_6_7_IRQn)

7. Set peripheral address


DMA1_Channel5->CPAR = (uint32_t)(&USART2->RDR)

8. Select channel5
DMA1_CSELR->CSELR &= (uint32_t)(DMA_CSELR_C5S)

9. Set memory address


DMA1_Channel5->CMAR = (uint32_t)(&uart_dat_buffer)

10. Number of transfer


DMA1_Channel5->CNDTR = (uint16_t)UART_DATA_BUFFER_SIZE

11. Enable DMA Channel


DMA1_Channel5->CCR |= DMA_CCR_EN

D. Configure USART2_Tx DMA1 Channel4

LPUART Implementation:

Initialization

Design Alternatives

I Describe the different alternatives that were considered, the tradeoffs, and the rationale

for the choices made. This should be based on concept evaluation methods communicated in Chapter 4.

Identify

the alternatives investigated (chapters 4, 5, and 5).

You might also like