目录
- 前言
- 代码下载:
- 功能介绍:
- 参考图
- STM8S103F3最小系统原理图
- 步进电机28BYJ-48
- ST-Link/V2
- 接线
- ST-Link/V2
- stm8s103f3
- 步进电机28BYJ-48+ULN2003
- 效果图
- 工程介绍+烧写
- 工程结构
- 工程设置
- 程序烧写
- 核心代码
- main.c
- step.c
- step.h
- led.c
- led.h
- delay.c
- dealy.h
- 中断服务函数 stm8s_it.c 中追加
前言
本文是根据STM32F103+步进电机28BYJ-48+ULN2003 实现简单的正反转demo这篇文章的拓展,针对此文章的程序进行了STM8S103F3版本的粗略适配,具体细节可以参考这篇文章。
源码参考:
步进电机28BYJ-48的驱动程序(stm32f103c8t6) STM32F103+步进电机28BYJ-48+ULN2003 实现简单的正反转demo
开发板:STM8S103F3P6 最小系统
烧录:正点原子 ST-LINK/V2 ,软件STVP
语言:C语言
开发环境:IAR EW For STM8 (官网:https://www.iar.com/)
开发板使用了 LED TIMER4 步进电机28BYJ-48 ULN2003驱动
代码下载:
功能介绍:
电机正转半圈,翻转LED,延时3秒,电机反转半圈,翻转LED,延时3秒。比stm32版更加简单。
参考图
STM8S103F3最小系统原理图
步进电机28BYJ-48
ST-Link/V2
参考文章:ST-link/V2引脚定义
接线
ST-Link/V2
VDD ——> 3V3
SWIM ——> SWIM
GND ——> GND
RESET ——> NRST
stm8s103f3
步进电机28BYJ-48+ULN2003
效果图
运行时需要拔掉 NRST脚的接线,程序无法运行或者 关闭STVP烧写程序。
图片进行过处理,不是实际效果。
工程介绍+烧写
工程结构
工程设置
程序路径
程序烧写
运行STVP
ST-LINK -> SWIM -> STM8S103F3
选择hex程序,进行烧写
核心代码
main.c
#include "stm8s.h"
#include "step.h"
#include "delay.h"
#include "led.h"
void main(void)
{
u8 flag = 0;
CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1); // 设置为内部高速时钟
timer4_init(); // TIM4初始化
LED_Init(); // LED初始化
Step_Motor_GPIO_Init(); // 步进电机初始化 IN1-IN4接C7-C4
while (1)
{
if(flag)
{
// 电机正转半圈
motor_circle(32, 1, 2);
flag = 0;
}
else
{
// 电机反转半圈
motor_circle(32, 0, 2);
flag = 1;
}
// 翻转LED
LED_Reverse();
Delay_ms(3000);
}
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval : None
*/
void assert_failed(u8* file, u32 line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif
step.c
#include "step.h"
#include "delay.h"
//IN4: PF4 d
//IN3: PF3 c
//IN2: PF2 b
//IN1: PF1 a
u8 forward[4] = {0x03,0x06,0x0c,0x09}; // 正转
u8 reverse[4]= {0x03,0x09,0x0c,0x06}; // 反转
//引脚初始化
void Step_Motor_GPIO_Init(void)
{
GPIO_Init(GPIOC, GPIO_PIN_7, GPIO_MODE_OUT_PP_LOW_FAST);
GPIO_Init(GPIOC, GPIO_PIN_6, GPIO_MODE_OUT_PP_LOW_FAST);
GPIO_Init(GPIOC, GPIO_PIN_5, GPIO_MODE_OUT_PP_LOW_FAST);
GPIO_Init(GPIOC, GPIO_PIN_4, GPIO_MODE_OUT_PP_LOW_FAST);
}
//引脚映射
void SetMotor(unsigned char InputData)
{
if(InputData == 0x03)
{
GPIO_WriteHigh(GPIOC,GPIO_PIN_7);
GPIO_WriteHigh(GPIOC,GPIO_PIN_6);
GPIO_WriteLow(GPIOC,GPIO_PIN_5);
GPIO_WriteLow(GPIOC,GPIO_PIN_4);
}
else if(InputData == 0x06)
{
GPIO_WriteLow(GPIOC,GPIO_PIN_7);
GPIO_WriteHigh(GPIOC,GPIO_PIN_6);
GPIO_WriteHigh(GPIOC,GPIO_PIN_5);
GPIO_WriteLow(GPIOC,GPIO_PIN_4);
}
else if(InputData == 0x09)
{
GPIO_WriteHigh(GPIOC,GPIO_PIN_7);
GPIO_WriteLow(GPIOC,GPIO_PIN_6);
GPIO_WriteLow(GPIOC,GPIO_PIN_5);
GPIO_WriteHigh(GPIOC,GPIO_PIN_4);
}
else if(InputData == 0x0c)
{
GPIO_WriteLow(GPIOC,GPIO_PIN_7);
GPIO_WriteLow(GPIOC,GPIO_PIN_6);
GPIO_WriteHigh(GPIOC,GPIO_PIN_5);
GPIO_WriteHigh(GPIOC,GPIO_PIN_4);
}
else if(InputData == 0x00)
{
GPIO_WriteLow(GPIOC,GPIO_PIN_7);
GPIO_WriteLow(GPIOC,GPIO_PIN_6);
GPIO_WriteLow(GPIOC,GPIO_PIN_5);
GPIO_WriteLow(GPIOC,GPIO_PIN_4);
}
}
/*
功能:转1/64圈
步距角5.625 360/5.625=64 减速比1/64
故64*64个脉冲转一圈
n 圈数
direction 方向 1正转 非1反转
delay delay时长 >= 2
*/
void motor_circle(int n, int direction, int delay)
{
int i, j;
for(i = 0; i < n * 8; i++)
{
for(j = 0; j < 4; j++)
{
if(1 == direction)
{
SetMotor(0x00);
SetMotor(forward[j]);
}
else
{
SetMotor(0x00);
SetMotor(reverse[j]);
}
Delay_ms(delay > 2 ? delay : 2);
/*for(k = 0; k < (delay > 2 ? delay : 2); k++)
{
Delay(150 * delay);
}*/
}
}
}
step.h
#ifndef __STEP_H
#define __STEP_H
#include "stm8s_gpio.h"
void Step_Motor_GPIO_Init(void);
/*
功能:转1/64圈
步距角5.625 360/5.625=64 减速比1/64
故64*64个脉冲转一圈
n 圈数
direction 方向 1正转 非1反转
delay delay时长ms >= 2
*/
void motor_circle(int n, int direction, int delay);
#endif
led.c
#include "led.h"
void LED_Init(void)
{
GPIO_Init(GPIOB, GPIO_PIN_5, GPIO_MODE_OUT_PP_LOW_FAST);
}
void LED_Reverse(void)
{
GPIO_WriteReverse(GPIOB, GPIO_PIN_5);
}
void LED_ON_OFF(u8 ON_OFF)
{
if(ON_OFF)
GPIO_WriteLow(GPIOB, GPIO_PIN_5);
else
GPIO_WriteHigh(GPIOB, GPIO_PIN_5);
}
led.h
#ifndef __LED_H
#define __LED_H
#include "stm8s.h"
#define ON 0
#define OFF 1
void LED_Init(void);
void LED_Reverse(void);
void LED_ON_OFF(u8 ON_OFF);
#endif
delay.c
#include "delay.h"
__IO uint32_t TimingDelay = 0;
__IO uint16_t g_Timing_tim4;
/***************************************
* TIMER1初始化
* 检测外部频率和脉冲
***************************************/
void timer4_init(void)
{
// disableInterrupts();
/* TIM4 configuration:
- TIM4CLK is set to 16 MHz, the TIM4 Prescaler is equal to 128 so the TIM4 counter
clock used is 16 MHz / 128 = 125 000 Hz
- With 125 000 Hz we can generate time base:
max time base is 2.048 ms if TIM4_PERIOD = 255 --> (255 + 1) / 125000 = 2.048 ms
min time base is 0.016 ms if TIM4_PERIOD = 1 --> ( 1 + 1) / 125000 = 0.016 ms
- In this example we need to generate a time base equal to 1 ms
so TIM4_PERIOD = (0.001 * 125000 - 1) = 124 */
/* Time base configuration */
TIM4_TimeBaseInit(TIM4_PRESCALER_128, 124);
/* Clear TIM4 update flag */
TIM4_ClearFlag(TIM4_FLAG_UPDATE);
/* Enable update interrupt */
TIM4_ITConfig(TIM4_IT_UPDATE, ENABLE);
/* enable interrupts */
enableInterrupts();
/* Enable TIM4 */
TIM4_Cmd(ENABLE);
// enableInterrupts();
}
void Tim4_Clean(void)
{
g_Timing_tim4 = 0;
}
/**
* @brief Inserts a delay time.
* @param nTime: specifies the delay time length, in milliseconds.
* @retval None
*/
void Delay_ms(__IO uint16_t nTime)
{
TimingDelay = nTime;
while (TimingDelay != 0);
}
/**
* @brief Decrements the TimingDelay variable.
* @param None
* @retval None
*/
void TimingDelay_Decrement(void)
{
if (TimingDelay != 0x00)
{
TimingDelay--;
}
}
void Delay(uint16_t nCount)
{
/* Decrement nCount value */
while (nCount != 0)
{
nCount--;
}
}
dealy.h
#ifndef __DELAY_H
#define __DELAY_H
#include "stm8s.h"
extern __IO uint32_t TimingDelay;
extern __IO uint16_t g_Timing_tim4;
void timer4_init(void);
void Delay_ms(__IO uint16_t nTime);
void TimingDelay_Decrement(void);
void Delay(uint16_t nCount);
#endif
中断服务函数 stm8s_it.c 中追加
头文件 导入 delay.h
#else /*STM8S208, STM8S207, STM8S105 or STM8S103 or STM8AF52Ax or STM8AF62Ax or STM8AF626x */
/**
* @brief Timer4 Update/Overflow Interrupt routine.
* @param None
* @retval None
*/
INTERRUPT_HANDLER(TIM4_UPD_OVF_IRQHandler, 23)
{
/* In order to detect unexpected events during development,
it is recommended to set a breakpoint on the following instruction.
*/
TimingDelay_Decrement();
/* Cleat Interrupt Pending bit */
TIM4_ClearITPendingBit(TIM4_IT_UPDATE);
g_Timing_tim4++;
if(g_Timing_tim4>=65535)
{
g_Timing_tim4 = 0;
}
}
#endif /*STM8S903*/