标签:style blog http color strong 文件
——用程序来控制轮子
PWM控制电路完工了,接下来得把电路接到单片机,由单片机进行控制了。回想电路图:
这个图中,输入有3根组,A,B,C,其中,A入口,我们可以当成PWM控制线,B,C为正反转、停止控制线,整个状态可以罗列为下面表格:
A控制 | B控制 | C控制 | Q1 | Q2 | Q3 | Q4 | 电机状态 |
X | 0 | 0 | 0/导通 | 0/导通 | 0/截止 | 0/截止 | 刹车 |
PWM | 1 | 0 | 1/截止 | 0/导通 | PWM | 0/截止 | 正转 |
PWM | 0 | 1 | 0/导通 | 1/截止 | 0/截止 | PWM | 反转 |
0 | 1 | 1 | 1/截止 | 1/截止 | 0/截止 | 0/截止 | 惰行 |
1 | 1 | 1 | 1/截止 | 1/截止 | 1/导通 | 1/导通 | 刹车 |
?
为了方便代码管理,我们在工程中建一个car.c和car.h文件,专门编写控制小车的程序:
?
程序开始,引入相应头文件:
#include<reg52.h>
#include "common.h"
#include "car.h"
?
定义好PWM电路的接入引脚:
sbit Ctl_R1=P2^4; //右轮控制端1
sbit Ctl_R2=P2^5; //右轮控制端2
sbit PWM_R=P2^3; //右轮PWM端
?
sbit Ctl_L1=P2^2; //左轮控制端1
sbit Ctl_L2=P2^1; //左轮控制端2
sbit PWM_L=P2^0; //左轮PWM端
?
为了代码清楚,我们将car这个(对象),整成2个函数:
void InitCar()
{
}
?
void CarGo(int left,int right)
{
}
将两个函数的函数体写入到car.c中,将函数的定义,写入到car.h中。
两个函数分别意义为:InitCar为小车初使化,CarGo为小车控制,参数left、right分别代表左右轮,然后值为-100~100,当为0时,则停止,当为负数时,则反转,数值大小代表转动速度,值越大越快。
好了,测试工作总是逐步的,而不是一步到位,我们先来试一下基本的正反转及停,调速的后面再来。
void InitCar()
{
CarGo(0,0);
PWM_R = 1;
PWM_L = 1;
}
void CarGo(int left,int right)
{
if ( right >0)
{
Ctl_R1=0;
Ctl_R2=1;
}
else if (right ==0)
{
Ctl_R1=0;
Ctl_R2=0;
}
else if (right<0)
{
Ctl_R1=1;
Ctl_R2=0;
}
?
if ( left >0)
{
Ctl_L1=0;
Ctl_L2=1;
}
else if (left ==0)
{
Ctl_L1=0;
Ctl_L2=0;
}
else if (left<0)
{
Ctl_L1=1;
Ctl_L2=0;
}
}
好了,简单的程序,应该很容易能看懂,测试么,得写个main函数咯。
#include "car.h"
#include "common.h"
?
void main()
{
//小车初使化
InitCar();
CarGo(100,0);
Delay(2000);
CarGo(0,100);
Delay(2000);
CarGo(-100,0);
Delay(2000);
CarGo(0,-100);
Delay(2000);
CarGo(0,0);
}
经常会用到一些通用函数,如里面的delay之类的,所以我们又建一个common.c和common.h文件,将一些通用的方法写入,比如这里的:
/*****************************************************
* 函数功能:延时若干毫秒
* 入口参数:n
***************************************************/
void Delay(unsigned int i)
{
unsigned int j;
for(;i>0;i--) //变量i由实际参数传入一个值,因此i不能赋初值
for(j=0;j<125;j++)
{;}
}
?
整个程序也容易看清的,每隔2秒后,可以看到电机会变换一个状态。将程序烧写到单片机中,运行,观察吧。
如果发现状态不对,那就得debug了。
?
一切调通后,就剩下PWM了,上一章中,我们知道速度通过占空比来实现的。
换句话说,我们要针对PWM引脚要连续的输出0和1变换值。所以这里我们得引入单片的计数器和中断。
TH0和TL0是计数器0的高8位和低8位计数器,计算办法:TL0=(65536-C)%256;TH0=(65536-C)/256,其中C为所要计数的次数即多长时间产生一次中断;TMOD是计数器工作模式选择,0X01表示选用模式1,它有16位计数器,最大计数脉冲为65536,最长时间为1ms*65536=65.536ms
#define V_TH0 0XFE
#define V_TL0 0XF6
#define V_TMOD 0X01
unsigned char ZKB1,ZKB2;
void InitCar()
{
CarGo(0,0);
?
/*定时器初始化 */
TMOD=V_TMOD;
TH0=V_TH0;
TL0=V_TL0;
TR0=1;
ET0=1;
EA=1;
?
ZKB1 = 0;
ZKB2 = 0;
}
?
?
/*中断函数 */
void timer0(void) interrupt 1 using 2
{
static uchar click=0; //中断次数计数器变量
TH0=V_TH0; //恢复定时器初始值
TL0=V_TL0;
++click;
if (click>=100)
click=0;
?
if (click<=ZKB1) //当小于占空比值时输出低电平,高于时是高电平,从而实现占空比的调整
PWM_R=0;
else
PWM_R=1;
?
if (click<=ZKB2) //当小于占空比值时输出低电平,高于时是高电平,从而实现占空比的调整
PWM_L=0;
else
PWM_L=1;
}
?
说明:iitcar中对定时器进行初使化。timer0函数中不对的计数,当click计值到ZKB1时,把PWM值反转一下。这个ZKB1在就是在CarGo中赋值的left,right值的绝对值。
OK,到此,这个Car.c文件,就可以收功了,后面只需要调用一下这里面的函数,就可以相应的来控制小车的电机了。
?
?
标签:style blog http color strong 文件
原文地址:http://www.cnblogs.com/zjfstudio/p/3841616.html