This is a custom CAN bus controller for my USA-spec Subaru Forester, built around an STM32F205RBT6 microcontroller. It handles transmission control by intercepting and sending CAN messages.
The controller monitors the vehicle's CAN bus and manipulates transmission behavior. Specifically:
- Reads vehicle speed from the CAN bus
- Monitors handbrake status
- Sends transmission control signals to prevent unwanted gear shifts
- Keeps the transmission in 2nd gear during normal driving to avoid harsh kickdowns
When you pull the handbrake, it automatically shifts to park. When you release it, the system keeps things in 2nd gear for smoother driving.
I'm using the STM32F205RBT6 chip - an ARM Cortex-M3 with 128KB flash and 64KB RAM, running at 120 MHz. The CAN peripheral talks to the vehicle's CAN bus at 500 kbps through pins PA11 (RX) and PA12 (TX).
Messages I'm listening for:
- 0x513 - Vehicle speed data
- 0x420 - Handbrake status (byte 6: 0xF9 = engaged, 0xFB = released)
Messages I'm sending:
- 0x420 - Transmission status with gear and handbrake info
- 0x421 - Control message with a rolling counter
- 0x422 - Gear selection commands
All messages go out every ~6ms.
Pretty straightforward logic:
If handbrake is ON:
→ Park gear (0x07)
→ First gear (0x01)
If handbrake is OFF:
→ Drive selector position (0x01)
→ Second gear (0x02) locked in
The 2nd gear lock prevents the annoying kickdowns that happen on these transmissions. I commented out some speed-based gear logic in the code if you want to experiment with that later.
You'll need STM32CubeIDE or an ARM GCC toolchain.
In STM32CubeIDE:
- Import the project
- Hit build (Ctrl+B)
- Flash it with your ST-Link
Or from command line:
make clean
make allFlash with ST-Link:
st-flash write build/F255_USA.bin 0x8000000Core/Src/main.c ← Main logic lives here
Core/Inc/main.h ← Header file
Drivers/ ← STM32 HAL and CMSIS libraries
F205_USA.ioc ← STM32CubeMX project file
The interesting stuff is in main.c - look for the while loop and the CAN callback function.
Running at 120 MHz system clock from the internal HSI oscillator through the PLL. APB1 is at 30 MHz, APB2 at 60 MHz.
CAN is configured for 500 kbps (prescaler=4, BS1=12TQ, BS2=2TQ, ~87% sample point).
Look, this messes with your transmission. Test everything on a bench first before installing it in the car. Make sure your CAN wiring is solid with proper 120Ω termination resistors. Don't blame me if something goes wrong - this is experimental stuff for tinkerers who know what they're doing.
Also check your local laws about vehicle modifications. Some places are picky about ECU stuff.
If you regenerate code with STM32CubeMX, your changes between the USER CODE BEGIN/END markers will be preserved. The CAN receive callback is where incoming messages get processed - that's in HAL_CAN_RxFifo0MsgPendingCallback().
CAN not working?
- Check your termination resistors (should be 120Ω on both ends of the bus)
- Verify CAN_H and CAN_L aren't swapped
- Make sure the baudrate matches (500 kbps)
- Get a CAN analyzer if you're serious about debugging this
Build issues?
- Double-check all the HAL drivers are included
- Make sure the linker script matches your chip's memory
The STM32 HAL code is from STMicroelectronics with their license. My application code - do whatever you want with it, but no warranties. Use at your own risk.
Current version locks 2nd gear when driving to prevent kickdowns. There's commented code in main.c for speed-based shifting if you want to try that approach instead.