草庐IT

STM32/51单片机实训day7——电机驱动|ULN2003A步进电机|Proteus电路设计|旋转角度控制函数|驱动函数|Keil5程序设计

alwaysuzybaiyy 2023-07-24 原文

目录

1  ULN2003A步进电机简介

2  步进电机电路设计

3 旋转角度控制函数

4 程序设计 

motor.c

motor.h

前期LCD参考文章:​​​​​​​

内  容:编程实现控制步进电机旋转不同角度

学  时:3学时

知识点: GPIO配置、步进电机电路设计、编程实现旋转角度控制

重点: 步进电机电路设计、编程实现旋转角度控制

难点:编程实现旋转角度控制

时间:2022年12月27日9:00~11:50 

总结:

1 步进电机使用GPIOA进行输入输出,需要进行GPIO配置;

2 使用proteus设计步进电机电路;

3 编程实现步进电机旋转角度控制。

51单片机Proteus仿真+Keil工程-实验4-外部中断-步进电机驱动_轩笑鹄的博客-CSDN博客_51单片机外部中断实验

掌握外部中断的打开方式;掌握步进电机的基本控制。

步进电机控制系统+LCD状态显示+详细源码注释+proteus仿真(超详细)_HNU_刘yuan的博客-CSDN博客_步进电机驱动设计实现电机lcd按键加减速


1  ULN2003A步进电机简介

ULN2003A是一个七路反向器电路,即输入端高电平时ULN2003A输出端低电平,相反当输入端低电平的时ULN2003A输出端高电平

ULN2300A内部结构如下图所示,两个三极管串联,第一个管子的发射极接第2个管子的基极,所以整个电路的放大倍数是两个三极管放大倍数的乘积,具有很大的放大倍数。IN端接到单片机上,当IN端接入高电平时,两个三极管均导通,OUT端则能输出较大的电流

图1 ULA2300A内部结构

步进电机原理图如图2,电机共有六个引脚线,其中有两条线与供电电源相接,剩下四条线(A、B、C、D)用来控制电机的旋转。每个引脚线相当于有一个控制开关,通电后则可旋转一定的角度。

 图2 步进电机原理图

2  步进电机电路设计

步进电机电路设计如下图所示,其中步进电机的引脚通过网络与单片机引脚进行连接。

图2 步进电机电路

我的电路连接图如下: 

四相步进电机有单四拍(A-B-C-D)和双四拍(AB-BC-CD-DA)和八拍(A-AB-B-BC-C-CD-D-DA)这三种工作方式。

第一种工作方式扭矩小,功耗小,但震动大。

第二种工作方式扭矩较大,功耗也大,震动小。

第三种工作方式步距角小,输出更平滑,推荐采用这种方式。

只需要控制单片机的IO口使得ULN2003芯片按A-AB-B-BC-C-CD-D-DA的次序输出低电平(ULN2003A会使电平反向输出,因此STM32在输出高电平时,到达步进电机的电平才会为低电平)即可完成步进电机转动的一轮循环。如果要按相反方向转动,只要把上面A-AB-B-BC-C-CD-D-DA的次序反过来即可。

3 旋转角度控制函数

ULN2003A有四条线(A、B、C、D)用来控制电机的旋转,本实训使用八拍方式来驱动电机的旋转,每一拍旋转45°。经过proteus仿真试验发现,当节拍为A时,对应角度为-45°,当节拍为AB时,对应角度为0°,故为使电机顺时针旋转一周,我们采用如下节拍方式:B-BC-C-CD-D-DA-A-AB,八拍驱动方式逻辑时序如下表所示。

4 程序设计 

motor.c

#include "stm32f10x.h"

//PA2 PA3 PA4 PA5
/*void delay(void){
	uint32_t cnt = 0x20000;
	while(cnt--);}*/

void motor_init(void){
	//定义GPIO结构体
	GPIO_InitTypeDef GPIO_InitStruct;
	//打开时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	//PB引脚
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5;    // 初始化4个引脚
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; // ?????????????
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;// 输出速率为50MHz
	GPIO_Init(GPIOA, &GPIO_InitStruct);    // ???????
	GPIO_ResetBits(GPIOA, GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5); }
	
void motor_45(void){
	//B
	GPIO_SetBits(GPIOA, GPIO_Pin_3);  
	GPIO_ResetBits(GPIOA, GPIO_Pin_2 | GPIO_Pin_4 | GPIO_Pin_5);
	delay();}
	
void motor_180(void){
	//B
	GPIO_SetBits(GPIOA, GPIO_Pin_3);  // 45°
	GPIO_ResetBits(GPIOA, GPIO_Pin_2 | GPIO_Pin_4 | GPIO_Pin_5);
	delay();
	//BC
	GPIO_SetBits(GPIOA, GPIO_Pin_3 | GPIO_Pin_4 );  // LED ON
	GPIO_ResetBits(GPIOA, GPIO_Pin_2 | GPIO_Pin_5);
	delay();
	//C
	GPIO_SetBits(GPIOA, GPIO_Pin_4 );  // LED ON
	GPIO_ResetBits(GPIOA, GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_5);
	delay();
	//CD
	GPIO_SetBits(GPIOA, GPIO_Pin_4 | GPIO_Pin_5);  // LED ON
	GPIO_ResetBits(GPIOA, GPIO_Pin_2 | GPIO_Pin_3);
	delay();
}

药品信息管理系统 :

#include "motor.h"
#include "stm32f10x.h"
#include "delay.h"

void delay(void){
	uint32_t cnt=0x20000;
	while(cnt--);
	
}



void Motor_GPIOInit (void)
{
	GPIO_InitTypeDef GPIO_InitStructure;	
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);	
	
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;	
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5;	
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	//GPIO_Write(GPIOB,0x0000);			/?????
  GPIO_ResetBits(GPIOA,GPIO_Pin_2|GPIO_Pin_3|	GPIO_Pin_4|	GPIO_Pin_5);	

}

void Motor_CW(void)			
{
	//B
	GPIO_SetBits(GPIOA,GPIO_Pin_3);
	GPIO_ResetBits(GPIOA,GPIO_Pin_2|GPIO_Pin_4|GPIO_Pin_5);
	delay();
	
	//BC
	GPIO_SetBits(GPIOA,GPIO_Pin_3|GPIO_Pin_4);
	GPIO_ResetBits(GPIOA,GPIO_Pin_2|GPIO_Pin_5);
	delay();
	//GPIO_SetBits(GPIOA,GPIO_Pin_1);
	//SysTick_Delay_Ms(DELAY_TIME);
	//GPIO_ResetBits(GPIOA,GPIO_Pin_1);
	
	//GPIO_SetBits(GPIOA,GPIO_Pin_2);
	//SysTick_Delay_Ms(DELAY_TIME);
	//GPIO_ResetBits(GPIOA,GPIO_Pin_2);
	
	//GPIO_SetBits(GPIOA,GPIO_Pin_3);
	//SysTick_Delay_Ms(DELAY_TIME);
	//GPIO_ResetBits(GPIOA,GPIO_Pin_3);
}
void Motor_RW(void){			
  GPIO_SetBits(GPIOA,GPIO_Pin_2|GPIO_Pin_3);
	GPIO_ResetBits(GPIOA,GPIO_Pin_4|GPIO_Pin_5);
	delay();
	//B
	GPIO_SetBits(GPIOA,GPIO_Pin_4|GPIO_Pin_5);
	GPIO_ResetBits(GPIOA,GPIO_Pin_2|GPIO_Pin_3);
	delay();
	
	//BC
	
	//GPIO_SetBits(GPIOA,GPIO_Pin_1);
	//SysTick_Delay_Ms(DELAY_TIME);
	//GPIO_ResetBits(GPIOA,GPIO_Pin_1);
	
	//GPIO_SetBits(GPIOA,GPIO_Pin_2);
	//SysTick_Delay_Ms(DELAY_TIME);
	//GPIO_ResetBits(GPIOA,GPIO_Pin_2);
	
	//GPIO_SetBits(GPIOA,GPIO_Pin_3);
	//SysTick_Delay_Ms(DELAY_TIME);
	//GPIO_ResetBits(GPIOA,GPIO_Pin_3);
}
void Motor_SW(void)			
{
	GPIO_SetBits(GPIOA,GPIO_Pin_3);
	//SysTick_Delay_Ms(DELAY_TIME);
	GPIO_ResetBits(GPIOA,GPIO_Pin_3);
	
	GPIO_SetBits(GPIOA,GPIO_Pin_2);
	//SysTick_Delay_Ms(DELAY_TIME);
	GPIO_ResetBits(GPIOA,GPIO_Pin_2);
	
	GPIO_SetBits(GPIOA,GPIO_Pin_1);
	//SysTick_Delay_Ms(DELAY_TIME);
	GPIO_ResetBits(GPIOA,GPIO_Pin_1);
	
	GPIO_SetBits(GPIOA,GPIO_Pin_0);
	//SysTick_Delay_Ms(DELAY_TIME);
	GPIO_ResetBits(GPIOA,GPIO_Pin_0);
}

void Motor_ctrl_angle(int dire ,int angle)		//dire??????,angle??????
{
	int j=0;
	if(dire==0)		
	{				
		for(j=0;j<64*angle/45;j++)	
		{
			Motor_SW();
			
		}
		 MotorStop();
	}
	else			
	{		
		for(j=0;j<64*angle/45;j++)
	{
		Motor_CW();
	
	}	
		 MotorStop();

}
}
void Motor_ctrl_motor(int dire,float cycle)			//dire??????;cycle??????,?????
{
	int angle=cycle*360;
	Motor_ctrl_angle(dire , angle);

}
	
	
void MotorStop(void) 
{  
    GPIO_Write(GPIOB,0x0000);  
}

void SysTick_Delay_Ms(__IO uint32_t ms)
{
	uint32_t i;
	SysTick_Config(72000);
	
	for(i=0; i<ms ; i++)
	{
		while(!(SysTick->CTRL)&(1<<16))
			;
	}
	SysTick->CTRL &= SysTick_CTRL_ENABLE_Msk;
}

motor.h

#include "stm32f10x.h"

void motor_init(void);

void motor_45(void);
void motor_180(void);

药品信息管理系统 :

#ifndef __BSP_GPIO_H
#define __BSP_GPIO_H
#include "delay.h"




void Motor_GPIOInit (void);	
void Motor_CW(void);				
void SysTick_Delay_Ms(__IO uint32_t );
void Motor_SW(void);			
void Motor_ctrl_angle(int dire ,int angle);	
void Motor_ctrl_motor(int dire,float cycle);	
void MotorStop(void);	

void Motor_RW(void);


#endif

 2学分

了解RFID应用

了解RFID系统组成

完成完整的实训项目设计


前期LCD参考文章:

LCD12864液晶显示模块的使用与分析_楼上小白_1001号的博客-CSDN博客_lcd12864 

STM32 LCD12864使用教程_是along不是alone的博客-CSDN博客_lcd12864复位

引脚介绍
1.一共有20个引脚,重要的只有那么几个;
3~VO就是调节对比度的,相当于调节每个点显示出来的深浅,虽然只有亮与不亮两种选择,但亮的模式下相当于可以调节每个点到底多亮;
4~RS,为1的时候表示发送的发送的数据,为0表示发送命令;
5~RW,就是控制我们是往LCD12864读数据(1)还是写数据(0),我们要控制LCD,当然是往里面写数据(0);
6~E,使能信号;
17~RST复位引脚;
接下来的DB0~DB7就是用来传输我们的数据,一个字节八个位刚好。

一、LCD12864(带字库的)使用教程:_布鲁格若门的博客-CSDN博客_lcd12864

51单片机——LCD12864_小白变形计的博客-CSDN博客_单片机lcd12864 

有关STM32/51单片机实训day7——电机驱动|ULN2003A步进电机|Proteus电路设计|旋转角度控制函数|驱动函数|Keil5程序设计的更多相关文章

  1. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  2. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  3. ruby-on-rails - 使用 rails 4 设计而不更新用户 - 2

    我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它​​不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数

  4. ruby-on-rails - 在 ruby​​ 中使用 gsub 函数替换单词 - 2

    我正在尝试用ruby​​中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了

  5. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  6. ruby-on-rails - 如何在 Ruby on Rails 中实现由 JSF 2.0 (Primefaces) 驱动的 UI 魔法 - 2

    按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭10年前。问题1)我想知道ruby​​onrails是否有功能类似于primefaces的gem。我问的原因是如果您使用primefaces(http://www.primefaces.org/showcase-labs/ui/home.jsf),开发人员无需担心javascript或jquery的东西。据我所知,JSF是一个规范,基于规范的各种可用实现,prim

  7. ruby - 在 Ruby 中按名称传递函数 - 2

    如何在Ruby中按名称传递函数?(我使用Ruby才几个小时,所以我还在想办法。)nums=[1,2,3,4]#Thisworks,butismoreverbosethanI'dlikenums.eachdo|i|putsiend#InJS,Icouldjustdosomethinglike:#nums.forEach(console.log)#InF#,itwouldbesomethinglike:#List.iternums(printf"%A")#InRuby,IwishIcoulddosomethinglike:nums.eachputs在Ruby中能不能做到类似的简洁?我可以只

  8. FOHEART H1数据手套驱动Optitrack光学动捕双手运动(Unity3D) - 2

    本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01  客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02  数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit

  9. STM32读取串口传感器数据(颗粒物传感器,主动上传) - 2

    文章目录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.串口通信(个人理解)我就从串口采集传感器数据这个过程说一下我自己的理解,

  10. C51单片机——实现用独立按键控制LED亮灭(调用函数篇) - 2

    说在前面这部分我本来是合为一篇来写的,因为目的是一样的,都是通过独立按键来控制LED闪灭本质上是起到开关的作用,即调用函数和中断函数。但是写一篇太累了,我还是决定分为两篇写,这篇是调用函数篇。在本篇中你主要看到这些东西!!!1.调用函数的方法(主要讲语法和格式)2.独立按键如何控制LED亮灭3.程序中的一些细节(软件消抖等)1.调用函数的方法思路还是比较清晰地,就是通过按下按键来控制LED闪灭,即每按下一次,LED取反一次。重要的是,把按键与LED联系在一起。我打算用K1来作为开关,看了一下开发板原理图,K1连接的是单片机的P31口,当按下K1时,P31是与GND相连的,也就是说,当我按下去时

随机推荐