STM32f103驱动四线无刷电机

总所周知stm32有很多的引脚而且能够通过寄存器来对引脚的io状态进行控制,我突然想到之前买的光驱上的电机四线无刷电机,但是电机的驱动电压是5V,而stm32的推挽输出电压最高位3.27v,我想应该能够让电机进行转动了,果不其然经过一系列的开发测试焊接终于成功的驱动了这个电机。

另外pc13引脚是开漏输出,在下文注释中并未改正

开发工具keil 5
开发版stm32f103c8t686314bc507934771a9ebbbc944679664.jpeg
ioPB 5 ,6,7,8    PC13
负载4线无刷电机ff286afcedf54436b153e1ac71528169.jpeg

 

 该电机的驱动电路时序有两种一种为8步,另一种为4步,经过测试因为电机电压小的缘故,4步驱动在该电机中工作较为正常。

4线无刷电机可简化为只有4个绕组的情况然后分别列出线圈的正负极和转子转动方向,其中8步时序和4步时序都能通过对时序序列的逐步输出控制其转动角度,8步时序其转动的角度控制更为精确。

下图为8步时序和4步时序的推理图

8eb53cc14e0d4bce88cfd8b390f33824.jpeg

由推理图可知只需将不同时刻不同绕组的电压加在相应的位子即可即理论可行

由于用stm32开发板,而且是基于寄存器原理开发的所以开发手册必不可少

第一步配置时钟

//--------------APB2使能时钟寄存器------------------------
#define RCC_APB2ENR		*((unsigned volatile int*)0x40021018)	

d25d498a199f4accaf1d3f699b2c3925.png

 然后使 B ,C组引脚的使能时钟开启

	RCC_APB2ENR|=1<<4;			//APB2-GPIOC外设时钟使能
	RCC_APB2ENR|=1<<3;			//APB2-GPIOB外设时钟使能	

 然后对所使用的引脚通过寄存器进行配置

输出模式:推挽输出

155ebf686f4045afb695ee83a1f95e2c.png

0c80d72b9fef4aea92cb346d1d93c782.png

 注意:该程序即用到了B组的高位也用了低位,所以注意高位低位不同的配置

//----------------GPIOB配置高位寄存器 ------------------------
#define GPIOB_CRH		*((unsigned volatile int*)0x40010C04)
//----------------GPIOB配置低位寄存器 ------------------------
#define GPIOB_CRL		*((unsigned volatile int*)0x40010C00)
#define	GPIOB_ODR		*((unsigned volatile int*)0x40010C0C)

//----------------GPIOC配置寄存器 ------------------------
#define GPIOC_CRH		*((unsigned volatile int*)0x40011004)
#define	GPIOC_ODR		*((unsigned volatile int*)0x4001100C)

 引脚配置

​

	GPIOB_CRL&=0xFF0FFFFF;    //设置位 清零
	GPIOB_CRL|=0x00200000;    //PB5推挽输出,把第23、22、21、20位变为0010
	
    GPIOB_CRL&=0xF0FFFFFF;		//设置位清零	
    GPIOB_CRL|=0x2000000;		  //PB6推挽输出,把第27、26、25、24变为0010
	
	GPIOB_CRL&=0xFFFFFFF;		  //设置位清零	
    GPIOB_CRL|=0x20000000;		//PB7推挽输出,把第27、26、25、24变为0010
	
	
	GPIOB_CRH&=0xFFFFFFF0;		//设置位清零	
    GPIOB_CRH|=0x00000002;		//PB8推挽输出,把第3、2、1、0变为0010
	
	
	
    GPIOC_CRH&=0xFF0FFFFF;		//设置位清零	
    GPIOC_CRH|=0x00200000;		//PC13推挽输出,把第23、22、21、20变为0010
  
​

这里的数据是通过将对应的数据位替换然后转换为16进制而得到的

406bb0d190aa409eba8d3cc70fa9d94b.png

 

ce5c76ad4ecf4b2f9b0c3e69f4d12162.png 

 通过端口输出寄存器可以同时快速的控制多个io

然后每一步之间进行一定的延时即可

 

 

总体代码展示

main.c

#include "motor.h"
int main(){
     RESET();
	while(1){
		TEST_left(5);
		//TEST_right(5);
  //LEFT(5);
	//	RIGHT(5);
		}
		
}

 

 

motor.c

​
#include "motor.h"
//时延函数
void Delay_ms( volatile  unsigned  int  t)
{
     unsigned  int  i;
     while(t--)
         for (i=0;i<10000;i++);
}
/*   8位步进驱动     */
void LEFT(int time){

	GPIOC_ODR = (0<<13);//高
		
/*          正转            */
		GPIOB_ODR = 0x4001082C;//设置引脚电平 1000
	
		Delay_ms(time);
		GPIOB_ODR = 0x4001092C;//设置引脚电平 1001
		Delay_ms(time);
		GPIOB_ODR = 0x4001090C;//设置引脚电平 0001
		Delay_ms(time);
		GPIOB_ODR = 0x4001094C;//设置引脚电平 0101
		GPIOC_ODR = (1<<13);//高
		Delay_ms(time);
		GPIOB_ODR = 0x4001084C;//设置引脚电平 0100
		Delay_ms(time);
		GPIOB_ODR = 0x400108CC;//设置引脚电平 0110
		Delay_ms(time);
		GPIOB_ODR = 0x4001088C;//设置引脚电平 0010
		Delay_ms(time);
		GPIOB_ODR = 0x400108AC;//设置引脚电平 1010
		Delay_ms(time);
		
		
		/*          反转            */
/*	  GPIOB_ODR = 0x4001082C;//设置引脚电平 1000
		Delay_ms(time);
		GPIOB_ODR = 0x4001092C;//设置引脚电平 1001
		Delay_ms(time);
		GPIOB_ODR = 0x4001090C;//设置引脚电平 0001
		Delay_ms(time);
		GPIOB_ODR = 0x4001098C;//设置引脚电平 0011
		Delay_ms(time);
		GPIOB_ODR = 0x4001088C;//设置引脚电平 0010
		Delay_ms(time);
		GPIOB_ODR = 0x400108CC;//设置引脚电平 0110
		Delay_ms(time);
		GPIOB_ODR = 0x4001084C;//设置引脚电平 0100
		Delay_ms(time);
		GPIOB_ODR = 0x4001086C;//设置引脚电平 1100
		Delay_ms(time);
		*/}
void RIGHT(int time){
	GPIOC_ODR = (0<<13);//高
		/*          反转            */
	  GPIOB_ODR = 0x4001082C;//设置引脚电平 1000
		Delay_ms(time);
		GPIOB_ODR = 0x4001092C;//设置引脚电平 1001
		Delay_ms(time);
		GPIOB_ODR = 0x4001090C;//设置引脚电平 0001
		Delay_ms(time);
		GPIOB_ODR = 0x4001098C;//设置引脚电平 0011
	GPIOC_ODR = (1<<13);//高
		Delay_ms(time);
		GPIOB_ODR = 0x4001088C;//设置引脚电平 0010
		Delay_ms(time);
		GPIOB_ODR = 0x400108CC;//设置引脚电平 0110
		Delay_ms(time);
		GPIOB_ODR = 0x4001084C;//设置引脚电平 0100
		Delay_ms(time);
		GPIOB_ODR = 0x4001086C;//设置引脚电平 1100
		Delay_ms(time);
	}
	
	void RESET(){
		RCC_APB2ENR|=1<<4;			//APB2-GPIOC外设时钟使能
	RCC_APB2ENR|=1<<3;			//APB2-GPIOB外设时钟使能	
	GPIOB_CRL&=0xFF0FFFFF;    //设置位 清零
	GPIOB_CRL|=0x00200000;    //PAB5推挽输出,把第23、22、21、20位变为0010
  GPIOB_CRL&=0xF0FFFFFF;		//设置位清零	
  GPIOB_CRL|=0x2000000;		  //PB6推挽输出,把第27、26、25、24变为0010
	GPIOB_CRL&=0xFFFFFFF;		  //设置位清零	
  GPIOB_CRL|=0x20000000;		//PB7推挽输出,把第27、26、25、24变为0010
	GPIOB_CRH&=0xFFFFFFF0;		//设置位清零	
  GPIOB_CRH|=0x00000002;		//PB8推挽输出,把第3、2、1、0变为0010
  GPIOC_CRH&=0xFF0FFFFF;		//设置位清零	
  GPIOC_CRH|=0x00200000;		//PC13推挽输出,把第23、22、21、20变为0010
	}
	
	/*   4位步进驱动*/
	void TEST_left(int time){
	GPIOC_ODR = (0<<13);//高
		/*          反转            */
	 
		GPIOB_ODR = 0x4001092C;//设置引脚电平 1001
		Delay_ms(time);
		GPIOB_ODR = 0x400108AC;//设置引脚电平 1010
		Delay_ms(time);
		GPIOB_ODR = 0x400108CC;//设置引脚电平 0110
		Delay_ms(time);
		GPIOB_ODR = 0x4001094C;//设置引脚电平 0101
		GPIOC_ODR = (1<<13);//高
		Delay_ms(time);
	}
	void TEST_right(int time){
	GPIOC_ODR = (0<<13);//高
		/*          反转            */
		GPIOB_ODR = 0x4001094C;//设置引脚电平 0101
		Delay_ms(time);
		GPIOB_ODR = 0x400108CC;//设置引脚电平 0110
		Delay_ms(time);
		GPIOB_ODR = 0x400108AC;//设置引脚电平 1010
		Delay_ms(time);
		GPIOB_ODR = 0x4001092C;//设置引脚电平 1001
		Delay_ms(time);
			GPIOC_ODR = (1<<13);//高
	}

​

motor.h


#ifndef _MOTOR_H_
#define _MOTOR_H_//写的源文件英文为小写这里也要用大写引用

//--------------APB2使能时钟寄存器------------------------
#define RCC_APB2ENR		*((unsigned volatile int*)0x40021018)	
//----------------GPIOB配置高位寄存器 ------------------------
#define GPIOB_CRH		*((unsigned volatile int*)0x40010C04)
//----------------GPIOB配置低位寄存器 ------------------------
#define GPIOB_CRL		*((unsigned volatile int*)0x40010C00)
#define	GPIOB_ODR		*((unsigned volatile int*)0x40010C0C)

//----------------GPIOC配置寄存器 ------------------------
#define GPIOC_CRH		*((unsigned volatile int*)0x40011004)
#define	GPIOC_ODR		*((unsigned volatile int*)0x4001100C)

//函数声明
void Delay_ms(volatile  unsigned  int);
//int time[8][4]={{1,0,0,0},{1,0,0,1},{0,0,0,1},{0,1,0,1},{0,1,0,0},{0,1,1,0},{0,0,1,0},{1,0,1,0}};
void LEFT( int time);
void RIGHT(int time);
void RESET(void);
void TEST_left(int time);
void TEST_right(int time);
#endif

 

 

 

  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值