STM32F446 CNC Motion Controller Design
Table
| Function | Requested Pin | Implemented Pin | Notes |
|---|---|---|---|
| X_STEP | PA0 | PA0 | Buffered to 5V output header |
| X_DIR | PA1 | PA1 | Buffered |
| X_EN | PA2 | PA2 | Buffered |
| Y_STEP | PA3 | PA3 | Buffered |
| Y_DIR | PA4 | PA4 | Buffered |
| Y_EN | PA5 | PA5 | Buffered |
| Z_STEP | PA6 | PA6 | Buffered |
| Z_DIR | PA7 | PA7 | Buffered |
| Z_EN | PB0 | PB0 | Buffered via second buffer |
| LIMIT_X | PB1 | PB1 | 10k pull-up + RC filter |
| LIMIT_Y | PB2 | PB2 | 10k pull-up + RC filter |
| LIMIT_Z | PB10 | PB10 | 10k pull-up + RC filter |
| ESTOP | PB11 | PC6 | PB11 is not present on the STM32F446RE LQFP64 symbol used in this project |
| FEED_HOLD | PB12 | PB12 | 10k pull-up + RC filter |
| CYCLE_START | PB13 | PB13 | 10k pull-up + RC filter |
| PROBE | PB14 | PB14 | 10k pull-up + RC filter |
| SPINDLE_PWM | PA8 | PA8 TIM1_CH1 | Buffered output |
| COOLANT | PB15 | PB15 | Buffered output |
| UART_TX | PA9 | PA9 | Debug UART header |
| UART_RX | PA10 | PA10 | Debug UART header |
| USB_DM | PA11 | PA11 | 22Ω series + ESD |
| USB_DP | PA12 | PA12 | 22Ω series + ESD |
| SWDIO | PA13 | PA13 | SWD header |
| SWCLK | PA14 | PA14 | SWD header |
| I2C_SCL | PB6 | PB6 | 4.7k pull-up |
| I2C_SDA | PB7 | PB7 | 4.7k pull-up |
Ini
[env:stm32f446re] platform = ststm32 board = nucleo_f446re framework = stm32cube upload_protocol = stlink monitor_speed = 115200
C
#include "main.h" #define X_STEP_GPIO GPIOA #define X_STEP_PIN GPIO_PIN_0 #define X_DIR_GPIO GPIOA #define X_DIR_PIN GPIO_PIN_1 #define X_EN_GPIO GPIOA #define X_EN_PIN GPIO_PIN_2 #define Y_STEP_GPIO GPIOA #define Y_STEP_PIN GPIO_PIN_3 #define Y_DIR_GPIO GPIOA #define Y_DIR_PIN GPIO_PIN_4 #define Y_EN_GPIO GPIOA #define Y_EN_PIN GPIO_PIN_5 #define Z_STEP_GPIO GPIOA #define Z_STEP_PIN GPIO_PIN_6 #define Z_DIR_GPIO GPIOA #define Z_DIR_PIN GPIO_PIN_7 #define Z_EN_GPIO GPIOB #define Z_EN_PIN GPIO_PIN_0 #define LIMIT_X_GPIO GPIOB #define LIMIT_X_PIN GPIO_PIN_1 #define LIMIT_Y_GPIO GPIOB #define LIMIT_Y_PIN GPIO_PIN_2 #define LIMIT_Z_GPIO GPIOB #define LIMIT_Z_PIN GPIO_PIN_10 #define ESTOP_GPIO GPIOC #define ESTOP_PIN GPIO_PIN_6 #define FEED_GPIO GPIOB #define FEED_PIN GPIO_PIN_12 #define CYCLE_GPIO GPIOB #define CYCLE_PIN GPIO_PIN_13 #define PROBE_GPIO GPIOB #define PROBE_PIN GPIO_PIN_14 #define COOLANT_GPIO GPIOB #define COOLANT_PIN GPIO_PIN_15 TIM_HandleTypeDef htim1; UART_HandleTypeDef huart1; I2C_HandleTypeDef hi2c1; static void MX_GPIO_Init(void) { __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); GPIO_InitTypeDef g = {0}; g.Mode = GPIO_MODE_OUTPUT_PP; g.Pull = GPIO_NOPULL; g.Speed = GPIO_SPEED_FREQ_HIGH; g.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7; HAL_GPIO_Init(GPIOA, &g); g.Pin = GPIO_PIN_0|GPIO_PIN_15; HAL_GPIO_Init(GPIOB, &g); g.Mode = GPIO_MODE_INPUT; g.Pull = GPIO_NOPULL; // external pull-ups and RC filters are fitted g.Speed = GPIO_SPEED_FREQ_LOW; g.Pin = GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_10|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14; HAL_GPIO_Init(GPIOB, &g); g.Pin = GPIO_PIN_6; HAL_GPIO_Init(GPIOC, &g); } static void MX_TIM1_Init(void) { __HAL_RCC_TIM1_CLK_ENABLE(); htim1.Instance = TIM1; htim1.Init.Prescaler = 0; htim1.Init.CounterMode = TIM_COUNTERMODE_UP; htim1.Init.Period = 999; // PWM frequency = timer_clk / 1000 htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; HAL_TIM_PWM_Init(&htim1); TIM_OC_InitTypeDef oc = {0}; oc.OCMode = TIM_OCMODE_PWM1; oc.Pulse = 0; oc.OCPolarity = TIM_OCPOLARITY_HIGH; HAL_TIM_PWM_ConfigChannel(&htim1, &oc, TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); } static inline void spindle_set_pwm_permille(uint16_t duty) { if (duty > 1000) duty = 1000; __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, duty); } int main(void) { HAL_Init(); SystemClock_Config(); // configure HSE=8MHz and PLL for USB-capable clock tree in CubeMX MX_GPIO_Init(); MX_TIM1_Init(); while (1) { GPIO_PinState estop = HAL_GPIO_ReadPin(ESTOP_GPIO, ESTOP_PIN); if (estop == GPIO_PIN_RESET) { spindle_set_pwm_permille(0); HAL_GPIO_WritePin(COOLANT_GPIO, COOLANT_PIN, GPIO_PIN_RESET); } HAL_Delay(1); } }
Platform & Toolchain
Pin Mapping
PlatformIO Example
HAL Bring-Up Skeleton
Bring-Up Notes