首先来看一下步进电机的样子,本介绍采用平时最常见也是最简单的28BYJ-48,这是一个五线四项电机。
五线:顾名思义 外部五条线
四项:电机内部的定子上有8个齿,正对着的2个齿上的绕组又是串联在一起的,也就是说正对着的2个绕组总是会同时导通或关断的,如此就形成了4相

步进电机是一种将电脉冲信号转换成相应角位移或线位移的电动机。每输入一个脉冲信号,转子就转动一个角度或前进一步,其输出的角位移或线位移与输入的脉冲数成正比,转速与脉冲频率成正比。
四拍驱动、八拍驱动。
四拍驱动:这是最简单的步进电机驱动方式。这种方式,电机在每个瞬间只有一个线圈导通。
A→B→C→D


第一个图更方便大家理解,第二个图就是相应拉高拉低。
大白话就是:按顺序给相应引脚拉高(1)拉低(0)。 一个拉高,其他三个拉低。
八拍驱动:就是在上述四拍切换过程中穿插两个线圈同时拉高的情况。
A→AB→B→BC→C→CD→D→DA


由于单片机IO口输出电流过小,无法带动电机运行,因此我们需要另外加一个驱动板,用ULN2003就行,简单便宜。

话不多说直接上代码。
#ifndef __STEP_MOTOR_H
#define __STEP_MOTOR_H
#include "sys.h"
#include "delay.h"
extern u8 STEP; //定义单步计数 全局变量
#define STEP_MOTOR_PORT GPIOG //定义IO接口所在组
#define STEP_MOTOR_A GPIO_Pin_2 //定义IO接口
#define STEP_MOTOR_B GPIO_Pin_3 //定义IO接口
#define STEP_MOTOR_C GPIO_Pin_4 //定义IO接口
#define STEP_MOTOR_D GPIO_Pin_5 //定义IO接口
#define STEP_MOTOR_CLK RCC_APB2Periph_GPIOG
void STEP_MOTOR_Init(void);//初始化
void STEP_MOTOR_OFF (void);//断电状态
void STEP_MOTOR_8A (u8 a,u16 speed);
void STEP_MOTOR_NUM (u8 RL,u16 num,u8 speed);//电机按步数运行
void STEP_MOTOR_LOOP (u8 RL,u8 LOOP,u8 speed);//电机按圈数运行
#endif
#include "step_motor.h"
u8 STEP;
void STEP_MOTOR_Init(void){ //接口初始化
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(STEP_MOTOR_CLK, ENABLE);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_Pin = STEP_MOTOR_A;
GPIO_Init(STEP_MOTOR_PORT, &GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = STEP_MOTOR_B;
GPIO_Init(STEP_MOTOR_PORT, &GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = STEP_MOTOR_C;
GPIO_Init(STEP_MOTOR_PORT, &GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = STEP_MOTOR_D;
GPIO_Init(STEP_MOTOR_PORT, &GPIO_InitStruct);
GPIO_ResetBits(STEP_MOTOR_PORT, STEP_MOTOR_A);
GPIO_ResetBits(STEP_MOTOR_PORT, STEP_MOTOR_B);
GPIO_ResetBits(STEP_MOTOR_PORT, STEP_MOTOR_C);
GPIO_ResetBits(STEP_MOTOR_PORT, STEP_MOTOR_D);
}
void STEP_MOTOR_OFF (void) //电机断电 全拉低
{
GPIO_ResetBits(STEP_MOTOR_PORT,STEP_MOTOR_A | STEP_MOTOR_B | STEP_MOTOR_C | STEP_MOTOR_D);//各接口置0
}
void STEP_MOTOR_8A (u8 a,u16 speed) //电机单步8拍
{
switch (a){
case 0:
GPIO_ResetBits(STEP_MOTOR_PORT,STEP_MOTOR_B | STEP_MOTOR_C | STEP_MOTOR_D);//0
GPIO_SetBits(STEP_MOTOR_PORT,STEP_MOTOR_A);//1
break;
case 1:
GPIO_ResetBits(STEP_MOTOR_PORT,STEP_MOTOR_C | STEP_MOTOR_D);//0
GPIO_SetBits(STEP_MOTOR_PORT,STEP_MOTOR_A | STEP_MOTOR_B);//1
break;
case 2:
GPIO_ResetBits(STEP_MOTOR_PORT,STEP_MOTOR_A | STEP_MOTOR_C | STEP_MOTOR_D);//0
GPIO_SetBits(STEP_MOTOR_PORT,STEP_MOTOR_B);//1
break;
case 3:
GPIO_ResetBits(STEP_MOTOR_PORT,STEP_MOTOR_A | STEP_MOTOR_D);//0
GPIO_SetBits(STEP_MOTOR_PORT,STEP_MOTOR_B | STEP_MOTOR_C);//1
break;
case 4:
GPIO_ResetBits(STEP_MOTOR_PORT,STEP_MOTOR_A | STEP_MOTOR_B | STEP_MOTOR_D);//0
GPIO_SetBits(STEP_MOTOR_PORT,STEP_MOTOR_C);//1
break;
case 5:
GPIO_ResetBits(STEP_MOTOR_PORT,STEP_MOTOR_A | STEP_MOTOR_B);//0
GPIO_SetBits(STEP_MOTOR_PORT,STEP_MOTOR_C | STEP_MOTOR_D);//1
break;
case 6:
GPIO_ResetBits(STEP_MOTOR_PORT,STEP_MOTOR_A | STEP_MOTOR_B | STEP_MOTOR_C);//0
GPIO_SetBits(STEP_MOTOR_PORT,STEP_MOTOR_D);//1
break;
case 7:
GPIO_ResetBits(STEP_MOTOR_PORT,STEP_MOTOR_B | STEP_MOTOR_C);//0
GPIO_SetBits(STEP_MOTOR_PORT,STEP_MOTOR_A | STEP_MOTOR_D);//1
break;
default:
break;
}
delay_ms(speed); //延时
STEP_MOTOR_OFF();//进入断电状态,防电机过热
}
void STEP_MOTOR_NUM (u8 RL,u16 num,u8 speed) //电机按步数运行
{
u16 i;
for(i=0;i<num;i++)
{
if(RL==1){ //当RL=1右转,RL=0左转
STEP++;
if(STEP>7)STEP=0;
}else{
if(STEP==0)STEP=8;
STEP--;
}
STEP_MOTOR_8A(STEP,speed);
}
}
void STEP_MOTOR_LOOP (u8 RL,u8 LOOP,u8 speed) //电机按圈数运行
{
STEP_MOTOR_NUM(RL,LOOP*4076,speed);
}
在主函数中调用这个函数来驱动电机。
函数第一个参数:控制正反转 1→正转 0→反转
第二个参数:控制电机转的圈数
第三个参数:延时
STEP_MOTOR_LOOP(1,1,1); //步进电机正传
STEP_MOTOR_LOOP(0,1,1); //步进电机反传
可以适当调节电机驱动函数的延时时间,就是调节8拍切换的延时,调大(2s)、调小(1s)都试一下,如果不是电机损坏的话 这种方法都可以解决问题。

这种情况会发现演示调为1s、2s都不好使,总是有一个正常、一个不正常,,,这时候需要将延时取中间大小,比如说1.5s,,,但是呢,你会发现程序中的 delay_ms() 函数只能设置整数,要么1 要么2,不能设置1.5,,这就需要我们更改一下 delay_ms() 函数了。改成这样即可:

全部工程链接:https://item.taobao.com/item.htm?spm=a1z10.1-c.w4004-24450682672.26.7aa61b42erNczw&id=693670548640
欢迎大家指正交流,有空可以一起讨论代码啊。
--------------一个正在努力的人
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭10年前。问题1)我想知道rubyonrails是否有功能类似于primefaces的gem。我问的原因是如果您使用primefaces(http://www.primefaces.org/showcase-labs/ui/home.jsf),开发人员无需担心javascript或jquery的东西。据我所知,JSF是一个规范,基于规范的各种可用实现,prim
本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01 客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02 数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit
文章目录1.开发板选择*用到的资源2.串口通信(个人理解)3.代码分析(注释比较详细)1.主函数2.串口1配置3.串口2配置以及中断函数4.注意问题5.源码链接1.开发板选择我用的是STM32F103RCT6的板子,不过代码大概在F103系列的板子上都可以运行,我试过在野火103的霸道板上也可以,主要看一下串口对应的引脚一不一样就行了,不一样的就更改一下。*用到的资源keil5软件这里用到了两个串口资源,采集数据一个,串口通信一个,板子对应引脚如下:串口1,TX:PA9,RX:PA10串口2,TX:PA2,RX:PA32.串口通信(个人理解)我就从串口采集传感器数据这个过程说一下我自己的理解,
LL库和HAL库简介LL:Low-Layer,底层库HAL:HardwareAbstractionLayer,硬件抽象层库LL库和hal库对比,很精简,这实际上是一个精简的库。LL库的配置选择如下:在STM32CUBEMX中,点击菜单的“ProjectManager”–>“AdvancedSettings”,在下面的界面中选择“AdvancedSettings”,然后在每个模块后面选择使用的库总结:1、如果使用的MCU是小容量的,那么STM32CubeLL将是最佳选择;2、如果结合可移植性和优化,使用STM32CubeHAL并使用特定的优化实现替换一些调用,可保持最大的可移植性。另外HAL和L
我使用的是最新版本的Chrome(32.0.1700.107)和Chrome驱动程序(V2.8)。但是当我在Ruby中使用以下代码运行示例测试时:require'selenium-webdriver'WAIT=Selenium::WebDriver::Wait.new(timeout:100)$driver=Selenium::WebDriver.for:chrome$driver.manage.window.maximize$driver.navigate.to'https://www.google.co.in'defapps_hoverele_hover=$driver.find_
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭9年前。多年来,我一直在使用多种语言进行编程,并且认为自己总体上相当擅长。但是,我从未编写过任何自动化测试:没有单元测试,没有TDD,没有BDD,什么都没有。我已经尝试开始为我的项目编写适当的测试套件。我可以看到在进行任何更改后能够自动测试项目中所有代码的理论值(value)。我可以看到像RSpec和Mocha这样的测试框架应该如何使设置和运行所述测试变得相当容易
如果我在功能规范中调用url_for,它会返回一个以http://www.example.com/开头的绝对URL.Capybara会很乐意尝试加载该站点上的页面,但这与我的应用程序无关。以下是重现该问题的最少步骤:从这个Gemfile开始:source'https://rubygems.org'gem"sqlite3"gem"jquery-rails"gem"draper"gem"rails",'4.1.0'gem"therubyracer"gem"uglifier"gem"rspec-rails"gem"capybara"gem"poltergeist"gem"launchy"运行
文章目录认识unity打包目录结构游戏逆向流程Unity游戏攻击面可被攻击原因mono的打包建议方案锁血飞天无限金币攻击力翻倍以上统称内存挂透视自瞄压枪瞬移内购破解Unity游戏防御开发时注意数据安全接入第三方反作弊系统外挂检测思路狠人自爆实战查看目录结构用il2cppdumper例子2-森林whoishe后记认识unity打包目录结构dll一般很大,因为里面是所有的游戏功能编译成的二进制码游戏逆向流程开发人员代码被编译打包到GameAssembly.dll中使用il2ppDumper工具,并借助游戏名_Data\il2cpp_data\Metadata\global-metadata.dat
在笔者前面有一篇文章《驱动开发:断链隐藏驱动程序自身》通过摘除驱动的链表实现了断链隐藏自身的目的,但此方法恢复时会触发PG会蓝屏,偶然间在网上找到了一个作者介绍的一种方法,觉得有必要详细分析一下他是如何实现的进程隐藏的,总体来说作者的思路是最终寻找到MiProcessLoaderEntry的入口地址,该函数的作用是将驱动信息加入链表和移除链表,运用这个函数即可动态处理驱动的添加和移除问题。MiProcessLoaderEntry(pDriverObject->DriverSection,1)添加MiProcessLoaderEntry(pDriverObject->DriverSection,
目录一、ESP32简单介绍二、ESP32Wi-Fi模块介绍三、ESP32Wi-Fi编程模型四、ESP32Wi-Fi事件处理流程 五、ESP32Wi-Fi开发环境六、ESP32Wi-Fi具体代码七、ESP32Wi-Fi代码解读6.1主程序app_main7.2自定义代码wifi_init_sta()八、ESP32Wi-Fi连接验证8.1测试方法8.2服务器模拟工具sscom58.3测试代码8.4测试结果前言为了开发一款亚马逊物联网产品,开始入手ESP32模块。为了能够记录自己的学习过程,特记录如下操作过程。一、ESP32简单介绍ESP32是一套Wi-Fi(2.4GHz)和蓝牙(4.2)双模解决方