单片机串行通讯工程心得——接收端

写在前面

  这篇博客记录下串行通信的接收端的信号处理代码。
  下面的两段代码分别为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",从而实现两块板不借助其他硬件完成数据传输。
  下一篇博客可能会分享红外遥控的发射和接收,这个工程写到这就算收尾了。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值