⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 步进电动机控制_2812.c

📁 里面包含了基于dsp2812的永磁同步电动机和步进电动机的5个源程序。用c语言编的。
💻 C
字号:
#include "DSP281x_Device.h"     
#include "IQmathLib.h"
#pragma DATA_SECTION(sine_table,"IQmathTables");

#define DIR_MASK         0x01        // 0x01 顺时针,0x00逆时针
#define STEP_MASK        0x02        // 0x00 全步,0x02半步
#define MOTION_MASK     0x04        // 0x00 连续,0x04单步

#define DEFAULT_RATE    0x8000       // 默认步进速度
#define MIN_RATE         0x8000       // 最小速度
#define MAX_RATE        0x0800       // 最大速度

// 默认状态:全步、顺时针、连续模式
unsigned char state = 1;             	// 状态变量
unsigned char stepIndex = 0;         	// 状态表索引
unsigned int  rate = DEFAULT_RATE;   // 步进速度
unsigned char change_rate_flag = 0;  		// 改变速度标识
unsigned int  max_rate = MAX_RATE;   // 最大步进速度
unsigned int  min_rate = MIN_RATE;   	// 最小步进速度

unsigned int SW[4] = {0, 0, 0, 0};   // 开关状态计数

// 系统初始化
void Gpio_select(void);
void InitSystem(void);   
void SCI_Init(void);
interrupt void T1_Compare_isr(void); 	// 定时器1中断服务程序
interrupt void SCI_RX_isr(void)     	// 串口接收数据中断服务程序

// 控制操作函数
void toggle_stepping_mode(void);
void increase_stepping_rate(void);
void decrease_stepping_rate(void);
void toggle_motion(void);
void toggle_direction(void);

// 全步状态表 table A
static const unsigned char fullStepA[] =
{
  0x00,
  0x00,
  0x01,
  0x01
};

// 全步状态表 table B
static const unsigned char fullStepB[] =
{
  0x01,
  0x00,
  0x00,
  0x01
};

// 半步状态表 table A
static const unsigned char HalfStepA[] =
{
  0x01,   // 001   1
  0x06,   // 110   2
  0x00,   // 000   3
  0x00,   // 000   4
  0x00,   // 000   5
  0x07,   // 111   6
  0x01,   // 001   7
  0x01    // 001   8
};

// 逆时针半步状态表 table B
static const unsigned char CcwHalfStepB[] =
{
  0x01,   // 001   1
  0x01,   // 001   2
  0x01,   // 001   3
  0x06,   // 110   4
  0x00,   // 000   5
  0x00,   // 000   6
  0x00,   // 000   7
  0x07    // 111   8
};

// 顺时针半步状态表 table B
static const unsigned char CwHalfStepB[] =
{
  0x00,   // 000   1
  0x00,   // 000   2
  0x00,   // 000   3
  0x07,   // 111   4
  0x01,   // 001   5
  0x01,   // 001   6
  0x01,   // 001   7
  0x06    // 110   8
};

// 主程序
void main(void)
{
 	InitSystem();			// 初始化DSP内核寄存器
	Gpio_select();			// 设置GPIO引脚功能
	InitPieCtrl();			// 初始化外设中断扩展单元 ( 代码在: DSP281x_PieCtrl.c)
	InitPieVectTable(); 		// 初始化外设中断扩展向量表( 代码在:DSP281x_PieVect.c )

// 重新映射定时器1(Timer 1)的比较中断入口 
	EALLOW;  			// 允许更改保护的寄存器
   	PieVectTable.T1CINT = &T1_Compare_isr;
	PieVectTable.RXAINT = &SCI_RX_isr;
   	EDIS;    				// 禁止更改保护的寄存器
	
// 使能T1比较中断:PIE-组2,中断5
	PieCtrlRegs.PIEIER2.bit.INTx5=1;	                    
    // 使能PIE中的SCI_A_RX_INT中断 
PieCtrlRegs.PIEIER9.bit.INTx1 = 1;

// 使能 CPU INT2,GP -Timer1的比较中断连接到该中断
// 使能 CPU INT 9
    IER |= 0x102;    

// 全局中断使能,并使能具有更高优先级的适时调试方式
   	EINT;    // 使能全局中断 INTM
   	ERTM;   // 使能全局适时中断DBGM
// 串口初始化
	SCI_Init();

// 配置事件管理器A EVA
// 假定事件管理器A的时钟已经在InitSysCtrl()中使能;
// T1/T2逻辑驱动T1PWM / T2PWM ;
    EvaRegs.GPTCONA.bit.TCMPOE = 1;
// GP Timer 1 比较输出配置:低电平有效
	EvaRegs.GPTCONA.bit.T1PIN = 1;
	
	EvaRegs.T1CON.bit.FREE = 0;				// 仿真操作时挂起
    EvaRegs.T1CON.bit.SOFT = 0;				// 仿真操作时挂起
    EvaRegs.T1CON.bit.TMODE = 2;				// 连续递增计数模式
    EvaRegs.T1CON.bit.TPS = 0;				// 预定标系数 = 1 : 75 MHz
    EvaRegs.T1CON.bit.TENABLE = 0;			// 禁止GP Timer 1操作
   	EvaRegs.T1CON.bit.TCLKS10 = 0;			// 使用内部时钟
   	EvaRegs.T1CON.bit.TCLD10 = 0;			// 等于0时比较装载
   	EvaRegs.T1CON.bit.TECMPR = 1;			// 使能比较操作
                                         	
   	EvaRegs.T1PR = 1500;
   	EvaRegs.T1CMPR = EvaRegs.T1PR/2;  
   	
   	EvaRegs.EVAIMRA.bit.T1CINT = 1;
   	EvaRegs.T1CON.bit.TENABLE = 1;			// 使能 GP Timer 1    
   	
	while(1)
	{    
  	    EALLOW;
		SysCtrlRegs.WDKEY = 0x55;		// 看门狗控制
	    SysCtrlRegs.WDKEY = 0xAA;		
	    EDIS;
    }
}

//  通用IO选择
void Gpio_select(void)
{
		EALLOW;
	GpioMuxRegs.GPAMUX.all = 0x0;		// 所有GPIO端口配置成I/O方式
    GpioMuxRegs.GPBMUX.all = 0x0; 
    GpioMuxRegs.GPDMUX.all = 0x0;
    GpioMuxRegs.GPFMUX.all = 0x0; 
    GpioMuxRegs.GPEMUX.all = 0x0; 
    GpioMuxRegs.GPGMUX.all = 0x0;
		
    GpioMuxRegs.GPADIR.all = 0xFFFF;		// GPIO PORT  配置为输入
    GpioMuxRegs.GPBDIR.all = 0xFFFF;	    	// GPIO PORT  配置为输出
    GpioMuxRegs.GPDDIR.all = 0x0;			// GPIO PORT  作为输入
    GpioMuxRegs.GPEDIR.all = 0x0;			// GPIO PORT  作为输入
    GpioMuxRegs.GPFDIR.all = 0x0;			// GPIO PORT  作为输入
    GpioMuxRegs.GPGDIR.all = 0x0;			// GPIO PORT  作为输入

    GpioMuxRegs.GPAQUAL.all = 0x0;		// 设置GPIO量化值为0
    GpioMuxRegs.GPBQUAL.all = 0x0;
    GpioMuxRegs.GPDQUAL.all = 0x0;
    GpioMuxRegs.GPEQUAL.all = 0x0;
    EDIS;
} 

// 系统初始化
void InitSystem(void)
{
	EALLOW;
	SysCtrlRegs.WDCR= 0x00AF;		// 配置看门狗 
								// 0x00E8  禁止看门狗,预定标系数Prescaler = 1
								// 0x00AF  使能看门狗,预定标系数Prescaler = 64
	SysCtrlRegs.SCSR = 0; 			// 看门狗产生RESET	
	SysCtrlRegs.PLLCR.bit.DIV = 10;	// 设置系统锁相环倍频系数5

	SysCtrlRegs.HISPCP.all = 0x1; 		// 配置高速外设时钟预定标系数:除以2
	SysCtrlRegs.LOSPCP.all = 0x2; 		// 配置低速外设时钟预定标系数:除以4
		
	// 使能本应用程序使用的外设时钟
	SysCtrlRegs.PCLKCR.bit.EVAENCLK=1;
	SysCtrlRegs.PCLKCR.bit.EVBENCLK=0;
	SysCtrlRegs.PCLKCR.bit.SCIAENCLK=0;
	SysCtrlRegs.PCLKCR.bit.SCIBENCLK=0;
	SysCtrlRegs.PCLKCR.bit.MCBSPENCLK=0;
	SysCtrlRegs.PCLKCR.bit.SPIENCLK=0;
	SysCtrlRegs.PCLKCR.bit.ECANENCLK=0;
	SysCtrlRegs.PCLKCR.bit.ADCENCLK=0;
	EDIS;
}

void SCI_Init(void)
{
	SciaRegs.SCICCR.all =0x0007;   	// 1bit 停止位    无循环模式 
                                   	// 无极性,   	  字符长度:8 bits,
                                   	// 异步模式,    空闲线协议
	SciaRegs.SCICTL1.all =0x0003;  	// 使能 TX, RX,  内部 SCICLK, 
                                   	// 禁止 RX ERR, SLEEP, TXWAKE
	SciaRegs.SCIHBAUD = 487 >> 8 ;   // 波特率:9600(LSPCLK = 37.5MHz) ; 
	SciaRegs.SCILBAUD = 487 & 0x00FF;
	SciaRegs.SCICTL2.bit.RXBKINTENA = 1;  // 使能SCI接收中断	 
	SciaRegs.SCIFFTX.all = 0xE060;	// bit 15 = 1 : 退出复位
									// bit 14 = 1 : 使能FIFO增强模式
									// bit 13 = 1 : 使能 TX FIFO操作
									// bit 6 = 1 :  CLR TXFFINT-标志
									// bit 5 = 1 :  使能TX FIFO匹配
									// bit 4-0 :    如果TX FIFO等于0, TX-ISR中断
	SciaRegs.SCIFFRX.all = 0xE065;	// Rx 中断级设置为5
	SciaRegs.SCICTL1.all =0x0023;	    // 使SCI退出复位   

}

//  Timer1中断服务程序
//
interrupt void T1_Compare_isr(void) 
{
  unsigned char index;
  unsigned char p2 = 0;
  unsigned char p3 = 0;

  // 检测步进速度改变标志
  if( change_rate_flag )
  {
    EvaRegs.T1CMPR = rate;
    change_rate_flag = 0;
  }

  //
  // 检查LED D1状态
  //
  if(GpioDataRegs.GPADAT. GPIOA4 & 1 )
  {
    GpioDataRegs.GPADAT. GPIOA4 =1;
  }

  // 检查LED D2状态
  //
  if(GpioDataRegs.GPBDAT. GPIOA4 & 1  )
  {
   GpioDataRegs.GPBDAT. GPIOA4 =1;
  }

  // 检查当前状态
  //
  switch( (state & 0x3) )
  {
    case 0x00:  // 全步,逆时针
      		index = stepIndex & 0x03;
      		p2 |= fullStepA[index];
      		p3 |= fullStepB[index];
      		GpioDataRegs.GPADAT. GPIOA2 = p2;
      		GpioDataRegs.GPADAT. GPIOA3 = p3;
      		++stepIndex;
      		break;
    case 0x01:  // 全步,顺时针
     		index = stepIndex & 0x03;
      		p3 |= fullStepA[index];
      		p2 |= fullStepB[index];
      		GpioDataRegs.GPADAT. GPIOA3 = p3;
      		GpioDataRegs.GPADAT. GPIOA2 = p2;
      		++stepIndex;
      		break;
    case 0x02:  // 半步,逆时针
      		index = stepIndex & 0x07;
      		p2 |= HalfStepA[index];
      		p3 |= CcwHalfStepB[index];
      		GpioDataRegs.GPADAT. GPIOA2 = p2;
      		GpioDataRegs.GPADAT. GPIOA3 = p3;
      		++stepIndex;
      		break;
    case 0x03:  // 半步,顺时针
      		index = stepIndex & 0x07;
      		p3 |= CwHalfStepB[index];
      		p2 |= HalfStepA[index];
      		GpioDataRegs.GPADAT. GPIOA3 = p3;
      		GpioDataRegs.GPADAT. GPIOA2 = p2;
      		++stepIndex;
      		break;
    default:
      _never_executed();
      break;
  };

  // 如果处于单步运行,禁止Timer 0中断
  if( state & MOTION_MASK )
  {
   	EvaRegs.T1CON.bit.TENABLE = 1;			// 使能 GP Timer 1    
  }
}

// 串口接收中断程序
//

interrupt void SCI_RX_isr(void)
{
	int i;
		UTXIFG0= SciaRegs.SCIRXBUF.all;
	 	
	SciaRegs.SCIFFRX.bit.RXFIFORESET = 0;	// 复位 FIFO指针  
	SciaRegs.SCIFFRX.bit.RXFIFORESET = 1;	// 使能操作
	SciaRegs.SCIFFRX.bit.RXFFINTCLR = 1;    // 清除FIFO INT中断标志
	PieCtrlRegs.PIEACK.all = 0x0100;        // 响应中断

  switch(U0RXBUF)
  {
  case 'D': // 方向(顺时针或逆时针)
  case 'd':
    toggle_direction();
    break;
  case 'C': // 运动(连续或单步)
  case 'c':
    toggle_motion();
    break;
  case 'M': // 步进模式(全步或半步)
  case 'm':
    toggle_stepping_mode();
    break;
  case 'F': // 提高速度
  case 'f':
    increase_stepping_rate();
    break;
  case 'S': // 降低速度
  case 's':
    decrease_stepping_rate();
    break;
  default:
    break;
  };

}

// 提高步进速度
void increase_stepping_rate(void)
{
  unsigned int new_rate;
// 检查是否工作在连续模式
  if( (state & MOTION_MASK) == 0 )
  {
    new_rate = rate >> 1;
    if( new_rate >= max_rate )
    {
      rate = new_rate;
      change_rate_flag = 1;
    }
  }
   // 复位定时器1比较中断标志
   EvaRegs.EVAIFRA.bit.T1CINT = 1;
   
   // 响应该中断并允许从组2中接收更多的中断
   PieCtrlRegs.PIEACK.all = PIEACK_GROUP2;
}

// 降低步进速度
void decrease_stepping_rate(void)
{
// 检查是否工作在连续模式
  if( (state & MOTION_MASK) == 0 )
  {
    if( rate <= (min_rate >> 1) )
    {
      rate <<= 1;
      change_rate_flag = 1;
    }
  }
   // 复位定时器1比较中断标志
   EvaRegs.EVAIFRA.bit.T1CINT = 1;
   
   // 响应该中断并允许从组2中接收更多的中断
   PieCtrlRegs.PIEACK.all = PIEACK_GROUP2;
}

// 全步或半步模式切换
//
void toggle_stepping_mode(void)
{
  // 切换步进模式状态
  state ^= STEP_MASK;

  // 检查是否工作在半步模式
  if( state & STEP_MASK )
  {
    // 从全步模式切换到半步模式
    // 改变定时器1中断周期为原2倍
    rate = (rate >> 1);
    change_rate_flag = 1;
    max_rate = (MAX_RATE >> 1);
    min_rate = (MIN_RATE >> 1);

    // Turn on LED D2
    P3OUT |= 0x08;
  }
  else // 全步模式
  {
    // 从半步模式切换到全步模式
    // 改变定时器1中断周期为原1/2倍
    rate = (rate << 1);
    change_rate_flag = 1;
    max_rate = MAX_RATE;
    min_rate = MIN_RATE;
    // 熄灭LED D2
   GpioDataRegs.GPBDAT. GPIOA4 = 0;
  }
}

// 连续模式和单步模式转换
void toggle_motion(void)
{
  state ^= MOTION_MASK;

  // 检查是否工作在连续工作状态
  if( (state & MOTION_MASK) == 0 )
  {
   // 复位定时器1比较中断标志
   EvaRegs.EVAIFRA.bit.T1CINT = 1;
      // 响应该中断并允许从组2中接收更多的中断
   PieCtrlRegs.PIEACK.all = PIEACK_GROUP2;
    // 熄灭LED D1
   GpioDataRegs.GPADAT. GPIOA4 = 0;
  }
  else
  {
    // 点亮 LED D1
    GpioDataRegs.GPADAT. GPIOA4 = 1;
  }
}

// 方向转换
void toggle_direction(void)
{
  state ^= DIR_MASK;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -