STM32 Programming Tutorial for Custom Hardware | SWD, PWM, USB, SPI - Phil's Lab #13
PCB Assembly and Features Overview
Introduction to the PCB
- The latest batch of PCBs from JLC PCB resembles a previously designed board, featuring an STM32F405 microcontroller with floating-point capabilities.
- Additional components have been integrated into the design to enhance functionality for software development and driver writing.
Board Components
- Key components include:
- A USB connector for power supply.
- A power connector supporting 5V (USB) or up to 12V, which connects to a buck regulator that outputs 3.3V for the board's operation.
- An inertial measurement unit (BMI088) by Bosch is included, providing both accelerometer and gyroscope functionalities via SPI interface with the STM32 microcontroller.
Additional Sensors and Features
- The board features:
- One gigabit flash memory interfacing through SPI.
- A barometric pressure sensor (BMP280 or SPL06), also communicating via SPI.
- An RGB LED connected to three timer channels on the STM32 for brightness control using PWM.
- Other additions include a serial wire debug connector and a boot mode select switch, allowing users to toggle between run and boot modes.
Testing Procedures After Assembly
Initial Checks
- Upon receiving the new board, it’s crucial to check for shorts created during assembly before applying power.
- Voltage should be applied gradually while monitoring current draw; excessive current may indicate shorts in the circuit. Ensure all voltages are as expected before connecting to an ST-Link debugger via USB.
Connecting Debugging Tools
- An ST-Link version two is used alongside an adapter cable connected to a mini connector.
- A micro USB cable connects the setup to a computer, powering up the board and indicating successful connections through LEDs: one green LED indicates power status while another shows RGB LED activity based on prior firmware interactions.
Ordering PCBs from JLC PCB
Steps for Ordering
- To order boards from JLC PCB including assembly:
- Visit GitHub repository at
github.com/bms67, navigate to repositories, and locate "brain sm3204 sensorboard" containing necessary files like Gerber files for production.
- Download or clone these files before uploading them on JLC PCB's quote page under their Gerber folder section.
Configuration Options
- When ordering:
- Select options such as impedance control for USB traces.
STM32 Cube IDE Project Setup
Initial Setup and Configuration
- The order number is hidden under the chip, allowing users to specify the location for SMT assembly. Users can confirm their selections and upload builder materials.
- The speaker mentions using STM32 Cube IDE for development, which is available for free on ST's website. Other environments like Keil and Atollic are also options but are less preferred due to integration issues.
- C programming language will be used in this project, although C++ is an alternative. The choice of language depends on personal preference.
Understanding Hardware Abstraction Layer (HAL)
- The Hardware Abstraction Layer (HAL) simplifies writing low-level drivers by abstracting register manipulation. However, it may introduce code bloat and bugs; caution is advised when using it.
- For simple testing purposes, HAL is deemed sufficient for ensuring board functionality.
Creating a New Project in STM32 Cube IDE
- To start a new project, users should select "File" then "New STM32 Project," entering the MCU number (e.g., STM32F405RG).
- After naming the project (e.g., "little brain firmware"), users should choose the latest firmware package for HAL before finishing setup.
Pin Assignment Process
- A pin assignment view opens where users can enable peripherals and assign pins based on their requirements.
- Serial Wire Debug (SWD) needs to be enabled along with SWO trace for debugging capabilities. This includes enabling data and clock pins.
Peripheral Configuration
- Users must enable essential peripherals such as high-speed crystals, USB connections, SPI interfaces, and timers based on their hardware configuration.
- Specific peripherals like USB Full Speed will require enabling certain pins (PA11 & PA12), while SPI settings include selecting full duplex master mode.
Finalizing Peripheral Connections
- Users need to configure connections for various components like inertial measurement units via SPI and RGB LEDs through timers.
- Timers are set up to control RGB LED intensity using PWM signals; specific channels must be selected accordingly.
PWM Generation and Configuration
Setting Up PWM Frequency and Clock Configuration
- The process begins with selecting channel one for PWM generation, but requires adjustments to the PWM frequency and SPI baud rate.
- A 16 MHz crystal is chosen as the PLL source, opting for a high-speed external crystal over the internal one. The system is set to run at a maximum clock frequency of 168 MHz.
- After entering these values, an automatic clock issue solver is run to ensure all PLL configurations are correct, resolving any errors indicated by a cross symbol.
USB Communication Setup
- The configuration continues with setting up USB communication to relay data back to the host computer via a virtual communications port.
- A middleware USB device class is selected for communication purposes, ensuring that necessary drivers are included in project files.
SPI Baud Rate Adjustment
- The SPI settings are reviewed; specifically, the baud rate needs adjustment from 42 Mbps down to a more manageable speed of around 12 Mbps.
- By changing the prescaler value to eight, the baud rate adjusts accordingly to approximately 10.5 Mbps, which suffices for project requirements.
Timer Configuration for PWM
- Timer setup involves configuring timers three and four for PWM generation that drives an LED. Key parameters include prescaler and counter period settings.
- To achieve a target frequency of 100 Hz from an input clock of 84 MHz (doubled from APB1 bus), calculations show that scaling down must occur through specific division factors.
Finalizing Project Settings
- Adjustments require subtracting one from both prescaler and counter period values due to inherent quirks in timer configurations.
- With timers configured alongside debug settings and USB communications established, all that's left is saving changes in STM32 Cube IDE which generates low-level drivers automatically.
Code Initialization and RGB LED Control
Code Structure Overview
- Upon saving in STM32 Cube IDE, generated code includes initialization functions for SPI and timers within
main.c, allowing immediate coding without extensive setup.
RGB LED Connection Insights
- An overview of how the RGB LED connects reveals it operates on 3.3 volts with GPIO outputs functioning as sinks; low outputs turn on LEDs while high outputs turn them off—indicating inverted PWM behavior.
Starting PWM Timers
Setting Up PWM with Timer 3
Initializing Timer Channels
- The first channel of timer 3 is selected for PWM configuration, followed by similar setups for timer 3 channel 2 and timer 4 channel 1.
- An 8-bit unsigned integer named
intensityis initialized to zero, which will be used to control the brightness in a loop.
Configuring Duty Cycle
- The duty cycle is set by accessing the
ccr1register of the structhtm3, determining how long the output remains on based on a counter period of 100 Hz.
- To invert the intensity value, it’s calculated as
100 - intensity, ensuring that as intensity increases, the duty cycle decreases appropriately.
Loop Execution and Delay
- A delay function (
how_delay) is introduced to slow down loop execution to allow visible changes in LED brightness; a delay of 100 milliseconds is suggested.
- Code correctness is verified through a build process that returns zero errors or warnings, indicating readiness for debugging.
Debugging and Running on Microcontroller
Setting Up Debug Configuration
- After connecting hardware via Zero Wire Debug, a debug configuration is created using default settings with some adjustments available under the debugger tab.
- The debugger recognizes the device family and flash size upon connection, confirming successful setup before running the program.
Observing LED Behavior
- Upon resuming execution, an LED's brightness gradually increases from zero to maximum intensity, demonstrating effective PWM control.
Code Organization and Functionality Enhancements
Refactoring Code Structure
- Two functions are added to clean up code: one initializes timers for RGB LEDs while another sets their intensities based on passed arguments (red, green, blue).
Managing RGB Intensity
- The second function directly manipulates registers corresponding to each color channel (ccr1 for red and ccr2 for green), allowing easy adjustments in light output.
Integrating USB Communication
Preparing USB Setup
- Focus shifts towards integrating USB functionality after cleaning up previous code sections related to RGB LEDs; drivers for CDC virtual COM port are confirmed included.
Including Necessary Libraries
USB Communication and SPI Driver Implementation
Setting Up the USB Transmission
- The speaker discusses creating a buffer to store information for transmission, suggesting a size of 100 characters as a reasonable limit.
- A counter is initialized starting from 1, which increments with each iteration in the main loop. The buffer is filled using
sprintfto format an unsigned integer followed by a newline.
- If the count exceeds 100, it resets back to 1, ensuring continuous data flow without overflow.
Transmitting Data via USB
- The function
cdc_transmit_fsis used to send the contents of the transmit buffer over USB. Proper casting is necessary to avoid type complaints from STM32 libraries.
- After setting up the transmission parameters, there’s a brief wait before sending data. Compilation and debugging options are discussed for running the program.
Connecting and Testing USB Communication
- Upon successful upload, the device appears in Device Manager as an STM virtual COM port (COM5).
- An attempt to connect using H-Term fails initially due to enumeration issues; unplugging and replugging the USB resolves this problem.
Observing Data Transmission
- Once connected successfully, numbers are transmitted continuously until they reset after reaching 100. This demonstrates effective communication through USB.
Considerations for Improvement
- Suggestions include refining code structure by utilizing
printfdirectly or implementing checks for ongoing transmissions to optimize performance.
Implementing an SPI Driver for BMI088
Overview of BMI088 Sensor
- Introduction of BMI088, which integrates a three-axis gyroscope and accelerometer. It can interface via SPI or I²C; SPI has been chosen for simplicity in testing.
Writing a Simple SPI Driver
- The driver will be polling-based—considered less efficient but straightforward for initial testing without complex setups like DMA or interrupts.
Importance of Data Sheets
- Emphasis on consulting the lengthy data sheet (50 pages), which details register access methods, interrupt setup, parameter configuration, and overall protocol understanding.
Understanding SPI Protocol Details
- Section 6.1 of the BMI088 datasheet outlines how both accelerometer and gyroscope share main SPI pins while having distinct chip select lines for interfacing.
Reading/Writing Mechanism Explained
Gyroscope and Accelerometer Data Handling
Overview of Data Transmission
- The accelerometer transmits a dummy byte followed by the actual data, creating a three-byte cycle for data reading. In contrast, the gyroscope operates on a two-byte cycle.
Gyroscope Read and Write Functions
- Simple functions have been created to read from and write to the gyroscope registers, taking in register addresses as arguments and storing results via pointers.
- To read a byte, the function sends the register address with its most significant bit flipped to one (using a bitmask of 0x80).
SPI Transaction Process
- The chip select line is pulled low before initiating an SPI transaction, which allows simultaneous transmission and reception due to full duplex capability.
- Two bytes are sent during transactions: first, the modified register address; second, a dummy byte is necessary for proper operation.
Reading Register Contents
- After executing an SPI transaction, if successful, the contents of the desired register will be found in the second byte of the receive buffer.
- The function returns status indicators based on whether or not the transaction was successful (status zero indicates failure).
Writing Data to Registers
- For writing data to registers, only one byte needs modification (the most significant bit can remain zero), while sending both address and data follows similar steps as reading.
Testing Gyroscope Functionality
- A test is conducted by reading from a specific register (address 0 for chip ID), utilizing breakpoints in debugging tools to verify correct values returned from operations.
- Successful retrieval of chip ID confirms functionality; value matches expected output (0x0F). Debugging aids in verifying without additional print statements.
Finalizing Driver Implementation
Microcontroller Programming and Data Logging
Overview of the Project
- The project involves using a BMI 088 sensor that triggers interrupts when data is ready, allowing for real-time reading of accelerometer and gyroscope data.
- Additional features include RGB LED color changes and USB logging to consolidate all functionalities demonstrated in the video.
Device Setup and Functionality
- The microcontroller is set up in run mode with a boot mode switch, powered via USB connected to a main computer, which recognizes it as COM5.
- Data logging occurs approximately every half second; accelerometer values reflect gravitational force (e.g., YZ axis shows about 9.81 m/s² when stationary).
Observations During Testing
- As the board is rotated, the accelerometer values change accordingly; for instance, tilting alters the X component from +9.81 to -9.81.
- Gyroscope readings also fluctuate with movement, demonstrating successful interfacing with the custom board and programming of peripherals like PWM RGB LEDs and SPI interfaces.
Conclusion
- The video concludes by summarizing how to interface with an STM32 microcontroller, emphasizing practical applications such as triggering LEDs and printing data over USB.