N76E003控制双路步进电机(开环)
2022-06-24 来源:eefocus
0、引言
实验材料
1、程序逻辑
1.1、程序采用PWM中断,实现对PWM脉冲计数,由此实现开环控制步进电机,设定为下降沿触发。
1.2、步进电机驱动器提供EN、Pulse、DIR、COM四个接口,其中COM接单片机的VCC,EN用于控制电机使能,DIR用于电机换向,Pulse为输入脉冲。
1.3、根据上述说明,单片机PWM持续产生脉冲,通过EN控制步进电机是否使能
1.4、流程图如下
2、程序代码
#include 'N76E003.h'
#include 'Common.h'
#include 'Delay.h'
#include 'SFR_Macro.h'
#include 'Function_define.h'
#define uint unsigned int
#define uchar unsigned char
uint time;//频率
uint temp[10];//存放输入捕获值
int i=0;
uint PWM_Value;//需要改变的占空比值
uchar UART0_RX_BUF[11];//串口0,串口1数据接收缓冲区
uchar UART0_RX_STA=0;//串口0,串口1接收计数器
uchar uFlag=0;//串口中断指令接收完成标志
char start=0;
//用于数据记录
uint ct1,ct2;
//脉冲期望值(0-6700)
uint evt1,evt2;
//状态机:
//0——初始状态
//1——串口
//2——运行到了指定距离。
uchar Flag1=0,Flag2=0;
//PWM中断计数器控制器
//0:关闭
//1:开启
char CEP1=0,CEP2=0;
//用于回到零点
sbit KEY1=P0^4;
sbit KEY2=P1^4;
//使能
sbit EN1=P1^0;
sbit EN2=P1^1;
//换向
sbit DIR1=P1^2;
sbit DIR2=P1^3;
//指示灯
sbit LED1=P0^5;
sbit LED2=P3^0;
void delay1(uint ms);
void PWM_DEAD_TIME_VALUE(UINT16 DeadTimeData);
/*
程序说明:
1、PWM一直保持输出,使用EN来控制步进电机输出
2、使用PWM中断,实现脉冲计数,设置为全局变量
3、串口接收数据,数据包见下'A1234B1234E'其中A为第一个步进电机、B为第二个,1234为期望脉冲数
4、程序流程:收到指令——》步进电机运动——》到指定位置,延时1S,返回0点——》等待下一次
Tips:程序仍存在问题:
1、在运行过程中不能二次接收数据(应对串口中断关闭,回到0点后再开启)
*/
void main (void)
{
//———————管脚配置 ——————————
Set_All_GPIO_Quasi_Mode;//所有IO设置为双向模式
P03_PushPull_Mode;
// P30_Input_Mode;//key1
EN1=0;EN2=0;//关闭步进电机
DIR1=0;DIR2=0;//向前方向
LED1=1;LED2=1;
Flag1=0;
Flag2=0;
CEP1=0;CEP2=0;
//----------串口0配置----------------
InitialUART0_Timer1(9600);
//在不配置SM1,SM2寄存器的情况下,默认工作在模式0(半双工)
RI=0;
TI=0;
Timer0_Delay1ms(100);
//—————1KHz的50%占空比——————————
PWM5_P03_OUTPUT_ENABLE;//使能PWM5,通过P03引脚输出
clr_PWMTYP;//边沿对齐模式
clr_PWMMOD0;//设置为独立输出模式
clr_PWMMOD1;
PWM_CLOCK_DIV_8;
PWMPH = 0x07;
PWMPL = 0xcf;
set_SFRPAGE;//PWM4 and PWM5 duty seting is in SFP page 1
PWM5H = 0x03;
PWM5L = 0xe8;
clr_SFRPAGE;
set_LOAD;//载入周期和占空比
set_PWMRUN;//开始输出PWM
//———————PWM配置————————————
EA=1;
set_EPWM;//使能pwm中断
// clr_EPWM;
PWM_INT_PWM5;//设定中断源为PWM5
PWM_FALLING_INT;//下降沿触发
Timer3_Delay100ms(1);
ES=1;//串口中断使能
//------------中断优先级---------------------
set_PSH;//设置串口0最高优先级:1
set_PS;//设置串口0最高优先级:1
clr_PPWMH;//设置PWM中断优先级低位:0
clr_PPWM;//设置PWM中断优先级低位:0
//---------输入你自己的代码-------------------
while(1)
{
//哪个电机先到,哪个先关闭使能
if(Flag2==2&&Flag1!=2)EN2=0;
if(Flag1==2&&Flag2!=2)EN1=0;
//两个电机均运行到指定位置,准备返航
if(!KEY1&&(Flag2==2&&Flag1==2))
{
LED2=0;//返航指示灯
CEP1=1;//重启PWM计数器
CEP2=1;//重启PWM计数器
EN1=1;//开始返航
EN2=1;//开始返航
Flag1=3;Flag2=3;
}
//初始化保持步进电机停车
if(Flag1==0){EN1=0;}
if(Flag2==0){EN2=0;}
if(!Flag1&&!Flag2)
{
LED1=1;
LED2=1;
}
//该状态为接收到指令,前向运动
if(Flag1==1&&Flag2==1)
{
LED1=0;//正向指示灯
EN1=1;//使能步进电机
EN2=1;
}
}
}
/****************串口0中断服务程序*****************/
void Uart0_test() interrupt 4
{
if(RI)//串口0接收中断标志(有数据时,硬件置1)
{
RI=0;//软件置0
TI=0;//同时打开,需要对TI也置低
UART0_RX_BUF[UART0_RX_STA]=SBUF;//从SBUF缓存中读取接收到的数据
UART0_RX_STA++ ; //计算接收长度
//进行数据校验,通过RX_BUF&RX_STA
if(UART0_RX_STA==11&&UART0_RX_BUF[10]==0X45)
{
if(UART0_RX_BUF[0]==0x41&&UART0_RX_BUF[5]==0x42)
{
//收到期望值
evt1=(UART0_RX_BUF[1]-48)*1000+(UART0_RX_BUF[2]-48)*100+(UART0_RX_BUF[3]-48)*10+(UART0_RX_BUF[4]-48);
evt2=(UART0_RX_BUF[6]-48)*1000+(UART0_RX_BUF[7]-48)*100+(UART0_RX_BUF[8]-48)*10+(UART0_RX_BUF[9]-48);
Send_Data_To_UART0(0x4f);
Send_Data_To_UART0(0x4b);
if(evt1>6700)evt1=6700;
if(evt2>6700)evt2=6700;
TI=0;
UART0_RX_STA=0;
Flag1=1;
Flag2=1;
ct1=0;
ct2=0;
DIR1=0;
DIR2=0;
CEP1=1;//开启计数器使能
CEP2=1;
EN1=1;//使能步进电机
EN2=1;
}
}
}
}
/****************PWM中断服务程序*****************/
void PWMISR() interrupt 13
{
if(PWMF)//检测到中断标志位
{
if(CEP1)
{
ct1++;
//检测是否达到指定位置
if(ct1>=evt1&&Flag1==1)//达到设定值,清空ct1,EN1=0;,正向移动
{
ct1=0;
EN1=0;//停止步进电机转动。
DIR1=1;//准备返航
Flag1=2;
CEP1=0;
}
//-----------------1号返航-------------------
if(ct1>=evt1&&Flag1==3)//回到零点
{
ct1=0;
EN1=0;//停止步进电机转动。
Flag1=0;
CEP1=0;
}
}
if(CEP2)
{
ct2++;
//检测是否达到指定位置
if(ct2>=evt2&&Flag2==1)
{
ct2=0;
EN2=0;//停止步进电机转动。
DIR2=1;//准备返航
Flag2=2;
CEP2=0;
}
//-----------------2号返航-------------------
if(ct2>=evt2&&Flag2==3)//回到零点
{
ct2=0;
EN2=0;//停止步进电机转动。
Flag2=0;
CEP2=0;
}
}
clr_PWMF;//清楚PWM中断标志位Timer0_Delay1ms(1)
}
}
上一篇:N76E003 避坑指南
下一篇:基于单片机的电机转速PID控制