写在前面
这篇博客记录下串行通信的接收端的信号处理代码。
下面的两段代码分别为C51和汇编语言,C51是为了方便理解而写的,不保证代码能工作,请读者见谅。
#include<reg52.h>
sbit remote = P1^1;
unsigned char tn,remote_num;
unsigned char code1,code2,remote_data1,remote_data2;
unsigned char flag0;
bit f_pulse = 0;
void read_pulse();
void value_jud();
void int_init(){
EA = 0;
TR0 = 0;
TMOD = 0x01;
TH0 = 0xFF; //此处由于我原工程用的中断为125us中断一次,算出来结果近似FF,所以直接用FF
TL0 = 0x00;
}
void timer0() interrupt 1 using 0{
TH0 = 0xFF;
TL0 = 0x00;
read_pulse();
flag0 = remote_data2
}
void read_pulse(){
if(tn <= 200){ //tn用于计I/O在发生电平变换时,其变化前持续的时间
tn++; //如0->1->0 0的持续时间为0.5ms,发送板在发完"0"的时候会持续将I/O口置0
if(remote&&(!f_pulse)){ //当发送"1"时,会持续将I/O口置1。接收板在接收到"0"时tn会开始从0自增,当开始接收"1"时
f_pulse = 1; //电平发生翻转,remote变为1,此时原先f_pulse值为0,进入程序f_pulse被置1,只调用一次
value_jud(); //value_jud程序,进入到value_jud程序中会根据tn的值来判断传输的是"0"还是"1",然后
} //再对code2的第0位进行操作,
else if((!remote)&&f_pulse){
f_pulse = 0; //设标志位的目的是为了只让电平翻转时才进入处理程序,其余时间只完成tn++就跳出程序
value_jud();
}
}
}
void value_jud(){
if(tn < 2 || tn >= 16){
remote_num = 0;
code2 = 0;
code1 = 0;
tn = 0;
}
code2 = code2<<1; //每次处理code2第0位之前,先将其左移一位
//code1 = code1<<1; //此处不清楚C51是否有进位位,暂时只收8位数据
if(tn > 2 && tn < 9){ //小于8*125 = 1ms则将其判断成发送"0"
code2 = code2&0xfe; //将code2第0位清零
if(++remote_num >= 8){
remote_data1 = code1;
remote_data2 = code2;
remote_num = 0;
code2 = 0;
code1 = 0;
tn = 0;
}
}
else if(tn >= 9 && tn < 16){ //大于8*125 = 1ms则将其判断成发送"1"
code2 = code2|0x01; //将code2第0位置1
if(++remote_num >= 8){
remote_data1 = code1;
remote_data2 = code2; //最终code2的数据存放在remote_data2中,只需要把flag0 = remote_data2即可
remote_num = 0; //完成主板信号到电源板信号的传输,电源板根据flag0中定义的开关标志位、高档
code2 = 0; //中档、低档等标志位控制相应的I/O口导通。
code1 = 0;
tn = 0;
}
}
}
void main(){
int_init();
remote = 1;
while(1);
}
汇编的源码如下:
LD A,TN
HSUBIA D'200'
SNZB STATUS,C
SZINCR TN
NOP
SNZB REMOTE ;REMOTE初值为1,SNZB命令的意思为:值为1时跳过下一条指令,不为1则执行
JP DECEND_PLUSE
RISE_PLUSE: ;上升沿
SZB F_PLUSE ;SZB命令的意思为:值为0时跳过下一条指令
JP END_REMOTE_RECEIVE
SETB F_PLUSE
JP VALUE_JUD
DECEND_PLUSE: ;下降沿
SNZB F_PLUSE
JP END_REMOTE_RECEIVE
CLRB F_PLUSE
VALUE_JUD:
LD A,TN
HSUBIA D'2' ;判断TN是否大于2
SNZB STATUS,C
JP ERROR_REMOTE ;小于2跳转到错误处理
LD A,TN
HSUBIA D'16' ;大于16也跳转到错误处理
SZB STATUS,C
JP ERROR_REMOTE
RLCR CODE2 ;CODE2收满8位后,再左移则CODE2.7移到C中
RLCR CODE1 ;通过C可将CODE2.7移到CODE1.0中,接收到的16位数据最头部在CODE1中
LD A,TN
HSUBIA D'9'
SZB STATUS,C
JP RECEIVE1
RECEIVE0:
CLRB CODE2,0
JP BIT_COUNT
RECEIVE1:
SETB CODE2,0
BIT_COUNT:
SZINCR REMOTE_NUM
NOP
LD A,REMOTE_NUM
HSUBIA D'16' ;根据需要,选择储存的数据位数
SNZB STATUS,C
JP END_BIT_JUD
LD A,CODE1
LD REMOTE_DATA1,A ;接收完16位数据,REMOTE_DATA1储存载波前8位
LD A,CODE2
LD REMOTE_DATA2,A ;REMOTE_DATA2储存载波后8位
SETB F_REMOTE
ERROR_REMOTE:
CLR REMOTE_NUM
CLR CODE1
CLR CODE2
END_BIT_JUD:
CLR TN
END_REMOTE_RECEIVE:
这种方式可以通过检测I/O口接收到的高电平or低电平持续时间来判断出控制板想送的是"0"还是"1",从而实现两块板不借助其他硬件完成数据传输。
下一篇博客可能会分享红外遥控的发射和接收,这个工程写到这就算收尾了。