以下为程序核心代码
timer.c
定时器配置,输出pwm
#include "timer.h"
#include "led.h"
#include "usart.h"
#include "Key.h"
void TIM3_PWM_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_1;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_SetBits(GPIOB, GPIO_Pin_0);
TIM3->CR1|=1<<2; //ÉèÖÃÖ»ÓмÆÊýÒç³ö×÷ΪT3¸üÐÂÖжÏ
TIM3->DIER|=1<<0; //ÔÊÐí¶¨Ê±Æ÷3¼ÆÊýÒç³öÖжÏ
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=TIM3->ARR>>1; //Æ¥ÅäÖµ1µÈÓÚÖØ×°ÖµÒ»°ë£¬ÊÇÒÔÕ¼¿Õ±ÈΪ50%
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3ÖжÏ
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //ÏÈÕ¼ÓÅÏȼ¶0¼¶
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //´ÓÓÅÏȼ¶3¼¶
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQͨµÀ±»Ê¹ÄÜ
NVIC_Init(&NVIC_InitStructure); //¸ù¾ÝNVIC_InitStructÖÐÖ¸¶¨µÄ²ÎÊý³õʼ»¯ÍâÉèNVIC¼Ä´æÆ÷
TIM_Cmd(TIM3, DISABLE);
}
void EXIT_Init(void)
{
EXTI_InitTypeDef EXTI_InitStruct;//
GPIO_InitTypeDef GPIO_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOA,ENABLE);//
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_5;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed= GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStruct);
GPIO_ResetBits(GPIOB,GPIO_Pin_5);
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);//exit0
EXTI_InitStruct.EXTI_Line=EXTI_Line0;//
EXTI_InitStruct.EXTI_LineCmd=ENABLE;
EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt;
EXTI_InitStruct.EXTI_Trigger= EXTI_Trigger_Falling;//
EXTI_Init(&EXTI_InitStruct);//
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);//
NVIC_InitStruct.NVIC_IRQChannel =EXTI0_IRQn;//
NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;//
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1;//
NVIC_InitStruct.NVIC_IRQChannelSubPriority=2;//
NVIC_Init(&NVIC_InitStruct);//
}
motor.c
步进电机加减速控制配置
#include "led.h"
#include "Delay.h"
#include "Key.h"
#include "sys.h"
#include "usart.h"
#include "timer.h"
#define MasterFrequency 0x100000//×î¸ßƵÂÊÏÞÖÆ100K
long Current; //µ±Ç°Î»ÖÃÂö³åÊý
long Target; //Ä¿±êλÖÃÂö³åÊý
long StartSave; //¶¨Î»Ö¸Áî¸Õ¿ªÊ¼Æô¶¯Ê±µÄµ±Ç°Öµ
long DownStartSave; //¿ªÊ¼½øÈë¼õËÙʱµÄµ±Ç°Öµ
/* TIME3¡ª¡ªCH4 µÄͨµÀ PB1 £¬PB0 ·½Ïò
**
** ÏÈÉèÖÃÆô¶¯ÆµÂÊ200HZ È»ºó¶ÔËùÐèƵÂÊ ½øÐзּ¶ ±ÈÈç 2k ·Ö10¼¶ Ôò (2k-2000)/10 ¼ÆËã³öÿ´ÎËù¼ÓƵÂÊ
**³ÌÐòÏÈ72M/(ARR+1)=6M psc=6M/(¼ÓËٵȼ¶ÆµÂÊ)-1 ¼ÆËã³öËùÐèµÄPSCÖµ£¬ ÿ´Î½øÖжϸıäPSCµÄÖµ
**
**
**
**
**
**
*/
typedef enum
{
OFF = 0,
ON = 1,
}STATUS_Type;
typedef enum
{
us=1,
ms=1000,
sce=1000000,
}DELAY_Type;
STATUS_Type RunFlag; //¶¨Î»Ö¸ÁîÂö³åÊä³öÖ´ÐбêÖ¾
STATUS_Type StopCommand;//¶¨Î»Ö¸ÁîÂö³åÊä³öÍ£Ö¹ÃüÁî±êÖ¾
STATUS_Type PlusMinus; //Õý¸º·½Ïò±êÖ¾
u32 StartFreq; //Æô¶¯ÆµÂÊ
u32 TargetFreq; //Ä¿±êƵÂÊ
u32 UDTimer=1000; //¼Ó¼õËÙʱ¼ä
u32 LadderFreq[102];
u16 LadderPSC[202]; //¼Ó¼õËÙ0ÖÁ9¼¶ËÙ¶È/ƵÂÊÔ¤·ÖƵֵ
u16 LadderNum; //¼Ó¼õËÙËٶȼ¶Êý
u16 LadderOrderNum; //¼Ó¼õËÙËٶȱàºÅ
long LadderTarget[202]; //¸÷Ëٶȵȼ¶Ä¿±êÖµ
void TIM3_IRQHandler(void) //¶¨Ê±Æ÷3È«¾ÖÖжϺ¯Êý
{
long temp;
if(TIM3->SR&0x0001)
{
if(PlusMinus==ON) //·½Ïò
{
temp=Current;
//Èç¹û·½ÏòΪÕý£¬µ±Ç°Öµ¼ÓÒ»
temp++;
Current=temp;
}
else
{
temp=Current;
temp--; //·ñÔò·½ÏòΪ¸º£¬µ±Ç°Öµ¼õÒ» µ¹×Å×ß
Current=temp;
}
if(Current==LadderTarget[LadderOrderNum])
{
if(LadderOrderNum< (LadderNum<<1))//¼Ó¼õËÙÔÚÕâ¶ùʵÏÖ ¡£µÈ¼¶±êºÅ<2±¶µÈ¼¶
{
LadderOrderNum++; //µÈ¼¶±êºÅ++£»
TIM3->PSC=LadderPSC[LadderOrderNum];//¸Ä±äÄãPSCµÄÖµ
}
else //¹Ø±Õ²½½øµç»ú
{
TIM3->CR1&=~(1<<0);
TIM3->CNT=0x0000;
RunFlag=OFF;
}
}
TIM3->SR=0x0000;
}
}
void Pluse_start(void)
{
RunFlag=ON; //Âö³åÊä³ö¶¨Î»Ö¸ÁîÖ´ÐбêÖ¾ÖÃON
StartSave=Current;
LadderOrderNum=0; //¼Ó¼õËÙ¼¶ÊýÐòºÅΪ0
TIM3->PSC=LadderPSC[0];
Delay_ms(2); //Âö³åÐźűȷ½ÏòÐźÅÖͺó£¬ÒÔÌá¸ß¿É¿¿ÐÔ
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)//3200 2khz
{
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;//¼Ó¼õËÙ¼¶Êý ·Ö³É100¼¶
j=(frequency-StartFreq)/LadderNum;//µÈ²î ÿ¸ö½×¶ÎËù¼ÓµÄƵÂÊÊý
for(i=0;i<LadderNum;i++) //»ñȡÿ¸ö½×¶ÎµÄËÙ¶ÈÖµ
{
LadderFreq[i]=i*j+StartFreq;//¼Ó¼õËÙ¸÷½×ÌÝƵÂÊ Ã¿¸ö½×¶ÎµÄËÙ¶È µÈ¼¶µ½J
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();//Âö³åÊä³öÕýʽÆô¶¯
}
}
/*********************************************************************************
º¯ÊýÃû³Æ£ºSLOPE
º¯Êý¹¦ÄÜ£ºÐ±ÆÂÉèÖÃ(ƶÈбÂÊÉèÖÃ) ÏÞ¶¨Æô¶¯ÆµÂÊÔÚ100---1000Ö®¼ä ÏÞÖÆʱ¼äÔÚ50---1000
Èë¿Ú²ÎÊý£ºu32 frequencyÆô¶¯ÆµÂÊ,u32 timer¼Ó¼õËÙʱ¼ä
·µ»ØÖµ£ºÎÞ
*********************************************************************************/
void SLOPE(u32 frequency,u32 timer)//200hz 600
{
if(frequency<100)
{
StartFreq=100;
}
else if(frequency>1000)
{
StartFreq=1000;
}
else
{
StartFreq=frequency;
}//Æô¶¯ÆµÂÊÉèÖôóÓÚµÈÓÚ100СÓÚµÈÓÚ1000
if(timer<50)
{
UDTimer=50;
}
else if(timer>1000)
{
UDTimer=1000;
}
else
{
UDTimer=(timer/10)*10; //È¡ÕûÊý
}//¼Ó¼õËÙʱ¼äÉèÖà ´óÓÚµÈÓÚ50СÓÚµÈÓÚ1000£¬ÇÒΪÕûÊ®Êý
}
void Variable_Init(void)
{
Target=0;//Ä¿±êλÖÃÂö³åÖµ
Current=0;//µ±Ç°Î»ÖÃÂö³åÖµ
RunFlag=OFF;//Âö³å¶¨Î»Ö¸ÁîÖ´ÐбêÖ¾
StopCommand=OFF;//¶¨Î»Ö¸ÁîÂö³åÊä³öÍ£Ö¹ÃüÁî±êÖ¾
}
void PAUSE(void)
{
while(RunFlag==ON);
}
硬件接线
PB1接驱动器的PUL+,PB0接驱动器的DIR+,同时stm32要与驱动器共地,PUL-,DIR-,ENA-接一起同时接到GND