单片机型号stc15w201s
42步进电机,tb6600驱动器,步距角1.8,细分3200,单片机与pwm方波为共同电路的。
脚位介绍:
①、p1.1脚和p1.2脚为读取解析pwm方波的。
②、p1.4脚给步进电机驱动器脉冲。
③、p3.7脚给步进电机驱动器方向。
④、p1.0脚led等,当有动作运行led闪烁,平时常亮。
总结:p1.1或1.2脚读取到pwm,p1.4和3.7脚给驱动器脉冲方向(正转或反转),p1.0的led灯闪烁。另外步进电机的旋转快慢是依照pwm占空比的。
求写pwm控制步进电机运行代码
- 写回答
- 好问题 0 提建议
- 追加酬金
- 关注问题
- 邀请回答
-
3条回答 默认 最新
- weixin_40681229 2022-09-29 15:46关注
#include <STC15.H>
/**********************************************************************************
*通过阅读tb6600驱动器资料:tb6600只需要脉冲输出与控制方向。
*tb6600驱动器的电流是由驱动器上的拔动开关控制的,不需要PWM控制电流。*不知道你为什么要用两个IO口来检测PWM的状态
*你是想一个开上升沿中断检测?
*一个开下降沿中断检测?
*本程序只用了一个IO口检测。实时检测上下沿变化,再取计时器中的时间判断
***********************************************************************************/
//定义端口
#define pwmOut P14 //PWM的输出
#define pwmDir P37 //PWM的方向//一个IO来解析PWM,然后用LED体现出来
#define scanpwm P11 //解析PWM
//#define scanpwmL P12 //解析PWM#define key P12 //一个按键,用来触发步进电机动作 默认高电平,按下低电平
//因为使用了步进电机驱动器,控制器通过拔码开关的方式调整电流,
//PWM的占空比是用来调整电流的,在这里对驱动步进电机没有意义了而,
//PWM的占空比设置个50%就可以了 pwmPeriod /2;
//定时器是0.1MS的中断,pwmPeriod = 20就是2MS一个周期,500HZ,满足低于1KHZ的要求。
//通过更改pwmPeriod,可以实现脉冲频率的变化,会改变步进电机的速度
//pwmPeriodH < pwmPeriod
#define pwmPeriod 20 //PWM的总时长 = 20*0.1=2ms 可以根据实际需求改小改大
#define pwmPeriodH 10 //PWM的高电平时长 = 10 *0.1=1ms//LED
#define ledtDisplayTime 3000 //LED显示时间
#define ledOn P10 = 0 //定义这个是为了方便修改LED亮/灭对应的电平
#define ledOff P10 = 1//***********************************************************************************************************定义变量
//1,步进电机
unsigned int turns_TO_Impulse; //步进电机的圈数转脉冲数
unsigned int turns_TO_ImpulseH; //步进电机的圈数转脉冲数 整数部分
unsigned int turns_TO_ImpulseL; //步进电机的圈数转脉冲数 整数部分
unsigned int scanTurns_TO_Impulse; //步进电机的圈数转脉冲数的自计算bit pwmOutEnable = 0; //使能PWM输出
unsigned char pwmTime; //PWM的电平翻转时间计时
unsigned char pwmOutStep; //PWM输出步骤//2,检测步进电机
unsigned int scanpwmtime; //检测步进电机的计时
unsigned int scanpwmtimeH; //PWM的高电平计时 = *0.1ms
unsigned int scanpwmtimeL; //PWM的低电平计时 两者相差等于或约等于PWM的总时间
unsigned char scanPwmStep; //检测PWM的步骤//3,LED
unsigned int ledtime; //LED闪烁计时
bit ledTwinkleEnable = 0; //LED闪使能
unsigned char ledStep; //LED输出步骤
//**************************************************************************************************************结束定义变量//************************************************************************************************************程序
//一些IO口的初始化
void GpioInit(void)
{
ledOff; //LED端口的输出接个电阻,LED,接上拉电源
pwmOut = 0; //默认输出低电平---检测端口初始也应该是低电平
pwmDir = 0; //视情况而定
}//开一个定时器中断
void Timer0Init(void) //100微秒@12.000MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x50; //设置定时初始值
TH0 = 0xFB; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时IE = 0X82; //开启定时器中断
}
//PWM输出程序
//输出脉冲 turns_TO_Impulse
void PwmOut(void)
{
if(pwmOutEnable == 0) //如果没有使能PWM脉冲输出
return;
switch(pwmOutStep)
{
case 0: //PWM输出高电平
pwmTime = 0; //清计时
pwmOut = 1; //PWM输出高电平
pwmOutStep = 1; //跳到下一步执行
break;
case 1: //PWM输出低电平
if(pwmTime >= (pwmPeriodH))
{
pwmTime = 0;
pwmOut = 0;
pwmOutStep = 2;
}
break;
case 2: //PWM输出低电平结束
if(pwmTime >= (pwmPeriod-pwmPeriodH))
{
pwmTime = 0; //清计时
pwmOut = 1; //PWM输出高电平
pwmOutStep = 1; //跳到下一步执行--------------视圈数到否?是否关闭了使能?
scanTurns_TO_Impulse++; //脉冲计数
if(scanTurns_TO_Impulse >= turns_TO_Impulse) //达到脉冲计数值后,关闭PWM输出
{
pwmOutEnable = 0;
}
}
break;
default:
pwmOutEnable = 0;
break;
}
}//步进电机驱动-----这个程序在你需要步进电机转动时,再调用
//dir 方向:取值为1或0
//turnsNumbers 转数:有2种表达方式
// 1,角度值 例如:720度, 900度,等等 1圈 = 360度
// 2,圈数 例如:2圈, 2.5圈,等等
//mode 0 = 角度值算法 1 = 圈数算法
void motor_Drive(bit dir,double turnsNumbers,bit mode)
{
unsigned int turns_TO_Impulse; //步进电机的圈数转脉冲数
unsigned int turns_TO_ImpulseH; //步进电机的圈数转脉冲数 整数部分
unsigned int turns_TO_ImpulseL; //步进电机的圈数转脉冲数 整数部分
//步进电机的方向
pwmDir = dir; //根据实际情况代入1或0//计算步进电机的圈数 //0.1125 = 1.8/16 = 360/3200 一个脉冲的度数 if(mode == 0)//度数 { turns_TO_Impulse = (unsigned int)(turnsNumbers/0.1125); } else//圈数 { turns_TO_ImpulseH = (unsigned int) turnsNumbers; //取出整数部分 turns_TO_ImpulseH *= 3200; //得到整数部分的脉冲数 turns_TO_ImpulseL = (unsigned int) (turnsNumbers*10000);//将小数*10000,移到整数 turns_TO_ImpulseL %= 10000;//取出小数 turns_TO_ImpulseL = turns_TO_ImpulseL/1152; //得到小数部分的脉冲数 0.1125 = 1.8/16 = 360/3200 turns_TO_Impulse = turns_TO_ImpulseH + turns_TO_ImpulseL; } //使能步进电机的输出 pwmOutStep = 0; pwmOutEnable = 1;
}
//检测PWM是否工作--------------------------------------------------------------------------------------------------------------------------
//PWM的初始状态是0 当检测到1时,视为PWM开始
//PWM结束输出时,PWM的输出电平是低电平
//scanpwmtimeH PWM的高电平计时 通过这两个变量,可以得到PWM的占空比(程序开头已说明,无需要PWM驱动)
//scanpwmtimeL PWM的低电平计时
void scanPWM(void)
{
switch(scanPwmStep)
{
case 0://检测是否有高电平产生
if(scanpwm == 1)
{
scanpwmtime = 0;
scanPwmStep = 1;
}
break;
case 1://检测是否有低电平产生
if(scanpwm == 0)
{
scanpwmtimeH = scanpwmtime; //获取高电平的时间 高电平时间与低电平时间,要相互印证。比如说一直高,一直低
scanpwmtime = 0;
scanPwmStep = 2;
}if(scanpwmtime > pwmPeriod*2) //当高电平持续过长/异常(未接到PWM) { scanPwmStep = 0; //如果电平一直为高,会造成0-1之间的循环,不影响LED灯的状态 ledTwinkleEnable = 0; //关闭LED闪功能 scanpwmtimeH = 0; //异常时清除PWM高低电平的计时 scanpwmtimeL = 0; } break; case 2://检测是否有高电平产生 if(scanpwm == 1) { scanpwmtimeL = scanpwmtime; //获取高电平的时间 scanpwmtime = 0; scanPwmStep = 1; // 高低电平的时间总长 > PWM总周期的一半 高低电平的时间总长 < PWM总周期的1.5倍 if(((scanpwmtimeL+scanpwmtimeH)> (pwmPeriod/2)) &&((scanpwmtimeL+scanpwmtimeH) < (pwmPeriod/2 + pwmPeriod)))//判断一下高低电平时间是否符合PWM的设定 { ledStep = 0; ledTwinkleEnable = 1; //使能LED闪功能 } } if(scanpwmtime > pwmPeriod*2) //当低电平持续过长说明PWM结束 { scanPwmStep = 0; ledTwinkleEnable = 0; //关闭LED闪功能 scanpwmtimeH = 0; //异常时清除PWM高低电平的计时 scanpwmtimeL = 0; } break; }
}
//LED输出------------------------------------------------------------------------------------------------------------------------------------
void ledOut(void)
{
if(ledTwinkleEnable == 0) //这个使能由检测来决定
{
ledOn;
return;
}switch(ledStep) { case 0://LED灭 ledOff; ledtime = 0; //清计时 = 0 ledStep = 1; //跳到下一步执行 break; case 1://LED亮 if(ledtime >= ledtDisplayTime) { ledOn; ledtime = 0; ledStep = 2; //跳到下一步执行 } break; case 2://LED灭 if(ledtime >= ledtDisplayTime) { ledOff; ledtime = 0; //清计时 = 0 ledStep = 1; //跳到下一步执行 视是否关闭了使能? } break; }
}
//一个简单的按键程序,用来调用步进电机的动作
//根据实际情况,按键的脚位调整位置
//按下去后,按键上的电平为0
void scanKey(void)
{if(key == 1) return; if(key == 0) { unsigned int a,b; //一段延时后动作,如果觉得按键后很久才动作,改小1000的值 //未做消抖处理,按下后速度松开 for(a = 0; a < 1000;a++) for(b = 0; b <100;b++); // 方向 转数 转数的模式 //motor_Drive(bit dir,double turnsNumbers,bit mode); //motor_Drive(0,2.5,1); //向一个方向转900度 motor_Drive(1,900,0); //向反方向转900度 }
}
//主程序------------------------------------------------------------------------------------------------------------------------------------------
//scanKey();//检测按键 一定要加一个按键,否则电机不会动作
void main(void)
{
//初始华
GpioInit();
Timer0Init();//主程序 while(1) { scanKey();//检测按键 一定要加一个按键,否则电机不会动作 PwmOut();//脉冲输出 scanPWM();//检测是否有PWM输出 ledOut();//灯输出 }
}
//定时器中断-------------------------------------------------------------------------------------------------------------------------------------------
void timer0_int (void) interrupt 1
{
//PWM电平计时变量
pwmTime++;//检测PWM的输出电平的计时变量 scanpwmtime++; //LED灯亮/灭的间隔时间 ledtime++;
}
本回答被题主选为最佳回答 , 对您是否有帮助呢?解决 无用评论 打赏 举报
悬赏问题
- ¥15 fluent里模拟降膜反应的UDF编写
- ¥15 MYSQL 多表拼接link
- ¥15 关于某款2.13寸墨水屏的问题
- ¥15 obsidian的中文层级自动编号
- ¥15 同一个网口一个电脑连接有网,另一个电脑连接没网
- ¥15 神经网络模型一直不能上GPU
- ¥15 pyqt怎么把滑块和输入框相互绑定,求解决!
- ¥20 wpf datagrid单元闪烁效果失灵
- ¥15 券商软件上市公司信息获取问题
- ¥100 ensp启动设备蓝屏,代码clock_watchdog_timeout