如何实现2个51单片机之间通过串口通信的源程序

如何实现2个51单片机之间通过串口通信的源程序,第1张

汇编编写的模拟串口通信程序

T2作为波特率控制

UART_RXD 是硬中断0或1口,如果能进入中断,说明该线有一个起始位产生,进入中断后调

用下面的接收程序。退出硬中断之前还需要将硬中断标志重新复位。

UART_TXD 是任何其它IO即可。

UART_SEND:

PUSH IE

PUSH DPH

PUSH DPL

PUSH PSW

PUSH 00H

PUSH ACC

CLR EA

SETB UART_TXD ;START BIT

MOV R0,A

CLR TR2 ;TR2置1,计数器2启动,时间计数启动。

MOV A,RCAP2L;计数器2重新装载值

MOV TL2,A ;置计数器2初值 ;T2需要重新装载

MOV A,DPH

MOV A,RCAP2H

MOV TH2,A

MOV A,R0

SETB TR2 ;TR2置1,计数器

JNB TF2,$

CLR TF2

JNB TF2,$

CLR TF2

CLR UART_TXD ;START BIT

JNB TF2,$

CLR TF2

JNB TF2,$

CLR TF2

MOV R0,#08H

UART_SEND_LOOP:

RRC A

MOV UART_TXD,C ;8 BIT

JNB TF2,$

CLR TF2

JNB TF2,$

CLR TF2

DJNZ R0,UART_SEND_LOOP

SETB UART_TXD ;END BIT

JNB TF2,$

CLR TF2

JNB TF2,$

CLR TF2

POP ACC

POP 00H

POP PSW

POP DPL

POP DPH

POP IE

RET

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

UART_REC:

PUSH IE

PUSH DPH

PUSH DPL

CLR EA

CLR TR2 ;TR2置1,计数器2启动,时间计数启动。

MOV A,RCAP2L;计数器2重新装载值

MOV TL2,A ;置计数器2初值 ;T2需要重新装载

MOV A,DPH

MOV A,RCAP2H

MOV TH2,A

JB UART_RXD,$ ;REC

SETB TR2 ;TR2置1,计数器2启动,时间计数启动。

JNB TF2,$

CLR TF2 ;05 BIT

JNB TF2,$

CLR TF2 ;1 BIT

JNB TF2,$

CLR TF2 ;15 BIT

MOV C,UART_RXD

MOV ACC0,C

JNB TF2,$

CLR TF2

JNB TF2,$

CLR TF2 ;25

MOV C,UART_RXD

MOV ACC1,C

JNB TF2,$

CLR TF2

JNB TF2,$

CLR TF2 ;35

MOV C,UART_RXD

MOV ACC2,C

JNB TF2,$

CLR TF2

JNB TF2,$

CLR TF2 ;45

MOV C,UART_RXD

MOV ACC3,C

JNB TF2,$

CLR TF2

JNB TF2,$

CLR TF2 ;55

MOV C,UART_RXD

MOV ACC4,C

JNB TF2,$

CLR TF2

JNB TF2,$

CLR TF2 ;65

MOV C,UART_RXD

MOV ACC5,C

JNB TF2,$

CLR TF2

JNB TF2,$

CLR TF2 ;75

MOV C,UART_RXD

MOV ACC6,C

JNB TF2,$

CLR TF2

JNB TF2,$

CLR TF2 ;85

MOV C,UART_RXD

MOV ACC7,C

JNB TF2,$

CLR TF2 ;95

JNB UART_RXD,$ ;等待停止位,并重新复位计数器

SETB UART_RXD

POP DPL

POP DPH

POP IE

RET

补充回答:

串口调试

1 发送:向总线上发命令

2 接收:从总线接收命令,并分析是地址还是数据

3 定时发送:从内存中取数并向主机发送

经过调试,以上功能基本实现,可以通过上位机对单片机进行实时控制。

程序如下:

//这是一个单片机C51串口接收(中断)和发送例程,可以用来测试51单片机的中断接收

//和查询发送,发送没有必要用中断,因为程序的开销是一样的

#include <reg51h>

#include<stdioh>

#include <stringh>

#define INBUF_LEN 4 //数据长度

unsigned char inbuf1[INBUF_LEN];

unsigned char checksum,count3 , flag,temp,ch;

bit read_flag=0;

sbit cp=P1^1;

sbit DIR=P1^2;

int i;

unsigned int xdata RAMDATA; /定义RAM地址指针/

unsigned char a[6] ={0x11,0x22,0x33,0x44,0x55,0x66} ;

void init_serialcomm(void)

{

SCON=0x50; //在110592MHz下,设置串行口波特率为9600,方式1,并允许接收

PCON=0x00;

ES=1;

TMOD=0x21; //定时器工作于方式2,自动装载方式

TH0=(65536-1000)%256;

TL0=(65536-1000)/256;

TL1=0xfd;

TH1=0xfd;

ET0=1;

TR0=1;

TR1=1;

// TI=0;

EA=1;

// TI=1;

RAMDATA=0x1F45;

}

void serial () interrupt 4 using 3

{

if(RI)

{ RI=0;

ch=SBUF;

TI=1; //置SBUF空

switch(ch)

{

case 0x01 :printf("A"); TI=0;break;

case 0x02 :printf("B"); TI=0;break;

case 0x03 :printf("C"); TI=0;break;

case 0x04 :printf("D"); TI=0;break;

default :printf("fg"); TI=0;break;

}

}

}

//向串口发送一个字符

void timer0() interrupt 1 using 3{

// char i;

flag++;

TH0=0x00;

TL0=0x00;

if(flag==10)

{// cp=!cp;

// for(i=0;i<6;i++)

P2=0x25;

TI=1;

temp=RAMDATA;

printf("%c",temp);

TI=0;

// RAMDATA--;

flag=0;

}

}

//主程序

main()

{

init_serialcomm(); //初始化串口

//向6264中送数据

{

RAMDATA=0x33;

}

while(1)

{

RAMDATA=0x33;;

}

}

调试需要注意的问题:

1 发送过程:在发送时必须保证TI=1:即发送缓冲器为空,否则将导致数据发不出去,如果想强制发送可以用:TI=1具体发送数据:利用printf(“abcd”);函数直接发送即可。

2 接收过程:在接收时多选用中断方式,这样可以节约CPU的时间,提高效率,

这里有两个晶振,一个是单片机的你选择12M,一个是sja1000的推荐选择16M。

给你程序你不一定能用啊,还要和硬件对应啊,比如你的地址确定问题。

这就是网络的程序为什么大多不能直接使用的原因啊。

给你提供一些思路

1、sja1000初始化

2、发送子程序

3、中断方式接收

下面是一些程序段

你参考下(已用于产品)

/SJA1000初始化//

void Init_SJA1000(void)

{

uchar state;

uchar ACRR[4]={0XAA,0XFF,0X22,0X11};// 接收代码寄存器

uchar AMRR[4]={0xff,0xff,0xff,0xff};// 接收屏蔽寄存器

//uchar AMRR[4]={0x00,0x00,0xff,0xff};// 接收屏蔽寄存器

do// 使用do--while语句确保进入复位模式

{

MODR = 0x09; // 设置MOD0=1--进入复位模式,以便设置相应的寄存器

state = MODR;

}

while( !(state & 0x01) );

// 对SJA1000部分寄存器进行初始化设置

CDR = 0x88; // CDR为时钟分频器,CDR3=1--时钟关闭, CDR7=0---basic CAN, CDR7=1---Peli CAN

BTR0 = 0x04;//0x31; // 总线定时寄存器0 ;总线波特率设定

BTR1 = 0x1c;//0x1c; // 总线定时寄存器1 ;总线波特率设定

IER = 0x01; // IER0=1--接收中断使能; IER1=0--关闭发送中断使能

OCR = 0xaa; // 配置输出控制寄存器

CMR = 0x04; // 释放接收缓冲器

ACR0 = ACRR[0];// 初始化接收代码寄存器

ACR1 = ACRR[1];

ACR2 = ACRR[2];

ACR3 = ACRR[3];

AMR0 = AMRR[0];// 初始化接收屏蔽寄存器

AMR1 = AMRR[1];

AMR2 = AMRR[2];

AMR3 = AMRR[3];

do// 使用do--while语句确保退出复位模式

{

MODR = 0x08; //MOD3=0--双滤波器模式

state = MODR;

}

while( state & 0x01 );

}//////////////////////////////////////

//CAN发送数据到CAN-Bus//

void CAN_TXD(void)

{

uchar state;

//初始化标示码头信息

TX_buffer[0] = 0x88; //7=0--扩展帧;6=0--数据帧; 0-3=100--数据长度为8字节

// TX_buffer[1] = 0xFF; //本帧信息的ID

//TX_buffer[2] = 0xFF;

TX_buffer[3] = 0xFF;

TX_buffer[4] = 0xFF;

do //查询SJA1000是否处于接收状态,当SJA1000不处于接收状态时才可继续执行

{

state = SR; //SR为SJA1000的状态寄存器

}

while( state & 0x10 ); //SR4=1 正在接收,等待

do //查询SJA1000是否处于发送完毕状态

{

state = SR;

}

while(!(state & 0x08)); //SR3=0,发送请求未处理完,等待直到SR3=1

do //查询发送缓冲器状态

{

state = SR;

}

while(!(state & 0x04)); //SR2=0,发送缓冲器被锁。等待直到SR2=1

//将待发送的一帧数据信息存入SJA1000的相应寄存器中

TBSR0 = TX_buffer[0];

TBSR1 = TX_buffer[1];

TBSR2 = TX_buffer[2];

TBSR3 = TX_buffer[3];

TBSR4 = TX_buffer[4];

TBSR5 = TX_buffer[5];

TBSR6 = TX_buffer[6];

TBSR7 = TX_buffer[7];

TBSR8 = TX_buffer[8];

TBSR9 = TX_buffer[9];

TBSR10 = TX_buffer[10];

TBSR11 = TX_buffer[11];

TBSR12 = TX_buffer[12];

CMR = 0x04; //置位发送请求

}//////////////////////////////////////

//中断接收来自CAN-Bus数据//

void inter1_can_rxd( void ) interrupt 0

{

uchar state;

EA = 0; //关CPU中断

IE0 = 0; //由于是中断INT1是电平触发方式,所以需要软件将INT1的中断请求标志IE0清零

state = IR; //IR为SJA1000的中断寄存器

if( state & 0x01) //若IR0=1--接收中断

{

RX_buffer[0] = RBSR0;

RX_buffer[1] = RBSR1;

RX_buffer[2] = RBSR2;

RX_buffer[3] = RBSR3;

RX_buffer[4] = RBSR4;

RX_buffer[5] = RBSR5;

RX_buffer[6] = RBSR6;

RX_buffer[7] = RBSR7;

RX_buffer[8] = RBSR8;

RX_buffer[9] = RBSR9;

RX_buffer[10] = RBSR10;

RX_buffer[11] = RBSR11;

RX_buffer[12] = RBSR12;

RXD_flag = 1; //接收标志置位,以便进入接收处理程序

CMR = 0x04; //CMR2=1--接收完毕,释放接收缓冲器

state = ALC; //释放仲裁随时捕捉寄存器(读该寄存器即可)

state = ECC; //释放错误代码捕捉寄存器(读该寄存器即可)

}

IER = 0x01; // IER0=1--接收中断使能

EA = 1; //重新开启CPU中断

}//////////////////////////////////////

// //

希望对你能有帮助

#发送程序#

#include<reg51h>

#define uchar unsigned char

void delay(unsigned int time)//延时约1ms

{

unsigned int j=0;

for(;time>0;time--)

for(j=0;j<125;j++);

}

void main(void)

{

uchar counter=0;

P2=0x3f;

TMOD=0x20;//定时器1为工作模式2

TH1=0xf4;//波特率为4800

TL1=0xf4;

PCON=0x00//波特率不加倍

TR1=1;//启动定时器1

SCON=0x50;//串口工作模式1,允许接收

while(1)

{

SBUF=counter;//发送counter

while(TI==0);//等待发送结束

TI=0;//清发送标志

while(RI==0);//等待接收数据

RI=0;//接收完毕,清标志

if(SBUF==counter)//如果接收数据等于counter则继续

{

P2=counter;//送显示

if(++counter>15)counter=0;//如果counter大于15则置0

delay(500);//延时500ms

}

}

}

#接收程序#//相同部分不注释了

#include<reg51h>

#define uchar unsigned char

void main(void)

{

uchar receiv;

P2=0x3f;

TMOD=0x20;

TH1=0xf4;

TL1=0xf4;

PCON=0x00;

TR1=1;

SCON=0x50;

while(1)

{

while(RI==1)//RI=0则执行循环

{

RI=0;

receiv=SBUF;//接收数据赋值给receiv

SBUF=receiv;//再将receiv发送出去

while(TI==0);//等待发送结束

TI=0;

P2=receiv;//receiv送显示

}

}

}

以上就是关于如何实现2个51单片机之间通过串口通信的源程序全部的内容,包括:如何实现2个51单片机之间通过串口通信的源程序、求CAN通信C程序。SJA1000+PC82C250.晶振是12M的。、两个单片机点对点的数据通信...有哪位高手...请教请教...等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/10218734.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-06
下一篇 2023-05-06

发表评论

登录后才能评论

评论列表(0条)

保存