刚弄的遥控控制电机转速(包括转向和速度),红外对管检测速度,用的是数脉冲的办法,led1602显示转速。(码盘20个齿),测量时候数值变化很大,超乎想象,还望高手指导!:handshake
/********************************包含头文件**************************/
#include<reg52.h> //52系列寄存器
#include<intrins.h> //包含内部函数头文件
/*******************************宏定义*******************************/
#define uchar unsigned char
#define uint unsigned int
#define K 1.0 //转速校准参数
char code reserve[3]_at_ 0x3b; //仿真器预留空间
/******************************IR1838 端口定义***********************/
sbit IR = P3^2;
/*************************L298 端口定义******************************/
//使能端为1时允许对电机的控制;控制端为不同值时电机转动
sbit motor_1 = P1^0; //电机1使能端
sbit input_1 = P1^1; //电机1控制端1
sbit input_2 = P1^2; //电机1控制端2
sbit motor_2 = P1^3; //电机2使能端
sbit input_3 = P1^4; //电机2控制端1
sbit input_4 = P1^5; //电机2控制端2
/*******************************标志位*******************************/
bit IR1838_Receiving_Ok; //开始红外接收
bit IR1838_Receive_Ok; //红外接收完毕
bit IR1838_Process_Ok; //红外数据处理完毕
bit caculate_flag;
/***************************1602显示器端口***************************/
sbit rs=P2^7; //数据命令控制端
sbit rw = P2^6; //读写控制端
sbit lcden=P2^5; //led使能端
/********************************变量声明****************************/
uchar IR_Byte[4]; //存放4byte的遥控接收信息,包括2byte用户码,1byte的数据码,1byte的数据反码
uchar IR1838_Count; //定时器0每0.277ms加一变量
uint Motor_Count; //pwm周期
uint count;
uint speed;
uchar mode; //电机模式
uchar Moter_Speed_Referance; //电机参考转速,改变其值大小实现不同脉宽调制
uchar i; //33bit遥控数据组下标
uchar IR_Data[33]; //33bit遥控数据
uchar code table[]=" hello lazy";
uchar code table1[]=" speed:";
/********************************函数声明***************************/
void delay_1ms(uchar prm); //1ms延时函数
void Variable_Init(void); //变量初始化
void Motor_Time0_Init(void); //定时器0初始化
void Motor_Stop(void); //电机停止
void Motor_Forward(void); //电机正传
void Motor_Reverse(void); //电机反转
void Motor_PWM_Out(void); //pwm调制
void Motor_Ctrol(void); //电机主控
void Caculate_Speed(void); //计算转速
void IR1838_Int0_Init(void); //中断0初始化
void IR1838_Process_Byte(void); //遥控字节数据处理
//名称:变量初始化
//参数: 无
//返回值: 无
//功能: 在进入主循环前初始化变量
void Variable_Init(void)
{
mode = 0;
Moter_Speed_Referance = 25;
IR1838_Count = 0;
IR1838_Receive_Ok = 0;
IR1838_Process_Ok = 0;
}
//定时器初始化
//参数: 无
//返回值: 无
//功能:初始化定时器1为16位计数器,定时器0为八位自动重装定时器
void Time_Init(void)
{
TMOD |= 0x52; //定时器0工作在模式3八位自动重装,定时器工作模式2十六位计数器
TH0 = 0;
TL0 = 0;
EA = 1; //开总中断
ET0 = 1; //开定时器0中断
ET1 = 1; //开定时器1中断
TR0 = 1; //开始计时
TR1 = 1; //开始计数
}
//名称: 定时器中断服务、
//参数: 无
//返回值: 无
//功能: 此函数每(12/11.0592)*255= 0.277ms中断一次,Pwm输出更新一次
// motor_count加一,用来标记遥控脉冲时间
// 转速计算周期为3610*0.277=100ms
void Motor_Timer0_Serv(void) interrupt 1 using 0
{
Motor_PWM_Out();
Motor_Count ++;
if(Motor_Count >= 50) Motor_Count = 0;
IR1838_Count ++;
count ++;
if(count == 3610) //1S
{
count =0;
caculate_flag = 1;
}
}
//名称: pwm调制
//参数: 无
//返回值: 无
//功能: 实现对电机转速的调节
void Motor_PWM_Out(void)
{
if(Motor_Count < Moter_Speed_Referance) motor_1 = 1;
else motor_1 = 0;
}
//名称: 电机停止
//参数: 无
//返回值: 无
//功能: 电机停止
void Motor_Stop(void)
{
input_1 = 0;
input_2 = 0;
}
//名称: 电机正转
//参数: 无
//返回值: 无
//功能: 电机正转
void Motor_Forward(void)
{
input_1 = 0;
input_2 = 1;
}
//名称: 电机反转
//参数: 无
//返回值: 无
//功能: 电机反转
void Motor_Reverse(void)
{
input_1 = 1;
input_2 = 0;
}
//名称: 计算转速
//参数:无
//返回值: 无
//功能: 读取计时器1计算转速
void Caculate_Speed(void)
{
if(caculate_flag)
{
caculate_flag = 0;
speed = (TH1 * 256 + TL1)*3;
TH1 = 0;
TL1 = 0;
}
}
//名称:延时
//参数:prm * 1ms
//返回值: 无
//功能: 延时
void delay_1ms(uchar prm)
{
uint a;
for(; prm > 0; prm --)
{
for(a = 102; a > 0; a --)
_nop_();
}
}
//名称:外部中断初始化
//参数:无
//返回值: 无
//功能: 初始化外部中断
void IR1838_Extn_Init(void)
{
IT0 = 1;
EA = 1;
EX0 = 1;
}
//名称:外部中断0服务
//参数:无
//返回值: 无
//功能: 处理遥控信息
void IR1838_Extn_Serv(void) interrupt 0
{
if(IR1838_Receiving_Ok)
{
if(IR1838_Count > 32) //检测到引导码
{
i = 0;
}
IR_Data = IR1838_Count; //保存计时时间
i ++;
IR1838_Count =0;
if(i == 33)
{
i = 0;
IR1838_Receive_Ok = 1; //接收完毕
}
}
else
{
IR1838_Count = 0;
IR1838_Receiving_Ok = 1; //开始有效数据接收
}
}
//名称:处理接收数据
//参数:无
//返回值: 无
//功能: 将32bit遥控数据处理为4Byte二进制数据
void IR1838_Process_Byte(void)
{
uchar i,j,k,value;
k = 1;
for(j = 0; j < 4; j++)
{
for(i = 0; i < 8; i ++,k++)
{
value =value>>1;
if(IR_Data[k] > 6)
{
value |= 0x80;
}
}
IR_Byte[j] = value;
}
IR1838_Process_Ok = 1;
}
//名称:led写命令
//参数:所写命令
//返回值: 无
//功能: 写入led控制信息
void Write_Command(uchar com)
{
rs=0;
lcden=0;
rw = 0;
P0=com;
delay_1ms(1);
lcden=1;
delay_1ms(1);
lcden=0;
}
//名称:led写数据
//参数:所写数据
//返回值: 无
//功能: 写入led数据
void Write_Date(uchar date)
{
rs=1;
rw = 0;
lcden=0;
P0=date;
delay_1ms(1);
lcden=1;
delay_1ms(1);
lcden=0;
}
//名称:led初始化
//参数:无
//返回值: 无
//功能: 初始化led
void Led1602_Init()
{
uchar num;
lcden=0;
Write_Command(0x38); //两行显示 八位数据
Write_Command(0x0c); //开显示
Write_Command(0x06); //AC自增 画面不动
Write_Command(0x01); //清屏
Write_Command(0x80); //首行显示
for(num=0;num<7;num++)
{
Write_Date(table[num]);
delay_1ms(2);
}
Write_Command(0x80+0x40);
for(num=0;num<7;num++)
{
Write_Date(table1[num]);
delay_1ms(2);
}
}
//名称:显示转速
//参数:显示地址,显示数据
//返回值: 无
//功能: 将转速处理为led可显示数据,送到特定位置显示
void Write_Speed(uchar add,uint date)
{
uchar qian,bai,shi,ge;
qian = date / 1000;
bai=date % 1000 / 100;
shi = date % 100/10;
ge=date % 10;
Write_Command(0x80+0X40+add);
Write_Date(0x30+qian);
Write_Date(0x30+bai);
Write_Date(0x30+shi);
Write_Date(0x30+ge);
}
//名称:电机主控
//参数:无
//返回值: 无
//功能: 将遥控与电机结合,实现对电机的控制
void Motor_Ctrol(void)
{
if(IR1838_Receive_Ok)
{
IR1838_Receive_Ok = 0;
IR1838_Process_Byte();
}
if(IR1838_Process_Ok)
{
IR1838_Process_Ok = 0;
switch(IR_Byte[3])
{
case 0xbb: Motor_Forward();
break;
case 0xbf: Motor_Reverse();
break;
case 0xbc: Motor_Stop();
break;
case 0xf3: Moter_Speed_Referance = 10;
break;
case 0xe7: Moter_Speed_Referance = 15;
break;
case 0xa1: Moter_Speed_Referance = 20;
break;
case 0xf7: Moter_Speed_Referance = 25;
break;
case 0xe3: Moter_Speed_Referance = 30;
break;
case 0xa5: Moter_Speed_Referance = 35;
break;
case 0xbd: Moter_Speed_Referance = 40;
break;
case 0xad: Moter_Speed_Referance = 45;
break;
case 0xb5: Moter_Speed_Referance = 50;
break;
}
}
}
//名称:主函数
//参数:无
//返回值: 无
//功能: 遥控控制电机,红外对管测速
void main(void)
{
Variable_Init();
Time_Init();
IR1838_Extn_Init();
Led1602_Init();
while(1)
{
Motor_Ctrol();
Caculate_Speed();
Write_Speed(9,speed);
}
} |