/*作者:曹备*/
/*最后修改日期:2015-04-05*/
/*创建日期: 2015-04-05*/
/*基于STM32的单轴简易运动控制器/脉冲发生器*/
/*脉冲+方向控制步进伺服电机*/
/*
优化记录:
增加急停GPIOC.0、正向极限GPIOC.1、负向极限GPIOC.2等输入IO接点
中断修改TIMx_PSC一个寄存器的值,而不是修改TIMx_ARR预加载寄存器+TIMx_CCRx比较值寄存器两个值,缩短中断处理时间
定位指令DRVI/DRVA中,目标频率设定过高、而实际输出脉冲数过少时,则不必加速到目标频率即进入减速区
*/
/*
DRVI(A);相对定位,输出A(A取绝对值)个脉冲
A不能为0
若A为正数,则方向为正、GPIOB.0为高电平
若A为负数,则方向为负、GPIOB.0为低电平
DRVA(A) 绝对定位,输出脉冲,运行至A个脉冲的位置
若目标位置A等于当前位置D,则不执行脉冲输出
若A大于D 则方向为正GPIOB.5为高电平
若A小于D 则方向为负GPIOB.5为低电平
GPIOB.1为脉冲输出
GPIOB.0为方向输出
占空比为50%
GPIOC.0急停
GPIOC.1正向极限
GPIOC.2反向极限
GPIOC.3
GPIOC.4
GPIOC.5
GPIOC.6
GPIOC.7启动
阶梯曲线形式加减速
加减速时间以10毫秒为基本单位
加减速以每10毫秒为一级
例如
加减速时间为50毫秒,则加减速级数为50/10=5
加减速时间为100毫秒,则加减速级数为100/10=10
加减速时间为150毫秒,则加减速级数为150/10=15
*/
#include "stm32reg.h"
#include "system_stm32.h"
#include "stm32_gpio.h"
#define MasterFrequency 0x100000//最高频率限制100K
long Current; //当前位置脉冲数
long Target; //目标位置脉冲数
long StartSave; //定位指令刚开始启动时的当前值
long DownStartSave; //开始进入减速时的当前值
STATUS_Type RunFlag; //定位指令脉冲输出执行标志
STATUS_Type StopCommand;//定位指令脉冲输出停止命令标志
STATUS_Type PlusMinus; //正负方向标志
u32 StartFreq; //启动频率
u32 TargetFreq; //目标频率
u32 UDTimer; //加减速时间
u32 LadderFreq[102];
u16 LadderPSC[202]; //加减速0至9级速度/频率预分频值
u16 LadderNum; //加减速速度级数
u16 LadderOrderNum; //加减速速度编号
long LadderTarget[202]; //各速度等级目标值
void MyTimer3_Init()//定时器3初始化
{
RCC_APB2ENR|=(1<<3)|(1<<0); //使能AFIO、GPIOB时钟
GPIOB_CRL&=0xffffff00;
GPIOB_CRL|=0x000000a2; //配置PORTB.1为复用推挽输出、配置PORTB.0为推挽输出,输出最大频率2MHz
GPIOB_BRR=1<<0;
RCC_APB1ENR|=1<<1; //使能定时器TIMER3时钟
TIM3_CR1|=1<<2; //设置只有计数溢出作为T3更新中断
TIM3_DIER|=1<<0; //允许定时器3计数溢出中断
Interrupt_Priority(29,2,2); //使能第29号中断(即定时器3全局中断),抢占2响应2,中断分组2
TIM3_CCMR2&=~(3<<8); //T3_CH4通道配置为输出模式
TIM3_CCMR2|=7<<12; //T3_CH4为PWM模式2
TIM3_CCER|=1<<12; //T3_CH4通道输出使能
TIM3_ARR=11; //
TIM3_CCR4=6; //匹配值1等于重装值一半,是以占空比为50%
}
void Pluse_start()
{
RunFlag=ON; //脉冲输出定位指令执行标志置ON
StartSave=Current;
LadderOrderNum=0;//加减速级数序号为0
TIM3_PSC=LadderPSC[0];
MyDelay(2,ms); //脉冲信号比方向信号滞后,以提高可靠性
TIM3_CR1|=1<<0; //启动定时器TIMER2计数
}
/*********************************************************************************
函数名称:DRVI
函数功能:相对定位
入口参数:long offset相对偏移脉冲,u32 frequency最高频率
返回值:无
*********************************************************************************/
void DRVI(long offset,u32 frequency)
{
u16 h;
u16 i;
u32 j;
if((offset!=0)&&(RunFlag==OFF)&&((GPIOC_IDR&0x01)==0))//相对偏移值为0则不接受命令,脉冲输出已执行,不接受命令
{
Target=Current+offset; //目标值等于当前值加上相对偏移值
if(frequency<StartFreq) //如果设定目标频率小于启动频率
{
frequency=StartFreq;
}
else if(frequency>MasterFrequency)//否则如果设定目标频率高于最高限制频率
{
frequency=MasterFrequency;
}
LadderNum=UDTimer/10;//加减速级数
j=(frequency-StartFreq)/LadderNum;//等差
for(i=0;i<LadderNum;i++)
{
LadderFreq[i]=i*j+StartFreq;//加减速各阶梯频率
LadderPSC[i]=(6000000/LadderFreq[i])-1;//加减速各阶梯频率对应定时器预分频值
}
LadderFreq[LadderNum]=frequency;//目标频率,最高频率
LadderPSC[LadderNum]=6000000/frequency-1;//目标频率(最高频率)对应定时器预分频值
if(offset>0)//相对偏移值为正数
{
GPIOB_BSRR=1<<0;//相对偏移值为正数,方向为正,方向信号高电平
PlusMinus=ON;//正负方向标志置ON
LadderTarget[0]=Current+StartFreq/100;//加速第一段目标脉冲值
for(i=1;i<LadderNum;i++)
{
LadderTarget[i]=LadderTarget[i-1]+LadderFreq[i]/100;//加速各段目标脉冲值
}
while(offset<=((LadderTarget[LadderNum-1]-Current)<<1))//如果偏移量小于二倍加速增量
{
LadderNum--;//加速等级数减一 频率设定过高、实际输出脉冲数过少的情况下不必加速至设定频率,避免过冲
}
for(i=0,h=LadderNum<<1; i<LadderNum; i++,h--)
{
LadderPSC[h]=LadderPSC[i];//减速各段定时器重装值
}
LadderTarget[LadderNum<<1]=Target;//减速最后一段目标脉冲值
for(i=(LadderNum<<1)-1,h=0;i>LadderNum;i--,h++)
{
LadderTarget[i]=LadderTarget[i+1]-LadderFreq[h]/100;//减速各段目标脉冲值
}
}
else//否则相对偏移值为负数
{
GPIOB_BRR=1<<0;//相对偏移值为负数,方向为负,方向信号低电平
PlusMinus=OFF;//正负方向标志OFF
LadderTarget[0]=Current-StartFreq/100;//加速第一段目标脉冲值
for(i=1;i<LadderNum;i++)
{
LadderTarget[i]=LadderTarget[i-1]-LadderFreq[i]/100;//加速各段目标脉冲值
}
while(offset>=((LadderTarget[LadderNum-1]-Current)<<1))//如果偏移量小于二倍加速增量
{
LadderNum--;//加速等级数减一 频率设定过高、实际输出脉冲数过少的情况下不必加速至设定频率,避免过冲
}
for(i=0,h=LadderNum<<1; i<LadderNum; i++,h--)
{
LadderPSC[h]=LadderPSC[i];
}
LadderTarget[LadderNum<<1]=Target;//减速最后一段目标脉冲值
for(i=(LadderNum<<1)-1,h=0;i>LadderNum;i--,h++)
{
LadderTarget[i]=LadderTarget[i+1]+LadderFreq[h]/100;//减速各段目标脉冲值
}
}
LadderTarget[LadderNum]=Target + Current - LadderTarget[LadderNum-1];
Pluse_start();//脉冲输出正式启动
}
}
/*********************************************************************************
函数名称:DRVA
函数功能:绝对定位
入口参数:long target目标位置脉冲,u32 frequency最高频率
返回值:无
*********************************************************************************/
void DRVA(long target,u32 frequency)
{
u16 h;
u16 i;
u32 j;
long offset=target-Current;
if((offset!=0)&&(RunFlag==OFF)&&((GPIOC_IDR&0x01)==0)) //目标位置等于当前位置,则不接受命令
{
Target=target; //目标位置设定(等于参数)
if(frequency<StartFreq) //如果设定目标频率小于启动频率
{
frequency=StartFreq;
}
else if(frequency>MasterFrequency)//否则如果设定目标频率高于最高限制频率
{
frequency=MasterFrequency;
}
LadderNum=UDTimer/10;//加减速级数
j=(frequency-StartFreq)/LadderNum;//等差
for(i=0;i<LadderNum;i++)
{
LadderFreq[i]=i*j+StartFreq;//加减速各阶梯频率
LadderPSC[i]=(6000000/LadderFreq[i])-1;//加减速各阶梯频率对应定时器初值
}
LadderFreq[LadderNum]=frequency;
LadderPSC[LadderNum]=6000000/frequency-1;
if(offset>0)//目标位置值大于当前位置值
{
GPIOB_BSRR=1<<0;//则方向为正,方向信号高电平
PlusMinus=ON;//正负方向标志置ON
LadderTarget[0]=Current+StartFreq/100;
for(i=1;i<LadderNum;i++)
{
LadderTarget[i]=LadderTarget[i-1]+LadderFreq[i]/100;
}
while(offset<=((LadderTarget[LadderNum-1]-Current)<<1))//如果偏移量小于二倍加速增量
{
LadderNum--;//加速等级数减一 频率设定过高、实际输出脉冲数过少的情况下不必加速至设定频率,避免过冲
}
for(i=0,h=LadderNum<<1; i<LadderNum; i++,h--)
{
LadderPSC[h]=LadderPSC[i];
}
LadderTarget[LadderNum<<1]=Target;//减速最后一段目标脉冲值
for(i=(LadderNum<<1)-1,h=0;i>LadderNum;i--,h++)
{
LadderTarget[i]=LadderTarget[i+1]-LadderFreq[h]/100;//减速各段目标脉冲值
}
}
else//否则目标位置值小于当前位置值,
{
GPIOB_BR