买了几个机器人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)