本帖最后由 qq511153186 于 2013-8-20 09:12 编辑
哪位大侠能提供一下简单的电路吗?谢谢了!!
当主机发送0xff命令时会有操作?
我的仿真效果是将 tbuf[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};数据给从机,从机再输出给流水灯,
现在出了点问题,流水灯是全亮的
主机代码:
#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
#define address 0x02 //从机的地址
uchar rbuf[8];
uchar code tbuf[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
void UART_init()
{
TMOD = 0x20; //计时计数器1工作方式2
TH1 = 0xfd; //串口的波特率为9600b/s
TL1 = 0xfd;
TR1 = 1; //开定时计数器
SCON = 0xf8; //1101 1000 工作方式3
}
void err(void)
{
SBUF=0xff; //复位信号,命令各从机复位
while(TI!=1); //发送过程中TI一直保持低电平,发完一帧后,硬件置1
TI=0;
}
uchar master(uchar addr,uchar command)
{
uchar aa,i,p;
while(1)
{
SBUF=addr; //发呼叫地址
while(TI!=1);
TI=0;
while(RI!=1); //从机比较地址后,等待从机把本机的地址发回主机
RI=0;
if(SBUF!=addr)
err();
else
{
TB8=0; //清地址标志
SBUF=command; //发命令
while(TI!=1);
TI=0;
while(RI!=1); //从机应答
RI=0;
aa=SBUF ; //接收状态
if(aa&0x08==0x08) //若命令未被接收,发复位信号
{
TB8=1;
err();
}
else
{
if(command==0x01) //主机发送数据命令
{
if((aa&0x01)==0x01) //从机准备好接收数据
{
do
{
p=0; //清检验和
for(i=0;i<8;i++)
{
SBUF=tbuf;
p+=tbuf;
while(TI!=1);
TI=0;
}
SBUF=p;
while(TI!=1);
TI=0;
while(RI!=1);
RI=0;
}
while(SBUF!=0); //校验和正确,回送正确信号00H
TB8=1;
return(0);
}
}
//if(command==0x02)
//{
else
{
if((aa&0x02)==0x02) //接收命令,从机准备好发送
{
while(1)
{
p=0; //清校验和
for(i=0;i<8;i++)
{
while(RI!=1); //等待接收完成
TI=0;
rbuf=SBUF;
p+=rbuf;
}
while(RI!=1);
RI=0;
if(SBUF==p)
{
SBUF=0x00; //校验和相同发00
while(TI!=1);
TI=0;
break;
}
else
{
SBUF=0xff; //校验和不同发ff重新接收
while(TI!=1);
TI=0;
}
}
TB8=1;
return(0);
}
}
}
}
}
}
void main()
{
UART_init();
master(address,0x01);
master(address,0x02);
while(1);
}
从机代码:
#include<reg52.h>
#define uchar unsigned char
#define address 0x02
uchar tbuf[8];
uchar rbuf[8];
bit tready;
bit rready;
void str(void);
void sre(void);
void delay_ms(int t);
main(void)
{
uchar i;
TMOD=0x20; //T1方式2
TL1=0xfd;
TH1=0xfd;
//PCON=0x00;
TR1=1;
SCON=0xf0; //串口为方式3
ES=1; //开串行中断
EA=1;
P1=0xff;
while(1)
{
tready=1;
rready=1;
for(i=0;i<8;i++)
{
P1=rbuf;
delay_ms(500);
}
}
}
void delay_ms(int t)
{
uchar i;
while(t--)
for(i=0; i<120; i++);
}
void ssio(void) interrupt 4
{
uchar a ;
RI=0; //清接收中断标志位
ES=0; //关串行中断
if(SBUF!=address) //接收到的不自己的地址,直接跳到程序最后
{
ES=1;
goto reti;
}
SM2=0; //与自己的地址相符,取消监听状态
SBUF=address; //回传地址给主机
while(TI!=1);
TI=0;
while(RI!=1); //等待主机回
RI=0;
if(RB8==1) //此为地址不符时的情况,主机发来的复位信号
{
SM2=1;
ES=1;
goto reti;
}
a=SBUF; //开始检测主机发来的命令
if(a==0x01) //主机命令从机接收数据
{
if(rready==1) //接收准备标志
SBUF=0x01; //从机应答,回发命令
else
SBUF=0x00;
while(TI!=1);
TI=0;
while(RI!=0); //等待主机发送数据
RI=0;
if(RB8==1) //数据出错
{
SM2=1;
ES=1;
goto reti;
}
sre(); //接收数据
}
else
{
if(a==0x02) //主机命令从机发送数据命令
{
if(tready==1)
SBUF=0x02; //回送命令检验
else
SBUF=0x00;
while(TI!=1);
TI=0;
while(RI!=0);
RI=0;
if(RB8==1) //数据出错
{
SM2=1;
ES=1;
goto reti;
}
str(); //发送数据
}
else //非法命令
{
SBUF=0x80; //命令非法,发状态
while(TI!=1);
TI=0;
SM2=1;
ES=1; //恢复监听
}
}
reti:;
}
void str(void) //发数据
{
uchar p,i;
tready=0;
do
{
p=0;
for(i=0;i<8;i++)
{
SBUF=tbuf;
p+=tbuf;
while(TI!=1);
TI=0;
}
SBUF=p; //发送校验和
while(TI!=1);
TI=0;
while(RI!=0);
RI=0;
}
while(SBUF!=0); //校验和正确,主机会发磅正确信号00H
SM2=1;
ES=1; //恢复监听
}
void sre(void) //接收数据
{
uchar p,i;
rready=0;
while(1)
{
p=0; //清校验和
for(i=0;i<8;i++)
{
while(RI!=1); //等待接收数据完成
RI=0;
rbuf=SBUF; //存接收到的数据
p+=rbuf;
}
while(RI!=1); //接收主机发来的校验和p
RI=0;
if(SBUF==p) //校验和正确
{
SBUF=0x00; //校验和正确回送正确信号00H
break; //跳了while(1)
}
else
{
SBUF=0xff; //校验和错误,回送0ffH, 重新接收
while(TI==0);
TI=0;
}
}
SM2=1; //回到监听状态
ES=1; //开串行中断
}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
我这里没用到电平转换 ,直接用得串口通信,方式3
一周热门 更多>