Unlocking the Power of STM32 with CAN Bus: A Step-by-Step Tutorial
Are you an embedded systems enthusiast, a student, or a professional looking to dive into the fascinating world of microcontrollers and communication protocols? If so, you're in for a treat! In this LinkedIn article, I will explore a step-by-step tutorial on how to use STM32 microcontrollers in combination with the Controller Area Network (CAN) bus. By the end of this tutorial, you'll have a strong understanding of how to leverage these powerful technologies for your projects.
Understanding CAN Bus:
The Controller Area Network (CAN) bus is a robust and widely-used communication protocol in various industries, including automotive, industrial automation, and more. It allows for reliable data exchange between nodes (devices) in a network, even in noisy and electrically harsh environments.
Why STM32?
STM32 microcontrollers, developed by STMicroelectronics, are known for their performance, versatility, and extensive peripheral set. They are a popular choice for embedded systems and are well-suited for CAN bus applications.
1. Hardware Setup
In this tutorial we are going to use the following parts:- Blue Pill Board – STM32F103C8T6- MCP2551 – CAN Tranceiver- 120R Resistor- 10K Resistor- 220R Resistor- 5MM LED
2. Software Download
After finishing the wiring, download and install STM32CubeIDE. Launch Device Configuration Tool and start a new project after installation. A screen similar to the one below will appear to you.
3. STM32CubeMX Configuration
An external oscillator is necessary for the STM32 chip's CAN Bus Peripheral to function properly. Thus, for our project, we make use of the onboard 8MHz crystal. Go to System Core > RCC and choose Crystal/Ceramic Resonator in HSE to activate the external oscillator.
I set my STM32F103 to run at 72 MHz, so go to clock configuration and adjust as needed.
Following these adjustments, the configuration screen should look like the picture below.
After completing this, return to the Pinout & Configuration view, choose Connectivity > CAN from the categories side menu, and make sure the Master Mode is selected.
I must modify the Parameters Settings section in order for my CAN bus to operate at 500kbps. Okay, so this section will require some maths, so it may be a little challenging at first, but it is really simple once you get the hang of it.
We want the CAN bus to move at 500kbps, or 500,000 bps. One bit's time is 1/500000 seconds, or 2000 nanoseconds. To obtain the necessary 2000ns in the Time for one Bit section, we must therefore modify Prescaler, Time Quanta in Bit Segment 1 and Time Quanta in Bit Segment 2.
领英推荐
Since Prescaler provides a rounded value of 250.0 ns in The clock quantum, I use it with a 9.
After that, select USB low priority or CAN RX0 interrupts in the NVIC Settings to enable interrupts whenever the CAN bus receives a message.
Now that we have an indication of some kind to determine whether data is arriving, we add an output on PA3.
4. Coding with HAL Library
A few local variables will be added, as shown below.
CAN_RxHeaderTypeDef rxHeader; //CAN Bus Transmit Header
CAN_TxHeaderTypeDef txHeader; //CAN Bus Receive Header
uint8_t canRX[8] = {0,0,0,0,0,0,0,0}; //CAN Bus Receive Buffer
CAN_FilterTypeDef canfil; //CAN Bus Filter
uint32_t canMailbox; //CAN Bus Mail box variable
We will then set the canfil CAN bus Filter variable to its values. This code can be written in the main function prior to the while loop. The purpose of this filter is to remove any incoming messages that contain their ID. When you need to accept messages from a specific CAN bus node, this is very helpful. We have set IdHigh and IdLow to 0 since we will be accepting all messages for the time being.
canfil.FilterBank = 0;
canfil.FilterMode = CAN_FILTERMODE_IDMASK;
canfil.FilterFIFOAssignment = CAN_RX_FIFO0;
canfil.FilterIdHigh = 0;
canfil.FilterIdLow = 0;
canfil.FilterMaskIdHigh = 0;
canfil.FilterMaskIdLow = 0;
canfil.FilterScale = CAN_FILTERSCALE_32BIT;
canfil.FilterActivation = ENABLE;
canfil.SlaveStartFilterBank = 14;
We will then set the Transmit header variable's values. Device IDs are ExtID and StdId.
txHeader.DLC = 8; // Number of bites to be transmitted max- 8
txHeader.IDE = CAN_ID_STD;
txHeader.RTR = CAN_RTR_DATA;
txHeader.StdId = 0x030;
txHeader.ExtId = 0x02;
txHeader.TransmitGlobalTime = DISABLE;
We have to initialize CAN Bus at this point and this has to be done before the while loop so take a look at below code
HAL_CAN_ConfigFilter(&hcan,&canfil); //Initialize CAN Filter
HAL_CAN_Start(&hcan); //Initialize CAN Bus
HAL_CAN_ActivateNotification(&hcan,CAN_IT_RX_FIFO0_MSG_PENDING);// Initialize CAN Bus Rx Interrupt
Alright no we can send and receive CAN bus messages. To send CAN bus Message use the following code.
uint8_t csend[] = {'H','E','L','L','O'}; // Tx Buffer
HAL_CAN_AddTxMessage(&hcan,&txHeader,csend,&canMailbox); // Send Message
and now add this function to the end of your code to receive messages.
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan1)
{
HAL_CAN_GetRxMessage(hcan1, CAN_RX_FIFO0, &rxHeader, canRX); //Receive CAN bus message to canRX buffer
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_3);// toggle PA3 LED
}
Data is accessed from the canRX buffer, which is filled up by the mcu when it receives data from the CAN bus.
The STM32 and CAN bus tutorial offers a solid foundation for both beginners and experienced developers looking to harness the potential of microcontrollers and communication protocols. Whether you're building an autonomous robot, a car telemetry system, or a smart industrial machine, the skills you acquire in this tutorial will be invaluable.
In the world of embedded systems, mastering STM32 and CAN bus opens doors to exciting possibilities. So, roll up your sleeves, fire up your STM32 development board, and let's embark on this incredible journey together!