一、实验目的
用IO口模拟步进电机脉冲的输出,方向的控制;
1、有两个步进电机;
每个步进电机需要两个线控制,
**方向控制:**一根线控制DIR,方向,DIR=0,正转,DIR=1,反转;
**距离和速度控制:**一根线PUL控制脉冲,来一个脉冲,走一个步距角,一般是1.8度,看驱动器的拨码开关的设置,看驱动器的详细信息;脉冲的频率越大,转速越快。
所以,通过控制PUL的个数,可以控制距离角度;控制PUL的频率,可以控制步进电机的速度;
我们这里由于速度要求不高,所以都用延时来控制,不用定时器来产生脉冲了。
假如有个IO口控制PUL;那么可以这么写
正转走100个脉冲,然后反向走100个脉冲;100个脉冲是多少mm,根据实际的传动比等确定。
dir=1;//正方向
for(i=0;i<100;i++)
{
pul=1;
delayms(1);
pul=0;
delayms(1);
}
dir=0; //改变方向
for(i=0;i<100;i++)
{
pul=1;
delayms(1);
pul=0;
delayms(1);
}
我们改造一下,编写一个函数,实现第一个步进电机可以指定方向和距离运动;
//头文件和c文件要设置端口和端口模式。
void MoveStepper1(unsigned char seldir,unsigned int pulnum,unsigned int selvel)
{
//判断方向
if(seldir==1)
DIR0=1;
else if(seldir==0)
DIR=0;
//走脉冲数
for(;pulnum>0;pulnum--)
{
PUL0=1;
msleep(selvel);
PUL0=0;
msleep(selvel)
}
}
在pin_config.h中,设置端口的映射;
在main,c中,设置端口的模式,并且在需要的地方这么使用
MoveStepper1(0,100,1);
//第一个参数,是方向,可以是0或者1;
//第二个参数是脉冲数,大于0;
//第三个参数是速度的毫秒,
上面的例子是走脉冲数,我们实际是需要走毫米,所以再改造下;
在main.c中,宏定义一个比例,比如假如1000个脉冲是1mm;那么比例是1000;
main.c中:
#define KPULMM 1000
//头文件和c文件要设置端口和端口模式。
void MoveStepper1(unsigned char seldir,unsigned int mm0,unsigned int selvel)
{
unsigned int pul0=0;
//判断方向
if(seldir==1)
DIR0=1;
else if(seldir==0)
DIR=0;
//将毫米转换成脉冲
pul0=mm0*KPULMM;//假如mm0=10,那么计算得到pul0=10*1000=10000个脉冲
//走脉冲数
for(;pulnum>0;pulnum--)
{
PUL0=1;
msleep(selvel);
PUL0=0;
msleep(selvel)
}
}
上面是原理讲解。
比赛要求:
在210开发板中,由于没太多IO口,所以我们将拨盘按钮和BOO0按钮作为电机控制使用,不用这个按键了,后续我们用串口屏的触摸屏来实现按钮的功能。
两个步进电机
DIR0-------(硬件IO)IO1--------------------软件映射
PUL0--------IO2
DIR1---------IO3
PUL1---------IO16
在main.c中;
设置这几个步进电机口的端口映射;
设置步进电机的端口模式
后面就能使能它为1或者0了。
pin_config.h
/**
* @par Copyright (C): 2016-2022, Shenzhen Yahboom Tech
* @file pin_config.c
* @author Gengyue
* @version V1.0
* @date 2020.05.27
* @brief 硬件引脚与软件GPIO的宏定义
* @details
* @par History 见如下说明
*
* version: 由于K210使用fpioa现场可编程IO阵列,允许用户将255个内部功能映射到芯片外围的48个自由IO上
* 所以把硬件IO和软件GPIO功能抽出来单独设置,这样更容易理解。
*/
#ifndef _PIN_CONFIG_H_
#define _PIN_CONFIG_H_
/*****************************HEAR-FILE************************************/
#include "fpioa.h"
/*****************************HARDWARE-PIN*********************************/
// 硬件IO口,与原理图对应
#define PIN_LED_0 (0) //LED灯
#define PIN_LED_1 (17)
#define PIN_LJT_0 (18) //垃圾桶LJT
#define PIN_LJT_1 (19)
#define PIN_LJT_2 (20)
#define PIN_LJT_3 (21)
#define PIN_LJT_4 (22)
#define PIN_LJT_5 (23)
#define PIN_DIR_0 (1) //传送步进电机0方向 IO12是普通IO
#define PIN_PUL_0 (2) //传送步进电机0脉冲输出 普通IO
#define PIN_DIR_1 (3) //传送步进电机1方向
#define PIN_PUL_1 (16) //传送步进电机1脉冲输出
/*****************************SOFTWARE-GPIO********************************/
// 软件GPIO口,与程序对应
#define LED0_GPIONUM (0)
#define LED1_GPIONUM (1)
#define LJT0_GPIONUM (2)
#define LJT1_GPIONUM (3)
#define LJT2_GPIONUM (4)
#define LJT3_GPIONUM (5)
#define LJT4_GPIONUM (6)
#define LJT5_GPIONUM (7)
#define StepDir0_GPIONUM (8)
#define StepPul0_GPIONUM (9)
#define StepDir1_GPIONUM (10)
#define StepPul1_GPIONUM (11)
/*****************************FUNC-GPIO************************************/
// GPIO口的功能,绑定到硬件IO口
#define FUNC_LED0 (FUNC_GPIO0 + LED0_GPIONUM)
#define FUNC_LED1 (FUNC_GPIO0 + LED1_GPIONUM)
//IO口18--23对应HS高速口,看芯片手册的引脚定义表
#define FUNC_LJT0 (FUNC_GPIOHS0 + LJT0_GPIONUM)
#define FUNC_LJT1 (FUNC_GPIOHS0 + LJT1_GPIONUM)
#define FUNC_LJT2 (FUNC_GPIOHS0 + LJT2_GPIONUM)
#define FUNC_LJT3 (FUNC_GPIOHS0 + LJT3_GPIONUM)
#define FUNC_LJT4 (FUNC_GPIOHS0 + LJT4_GPIONUM)
#define FUNC_LJT5 (FUNC_GPIOHS0 + LJT5_GPIONUM)
#define FUNC_DIR0 (FUNC_GPIOHS0 + StepDir0_GPIONUM)
#define FUNC_PUL0 (FUNC_GPIOHS0 + StepPul0_GPIONUM)
#define FUNC_DIR1 (FUNC_GPIOHS0 + StepDir1_GPIONUM)
#define FUNC_PUL1 (FUNC_GPIOHS0 + StepPul1_GPIONUM)
#endif /* _PIN_CONFIG_H_ */
main.c
//IO18---IO23,普通IO口,输入状态,判断是不是0,是0,说明垃圾满
#include <stdio.h>
#include <unistd.h>
#include "gpio.h"
#include "gpiohs.h"
#include "pin_config.h"
#include "sleep.h"
#include "sysctl.h"
#include "plic.h"
//cmake .. -DPROJ=keypad -G "MinGW Makefiles"
#define xmmpul 2 //1000个脉冲,是1mm,测试可以修改
/**
* Function hardware_init
* @author Gengyue
* @date 2020.05.27
* @brief 硬件初始化,绑定GPIO口
* @param[in] void
* @param[out] void
* @retval void
* @par History 无
*/
void hardware_init(void)
{
fpioa_set_function(PIN_LED_0, FUNC_LED0);
fpioa_set_function(PIN_LED_1, FUNC_LED1);
fpioa_set_function(PIN_LJT_0, FUNC_LJT0);
fpioa_set_function(PIN_LJT_1, FUNC_LJT1);
fpioa_set_function(PIN_LJT_2, FUNC_LJT2);
fpioa_set_function(PIN_LJT_3, FUNC_LJT3);
fpioa_set_function(PIN_LJT_4, FUNC_LJT4);
fpioa_set_function(PIN_LJT_5, FUNC_LJT5);
fpioa_set_function(PIN_DIR_0, FUNC_DIR0);
fpioa_set_function(PIN_PUL_0, FUNC_PUL0);
fpioa_set_function(PIN_DIR_1, FUNC_DIR1);
fpioa_set_function(PIN_PUL_1, FUNC_PUL1);
}
//步进电机运动函数,因为电机的步距角不一样
void movestepper0(int seldir ,uint32_t mm0; int vms) //1mm----pul个脉冲
{
uint64_t i;
//和51单片机不一样,这个是GPIO_PV_HIGH代表高电平
gpio_pin_value_t valuetemp = GPIO_PV_HIGH;
gpio_pin_value_t valuehigh = GPIO_PV_HIGH;
gpio_pin_value_t valuelow = GPIO_PV_LOW;
//判断方向
if(seldir==1)
{
valuetemp = GPIO_PV_HIGH;
}
else if(seldir==0)
{
valuetemp = GPIO_PV_LOW;
}
//设置方向
//用的是高速IO端口模式,所以是gpiohs
gpiohs_set_pin(StepDir0_GPIONUM, valuetemp);
//根据mm,计算脉冲数
for(i=0;i<mm0*xmmpul;i++)
{
gpiohs_set_pin(StepPul0_GPIONUM, valuehigh);
msleep(vms);//
gpiohs_set_pin(StepPul0_GPIONUM, valuelow);
msleep(vms);//
}
}
/**
* Function main
* @author Gengyue
* @date 2020.05.27
* @brief 主函数,程序的入口
* @param[in] void
* @param[out] void
* @retval 0
* @par History 无
*/
int main(void)
{
int i=0;
hardware_init();// 硬件引脚初始化
gpio_init(); // 使能GPIO的时钟
// 设置LED0和LED1的GPIO模式为输出
gpio_set_drive_mode(LED0_GPIONUM, GPIO_DM_OUTPUT);
gpio_set_drive_mode(LED1_GPIONUM, GPIO_DM_OUTPUT);
// 先关闭LED0和LED1
gpio_pin_value_t value = GPIO_PV_HIGH;
gpio_set_pin(LED0_GPIONUM, value);
gpio_set_pin(LED1_GPIONUM, value);
// 设置垃圾桶的传感器的GPIO模式为上拉输入
gpiohs_set_drive_mode(LJT0_GPIONUM, GPIO_DM_INPUT_PULL_UP);
gpiohs_set_drive_mode(LJT1_GPIONUM, GPIO_DM_INPUT_PULL_UP);
gpiohs_set_drive_mode(LJT2_GPIONUM, GPIO_DM_INPUT_PULL_UP);
gpiohs_set_drive_mode(LJT3_GPIONUM, GPIO_DM_INPUT_PULL_UP);
gpiohs_set_drive_mode(LJT4_GPIONUM, GPIO_DM_INPUT_PULL_UP);
gpiohs_set_drive_mode(LJT5_GPIONUM, GPIO_DM_INPUT_PULL_UP);
//设置步进电机的方向和脉冲引脚是输出模式
gpiohs_set_drive_mode(StepDir0_GPIONUM, GPIO_DM_OUTPUT);
gpiohs_set_drive_mode(StepPul0_GPIONUM, GPIO_DM_OUTPUT);
gpiohs_set_drive_mode(StepDir1_GPIONUM, GPIO_DM_OUTPUT);
gpiohs_set_drive_mode(StepPul1_GPIONUM, GPIO_DM_OUTPUT);
while (1)
{
//查询几个GPIO垃圾桶,返回传感器..参考keypad的案例代码
gpio_pin_value_t state_LJT0 = gpiohs_get_pin(LJT0_GPIONUM);
gpio_pin_value_t state_LJT1 = gpiohs_get_pin(LJT1_GPIONUM);
gpio_pin_value_t state_LJT2 = gpiohs_get_pin(LJT2_GPIONUM);
gpio_pin_value_t state_LJT3 = gpiohs_get_pin(LJT3_GPIONUM);
gpio_pin_value_t state_LJT4 = gpiohs_get_pin(LJT4_GPIONUM);
gpio_pin_value_t state_LJT5 = gpiohs_get_pin(LJT5_GPIONUM);
//gpio_pin_value_t value = GPIO_PV_HIGH; GPIO_PV_LOW
//LED 低电平亮,高电平不亮
if(!state_LJT0)
{
// gpio_set_pin(LED0_GPIONUM, GPIO_PV_LOW);
gpio_set_pin(LED1_GPIONUM, GPIO_PV_LOW);
}
if(!state_LJT1)
{
// gpio_set_pin(LED0_GPIONUM, GPIO_PV_LOW);
gpio_set_pin(LED1_GPIONUM, GPIO_PV_HIGH);
}
if(!state_LJT2)
{
//gpio_set_pin(LED0_GPIONUM, GPIO_PV_HIGH);
gpio_set_pin(LED1_GPIONUM, GPIO_PV_LOW);
}
if(!state_LJT3)
{
// gpio_set_pin(LED0_GPIONUM, GPIO_PV_HIGH);
gpio_set_pin(LED1_GPIONUM, GPIO_PV_HIGH);
}
//步进电机测试,正方向,两个电机都走100000个脉冲
gpiohs_set_pin(StepDir0_GPIONUM, GPIO_PV_HIGH);
gpiohs_set_pin(StepDir1_GPIONUM, GPIO_PV_HIGH);
for(i=0;i<100000;i++)
{
gpiohs_set_pin(StepPul0_GPIONUM, GPIO_PV_HIGH);
gpiohs_set_pin(StepPul1_GPIONUM, GPIO_PV_HIGH);
msleep(1);//5000
gpiohs_set_pin(StepPul0_GPIONUM, GPIO_PV_LOW);
gpiohs_set_pin(StepPul1_GPIONUM, GPIO_PV_LOW);
msleep(1);//5000
}
sleep(10);
//步进电机测试,反方向,两个电机都走100000个脉冲
gpiohs_set_pin(StepDir0_GPIONUM, GPIO_PV_LOW);
gpiohs_set_pin(StepDir1_GPIONUM, GPIO_PV_LOW);
//步进电机测试,正方向,两个电机都走100000个脉冲
for(i=0;i<100000;i++)
{
gpiohs_set_pin(StepPul0_GPIONUM, GPIO_PV_HIGH);
gpiohs_set_pin(StepPul1_GPIONUM, GPIO_PV_HIGH);
msleep(1);//5000
gpiohs_set_pin(StepPul0_GPIONUM, GPIO_PV_LOW);
gpiohs_set_pin(StepPul1_GPIONUM, GPIO_PV_LOW);
msleep(1);//5000
}
sleep(10);
movestepper0(0,100; 1) //0方向,100个mm,速度是1ms
sleep(10);
movestepper0(1,100; 1) //0方向,100个mm,速度是1ms
sleep(10);
}
return 0;
}