精华内容
下载资源
问答
  •   这篇博客记录下串行通信的接收端的信号处理代码。  下面的两段代码分别为C51和汇编语言,C51是为了方便理解而写的,不保证代码能工作,请读者见谅。 #include<reg52.h> sbit remote = P1^1; unsigned ...

    写在前面

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

    展开全文
  • 目前,逆变器在很多领域有着越来越广泛地应用。对逆变器的研究具有十分重要的意义和广阔的工程应用前景。常见逆变技术的控制方法大致分为开环控制的载波调制方法和闭环控制的跟踪控制方法。
  •  我此处的工程较为简单,两块板通过导线直接连接,然后电源板只需要根据其I/O口的高低电平的持续时间即可判断出控制板发出的信号为“0”还是“1”。  此处的代码为汇编代码,语言可能有读者会看不懂,我大致会...

    写在前面

      这篇博客记录下最近一个星期研究的两块板通过一个口线实现的数据传输。
      我用的两块板上各有一个单片机,此处称为控制板和电源板。两单片机各出一个I/O口,一个输入一个输出,然后通过规定此I/O口高电平和低电平的持续时间来传输“0”和“1”,这种传输方式非常普遍,红外遥控基本原理与这个十分类似,不过红外遥控是通过A发出红外光,然后B接受红外光,根据是否接收到红外光和他的持续时间来编码为“0”或“1”,再把不同的“0”“1”组合来规定不同的键。
      我此处的工程较为简单,两块板通过导线直接连接,然后电源板只需要根据其I/O口的高低电平的持续时间即可判断出控制板发出的信号为“0”还是“1”。
      此处的代码为汇编代码,语言可能有读者会看不懂,我大致会注释一下:

    #include<reg52.h>
    
    sbit send_data = P1^1;
    unsigned char bit_step,bit_num,bit_step;
    unsigned char trans_buf1,trans_data1,trans_buf2,trans_data2,bit_trans;
    unsigned char flag0;
    void transmit();
    
    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;
    	transmit();
    	if(++timer_12ms >= 96){
    		timer_12ms = 0;
    		trans_buf1 = flag0;
    	}
    }
    
    void transmit(){
    	bit_step++;
    	if((bit_step >= 40) && (bit_num == 0)){
    		bit_step = 0;
    		bit_num=1;
    		trans_data1 = trans_buf1;
    		trans_data2 = trans_buf2;
    		send_data = 0;
    	}
    	else if((bit_step < 40) && (bit_num == 0)){		//发5ms高电平作为开始标志
    		send_data = 1;
    	}
    	
    	if((bit_num > 0) && (bit_num <= 8)){
    		bit_trans = trans_data1&0x80;				//储存trans_data1的第7位
    		if((bit_trans != 0)&&(bit_step >= 12)){		//判断储存trans_data1的第7位为0还是1
    			bit_num++;								//传输位数变量加一
    			send_data = ~send_data;					//取反口线的电平,传输下一位(如果这里只是简单的置0或1的话,连续传输多位"0"或"1",
    			bit_step = 0;	//清零计时				//则波形就连续了,接收板就无法分辨出此时发送的是1位还是多位数据)
    			trans_data1 = trans_data1<<1;			//C51由于不清楚是否有进位位,这里暂时只送八位数据了
    		}
    		else if((bit_trans == 0) && (bit_step > 4)){
    			send_data = ~send_data;
    			bit_num++;
    			bit_step = 0;
    			trans_data1 = trans_data1<<1;			
    		}
    	}
    	else if(bit_num >= 9){
    		if(bit_step >= 4){
    			bit_num = 0;
    		}
    		else{
    			send_data = 0;							//结束标志:0.5ms低电平
    		}
    	}
    }
    
    void main(){
    	int_init();
    	while(1);
    }
    

      原汇编代码为:

    TRANSMIT:								
    		SZINCR		BIT_STEP					;BIT_STEP变量自增
    		NOP		
    		LD			A,BIT_NUM					;传值
    		SNZB		STATUS,Z					;判断BIT_NUM是否为空,为空跳过下一条指令
    		JP			TRANSMIT1
    TRANSMIT0:										; 5ms高电平
    		LD			A,BIT_STEP
    		HSUBIA		D'40'						;BIT_STEP减40
    		SNZB		STATUS,C					;判断是否溢出,不溢出则跳过下一条指令
    		JP			SEND1
    		CLR			BIT_STEP					;清BIT_STEP
    		LDIA		D'1'						;赋值1给ACC
    		LD			BIT_NUM,A					;传值
    		LD			A,TRANS_BUF1			
    		LD			TRANS_DATA1,A
    		/*将TRANS_BUF1的值传给TRANS_DATA1   此处的TRANS_BUF1的值是在另一段函数中由flag0赋的,
    		而flag0中每一位储存的各设为我单片机的标志位,包括了开关标志位,高档,中档,低档等(产品为塔式风扇),
    		传输flag0即可告诉电源板 这边控制板的状态和命令,以便电源板输出相应的命令,如将高档位导通,则电机以高档频率运行*/
    		LD			A,TRANS_BUF2				;将TRANS_BUF2的值传给TRANS_DATA2
    		LD			TRANS_DATA2,A
    		JP			SEND0						;置成低电平,否则发送的第一位数据的波形一直持续为高
    TRANSMIT1:										; 16位代码
    		LD			A,BIT_NUM	
    		HSUBIA		D'17'
    		SZB			STATUS,C					;判断是否溢出,溢出则跳过下一条
    		JP			STOP_TRANSMIT
    		SNZB		TRANS_DATA1,7				;判断TRANS_DATA1的第7位,为1则跳过,为0不跳过下一条代码
    		JP			BIT0						;跳转到发送“0”
    BIT1:											; “1”:1.5ms脉宽
    		LD			A,BIT_STEP
    		HSUBIA		D'12'						;12*125us=1500us
    		SNZB		STATUS,C					;判断是否溢出,溢出则不跳过
    		JP			END_TRANSMIT				;离开这段代码
    		JP			BIT_JUD						;跳转到后续处理
    BIT0:											; 0:0.5ms脉宽
    		LD			A,BIT_STEP
    		HSUBIA		D'4'						;4*125us = 500us
    		SNZB		STATUS,C
    		JP			END_TRANSMIT 
    BIT_JUD:										;后续处理
    		CLR			BIT_STEP					;清掉脉冲计时变量
    		SZINCR		BIT_NUM						;增加发送位数变量
    		NOP
    		RLCR		TRANS_DATA2					;带进位左移
    		RLCR		TRANS_DATA1					
    		/*带进位左移,此处通过进位标志位C来传值,TRANS_DATA2最高位左移会传给进位标志位C,
    		TRANS_DATA1左移会把C中的值移到最低位*/
    		LDIA		B'00000100'					; P2.2为数据发送口
    		XORR		P2							;异或,确保波形随着位数的增加而取反
    		JP			END_TRANSMIT
    STOP_TRANSMIT:									; 结束0.5ms低电平
    		LD			A,BIT_STEP
    		HSUBIA		D'4'
    		SZB			STATUS,C
    		CLR			BIT_NUM						;结束时清除发送位数变量
    SEND0:
    		CLRB		OUT_DATA					;OUT_DATA端口输出低电平
    		JP			END_TRANSMIT
    SEND1:
    		SETB		OUT_DATA					;OUT_DATA端口输出高电平
    END_TRANSMIT:									;离开函数
    

      上文中的C代码是我根据汇编代码翻译过来的,没有经过仿真或实物运行,所以不保证代码的正确性,只是为了自己和读者以后能更好的理解汇编代码的原意而写,如有错误,请见谅。
      然后还需要提到的一点是汇编相比于C51而言,可以单独操作自定义变量的每一位,其逻辑与C51中的特殊寄存器类似,即f_onoff = flag0^0 与 button1 = P3^0 类似,我此处没有给出我汇编中关于flag0的定义,解释起来有点麻烦。我在C51中是用先与0x80来保存第7位然后判断其值,然后再跳到相应的输出电平程序,比如第7位为1,则跳到输出“1”的段,让其时间增加到1.5ms再跳到后续处理代码段,先清掉计1.5ms的变量,然后让计算已传位数的变量+1,然后再取反该I/O口的电平。而在汇编中则是通过判断TRANS_DATA1的第7位,然后跳到对应的发“0”或发“1”的延时程序中,等到延时时间到了,首先将TRANS_DATA2的第7位移到进位标志位C中,因为第7位再左移就会将原值直接移入进位标志位C中(C是单片机状态寄存器中的某一位),紧接着再让TRANS_DATA1左移,就会把C左移到TRANS_DATA1中的第0位,同时把TRANS_DATA1的最高位移入进位标志位C中,下次再进入程序时TRANS_DATA2的第0位就是TRANS_DATA1的最高位。这样就把TRANS_DATA2的值逐个传到了TRANS_DATA1中,同时TRANS_DATA1的值已经通过每次进入函数的检测第7位的值然后输出相应高低电平传输到了电源板,当传了8次之后,TRANS_DATA1的值已经完全发送到了电源板中,此时TRANS_DATA1中储存的是TRANS_DATA2的值,再移8次,即可把TRANS_DATA2的值也发送到电源板中。接收端通过连接的导线可以接收到发送端发送过去的高低电平信号,并通过计算高低电平的持续时间来判断发送端想要送的是“0”还是“1”。(此段较为难以理解,如果有实物结合示波器看发送端的I/O口的波形就可以很好的理解)
      写到这里,大致理清了这几天一直没想明白的地方,下一篇会分享接收端是如何解码其收到的高低电平信号,再过段时间会做红外遥控的工程并分享红外的发送和接收。

    展开全文
  • 做Quartus2实验的同学可以使用此资源,其中包括半加器,全加器和四位加法器。能够帮助你的更高的EDA分数
  • 工程说明:USART1-同步异步串行通信.docx。
  • VS2010工程 我们能都知道单文档多文档串行化非常简单,因为框架已经为我们生成好了. 但是单文档串行化这方面,资料还真是少.
  • * 使用其四线串行模式(SQI)的方式进行访问; * 尽量使用序列读写方式,而不是每次完成完整的**命令+地址+数据**的腹泻方式 下面为了配合[**``AD7606八通道AD采集模块测试``**]...
  • 对逆变器的研究具有十分重要的意义和广阔的工程应用前景。常见逆变技术的控制方法大致分为开环控制的载波调制方法和闭环控制的跟踪控制方法。跟踪控制方法属于闭环控制,闭环反馈中的检测环节需要与高压主电路相互...
  • 对逆变器的研究具有十分重要的意义和广阔的工程应用前景。常见逆变技术的控制方法大致分为开环控制的载波调制方法和闭环控制的跟踪控制方法。跟踪控制方法属于闭环控制,闭环反馈中的检测环节需要与高压主电路相互...
  • STM32驱动AD9850,串行方式,完整工程

    热门讨论 2013-08-05 16:14:52
    基于STM32的AD9850的驱动程序 完整工程 亲测
  • 串行通信的工程,测试和调试。 支持RS-232 / 422/423/485以及TCP / IP客户端/服务器/自动套接字,UDP / IP客户端/服务器/ PairSocket和USB Ser / HID。 针对例如嵌入式系统的简单命令集进行了优化。
  • 51单片机Proteus仿真+Keil工程-实验5-单片机串行口中断实验:放置两个单片机,通过串行口线的互连,应用方式1和方式3,同时设计发送和接受程序,完成两个方式的应用,将发送和接收的内容在虚拟串口中显示。

    实验5-单片机单片机串行口中断实验

      之前做的一次实验,51单片机串行口中断实验,感觉不够完美,待改进。如有问题欢迎指正。

    实验目的:

      掌握串行口的工作方式;掌握不同串行口工作方式下的通讯方法。

    实验目标:

      放置两个单片机,通过串行口线的互连,应用方式1和方式3,同时设计发送和接受程序,完成两个方式的应用,将发送和接收的内容在虚拟串口中显示。

    实验环境:

       MDK-ARM V5.21a、Proteus 8.6

    Proteus原理图

       方式1:
    在这里插入图片描述
       方式3:
    在这里插入图片描述

    选择元器件:

    DEVICES 说明
    AT89C51 MCU
    BUTTON 按键
    CAP 普通电容
    CAP-ELEC 电解电容
    CRYSTAL 晶振
    RES 电阻
    RESPACK-8 排阻

      51单片机的P0口做IO口使用时是漏极开路输出,其引脚一般需要在片外接一定阻值的上拉电阻,此时端口不存在高阻抗的悬浮状态,因此它是一个准双向口。同时,P0口每一位的驱动能力是P1~P3口的两倍,每位可以驱动8个LSTTL(Low-power Schottky TTL,即低功耗肖特基TTL)输入,89C51等单片机任何一个端口想要获得较大的驱动能力,必须采用低电平输出。
      时钟晶体振荡频率为fosc=11.0592MHZf_{osc}=11.0592MHZ
      时钟周期相当于Tosc=1fosc90.42nsT_{osc}=\frac{1}{f_{osc}} \approx 90.42ns
      复位电路的话通过给89C51等单片机的复位引脚RST加上大于2个机器周期的高电平(即24个时钟振荡周期)就可以使单片机复位。

    KEIL工程:

    方式1:
      1.甲乙两机以方式1进行串行通信,双方晶体振荡器频率均为11.0592MHz,波特率为2400bit/s。甲机的TXD脚、RXD脚分别与乙机的RXD、TXD脚相连。
      2.为观察串行口传输的数据,电路中添加了两个虚拟终端来分别显示串行口发出的数据。添加虚拟终端,只需单击Proteus左侧工具箱中的虚拟仪器图标图,在预览窗口中显示的各种虚拟仪器选项,单击“VIRTUAL TERMINAL"项,并放置在原理图编辑窗口,然后把虚拟终端的“RXD”端与单片机的“TXD”端相连即可。
      3.当串行通信开始时,甲机首先发送数据AAH,乙机收到后应答BBH,表示同意接收。甲机收到BBH后,即可发送数据。如果乙机发现数据出错,就向甲机发送FFH,甲机收到FFH后,重新发送数据给乙机。
      4.选择定时器TI为方式2定时,波特率不倍增,即SMOD=0,经过计算:2SMOD32×11.0592M12=2400×256X(SMOD=0),X=244D=F4H\frac{2^{SMOD}}{32}×\frac{11.0592M}{12}=2400×(256-X)(其中SMOD=0),X=244D=F4H,可得写入T1的初值应为F4H。
      5.以下双机通信程序,该程序可以在甲乙两机中运行,不同的是在程序运行之前,要人为地设置TR。若选择TR=0,表示该机为发送方;若TR=1,表示该机是接收方。程序根据TR设置,利用发送函数send( )和接收丽数receive( )分别实现发送和接收功能。

      甲机串口通信程序:

    #include <reg52.h>
    #include <intrins.h>
    #define uchar unsigned char
    #define uint unsigned int
    #define TR 0					//接收发送的区别值,TR=0为发送
    uchar buf[10]={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a};//发送的10个数据
    uchar sum;
    void delay(uint i);
    void init();
    void send(void);	//甲机发送函数
    void receive(void);	//甲机接收函数
    
    void main(void)
    {
    	init();
    	if(TR==0)//TR=0为发送
    	{send();}
    	if(TR==1)//TR=1为接收
    	{receive();}
    }
    void delay(uint i)
    {
    	uchar j;
    	for(;i>0;i--)
    		for(j=0;j<125;j++);
    }
    void init()
    {
    	TMOD=0x20;	//T1的方式2定时
    	TH1=0xf4;	//波特率为2400
    	TL1=0xf4;
    	PCON=0x00;	//SMOD=0
    	SCON=0x50;	//串行口方式1,REN=1允许接收
    	
    	TR1=1;		//启动定时器T1
    }
    void send(void)//甲机发送函数
    {
    	uchar i;
    	do{
    		delay(1000);
    		SBUF=0xaa;			//发送联络信号
    		while(TI==0);		//等待数据发送完毕
    		TI=0;
    		while(RI==0);
    		RI=0;				//等待乙机应答
    	}while(SBUF!=0xbb);		//乙机未准备好继续联络
    	do{
    		sum=0;				//校验和变量清零
    		for(i=0;i<10;i++)
    		{
    			delay(1000);
    			SBUF=buf[i];
    			sum+=buf[i];	//求校验和
    			while(TI==0);
    			TI=0;
    		}
    		delay(1000);
    		SBUF=sum;			//发送校验和
    		while(TI==0);TI=0;
    		while(RI==0);RI=0;
    	}while(SBUF!=0x00);		//出错,重新发送
    	while(1);
    }
    void receive(void)
    {
    	uchar i;
    	RI=0;
    	while(RI==0); RI=0;
    	while(SBUF!=0xaa);		//判断甲机是否发出请求
    	SBUF=0xbb;				//发送应答信号BBH
    	while(TI==0);			//等待发送结束
    	TI=0;
    	sum=0;
    	for(i=0;i<10;i++)
    	{
    		while(RI==0);RI=0;	//接收校验和
    		buf[i]=SBUF;		//接收一个数据
    		sum+=buf[i];		//求校验和
    	}
    	while(RI==0);
    	RI=0;					//接收甲机的校验和
    	if(SBUF==sum)			//比较校验和
    	{
    		SBUF=0x00;			//校验和相等,则发送00h
    	}
    	else
    	{
    		SBUF=0xFF;			//出错发送FFH,重新接收
    		while(TI==0);TI=0;
    	}
    }
    

      乙机串口通信程序:

    #include <reg52.h>
    #include <intrins.h>
    #define uchar unsigned char
    #define uint unsigned int
    #define TR 1					//接收发送的区别值,TR=1为接收
    uchar idata buf[10];//={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a};//发送的10个数据
    uchar sum;
    void delay(uint i);
    void init();
    void send(void);			//乙机发送函数
    void receive(void);			//乙机接收函数
    
    void main(void)
    {
    	init();
    	if(TR==0)				//TR=0为发送
    	{	
    		send();				//调用发送函数
    	}
    	else
    	{
    		receive();			//调用接收函数
    	}
    }
    void delay(uint i)
    {
    	uchar j;
    	for(;i>0;i--)
    		for(j=0;j<125;j++);
    }
    void init()
    {
    	TMOD=0x20;				//T1的方式2定时
    	TH1=0xf4;				//波特率为2400
    	TL1=0xf4;
    	PCON=0x00;				//SMOD=0
    	SCON=0x50;				//串行口方式1,REN=1允许接收
    	TR1=1;					//启动定时器T1
    }
    void send(void)//乙机发送函数
    {
    	uchar i;
    	do{
    							//delay(1000);
    		SBUF=0xaa;			//发送联络信号
    		while(TI==0);TI=0;	//等待数据发送完毕
    		while(RI==0);RI=0;	//等待乙机应答
    	}while(SBUF!=0xbb);		//乙机未准备好,继续联络
    	do{
    		sum=0;				//校验和变量清零
    		for(i=0;i<10;i++)
    		{
    			//delay(1000);
    			SBUF=buf[i];
    			sum+=buf[i];	//求校验和
    			while(TI==0);
    			TI=0;
    		}
    		//delay(1000);
    		SBUF=sum;			//发送校验和
    		while(TI==0);TI=0;
    		while(RI==0);RI=0;
    	}while(SBUF!=0);		//出错,重新发送
    }
    void receive(void)			//乙机接收函数
    {
    	uchar i;
    	RI=0;
    	while(RI==0); RI=0;
    	while(SBUF!=0xaa)		//判断甲机是否发出请求
    	{
    		SBUF=0xff;
    		while(TI!=1);TI=0;
    		delay(1000);
    	}
    	SBUF=0xbb;				//发送应答信号BBH
    	while(TI==0);			//等待发送结束
    	TI=0;
    	sum=0;					//清校验和
    	for(i=0;i<10;i++)
    	{
    		while(RI==0);RI=0;	//接收校验和
    		buf[i]=SBUF;		//接收一个数据
    		sum+=buf[i];		//求校验和
    	}
    	while(RI==0);
    	RI=0;					//接收甲机的校验和
    	if(SBUF==sum)			//比较校验和
    	{
    		SBUF=0x00;			//校验和相等,则发送00h
    	}
    	else
    	{
    		SBUF=0xFF;			//出错发送FFH,重新接收
    		while(TI==0);TI=0;
    	}
    }
    

    方式3:
      先比较方式2与方式1,有两点不同之处:
      1. 方式2接收/发送11位信息,第0位为起始位,第1~8位为数据位,第9位是程控位,由用户设置的TB8位决定,第10位是停止位1,这是方式2与方式1的一个不同点。
      2. 方式2的波特率变化范围比方式1小,方式2的波特率=振荡器频率/n。
      当SMOD=0时,n=64。
      当SMOD=1时,n=32。
      而方式3和方式2相比,除了波特率的差别外,其他都相同。
      甲机串口通信程序:

    #include <reg52.h>
    #include <intrins.h>
    #define uchar unsigned char
    #define uint unsigned int
    #define TR 0					//接收发送的区别值,TR=0为发送
    sbit p=PSW^0;					//p位定义为PSW寄存器的第0位,即奇偶校验位
    uchar buf[10]="I LOVE YOU";//{0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//发送的8个数据
    void delay(void);
    void init();
    void send(uchar dat);	//甲机发送函数
    void receive(void);		//甲机接收函数
    
    void main(void)
    {
    	uchar i;
    	init();
    	if(TR==0)		//TR=0为发送
    	{
    		while(1)
    		{
    			for(i=0;i<8;i++)
    			{
    				send(buf[i]);
    				delay();//大概200ms发送一次数据
    			}
    		}
    	}
    	if(TR==1)		//TR=1为接收
    	{
    		receive();
    	}
    }
    void send(uchar dat)
    {
    	TB8=P;
    	SBUF=dat;
    	while(TI==0);
    	;
    	TI=0;	
    }
    	
    void init()
    {
    //	TMOD=0x20;	//T1的方式2定时-方式2
    //	SCON=0x90;	//串行口方式2,REN=1允许接收
    //	PCON=0x00;	//SMOD=0
    //	
    //	TH1=0xfd;	//波特率为9600
    //	TL1=0xfd;
    //	TR1=1;		//启动定时器T1
    	
    	//Success
    	TMOD=0x20;	//T1的方式2定时-方式2
    	SCON=0xc0;	//串行口方式3,REN=1允许接收
    	PCON=0x00;	//SMOD=0
    	
    	TH1=0xfd;	//波特率为9600
    	TL1=0xfd;
    	TR1=1;		//启动定时器T1
    	REN=1;
    }
    
    void delay(void)
    {
    	uchar m,n;
    	for(m=0;m<250;m++)
    		for(n=0;n<125;n++);
    }
    

      乙机串口通信程序:

    #include <reg52.h>
    #include <intrins.h>
    #define uchar unsigned char
    #define uint unsigned int
    #define TR 1					//接收发送的区别值,TR=1为接收
    sbit p=PSW^0;					//p位定义为PSW寄存器的第0位,即奇偶校验位
    uchar idata buf[10];//={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a};//发送的10个数据
    void delay(void);
    void init();
    void send(void);			//乙机发送函数
    uchar receive(void);		//乙机接收函数
    
    void main(void)
    {
    	init();
    	if(TR==0)				//TR=0为发送
    	{	
    		//send();				//调用发送函数
    	}
    	else
    	{
    		while(1)
    		{
    			P1=receive();			//调用接收函数
    		}
    		
    	}
    }
    
    void init()
    {
    //	TMOD=0x20;	//T1的方式2定时-方式2
    //	SCON=0x90;	//串行口方式2,REN=1允许接收
    //	PCON=0x00;	//SMOD=0
    //	
    //	TH1=0xfd;	//波特率为9600
    //	TL1=0xfd;
    //	TR1=1;		//启动定时器T1
    //	REN=1;
    	
    	//Success
    	TMOD=0x20;	//T1的方式2定时-方式2
    	SCON=0xd0;	//串行口方式3,REN=1允许接收
    	PCON=0x00;	//SMOD=0
    	
    	TH1=0xfd;	//波特率为9600
    	TL1=0xfd;
    	TR1=1;		//启动定时器T1
    	REN=1;
    }
    void delay(void)
    {
    	uchar m,n;
    	for(m=0;m<250;m++)
    		for(n=0;n<125;n++);
    }
    uchar receive(void)
    {
    	uchar dat;
    	while(RI==0);
    	;
    	RI=0;
    	ACC=SBUF;
    	if(RB8==P)
    	{
    		dat=ACC;
    		return dat;
    	}
    }
    

    参考文献
    1.《单片机原理与接口技术》张毅刚

    返回目录

    展开全文
  • 对逆变器的研究具有十分重要的意义和广阔的工程应用前景。常见逆变技术的控制方法大致分为开环控制的载波调制方法和闭环控制的跟踪控制方法。跟踪控制方法属于闭环控制,闭环反馈中的检测环节需要与高压主电路相互...
  • 【课题7】利用8251实现串行口自发自收,并显示。 设计要求: 1. 按“A”键:清除数码管显示,并通过小键盘输入四位16进制数,同时显示在右侧四个数码管上。 2. 按“B”键:执行串行发送,并在最右一个数码管上显示...
  • 串行通讯协议

    2015-09-21 23:29:00
    个人编写的串口通讯协议,支持多字节和校验和,已经用于实际工程,可在所有串行通讯接口中使用,比如RS232,485,SPI等
  • 153、Java8新特性之并行流和串行流 并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流。Java8中将并行做了优化,我们可以很容易的对数据进行并行操作。StreamAPI可以声明性的通过parallel...

    153、Java8新特性之并行流和串行流

    并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流。Java8中将并行做了优化,我们可以很容易的对数据进行并行操作。StreamAPI可以声明性的通过parallel()与sequential()在并行流与顺序流之间进行切换。

    再说并行流之前,我们先了解一个框架Fork/Join:Fork/Join框架就是在必要情况下,将一个大的任务进行拆分fork成若干个小的任务,知道不可再拆分,然后再将一个个小的任务的运算结果进行join汇总。

    Fork/Join框架使用起来比较复杂,但是效率高。Fork/Join框架采取“工作窃取”模式(work-stealing):当执行新的任务时,它可以将其拆分为更小的任务执行,并将小任务加入到线程队列中,然后再从一个随机线程的队列中偷一个并把它放在自己的队列中。

    相对于一般的线程池实现,Fork/Join框架的优势体现在对其中包含的任务的处理方式上。在一般的线程池中,如果一个线程正在执行的任务由于某些原因无法继续执行,那么该线程会处于等待状态,而在Fork/Join框架实现中,如果某个子问题由于等待另外一个子问题的完成而无法继续运行,那么处理该子问题的线程会主动寻找其他尚未运行的子问题来执行。这种方式减少了线程的等待时间,提高了性能。

     Fork/Join模式使用:

    * 1.继承抽象类RecusiveTask(有返回值,泛型指定返回值)或者抽象类RecusiveAction(无返回值)

    * 2.实现其中的compute方法,以递归形式拆分任务

    * 3.任务拆分完成之后,调用fork,压入线程队列

    * 4.任务处理完成之后,调用join,返回值

    * 5.运行程序时,需要ForkJoinPool的支持

                          * 5.1.新建ForkJoinPool

                          * 5.2.用父类ForkJoinTask去引用需要新建的对象

                          * 5.3.调用ForkJoinPool的invoke,进行fork/join,接收返回值

    测试Fork/Join框架:

    public class ForkJoinCalculate extends RecursiveTask {
    
        private long start;
        private long end;
    
        private static final long THRESHOLD = 10000;
    
        public ForkJoinCalculate(long start, long end) {
            this.start = start;
            this.end = end;
        }
    
        @Override
        protected Long compute() {
            long length = end - start;
            if (length <= THRESHOLD){
                long sum = 0;
                for (long i = start; i <= end; i++){
                    sum += i;
                }
                return sum;
            }else {
                long middle = (start + end) / 2;
                ForkJoinCalculate left = new ForkJoinCalculate(start,middle);
                left.fork();//拆分子任务,同时压入线程队列
    
                ForkJoinCalculate right = new ForkJoinCalculate(middle,end);
                right.fork();
    
                return (long)right.join() + (long)left.join();
            }
        }
    }
    
    public class TestForkJoin {
    
        //使用ForkJoin框架计算从0加到1亿的和
        @Test
        public void test1(){
            Instant start = Instant.now();
    
            ForkJoinPool pool = new ForkJoinPool();
            ForkJoinTask<Long> task = new ForkJoinCalculate(0,100000000L);
            Long sum = pool.invoke(task);
            System.out.println("和是:" + sum);
    
            Instant end = Instant.now();
            System.out.println("耗费时间是:" + Duration.between(start,end).toMillis() + "毫秒");
        }
    
        //使用普通for循环计算求和
        @Test
        public void test2(){
            Instant start = Instant.now();
            
            long sum = 0L;
            for (long i = 0; i <= 100000000L; i++){
                sum += i;
            }
            System.out.println("和是:" + sum);
            
            Instant end = Instant.now();
            System.out.println("耗费时间是:" + Duration.between(start,end).toMillis() + "毫秒");
        }
    }
    

    数据量越大,Fork/Join框架的优势越明显。

    下面看Java8使用并行流怎么实现:

        //使用Java8并行流计算求和
        @Test
        public void test3(){
            Instant start = Instant.now();
    
            long sum = LongStream.rangeClosed(0, 100000000L).parallel().reduce(0, Long::sum);
    
            System.out.println("和是:" + sum);
    
            Instant end = Instant.now();
            System.out.println("耗费时间是:" + Duration.between(start,end).toMillis() + "毫秒");
        }

     

    展开全文
  • 本节书摘来自华章计算机《高性能科学与工程计算》一书中的第2章,第2.1节,作者:(德)Georg Hager Gerhard Wellein 更多章节内容可以访问云栖社区“华章计算机”公众号查看。 第2章 串行代码基本优化技术 在千核级...
  • linux串行通信信号 作为系统工程师,我在数据中心花费大量时间来配置服务器和其他计算机设备。 我在工具箱中保留的两个项目是RS-232串行USB转换器和标准DB-9串行电缆。 当您无法通过其他方式访问设备时,这些可能是...
  • 8086+8251 串行通信

    2018-08-04 10:51:14
    使用8086 8251通过RS232实现两台8086之间的串行通信 内容包括Proteus工程文件,以及实现串行通信的汇编源程序
  • 串行接口.rar

    2019-08-26 15:37:23
    《xilinx fpga 高速串行传输技术与应用》电子工业出版社。高清扫描版,非pdf文档版本,主讲高速serdes接口,适合新手以及调试遇到问题的工程师看。
  • 攀枝花学院学报 2012年8月 VoL 29No4 of JournalPanzhihua University Au昏2012 自然科学研究 基于VHDL的并行到串行转换器算法模型 曾日 仅技 (攀枝花学院电气信息工程学院ItJ sl攀枝花617000) 摘要以并行到串行转换...
  • 串行 RapidIO

    千次阅读 2014-05-08 10:27:36
    串行 RapidIO: 高性能嵌入式互连技术 作者: 德州仪器技术应用工程师 冯华亮/ Brighton Feng/ bf@ti.com 摘要 串行RapidIO针对高性能嵌入式系统芯片间和板间互连而设计,它将是未来十几年中嵌入式系统...
  • c51 仿真 串行通信.zip

    2021-05-08 20:28:13
    C51编写串行通信,在proteus中仿真调试 工程文件,可以直接打开的
  • USB串行接口

    2017-05-30 15:45:23
    USB作为一种串行接口,应用日益广泛。如同每个工程设计人员必须掌握I2C,RS232这些接口一样,我们也必须掌握USB.但是USB的接口协议实在有点费解,Linux UCHI驱动作者之一Alan Stern曾经就说过“The USB documentation...
  • 串行12864launchpad

    2015-04-23 12:34:31
    穿行12864的launcpad程序。反复测试成功,由于是在linux下开发,因此没有IAR工程文件,下载者可自行建立工程,接好引脚后即可使用。
  • 并行工程作为一种思想和哲理,本质在于全面考虑产品特性与开发过程的固有约束性,核心是并行设计。本文首先论述了并行工程哲理的内涵,着重从信息论的角度对其进行描述,解释了并行工程优于串行工程的原因和实质。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,594
精华内容 637
关键字:

串行工程