五、测试/调试及实验结果分析 实验结果: 实验现象观察,电机会进行正向旋转和反向旋转; 24BYJ48 步进电机简介: 步进电机是将电脉冲信号转变为角位移或线位移的开环控制元件。在非超载的情 况下,电机的转速、停止的位置只取决于脉冲信号的频率和脉冲数,而不受负载 变化的影响,即给电机加一个脉冲信号,电机则转过一个步距角。这一线性关系 的存在,加上步进电机只有周期性的误差而无累积误差等特点。使得在速度、位 置等控制领域用步进电机来控制变的非常的简单。为此,三兄弟开发板套件中首 次引入了步进电机技术,采用扩展的方式,方便用户应用掌握。 虽然步进电机已被广泛地应用,但步进电机并不能象普通的直流电机,交流 电机在常规下使用。它必须由双环形脉冲信号、功率驱动电路等组成控制系统方 可使用。因此用好步进电机却非易事,它涉及到机械、电机、电子及计算机等许 多专业知识。 步进电机的主要特性: 1、步进电机必须加驱动才可以运转, 驱动信号必须为脉冲信号,没有脉冲的 时候,步进电机静止, 如果加入适当的脉冲信号, 就会以一定的角度(称为步角)转 动。转动的速度和脉冲的频率成正比。 2、我们用的是28BYJ48 5V驱动的4相5线的步进电机,而且是减速步进电机,减速比为 1:64,步进角为5.625/64度。如果需要转动1圈,那么需要360/5.625*64=4096个脉冲信号。 3、步进电机具有瞬间启动和急速停止的优越特性。 4、改变脉冲的顺序,可以方便的改变转动的方向。 程序解析: main.c // ###########################################################################
#include "DSP28x_Project.h" // 设备头文件和示例包括文件
extern void Step_dianji_test(void);
extern void step_Gpio_select();
extern void Step_dianji_test2(void);
Uint16 Timer_1ms_flag;
Uint16 Timer_10ms_flag;
Uint16 Timer_100ms_flag;
Uint16 Buzzer_flag;
Uint16 Timer_10ms_Count;
Uint16 Timer_100ms_Count;
Uint32 Timer_1000ms_Count;
Uint32 Timer_5000ms_Count;
// 为了Buzzer_On1000ms()函数的可移植性,使用了宏定义。
// 蜂鸣器的接通与断开要参考实际驱动电路硬件,本次使用蜂鸣器驱动电路是低电平接通并工作
#define Buzzer_Pin_On GpioDataRegs.GPBDAT.bit.GPIO53 = 0 //打开蜂鸣器
#define Buzzer_Pin_Off GpioDataRegs.GPBDAT.bit.GPIO53 = 1 //关闭蜂鸣器
// 蜂鸣器响一秒钟触发条件
#define Buzzer_On1000ms_Trigger Buzzer_flag = 1 //蜂鸣器响一秒钟触发条件
// 函数初始化
void GPIO_Init(void);
void Buzzer_On1000ms(void);
// Prototype statements for functions found within this file.
__interrupt void cpu_timer0_isr(void);
__interrupt void cpu_timer1_isr(void);
__interrupt void cpu_timer2_isr(void);
void main(void)
{
// Step 1. 初始化系统控制:
// PLL, WatchDog, 启用外围时钟
InitSysCtrl();
//变量初始化
Timer_1ms_flag = 0;
Timer_10ms_flag = 0;
Timer_100ms_flag = 0;
Timer_10ms_Count = 0;
Timer_100ms_Count = 0;
Timer_1000ms_Count = 0;
Timer_5000ms_Count = 0;
Buzzer_flag = 0;
// Step 2. 初始化GPIO:
GPIO_Init();
step_Gpio_select();
// Step 3. 清除所有中断并初始化PIE向量表:
// 禁用CPU中断
DINT;
// 将PIE控制寄存器初始化为其默认状态.
// 默认状态是禁用所有PIE中断并清除标志
InitPieCtrl();
// 禁用CPU中断并清除所有CPU中断标志:
IER = 0x0000;
IFR = 0x0000;
// 用指向shell Interrupt的指针初始化PIE向量表
// 服务程序(ISR).
InitPieVectTable();
.
EALLOW;
// 这是写入EALLOW保护寄存器所必需的
PieVectTable.TINT0 = &cpu_timer0_isr;
PieVectTable.XINT13 = &cpu_timer1_isr;
PieVectTable.TINT2 = &cpu_timer2_isr;
EDIS;
// 这需要禁用对EALLOW保护寄存器的写操作
// Step 4. 初始化设备外设.
InitCpuTimers();
// 对于本例,只初始化Cpu计时器
#if (CPU_FRQ_150MHZ)
// 配置CPU-Timer 0、1、2分别为每1ms、1s、1s中断一次:
ConfigCpuTimer(&CpuTimer0, 150, 1000);
ConfigCpuTimer(&CpuTimer1, 150, 1000000);
ConfigCpuTimer(&CpuTimer2, 150, 1000000);
#endif
#if (CPU_FRQ_100MHZ)
// 配置CPU-Timer 0、1、2分别为每1ms、1s、1s中断一次:
ConfigCpuTimer(&CpuTimer0, 100, 1000);
ConfigCpuTimer(&CpuTimer1, 100, 1000000);
ConfigCpuTimer(&CpuTimer2, 100, 1000000);
#endif
// 为了确保精确的计时,请使用只写指令来写入整个寄存器。
CpuTimer0Regs.TCR.all = 0x4000;
// 使用只写指令设置TSS位 = 0
CpuTimer1Regs.TCR.all = 0x4000;
// 使用只写指令设置TSS位 = 0
CpuTimer2Regs.TCR.all = 0x4000;
// 使用只写指令设置TSS位 = 0
// Step 5. 用户特定代码,启用中断:
// 使能与CPU- timer 0相连的CPU int1、与CPU- timer 1相连的CPU int13和与CPU- timer 2相连的CPU int14:
IER |= M_INT1;
IER |= M_INT13;
IER |= M_INT14;
// 使能PIE: Group 1中断7中的TINT0
PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
// 启用全局中断和更高优先级的实时调试事件:
EINT;
// 启用全局中断INTM
ERTM;
// 启用全局实时中断DBGM
// Step 6. 空闲循环或用户代码:
while (1)
{
if (Timer_1ms_flag) //1ms进去执行一次
{
Timer_1ms_flag = 0;
Step_dianji_test2();
if (++Timer_10ms_Count >= 10)
{
Timer_10ms_Count = 0;
Timer_10ms_flag = 1;
}
}
if (Timer_10ms_flag) //10ms进去执行一次
{
Timer_10ms_flag = 0;
if (++Timer_100ms_Count >= 10)
{
Timer_100ms_Count = 0;
Timer_100ms_flag = 1;
}
}
if (Timer_100ms_flag) //100ms进去执行一次
{
Timer_100ms_flag = 0;
//Buzzer_On1000ms();
}
if (Timer_1000ms_Count >= 50) //500ms进去执行一次
{
Timer_1000ms_Count = 0;
//GpioDataRegs.GPATOGGLE.bit.GPIO0 = 1; //LED
}
if (Timer_5000ms_Count >= 5) //5000ms进去执行一次
{
Timer_5000ms_Count = 0;
//Buzzer_flag=1;
Buzzer_On1000ms_Trigger;
}
}
}
__interrupt void cpu_timer0_isr(void)
{
CpuTimer0.InterruptCount++;
Timer_1ms_flag = 1;
Timer_1000ms_Count++;
// 确认此中断以接收来自组1的更多中断
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}
__interrupt void cpu_timer1_isr(void)
{
CpuTimer1.InterruptCount++;
Timer_5000ms_Count++;
// CPU确认中断.
EDIS;
}
__interrupt void cpu_timer2_isr(void)
{
EALLOW;
CpuTimer2.InterruptCount++;
// CPU确认中断
EDIS;
}
Step_Motor.c
/*
* Step_Motor.c
*
* Created on: 2024年3月19日
* Author: yhr
*/
#include "DSP2833x_Device.h" // DSP2833x头文件
#include "DSP2833x_Examples.h" // DSP2833x示例包括文件
void step_Gpio_select(void);
unsigned char Step_table[] = {0x0004, 0x0008, 0x0010, 0x0020};
unsigned char Step_table1[] = {0x0020, 0x0010, 0x0008, 0x0004};
void Step_dianji_test(void);
void Step_dianji_test2(void);
// 初始化GPIO
void step_Gpio_select(void)
{
EALLOW;
GpioCtrlRegs.GPAMUX1.bit.GPIO2 = 0;
// All GPIO
GpioCtrlRegs.GPAMUX1.bit.GPIO3 = 0;
// All GPIO
GpioCtrlRegs.GPAMUX1.bit.GPIO4 = 0;
// All GPIO
GpioCtrlRegs.GPAMUX1.bit.GPIO5 = 0;
// All GPIO
GpioCtrlRegs.GPADIR.bit.GPIO2 = 1;
// All outputs
GpioCtrlRegs.GPADIR.bit.GPIO3 = 1;
// All outputs
GpioCtrlRegs.GPADIR.bit.GPIO4 = 1;
// All outputs
GpioCtrlRegs.GPADIR.bit.GPIO5 = 1;
// All outputs
//GPIO0-GPIO31输出低电平
GpioDataRegs.GPADAT.bit.GPIO2 = 0;
GpioDataRegs.GPADAT.bit.GPIO3 = 0;
GpioDataRegs.GPADAT.bit.GPIO4 = 0;
GpioDataRegs.GPADAT.bit.GPIO5 = 0;
EDIS;
}
void Step_dianji_test2(void)
{
static Uint16 j;
static Uint16 flag;
static Uint16 timer_Count;
if (++timer_Count >= 5)
{
timer_Count = 0;
if (j < 2048)
{
if (flag == 1)
//正转
{
// 以下两步操作为了除GPIO2-GPIO5之外的同组IO口操作不受影响
GpioDataRegs.GPADAT.all = GpioDataRegs.GPADAT.all & 0xffc3;
GPIO2-GPIO5全设置为零,清零操作
GpioDataRegs.GPADAT.all = GpioDataRegs.GPADAT.all | Step_table[j % 4];
//GPIO2-GPIO5依次输出高电平
}
else
//反转
{
// 以下两步操作为了除GPIO2-GPIO5之外的同组IO口操作不受影响
GpioDataRegs.GPADAT.all = GpioDataRegs.GPADAT.all & 0xffc3;
GPIO2-GPIO5全设置为零,清零操作
GpioDataRegs.GPADAT.all = GpioDataRegs.GPADAT.all | Step_table1[j % 4];
//GPIO2-GPIO5依次输出高电平
}
j++;
}
else
{
j = 0;
if (flag == 0)
{
flag = 1;
}
else
{
flag = 0;
}
}
}
} |