前言
不知道该说什么好。我买了STM32了,opencv终于有用武之地了。
PPM与PWM
PPM,pulse position modulation.比如调制ton长度,保持toff不变。
PWM,pulse width modulation.比如调制占空比Tton,但是周期不变。
我的单片机上的遥控器是发送PPM编码形式的数据。通过不同长度的ton来定义0和1
红外传输的数据格式
接收完这个32位数据后,用数据反码和数据码比对,作为校验有无错误的措施。
可以看出,周期和起始码的控制是比较麻烦的。
红外遥控原理图
发送端发送脉冲信号,到接收端后转变成数字信号。
红外接收模块
发送模块
用红外接收产生外部中断
通过原理图得知,接收模块的输出端接的是外部中断INT0口。所以可以把接收内容的代码写在外部中断的函数里。
#include"reg52.h"
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
sbit IR_IN=P3^2;//INT0
unsigned char IR_Receive[6];
unsigned char time;
unsigned char leds[3];
unsigned char code table[]={
0x3f,0x06,0x5b,0x4f,0x66, //01234
0x6d,0x7d,0x07, 0x7f,0x6f,//56789
0x77,0x7c,0x39,0x5e,0x79, //abcde
0x71,0X76 //fh
};
void delay(unsigned int i);
void show();
void IR_Init();
void main(){
IR_Init();
while(1)show();
}
void delay(unsigned int i){
while(i--);
}
void show(){
unsigned int j;
leds[0]=table[16];///h
leds[1]=table[IR_Receive[2]%16];
leds[2]=table[IR_Receive[2]/16];
for(j=0;j<3;j++){
switch(j){
case 0:
LSC=0,LSB=0,LSA=0;
break;
case 1:
LSC=0,LSB=0,LSA=1;
break;
case 2:
LSC=0,LSB=1,LSA=0;
break;
}
P0=leds[j];
delay(100);
P0=0;
}
}
void IR_Init(){
TCON=0x01;//IT0=1
IE=0x81;//EA=1,EX0=1
IR_IN=1;//initialize the port
}
void IR_Read()interrupt 0{
unsigned char i,j;
unsigned int error;
delay(700);//~7ms
if(IR_IN==0){
error=1000;
while(IR_IN==0&&error>0){ //~9ms
delay(1);//~10us
error--;
}
if(IR_IN==1){
error=500;
while(IR_IN==1&&error>0){ //~4.5ms
delay(1);
error--;
}
//4X8=32位数据 用户码16位 ,数据码8位,反数据码8位
for(i=0;i<4;i++){
for(j=0;j<8;j++){
time=0;
error=60;
while(IR_IN==0&&error>0){//~560us
delay(1);
error--;
}
error=500;
while(IR_IN==1&&error>0){ //计算高电平的时间长度
delay(10);//~100us
error--;
if(++time>30)return;
}
//数据从低位开始传递
IR_Receive[i]>>=1;
if(time>=8)
IR_Receive[i]|=0x80;
}
}
}
//将数据码和数据反码进行比对
if(IR_Receive[2]!=~IR_Receive[3])
return;//出错
}
}
经过显示,我们明白遥控器上21个按键的编码如下。
45H(开关) 46H(Mode) 47H(声音开关)
44H(播放) 40H(后退) 43H(前进)
07H(EQ) 15H(VOL-) 09H(VOL+)
16H(0) 19H(RPT) 0DH(U/SD)
0CH(1) 18H(2) 5EH(3)
08H(4) 1CH(5) 5AH(6)
42H(7) 52H(8) 4AH(9)
舵机转动
舵机是靠PWM控制的,所以需要改ton就行了。