求教高人指点单片机多机通信的C语言程序
哪个按键按下,对应的指示灯亮,主单片机得到信息。 展开
再另一个DSP上总共有4个字节,要发送到这个SPI上来做比较. 一个一个的发送的
我想请教你一下. 以下是我写的勒个接收比较函数
unsigned char CheckSum_RevData(unsigned flag) //接收函数
{
unsigned char ret_byte=0;
...
...
return ret_byte; //这里就返回了一个字节
}
void MCU_CheckSum(void)
{
unsigned char retdata_group[4];
unsigned char valid;
....
....
...
... //valid以计算出来了
for( i=0; i <4; i++ )
{
retdata_group = CheckSum_RevData(); //接收到的4个字节赋给数组了. (这一步其实我想要的效果是一个一个的接收,比较一个接收一个)
}
for(i=0; i <4; i++)
{
if( retdata_group == valid_data )
SPI_Printf("\n CHECKSUM OK");
else
SPI_Printf("\n CHECKSUM FAIL");
}
}
我上面写的这个是一次性把4个字节接收完后.再一一做比较..但是.我想要的效果是接收一个字节比较一个字节.如果当第一个字节就相同后,.就OK. 不同的话再接收比较第二个..我在这里应该怎么使用这个返回值啊?
retdata_group[0] = CheckSum_RevData()
if(valid_data == retdata_group[0])
SPI_Printf("OK");
else
retdata_group[1] = CheckSum_RevData()
if(valid_data == retdata_group[1])
SPI_Printf("OK");
else
SPI_Printf("FAIL");
像我这么写的 .那么retdata_group[0]和retdata_group[1]得到的返回值都是一样的吧? 肯定不对吧.我应该怎么书写啊,才能得到我要的效果啊.
从机:
#include<reg52.h>
#include <intrins.h>
char shou=0xff,fa=0,flag=0;
unsigned char code tab[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};
#define DATA P1
sbit rs=P3^5;
sbit rw=P3^6;
sbit en=P3^7;
void cmd(unsigned char x);
void dat(unsigned char x);
void ready();
void delay(unsigned int x);
void LCD_1602_init(void);
void LCD_1602_init(void)
{
cmd(0x38);
cmd(0x0c);
cmd(0x01);
cmd(0x06);
}
void delay(unsigned int x)
{
while(x--);
}
void ready()
{
rw=1;
rs=0;
en=1;
while(!DATA&0x80);
en=0;
delay(100);
}
void cmd(unsigned char x)
{
ready();
DATA=x;
rs=0;
rw=0;
en=1;
delay(100);
en=0;
}
void dat(unsigned char x)
{
ready();
DATA=x;
rs=1;
rw=0;
en=1;
delay(100);
en=0;
}
void DELAY(void) //误差 0us
{
unsigned char a,b;
for(b=215;b>0;b--)
for(a=45;a>0;a--);
_nop_(); //if Keil,require use intrins.h
_nop_(); //if Keil,require use intrins.h
}
void main()
{
TMOD=0X20;
SCON=0X50;
PCON=0X80;
TH1=0XF3;
TL1=0XF3;
TR1=1;
ES=1;
EA=1;
LCD_1602_init();
while(1)
{
cmd(0x80);
dat(tab[(shou>>7)&0x01]);
dat(tab[(shou>>6)&0x01]);
dat(tab[(shou>>5)&0x01]);
dat(tab[(shou>>4)&0x01]);
dat(tab[(shou>>3)&0x01]);
dat(tab[(shou>>2)&0x01]);
dat(tab[(shou>>1)&0x01]);
dat(tab[(shou>>0)&0x01]);
}
}
void ser_int (void) interrupt 4 using 1
{
if(RI==1) /*本机的接收通过串行口中断来实现,即他时刻在准备着接收数据。*/
{
RI=0;
shou=SBUF;
SBUF=4; /*收到数据后,立即发送确认信号“4”,以便对方确认。*/
while(TI==0);
TI=0;
}
}
主机:
#include<reg52.h>
#include <intrins.h>
sbit LED=P3^7;
char fa=0,shou=0,mark=1,key=0xff;
void delay(void) //误差 0us
{
unsigned char a,b;
for(b=215;b>0;b--)
for(a=45;a>0;a--);
_nop_(); //if Keil,require use intrins.h
_nop_(); //if Keil,require use intrins.h
}
void main()
{
P2=0xff;
LED=1;
TMOD=0X20;
SCON=0X50;
PCON=0X80;
TH1=0XF3;
TL1=0XF3;
TR1=1;
ES=1;
EA=1;
while(1)
{
if(key!=0xff)
{
delay();
if(P2!=0xff)
{
key=P2;
mark=0;
LED=0;
}
while(P2!=0xff);
}
else {LED=1;mark=1;}
if(mark==0)
{
SBUF=key;
while(TI==0); /*有按键按下时,通过串行口不停向外面发出键值,直到接收到外面发出的确认信号“4”*/
TI=0; /*时,才停止发送数据,等待有新的按键被按下。如此反复。*/
} /*本机的接收通过串行口中断来实现,即他时刻在准备着接收数据。*/
delay();
}
}
void ser_int (void) interrupt 4 using 1
{
if(RI==1)
{
RI=0;
shou=SBUF;
if(shou==4)
{
mark=1;
}
}
}
非常感谢你的回答,刚才我一直在看你写的程序,编译都正确,但是我做的是长距离的多机通信,所以麻烦你帮我做一下程序的修改吧,谢谢了,我会提高悬赏的。
这就要靠自己了,
按你的图仿真的,调试通过
从机按键按一次主机的对应的LED状态的取反一次
//主机A
#include <REGX51.H>
#define uchar unsigned char
#define F_OSC 12000000UL //外部晶振频率率Hz
#define F_BAUD 1200UL //定义波特率
#define RELOAD (uchar)(256-F_OSC/12/32/F_BAUD)
#define B_ID 2 //来至B从机的信息
#define C_ID 3 //来至于c从机
#define LED_ON 4 //信息为开LED
#define LED_OFF (~LED_ON) //信息为关LED
sbit P20 = P2^0;
sbit LEDB = P1^0;
sbit LEDC = P1^1;
typedef union
{
uchar buf[2];
struct
{
uchar databuf;
uchar TXID;
}Option;
}TYPE_UART_SERIAL;
TYPE_UART_SERIAL SysUart;
void UartInit()
{
SCON = 0x50;//工作与方式1允许接受
TMOD = 0x20;//定时器1工作与方式2自动重装模式
TH1 = RELOAD;
TR1 = 1;
TI = 0;
EA = 1;
ES=1;
P20=0;
}
void main(void)
{
UartInit();
LEDB=0;
LEDC=0;
while(1)
{
if((SysUart.Option.TXID==B_ID)&&(SysUart.Option.databuf!=0))
{
SysUart.Option.TXID=0;
if (SysUart.Option.databuf==LED_ON)
{
LEDB=1;
}
if(SysUart.Option.databuf==LED_OFF)
{
LEDB=0;
}
SysUart.Option.databuf=0;
}
if((SysUart.Option.TXID==C_ID)&&(SysUart.Option.databuf!=0))
{
SysUart.Option.TXID=0;
if (SysUart.Option.databuf==LED_ON)
{
LEDC=1;
}
if(SysUart.Option.databuf==LED_OFF)
{
LEDC=0;
}
SysUart.Option.databuf=0;
}
}
}
void SerialServe() interrupt 4
{
static uchar pcnt=0;
if (RI == 1)
{
RI = 0;
SysUart.buf[pcnt] = SBUF;
pcnt =(pcnt+1)%2;
}
if (TI == 1)
{
}
}
//从机B
#include <REGX51.H>
#define uchar unsigned char
#define F_OSC 12000000UL //外部晶振频率率Hz
#define F_BAUD 1200UL //定义波特率
#define RELOAD (uchar)(256-F_OSC/12/32/F_BAUD)
#define B_ID 2
#define LED_ON 4
#define LED_OFF (~LED_ON)
sbit P20 = P2^0;
sbit key = P1^0;
typedef union
{
uchar buf[2];
struct
{
uchar databuf;
uchar TXID;
}Option;
}TYPE_UART_SERIAL;
TYPE_UART_SERIAL SysUart;
void UartInit()
{
SCON = 0x40;//工作与方式1允许接受
TMOD = 0x20;//定时器1工作与方式2自动重装模式
TH1 = RELOAD;
TR1 = 1;
TI = 0;
EA = 1;
P20=1;
}
void SerialSenData(uchar *SerialBuf)
{
uchar i;
i=2;
while (i--)
{
SBUF = *SerialBuf;
SerialBuf++;
while (!TI);
TI = 0;
}
}
void main(void)
{
uchar ledbuf;
UartInit();
ledbuf=LED_OFF;
while(1)
{
if(key==0)
{
ledbuf=~ledbuf;
SysUart.Option.databuf=ledbuf;
SysUart.Option.TXID = B_ID;
SerialSenData(SysUart.buf);
while(key==0);
}
}
}
void SerialServe() interrupt 4
{
if (RI == 1)
{
RI = 0;
}
if (TI == 1)
{
}
}
//从机C
#include <REGX51.H>
#define uchar unsigned char
#define F_OSC 12000000UL //外部晶振频率率Hz
#define F_BAUD 1200UL //定义波特率
#define RELOAD (uchar)(256-F_OSC/12/32/F_BAUD)
#define C_ID 3
#define LED_ON 4
#define LED_OFF (~LED_ON)
sbit P20 = P2^0;
sbit key = P1^0;
typedef union
{
uchar buf[2];
struct
{
uchar databuf;
uchar TXID;
}Option;
}TYPE_UART_SERIAL;
TYPE_UART_SERIAL SysUart;
void UartInit()
{
SCON = 0x40;//工作与方式1允许接受
TMOD = 0x20;//定时器1工作与方式2自动重装模式
TH1 = RELOAD;
TR1 = 1;
TI = 0;
EA = 1;
P20=1;
}
void SerialSenData(uchar *SerialBuf)
{
uchar i;
i=2;
while (i--)
{
SBUF = *SerialBuf;
SerialBuf++;
while (!TI);
TI = 0;
}
}
void main(void)
{
uchar ledbuf;
UartInit();
ledbuf=LED_OFF;
while(1)
{
if(key==0)
{
ledbuf=~ledbuf;
SysUart.Option.databuf=ledbuf;
SysUart.Option.TXID = C_ID;
SerialSenData(SysUart.buf);
while(key==0);
}
}
}
void SerialServe() interrupt 4
{
if (RI == 1)
{
RI = 0;
}
if (TI == 1)
{
}
}
非常感谢你的回答,但是我仿真的时候,从机B正常,从机C的结果出不来,请问是什么原因?如果你的仿真成功了,可不可以发到我的邮箱里,417530976@qq.com,或者QQ发给我也行,谢谢了
2、长线的话对于这个应用来说,还不如用线的钱买无线模块。485通信的话,程序跟直接一样的,无需改变。多机通信就是地址的区别。
3、这个设计就试试而已,没有现实意义,个人觉得用短线代替就可以,就做做实验吗,没必要485转换。做个转换还不如直接两根线将按键拉到U1,就算你的线再长,我用总是可以用两个单片机的成本来做滤波和驱动,程序比你简单,可靠性绝对不比你低。
我就是想做一个远程的报警系统,你有什么好的建议吗?针对我的电路图需要做那些改动吗?既然你说线太长,成本太高,那么怎么来做一个远程的报警系统呢
那要看你的要求了,距离、可靠性、成本、联机数量等。我觉得你如果只做做毕业设计,就用你现在的好了。