200字范文,内容丰富有趣,生活中的好帮手!
200字范文 > 51单片机3个定时器驱动机器人PWM无刷直流电机进行编程运动 源程序

51单片机3个定时器驱动机器人PWM无刷直流电机进行编程运动 源程序

时间:2022-02-23 15:26:24

相关推荐

51单片机3个定时器驱动机器人PWM无刷直流电机进行编程运动 源程序

买了几个机器人PWM无刷直流电机,内部有驱动器,所有功能都可以单片编程IO口控制,弄了个简单程序先动行一下,有1602液晶显示器,可同时驱动4路PWM信号,用了3个定时器

制作出来的实物图如下:

单片机程序源码:

#include"reg52.h"

#define uint unsigned int

#define uchar unsigned char

//sfr T2MOD =0xC9;//定时器中断2TMOD必须定义

/*-----------------------PWM定义---------------------------*/

sbit RS = P2^6 ;

sbit RW = P2^5 ;

sbit EN = P2^7 ;

sbit STA7 = P0^7;

uchar PWM_T=0;//PWM脉冲周期PWM_T(max)=256*中断定时时间(1ms)

//PWM物理地址通道定义,物理地址根据需要自由定义

sbit PWM_IO0 = P1^0;//接电机NO.1

sbit PWM_IO1 = P1^1;//接电机NO.2

sbit PWM_IO2 = P1^2;//接电机NO.3

sbit PWM_IO3 = P1^3;//接电机NO.4

//PWM脉冲占空比

uint PWM_IO0_ZKB=20;//脉冲占空比,0~255,=0时输出最大

uint PWM_IO1_ZKB=20;

uint PWM_IO2_ZKB=20;

uint PWM_IO3_ZKB=20;

/*---------------------------------------------------------*/

sbit s0 = P3^6; //按s0减小占空比

sbit s1 = P3^7;//按s1增加占空比

sbit RL = P3^5;//按健 正反转

sbit RUN_STOP = P3^4;//按健启动与停止

sbit RL1 = P3^3;//输出 正反转

sbit RUN_STOP1 = P3^2;//输出 启动与停止

uint KG;//开关

uint FX;//方向

void Delay1ms(uint a)//@11.0592MHz

{

unsigned char i, j;

i = 2;

j = 199;

do

{

while (--j);

} while (--i);

}

/*---------------定时器2初始化-------------------*/

void timer2_init()//定时器2初始化

{

RCAP2H=0xff;//16位计数器,定时39us

RCAP2L=0xdc;//X=0xffdc=65500;T=(65536-X)*机器周期(11.0592MHz,1.085us)

//TH2=RCAP2H; //会自动重装

//TL2=RCAP2L;

T2CON=0;

T2MOD=0;

EA=1;

ET2=1;

TR2=1;

}

/*--------------定时器2中断服务程序----------------------------*/

void timer2() interrupt 5

{

TF2=0; //注意:定时器2必须由软件对溢出标志位清零,

//这里与定时器0和定时器1不同

//PWM处理

PWM_T++;

if(PWM_T == 255)//取到最大值

{PWM_T = PWM_IO0 = PWM_IO1 = PWM_IO2 = PWM_IO3 = 0;} //所有通道脉冲拉至低电平

//通道脉冲电平拉高

if(PWM_T == PWM_IO0_ZKB)//通道0脉冲得高电平

PWM_IO0 = 1;

if(PWM_T == PWM_IO1_ZKB)//通道1脉冲得高电平

PWM_IO1 = 1;

if(PWM_T == PWM_IO2_ZKB)//通道2脉冲得高电平

PWM_IO2 = 1;

if(PWM_T == PWM_IO3_ZKB)//通道3脉冲得高电平

PWM_IO3 = 1;

}

/**

* 等待繁忙标志

*/

void wait(void)

{

P0 = 0xFF;

do

{

RS = 0;

RW = 1;

EN = 0;

EN = 1;

}while (STA7 == 1);

EN = 0;

}

/**

* 写数据

*/

void w_dat(uint dat)

{

wait();

EN = 0;

P0 = dat;

RS = 1;

RW = 0;

EN = 1;

EN = 0;

}

/**

* 写命令

*/

void w_cmd(uint cmd)

{

wait();

EN = 0;

P0 = cmd;

RS = 0;

RW = 0;

EN = 1;

EN = 0;

}

/**

* 发送字符串到LCD

*/

void write_zfc(uchar *p)//定义一个带指针的函数?(字符串)

{

while(*p!=0)//不能用";"

w_dat(*p++);

}

/**

* 初始化1602

*/

void Init_LCD1602(void)

{

w_cmd(0x38);// 16*2显示,5*7点阵,8位数据接口

w_cmd(0x0C);// 显示器开、光标开、光标允许闪烁

w_cmd(0x06);// 文字不动,光标自动右移

w_cmd(0x01);// 清屏

}

void KEY()//

{

if(s0==0) //按s0减小占空比

{

while(!s0);//等待

{

PWM_IO0_ZKB = PWM_IO0_ZKB-1;

PWM_IO1_ZKB = PWM_IO1_ZKB-1;

PWM_IO2_ZKB = PWM_IO2_ZKB-1;

PWM_IO3_ZKB = PWM_IO3_ZKB-1;

}

if(PWM_IO0_ZKB<=20)PWM_IO0_ZKB=20;//太小不能启动

}

if(s1==0)//按s1增加占空比

{

while(!s1);//等待

{

PWM_IO0_ZKB = PWM_IO0_ZKB+1;

PWM_IO1_ZKB = PWM_IO1_ZKB+1;

PWM_IO2_ZKB = PWM_IO2_ZKB+1;

PWM_IO3_ZKB = PWM_IO3_ZKB+1;

}

if(PWM_IO0_ZKB>100)PWM_IO0_ZKB=100;//太大不能启动

}

if(RL==0)//按RL

{

Delay1ms(2);

if(RL==0)//按RL

while(!RL);//等待按健松手

RL1=~RL1;//取反(=1正转,=0反转)

}

if(RUN_STOP==0)//按启停

{

Delay1ms(2);

if(RUN_STOP==0)//按启停

while(!RUN_STOP);//等待按健松手

RUN_STOP1=~RUN_STOP1;//取反(=1启动,=0停止)

}

}

/*------------------------------------------------

定时器初始化子程序

------------------------------------------------*/

void Init_Timer1(void)

{

TMOD |= 0x10; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响

TH1=0x00; //给定初值,这里使用定时器最大值从0开始计数一直到65535溢出

TL1=0x00;

EA=1; //总中断打开

ET1=1; //定时器中断打开

TR1=1; //定时器开关打开

}

/*------------------------------------------------

定时器初始化子程序

------------------------------------------------*/

void Init_Timer0(void)

{

TMOD |= 0x01; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响

TH0=0x00; //给定初值,这里使用定时器最大值从0开始计数一直到65535溢出

TL0=0x00;

EA=1; //总中断打开

ET0=1; //定时器中断打开

TR0=1; //定时器开关打开

}

void PIAY(void)////显示运行状态

{

if(RUN_STOP1==1)

{

w_cmd(0xC0);//LCD1602显示地址为第一排第一个

write_zfc("RUN");

}

else

{

w_cmd(0xC0);//LCD1602显示地址为第一排第一个

write_zfc("OFF");

}

if(RL1==0)

{

w_cmd(0xC0+4);//LCD1602显示地址为第一排第一个

write_zfc("<<--");

}

else

{

w_cmd(0xC0+4);//LCD1602显示地址为第一排第一个

write_zfc("-->>");

}

}

/*------------主函数---------------*/

void main()

{

timer2_init();//定时器2初始化

Init_LCD1602(); //LCD1602初始化

Init_Timer0();//定时器0初始化

Init_Timer1();//定时器1初始化

RL1=1;//初始化=1,开机电机正转

RUN_STOP1=1;//初始化=1,开机电机转动

while(1)

{

KEY();//按健扫描

PIAY();//显示运行状态

w_cmd(0x80);//LCD1602显示地址为第一排第一个

write_zfc("PWM:");

//w_dat(PWM_IO0_ZKB/1000+0x30);

w_dat(PWM_IO0_ZKB%1000/100+0x30);

w_dat(PWM_IO0_ZKB%100/10+0x30);

w_dat(PWM_IO0_ZKB%10+0x30);

//write_zfc(" KHz");

w_cmd(0xc0+9);//LCD1602显示地址为第一排第一个

write_zfc("FX:");

//w_dat(PWM_IO0_ZKB/1000+0x30);

w_dat(FX%1000/100+0x30);

w_dat(FX%100/10+0x30);

w_dat(FX%10+0x30);

w_cmd(0x80+9);//LCD1602显示地址为第一排第一个

write_zfc("KG:");

//w_dat(PWM_IO0_ZKB/1000+0x30);

w_dat(KG%1000/100+0x30);

w_dat(KG%100/10+0x30);

w_dat(KG%10+0x30);

}

}

/*------------------------------------------------

定时器中断子程序

------------------------------------------------*/

void Timer1_isr(void) interrupt 3 using 1

{

TH1=0x00;//重新赋值

TL1=0x00;

FX++;//运行方向调节

if(FX>30)

{

FX=0;

//RUN_STOP1=~RUN_STOP1;//取反(=1启动,=0停止)

省去几多行…………

复制代码

全部资料51hei下载地址:

1602显并STC89机器人电机PWM控器OK3.zip(54.21 KB, 下载次数: 25)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。