📄 zong.c
字号:
#include <AT89X52.h>
#define fosc 6
#define time0 4150 //定时器0定时规则,定时长度为time0*2.5us.理论上应该是:定时长度=65536-time0*fosc/12(us)
#define uchar unsigned char
//在此程序内将一直进行键盘扫描、中断、显示、按命令进行相应电机的控制与测速
void work(void);
//获得键码,注意返回的键码是八位,其中高四位中哪一位为1表示该列的键按下
//同理低四位表示行,通过行与列确定哪个键按下
uchar getchar(void);
//键盘扫描程序,程序负责对有没有按键的判断,如果有将调用上程序判断是哪个键按下,并得到相应的键值(字母)
uchar scankey(void);
//延时程序
void delay(int t);
//输出PWM波的初始化程序
void PWM(void);
//控制电机正转程序
void zhengzhuan(void);
//控制电机反转程序
void fanzhuan(void);
//控制电机加速程序
void jiasu(void);
//控制电机减速程序
void jiansu(void);
//控制电机停止程序
void stop(void);
uchar out[4]; //该变量负责保存要输出的四位数的每个位上的数值
unsigned int count; //保存计算转速的变量
uchar roop = 100; //该变量将与定时器0的中断控制每次计算转速的时间周期
unsigned int t; //计算中断时间的中间变量
unsigned int t2; //计算中断时间的中间变量
//uchar p2; //
int c_out = 0; //用于保存要输出的转速的值
uchar sellect[4]={1,2,4,8}; //数码管的选通信号
int led_n; //数码管编号
unsigned int time3 = 1500; //产生PWM定时特点,定时长度为time3*2us
unsigned int time4 = 3500; //用于产生PWM0。--注:这样的数据定时的PWM波的频率是100Hz
uchar t2_1; //以下四个定时用的中间变量
uchar t2_0;
uchar t0_1;
uchar t0_0;
bit flag = 1; //用于判断PWM是处于1还是0
sbit p20 = P2^0; //以下四个是与四个端口关联的变量
sbit p21 = P2^1;
sbit p22 = P2^2;
sbit p23 = P2^3;
//延时,可以通过参数t改变延时的时间长度
void delay(int t)
{
int i;
while(t--)
{
for(i=0;i<62;i++);
}
}
//PWM波的初始化程序,主要是进行定时器2的定时时间的初始化
void PWM(void)
{
p20 = 1; //p20口输出PWM波,初始时输出高电平,且标志flag为1,表时现在输出的是高电平
flag = 1;
t2 = 65536 - time3;
t2_1 = t2 / 256 - 1;
t2_0 = t2 % 256;
T2CON = 0x01; //选择16位捕获模式,exen2为0,作为普通定时器使用
T2MOD = 0x00;
TH2 = t2_1;
TL2 = t2_0;
ET2 = 1;
EA = 1;
TR2 = 1;
}
void work()
{
uchar key;
int temp[4];
uchar s = 0;
key = scankey();//进行键盘扫描,当按下A键时系统启动,相当于开关
if(key=='A')
{
//中断与定时器初始化
IT0 = 1; //外部中断使用下降沿方式
EX0 = 1;
t = 65536 - time0 * fosc /12;
t0_1 = t / 256 - 1;
t0_0 = t % 256;
TMOD = 0x01;
TH0 = t0_1; //定时器0用于记录转速,定时10ms
TL0 = t0_0;
EA = 1;
ET0 = 1;
TR0 = 1;
led_n = 0;//初始时选通第一个LED
while(1) //死循环,让系统一直处于工作状态
{
if(!roop)//1s记录一次转速
{
p23 = !p23;
temp[s] = count;//临时变量用于记录上一个记速周期内的转速值
s++;//用于数字滤波
if(s == 4)//当S为4,即到了4秒时,输出经过求平均的转速
{
c_out = (temp[0] + temp[1] + temp[2] + temp[3]) / 4;//求平均
s = 0;
}
out[0] = (c_out / 1000);//取出千位数
out[1] = ((c_out % 1000) / 100);//取出百位数
out[2] = ((c_out % 100) / 10);//取出十位数
out[3] = (c_out % 10);//取出个数数
count = 0;//转速计数清0
roop = 100;//进入下一个计时
}
key = scankey();//扫描控制信息
switch(key)
{
case 'C'://C为电机正转控制键
zhengzhuan();
break;
case 'D'://D为电机反转控制键
fanzhuan();
break;
case 'E'://E为电机加速控制键
jiasu();
break;
case 'F'://F为电机减速控制键
jiansu();
break;
case 'B'://B为电机停止控制键
stop();
break;
default:
break;
}
}
}
}
//关于正转与反转,要与连线结合。实现这些功能要输出三组信号
//一个是全能信号,由p20口输出,这个使能信号是个PWM信号,这样就可通过控制PWM占空比实现调速
//p21,p22口输出正转与反转的控制信号,与电机控制芯片L298的两个对应的控制入口相连
void zhengzhuan(void)
{
p20 = 1;
p21 = 1;
p22 = 0;
flag = 1;
PWM();
}
void fanzhuan(void)
{
p20 = 1;
p21 = 0;
p22 = 1;
flag = 1;
PWM();
}
//加速与减速是通过改变输出高电平与低电平的时间长度来达到改变占空比的目的
void jiasu(void)
{
if(time3 < 4500)
{
time3 = time3 + 500;
delay(50); //为了解决不会一下加到最大的问题,在每次加速后加一个延时,减速同理
PWM();
}
if(time4 > 500)
{
time4 = time4 - 500;
delay(50);
PWM();
}
}
void jiansu(void)
{
if(time3 > 500)
{
time3 = time3 -500;
delay(50);
PWM();
}
if(time4 < 4500)
{
time4 = time4 + 500;
delay(50);
PWM();
}
}
//电机停止,控制电机的信号全清0,同时PWM的占空比调整为初始值
void stop(void)
{
P2 = 0x00;
time3 = 1500;
time4 = 3500;
}
uchar getkey()
{
uchar scancode, tmpcode;
if((P1 & 0xf0) == 0xf0)
return 0;
scancode = 0xfe;//行扫描码
while((scancode & 0x10) != 0)
{
P1 = scancode;
if((P1 & 0xf0) != 0xf0)
{
tmpcode = (P1 & 0xf0) | 0x0f;
return ((~scancode) + (~tmpcode));//列码+行码=键植(键值形式:高4位行码,低4位列码,哪一位为1说明该行/列按下
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -