汇编编写的模拟串口通信程序
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的。、两个单片机点对点的数据通信...有哪位高手...请教请教...等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)