STM32F103ZET6【标准库函数开发】------通过ULN2003驱动步进电机(非PWM方式)01

如何用STM32单片机通过ULN2003驱动步进电机28BYJ-48
单片机:STM32F103ZET6
步进电机:28BYJ-48
驱动电路:ULN2003芯片的驱动板
引脚连接如下:
IN1:PC3
IN2:PC2
IN3:PC0
IN4:PC13

OUT1:步进电机4
OUT2:步进电机3
OUT3:步进电机2
OUT4:步进电机1
步进电机5:VCC电源正极(5V)
GND:共地
COM:VCC电源正极(5V)
5V直流电源:STM32F103ZET6开发板上的5V电压引脚

具体连接如下图:

代码:分三种通电方式单四拍,双四拍,八拍

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "stm32f10x.h"
 
//引脚连接
//IN1:PC3
//IN2:PC2
//IN3:PC0
//IN4:PC13

//步进电机初始化函数
void Motor_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//开启时钟
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_0|GPIO_Pin_2|GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOC, &GPIO_InitStructure);

//默认ULN2003四路输入低电平,输出高电平	
	GPIO_ResetBits(GPIOC,GPIO_Pin_13);
	GPIO_ResetBits(GPIOC,GPIO_Pin_0);
	GPIO_ResetBits(GPIOC,GPIO_Pin_2);
	GPIO_ResetBits(GPIOC,GPIO_Pin_3);	
}
 
//步进电机正转函数
//一相励磁:单(单相绕组通电)四拍(A-B-C-D-A。。。)
void Motorcw(void)
{
	GPIO_SetBits(GPIOC,GPIO_Pin_3);//ULN2003输入高电平,输出低电平
	GPIO_ResetBits(GPIOC,GPIO_Pin_2);
	GPIO_ResetBits(GPIOC,GPIO_Pin_0);
	GPIO_ResetBits(GPIOC,GPIO_Pin_13);
	delay_ms(5);	
	
	GPIO_ResetBits(GPIOC,GPIO_Pin_3);
	GPIO_SetBits(GPIOC,GPIO_Pin_2);//ULN2003输入高电平,输出低电平
	GPIO_ResetBits(GPIOC,GPIO_Pin_0);
	GPIO_ResetBits(GPIOC,GPIO_Pin_13);
	delay_ms(5);		
	
	GPIO_ResetBits(GPIOC,GPIO_Pin_3);
	GPIO_ResetBits(GPIOC,GPIO_Pin_2);
	GPIO_SetBits(GPIOC,GPIO_Pin_0);//ULN2003输入高电平,输出低电平
	GPIO_ResetBits(GPIOC,GPIO_Pin_13);
	delay_ms(5);		
	
	GPIO_ResetBits(GPIOC,GPIO_Pin_3);
	GPIO_ResetBits(GPIOC,GPIO_Pin_2);
	GPIO_ResetBits(GPIOC,GPIO_Pin_0);
	GPIO_SetBits(GPIOC,GPIO_Pin_13);//ULN2003输入高电平,输出低电平
	delay_ms(5);			
}
 
int main(void)
{
//函数初始化
	delay_init();
	Motor_Init();
	
//电机循环执行
	while(1)
		{
			Motorcw();
		}
}
//二相励磁:双(双相绕组通电)四拍(AB-BC-CD-DA-AB-。。。)
void Motorcw(void)
{
	GPIO_SetBits(GPIOC,GPIO_Pin_3);//ULN2003输入高电平,输出低电平
	GPIO_SetBits(GPIOC,GPIO_Pin_2);//ULN2003输入高电平,输出低电平
	GPIO_ResetBits(GPIOC,GPIO_Pin_0);
	GPIO_ResetBits(GPIOC,GPIO_Pin_13);
	delay_ms(5);	
	
	GPIO_ResetBits(GPIOC,GPIO_Pin_3);
	GPIO_SetBits(GPIOC,GPIO_Pin_2);//ULN2003输入高电平,输出低电平
	GPIO_SetBits(GPIOC,GPIO_Pin_0);//ULN2003输入高电平,输出低电平
	GPIO_ResetBits(GPIOC,GPIO_Pin_13);
	delay_ms(5);		
	
	GPIO_ResetBits(GPIOC,GPIO_Pin_3);
	GPIO_ResetBits(GPIOC,GPIO_Pin_0);
	GPIO_SetBits(GPIOC,GPIO_Pin_13);//ULN2003输入高电平,输出低电平
	GPIO_SetBits(GPIOC,GPIO_Pin_2);//ULN2003输入高电平,输出低电平
	delay_ms(5);		
	
	GPIO_SetBits(GPIOC,GPIO_Pin_3);//ULN2003输入高电平,输出低电平
	GPIO_ResetBits(GPIOC,GPIO_Pin_2);
	GPIO_ResetBits(GPIOC,GPIO_Pin_0);
	GPIO_SetBits(GPIOC,GPIO_Pin_13);//ULN2003输入高电平,输出低电平
	delay_ms(5);			
}
//一二相励磁:八拍(A-AB-B-BC-C-CD-D-DA-A。。。)
void Motorcw(void)
{
	GPIO_SetBits(GPIOC,GPIO_Pin_3);//ULN2003输入高电平,输出低电平
	GPIO_ResetBits(GPIOC,GPIO_Pin_2);
	GPIO_ResetBits(GPIOC,GPIO_Pin_0);
	GPIO_ResetBits(GPIOC,GPIO_Pin_13);
	delay_ms(5);	
	
	GPIO_SetBits(GPIOC,GPIO_Pin_3);//ULN2003输入高电平,输出低电平
	GPIO_SetBits(GPIOC,GPIO_Pin_2);//ULN2003输入高电平,输出低电平
	GPIO_ResetBits(GPIOC,GPIO_Pin_0);
	GPIO_ResetBits(GPIOC,GPIO_Pin_13);
	delay_ms(5);	
	
	GPIO_ResetBits(GPIOC,GPIO_Pin_3);
	GPIO_SetBits(GPIOC,GPIO_Pin_2);//ULN2003输入高电平,输出低电平
	GPIO_ResetBits(GPIOC,GPIO_Pin_0);
	GPIO_ResetBits(GPIOC,GPIO_Pin_13);
	delay_ms(5);	
	
	GPIO_ResetBits(GPIOC,GPIO_Pin_3);
	GPIO_SetBits(GPIOC,GPIO_Pin_2);//ULN2003输入高电平,输出低电平
	GPIO_SetBits(GPIOC,GPIO_Pin_0);//ULN2003输入高电平,输出低电平
	GPIO_ResetBits(GPIOC,GPIO_Pin_13);
	delay_ms(5);		
	
	GPIO_ResetBits(GPIOC,GPIO_Pin_3);
	GPIO_ResetBits(GPIOC,GPIO_Pin_0);
	GPIO_SetBits(GPIOC,GPIO_Pin_13);//ULN2003输入高电平,输出低电平
	GPIO_ResetBits(GPIOC,GPIO_Pin_2);
	delay_ms(5);	
	
	GPIO_ResetBits(GPIOC,GPIO_Pin_3);
	GPIO_ResetBits(GPIOC,GPIO_Pin_0);
	GPIO_SetBits(GPIOC,GPIO_Pin_13);//ULN2003输入高电平,输出低电平
	GPIO_SetBits(GPIOC,GPIO_Pin_2);//ULN2003输入高电平,输出低电平
	delay_ms(5);		

	GPIO_ResetBits(GPIOC,GPIO_Pin_3);
	GPIO_ResetBits(GPIOC,GPIO_Pin_2);
	GPIO_ResetBits(GPIOC,GPIO_Pin_0);
	GPIO_SetBits(GPIOC,GPIO_Pin_13);//ULN2003输入高电平,输出低电平
	delay_ms(5);
	
	GPIO_SetBits(GPIOC,GPIO_Pin_3);//ULN2003输入高电平,输出低电平
	GPIO_ResetBits(GPIOC,GPIO_Pin_2);
	GPIO_ResetBits(GPIOC,GPIO_Pin_0);
	GPIO_SetBits(GPIOC,GPIO_Pin_13);//ULN2003输入高电平,输出低电平
	delay_ms(5);			
}

一一一一一一一一一一一一一一一一一一一一
电机正转和反转的代码(都是用单四拍驱动步进电机):

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "stm32f10x.h"

#define DC_A_OFF  GPIO_ResetBits(GPIOC,GPIO_Pin_3)
#define DC_B_OFF  GPIO_ResetBits(GPIOC,GPIO_Pin_2)
#define DC_C_OFF  GPIO_ResetBits(GPIOC,GPIO_Pin_0)
#define DC_D_OFF  GPIO_ResetBits(GPIOC,GPIO_Pin_13)

#define DC_A_ON  GPIO_SetBits(GPIOC,GPIO_Pin_3)
#define DC_B_ON  GPIO_SetBits(GPIOC,GPIO_Pin_2)
#define DC_C_ON  GPIO_SetBits(GPIOC,GPIO_Pin_0)
#define DC_D_ON  GPIO_SetBits(GPIOC,GPIO_Pin_13)


//步进电机初始化函数
void Motor_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//开启时钟
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_0|GPIO_Pin_2|GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOC, &GPIO_InitStructure);

//默认ULN2003四路输入低电平,输出高电平	
	GPIO_ResetBits(GPIOC,GPIO_Pin_13);
	GPIO_ResetBits(GPIOC,GPIO_Pin_0);
	GPIO_ResetBits(GPIOC,GPIO_Pin_2);
	GPIO_ResetBits(GPIOC,GPIO_Pin_3);	
}
 
步进电机正转函数
void Motorcw1(void)
{
	DC_A_ON;
	DC_B_OFF;
	DC_C_OFF;
	DC_D_OFF;
	delay_ms(6);
	
	DC_A_OFF;
	DC_B_ON;
	DC_C_OFF;
	DC_D_OFF;
	delay_ms(6);
	
	DC_A_OFF;
	DC_B_OFF;
	DC_C_ON;
	DC_D_OFF;
	delay_ms(6);	
	
	DC_A_OFF;
	DC_B_OFF;
	DC_C_OFF;
	DC_D_ON;
	delay_ms(6);	
}
步进电机反转函数
void Motorcw2(void)
{	
	DC_A_OFF;
	DC_B_OFF;
	DC_C_OFF;
	DC_D_ON;
	delay_ms(6);

	DC_A_OFF;
	DC_B_OFF;
	DC_C_ON;
	DC_D_OFF;
	delay_ms(6);	

	DC_A_OFF;
	DC_B_ON;
	DC_C_OFF;
	DC_D_OFF;
	delay_ms(6);

	DC_A_ON;
	DC_B_OFF;
	DC_C_OFF;
	DC_D_OFF;
	delay_ms(6);
}
//电机停止函数
void MotorStop(void)  
{  
    GPIO_Write(GPIOC,0x0000);  
}

int main(void)
{
//函数初始化
	delay_init();
	Motor_Init();
	
//电机循环执行
	while(1)
		{
			MotorStop();
		}
}

一一一一一一一一一一一一一一一一一一一一
用数组的方式配置电平(用单四拍驱动步进电机):
有个bug,电机可以正转,不能反转。

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "stm32f10x.h"

//单四拍
u16 phasecw1[4] ={0x0008,0x0040,0x0001,0x2000};// 逆时针
u16 phaseccw2[4]={0x2000,0x0001,0x0040,0x0008};// 顺时针


//步进电机初始化函数
void Motor_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//开启时钟
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_0|GPIO_Pin_2|GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOC, &GPIO_InitStructure);

//默认ULN2003四路输入低电平,输出高电平	
	GPIO_ResetBits(GPIOC,GPIO_Pin_13);
	GPIO_ResetBits(GPIOC,GPIO_Pin_0);
	GPIO_ResetBits(GPIOC,GPIO_Pin_2);
	GPIO_ResetBits(GPIOC,GPIO_Pin_3);	
}
 
步进电机正转函数
void Motorcw1(void)
{
	{  
			uint8_t i;    
			for(i=0;i<4;i++)  
			{  
					GPIO_Write(GPIOC,phasecw1[i]);  
					delay_ms(6); 
			}  
	}		
}
步进电机反转函数
void Motorcw2(void)
{
	{  
			uint8_t a;    
			for(a=0;a<4;a++)  
			{  
					GPIO_Write(GPIOC,phaseccw2[a]);  
					delay_ms(6); 
			}  
	}		
}
//电机停止函数
void MotorStop(void)  
{  
    GPIO_Write(GPIOC,0x0000);  
}

int main(void)
{
//函数初始化
	delay_init();
	Motor_Init();
	
//电机循环执行
	while(1)
		{
			Motorcw1();
		}
}

  • 5
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 基于STM32F103ZET6的通过Modbus-485RTU协议采集pH和溶解氧数据需要进行以下步骤: 1. 首先,我们需要准备一块STM32F103ZET6开发板作为主控制器,该微控制器具有强大的计算和通信能力。另外,还需要一个RS485通信模块,该模块将实现STM32与外部设备的通信。 2. 接下来,我们需要连接pH和溶解氧传感器到STM32开发板。这些传感器通常具有模拟输出,我们需要将其连接到STM32的模拟输入引脚上。 3. 然后,在STM32开发板上编写代码。首先,我们需要初始化串口通信,设置通信参数,包括波特率和数据位数等。接着,我们需要编写Modbus协议的相关代码,实现数据的读取和写入功能。这可以使用现有的Modbus库来简化开发流程。 4. 在代码中,我们需要设置STM32的定时器,以固定的时间间隔读取pH和溶解氧传感器的数据。然后,通过Modbus协议将这些数据封装为Modbus数据包,并通过RS485通信模块发送给外部设备。 5. 外部设备接收到Modbus数据包后,会解析其中的数据,并进行相应的处理。例如,可以在外部设备上显示pH和溶解氧数值,或者将这些数据存储在数据库中进行后续的分析。 通过以上步骤,我们可以实现基于STM32F103ZET6的Modbus-485RTU协议采集pH和溶解氧数据的功能。这种方案具有高效、稳定和可靠的特点,适用于需要远程监测和控制环境参数的应用场景,例如水质监测和水产养殖等领域。 ### 回答2: 基于STM32F103ZET6芯片,我们可以通过Modbus-485RTU协议实现PH和溶解氧数据的采集。Modbus-485RTU协议是一种串行通信协议,常用于工业自动化领域,通过采用RS485总线传输数据,具有传输距离远、抗干扰能力强等特点。 首先,我们需要使用STM32F103ZET6芯片搭建硬件平台。该芯片具有丰富的外设接口,如USART、GPIO等。我们可以通过连接STM32F103ZET6芯片的USART接口和RS485模块,实现与外部设备的通信。 接下来,我们需要编写软件程序实现Modbus协议的功能。在STM32F103ZET6芯片上,可以使用相关的开发工具,如Keil MDK等进行开发。通过编写C语言程序并使用相应的库函数,我们可以实现Modbus-485RTU协议的编码和解码,以及数据的读取和写入。 对于PH和溶解氧数据的采集,我们可以使用相关的传感器。连接传感器到STM32F103ZET6芯片的IO口,并通过程序读取传感器输出的模拟信号。对于PH值的采集,我们可以使用PH传感器,通过将传感器输出的电压信号转换为数字信号,便可以得到PH值。对于溶解氧值的采集,我们可以使用溶解氧传感器,通过读取传感器输出的模拟电流信号并进行一定的计算,即可得到溶解氧值。 最后,在程序中实现Modbus协议的逻辑,通过Modbus指令对PH和溶解氧数据进行读写操作。通过编码和解码过程,可以将数据正确地传输给外部设备,实现与其他设备的通信。 总的来说,基于STM32F103ZET6芯片,使用Modbus-485RTU协议采集PH和溶解氧数据需要搭建硬件平台、编写软件程序,并连接传感器进行数据的获取。通过这些步骤,我们可以实现PH和溶解氧数据的采集与传输。 ### 回答3: 基于STM32F103ZET6微控制器,可以通过Modbus-485RTU协议来采集pH和溶解氧数据。 首先,我们需要连接STM32F103ZET6与pH和溶解氧传感器之间的Modbus-485RTU通信线路。该线路由一个RS-485转接器负责,将STM32F103ZET6的UART串口信号转换为RS-485电平信号,并通过一根485通信线连接到pH和溶解氧传感器。 接下来,我们需要在STM32F103ZET6上编写相应的软件程序来实现Modbus-485RTU通信协议。可以使用现有的Modbus库来简化开发过程。首先,需要配置STM32的UART串口通信参数,例如波特率、数据位、停止位和校验位等。然后,按照Modbus协议的规定,编写发送和接收数据的函数。 在发送方面,我们可以根据Modbus协议要求,构建相应的读取和写入命令,并通过UART串口发送给pH和溶解氧传感器。在接收方面,我们需要设置一个接收缓冲区来接收传感器返回的响应数据,并进行解析和处理。可以根据Modbus协议的规定,解析响应数据,获取pH和溶解氧数据,并进行进一步的处理和显示。 最后,我们可以根据具体的应用需求,将采集到的pH和溶解氧数据进行进一步的存储、显示或发送到其他设备,如计算机或上位机等。 总之,基于STM32F103ZET6微控制器,通过Modbus-485RTU协议采集pH和溶解氧数据需要我们进行硬件连接以及编写相应的软件程序来实现通信协议的要求,并对接收到的数据进行合理处理和应用。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值