基于TQ2440驱动28BYJ-48步进电机

所需要硬件:

TQ2440开发板一块

28BYJ-48步进电机两个

ULN2003驱动模块两个

杜邦线若干

5号电池4节

 

一、首先设计用CPU的哪些引脚来驱动步进电机

用五线四线步进电机连接ULN2003驱动模块,每个驱动模块需要4个GPIO,要想驱动两个步进电机所以需要用到8个GPIO口。

我选择用了4个LED灯口和4个中断口

 

二、修改GPIO的驱动LED的驱动为我们需要的驱动。

下面上一部分主要的修改后的GPIO驱动,主要是把这8个引脚设置成GPIO的功能,提供接口用以上层应用调用控制输入高电平或低电平。

 

#define DEVICE_NAME "GPIO-Control"

/* 应用程序执行ioctl(fd, cmd, arg)时的第2个参数 */
#define IOCTL_GPIO_ON	1
#define IOCTL_GPIO_OFF	0

/* 用来指定LED所用的GPIO引脚 */
static unsigned long gpio_table [] =
{
	S3C2410_GPB5,	//LED1
	S3C2410_GPB6,	//LED2
	S3C2410_GPB7,	//LED3
	S3C2410_GPB8,	//LED4
	S3C2410_GPG5, 	//EINT13
	S3C2410_GPG6, 	//EINT14
	S3C2410_GPG7, 	//EINT15
	S3C2410_GPG11, 	//EINT19
};

/* 用来指定GPIO引脚的功能:输出 */
static unsigned int gpio_cfg_table [] =
{
	S3C2410_GPB5_OUTP,
	S3C2410_GPB6_OUTP,
	S3C2410_GPB7_OUTP,
	S3C2410_GPB8_OUTP,
	S3C2410_GPG5_OUTP,
	S3C2410_GPG6_OUTP,
	S3C2410_GPG7_OUTP,
	S3C2410_GPG11_OUTP,
};

static int tq2440_gpio_ioctl(
	struct inode *inode, 
	struct file *file, 
	unsigned int cmd, 
	unsigned long arg)
{
	if (arg > 8)
	{
		return -EINVAL;
	}

	switch(cmd)
	{
		case IOCTL_GPIO_ON:
			// 设置指定引脚的输出电平为0
			s3c2410_gpio_setpin(gpio_table[arg], 0);
			return 0;

		case IOCTL_GPIO_OFF:
			// 设置指定引脚的输出电平为1
			s3c2410_gpio_setpin(gpio_table[arg], 1);
			return 0;

		default:
			return -EINVAL;
	}
}

 

三、编写程序来简单的控制电机正转和反转

程序很简单只是简单的控制两个电机同时正转、反转或停止。

moto.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>

int setGPIO(int led_no,int on)
{
	int fd;
	fd = open("/dev/GPIO-Control", 0);
	if (fd < 0) {
		perror("open device leds");
		exit(1);
	}
	ioctl(fd, on, (led_no-1));
	close(fd);
	return 0;
}
#define uchar unsigned char
#define uint unsigned int

uchar CCW[8]={0x08,0x0c,0x04,0x06,0x02,0x03,0x01,0x09};   //逆时钟旋转相序表
uchar CW[8]={0x09,0x01,0x03,0x02,0x06,0x04,0x0c,0x08};    //正时钟旋转相序表

int K1=0;
int K2=1;
int K3=1;

void switchPort(char value,int flag){
#if 1
	int p1,p2,p3,p4;
	if(flag==1){
		p1=1;
		p2=2;
		p3=3;
		p4=4;
	}else if(flag==2){
		p1=5;
		p2=6;
		p3=7;
		p4=8;
	}
	setGPIO(p1,value&1);
	setGPIO(p2,(value >> 1) & 1);
	setGPIO(p3,(value >> 2) & 1);
	setGPIO(p4,(value >> 3) & 1);
#endif
}

void beep(){
#if 1
	int fd,i;
	unsigned long temp = 0;
	fd=open("dev/PWM-Test",0);
	if(fd<0){
		perror("open device error\n");
		exit(1);
	}
	ioctl(fd,1,3);
	usleep(500);
	ioctl(fd,0);
	close(fd);
#endif
}
void motor_ccw(void)
{
	uchar i,j;
	for(j=0;j<8;j++)  //电机旋转一周,不是外面所看到的一周,是里面的传动轮转了一周
	{
		for(i=0;i<8;i++)  //旋转45度
		{
			switchPort(CCW[i],1);
			switchPort(CCW[i],2);
			usleep(1);//调节转速
		}
	}
}


void motor_cw(void)
{
	uchar i,j;
	for(j=0;j<8;j++)
	{
		for(i=0;i<8;i++)  //旋转45度
		{
			switchPort(CW[i],1);
			switchPort(CW[i],2);
			usleep(1);//调节转速
		}
	}
}

void switchDir(uint key){
	if(key==0){ 		//ting
		K1=1;
		K2=1;
	}else if(key==1){ 	//zheng
		K1=0;
		K2=1;
	}else if(key==2){ 	//fan
		K1=1;
		K2=0;
	}else
		printf("please put 0|1|2 \n");
}

int main(int argc,char **argv)
{
	uint tmp;
	uchar r;
	uchar N=64;         //因为步进电机是减速步进电机,减速比的1/64,
			    //所以N=64时,步进电机主轴转一圈
	printf("Please enter the direction number (0 is stop) :\n");
	scanf("%d",&tmp);
	switchDir(tmp);
	while(1)
	{
		if(K1==0)
		{
			beep();
			for(r=0;r<N;r++)
			{
				motor_ccw();  //电机逆转
				if(K3==0)
				{
					beep();
					printf("break ccw!\n");
					break;
				}
			}
		}
		else if(K2==0)
		{
			beep();
			for(r=0;r<N;r++)
			{
				motor_cw();    //电机反转
				if(K3==0)
				{
					beep();
					printf("break cw!\n");
					break;
				}
			}
		}
		else{
			switchPort(0xf0,1);//电机停止
			switchPort(0xf0,2);//电机停止
		}
	}
	return 0;
}

 

四、重新编译内核和moto.c

将内核烧到开发板,并将moto.c生成的moto放到文件系统中,在串口运行./moto。

最后上一张电机成功转动的图片。

 

 

仅仅只是在下班后做着玩的,功能很简单,有时间后期还会慢慢完善的,文章写得很简单,不足之处请见谅。

致我们逝去的不眠夜

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值