Arduino IDE下使用STM32开发板脉冲控制步进电机(一)IDE串口指令控制

本例程演示通过Arduino IDE(2.3.8)下使用STM32开发板脉冲控制步进电机旋转

在控制上,采用Arduino IDE输入指令的方式

 

由于STM32最小系统板(STM32F103C8T6)没有板载串口芯片(Type-C接口附近有没有 CH340、CP2102 或 FT232 这样的芯片)

需要外接USB转TTL模块来通信

 

1.接线(USB转TTL模块同时为开发板供电)

image

  • STM32也可以通过Type-C单独供电(只接5V电源线,模块的GND还是接STM32的GND(共地))

  • 跳线帽短接VCC和3V3,表示模块输出3.3V逻辑电平,以匹配STM32

 

2.程序

#define PUL_PIN PA0
#define DIR_PIN PA1
#define LED_PIN PC13

String inputString = "";
boolean stringComplete = false;
int currentFreq = 0;
bool motorRunning = false;
bool pwmRunning = false;  // 新增:跟踪PWM状态

HardwareTimer *pwmTimer;

void setup() {
  Serial.begin(115200);
  
  Serial.println();
  Serial.println("========================================");
  Serial.println("  CA-4022M 电机控制程序 - 硬件PWM版");
  Serial.println("========================================");
  
  pinMode(DIR_PIN, OUTPUT);
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(DIR_PIN, LOW);
  
  // 初始化PWM(但先不启动)
  pwmTimer = new HardwareTimer(TIM2);
  pwmTimer->setPrescaleFactor(1);
  pwmTimer->setOverflow(1000, HERTZ_FORMAT);
  pwmTimer->setCaptureCompare(1, 50, PERCENT_COMPARE_FORMAT);
  pwmTimer->setMode(1, TIMER_OUTPUT_COMPARE_PWM1, PUL_PIN);
  pwmTimer->pause();  // 先暂停,等命令再启动
  pwmRunning = false;
  
  Serial.println("[信息] 硬件PWM初始化完成");
  printMenu();
  inputString.reserve(64);
}

void setPWMFrequency(uint32_t freqHz) {
  if (freqHz == 0) {
    pwmTimer->pause();
    pwmRunning = false;
    Serial.println("[信息] PWM停止");
    return;
  }
  
  // 限制频率范围
  if (freqHz < 10) freqHz = 10;
  if (freqHz > 100000) freqHz = 100000;
  
  // 重新设置频率并启动
  pwmTimer->setOverflow(freqHz, HERTZ_FORMAT);
  pwmTimer->setCaptureCompare(1, 50, PERCENT_COMPARE_FORMAT);
  pwmTimer->resume();
  pwmRunning = true;
  
  Serial.print("[信息] PWM频率: ");
  Serial.print(freqHz);
  Serial.println(" Hz");
}

void handleDirectionAndSpeed(String cmd) {
  char dir = cmd.charAt(0);
  int spaceIndex = cmd.indexOf(' ');
  
  if (spaceIndex == -1) {
    Serial.println("[错误] 格式错误,正确格式: F 1000");
    return;
  }
  
  String freqStr = cmd.substring(spaceIndex + 1);
  int freq = freqStr.toInt();
  
  if (freq < 0) {
    Serial.println("[错误] 频率不能为负数");
    return;
  }
  
  // 设置方向
  digitalWrite(DIR_PIN, (dir == 'F') ? LOW : HIGH);
  Serial.print("[信息] 方向: ");
  Serial.println(dir == 'F' ? "正转" : "反转");
  
  // 设置频率
  setPWMFrequency(freq);
  
  motorRunning = (freq > 0);
  currentFreq = freq;
}

void stopMotor() {
  setPWMFrequency(0);
  motorRunning = false;
  currentFreq = 0;
  Serial.println("[信息] 电机停止");
}

void loop() {
  if (stringComplete) {
    processCommand(inputString);
    inputString = "";
    stringComplete = false;
  }
  
  // LED指示
  if (motorRunning) {
    digitalWrite(LED_PIN, !digitalRead(LED_PIN));
    delay(200);
  } else {
    digitalWrite(LED_PIN, !digitalRead(LED_PIN));
    delay(1000);
  }
}

void serialEvent() {
  while (Serial.available()) {
    char inChar = (char)Serial.read();
    Serial.print(inChar);  // 回显
    
    if (inChar == '\n' || inChar == '\r') {
      if (inputString.length() > 0) {
        stringComplete = true;
        Serial.println();  // 换行
      }
    } else {
      inputString += inChar;
    }
  }
}

void processCommand(String cmd) {
  cmd.trim();
  cmd.toUpperCase();
  
  Serial.println();
  Serial.print("[收到] ");
  Serial.println(cmd);
  
  if (cmd.length() == 0) {
    printMenu();
    return;
  }
  
  switch (cmd.charAt(0)) {
    case 'F': 
    case 'R':
      handleDirectionAndSpeed(cmd);
      break;
    case 'S':
      stopMotor();
      break;
    case 'P':
      printStatus();
      break;
    case 'H': 
    case '?':
      printMenu();
      break;
    default:
      Serial.println("[错误] 未知命令");
      printMenu();
  }
}

void printMenu() {
  Serial.println("\n********** 可用命令 **********");
  Serial.println("  F 1000  - 正转 1000Hz");
  Serial.println("  R 1000  - 反转 1000Hz");
  Serial.println("  S       - 停止电机");
  Serial.println("  P       - 显示当前状态");
  Serial.println("  H 或 ?  - 显示本菜单");
  Serial.println("********************************\n");
}

void printStatus() {
  Serial.println("\n********** 当前状态 **********");
  Serial.print("方向: "); 
  Serial.println(digitalRead(DIR_PIN) ? "反转" : "正转");
  Serial.print("频率: "); 
  Serial.print(currentFreq); 
  Serial.println(" Hz");
  Serial.print("电机状态: "); 
  Serial.println(motorRunning ? "运行中" : "停止");
  Serial.print("PWM输出: "); 
  Serial.println(pwmRunning ? "运行" : "停止");
  Serial.println("********************************\n");
}

3.安装环境

1)STM32CubeProgrammer

STM32CubeProg | Software - STMicroelectronics

2)STM32离线支持包(参考上一篇文章)

3) 安装 CH340 驱动

链接: https://pan.baidu.com/s/1FR35uEx5rUOnTvcGxqfHIQ?pwd=2hex 提取码: 2hex 

4.配置环境

1)工具->开发板选择STM32F1 Serials

2)  工具->端口

3)Upload Method->STM32CubeProgramer(Serial)

4) 打开串口监视器,波特率选择115200(与程序一致,否则乱码)

5.上传程序

1)将USB转TTL模块插入电脑USB口

2)STM32设置为ISP模式(BOOT0=1, BOOT1=0)

3)按复位键

4)点击上传

6.测试程序

1)上传完成后,将STM32设为运行模式(BOOT0=0, BOOT1=0)

2)按复位键

3)  输入命令控制电机

 

image

 

image

 

image

 

image

 

image

 

image

 

posted @ 2026-03-04 17:24  尼古拉-卡什  阅读(2)  评论(0)    收藏  举报