/* p2p_m.c */
/* 双机点对点通信的主机部分 */
#ifndef __P2P_M_C__
#define __P2P_M_C__
#include <REGX52.H>
#include <STRING.H>
#define __MAX_LEN_ 64 // 数据最大长度
#define _MHZ_ 11 // 设置单片机使用的晶振频率(11.0592MHz)
/* 以下为程序协议中使用的握手信号 */
#define __RDY_ 0x06 // 主机开始通信时发送的呼叫信号
#define __BUSY_ 0x15 // 从机忙应答
#define __OK_ 0x00 // 从机准备好
#define __SUCC_ 0x0f // 数据传送成功
#define __ERR_ 0xf0 // 数据传送错误
void init_serial(); // 串口初始化
void send_data(unsigned char *buf); // 发送数据
void delay10ms(unsigned int count); // 延时子程序(10ms)
void main()
{
// char buf[__MAX_LEN_];
char buf[] = {1,2,3,4,5,6,7,8,9,0};
unsigned char i = 0;
unsigned char tmp = __BUSY_;
/* 为缓冲区赋初值 */
/* P0 = 0xff;
while(P1 != 0) // 每隔100ms从P0口读取,若读取到0则表明数据采集结束
{
*(buf+i) = P0;
delay10ms(10); // 延时100ms
P0 = 0xff;
i++;
}
*(buf+i) = 0; // 缓冲区最后一个字节为0表示数据结束 */
/* 串口初始化 */
init_serial(); // 初始化串口
EA = 0; // 关闭所有中断
/* 发送握手信号06H */
TI = 0;
SBUF = __RDY_;
while(!TI);
TI = 0;
/* 接收应答信息,如果接收的信号为00H,表示从机允许接收 */
while(tmp != __OK_)
{
RI = 0;
while(!RI);
tmp = SBUF;
RI = 0;
}
/* 发送数据并接收校验信息,如果接收的信号为0FH,表示从机接收成功,否则将重新发送该组数据 */
tmp = __ERR_;
while(tmp != __SUCC_)
{
send_data(buf); // 发送数据
RI = 0;
while(!RI);
tmp = SBUF;
RI = 0;
}
while(1); // 程序结束,进入死循环
}
/* 初始化串口 */
void init_serial()
{
TMOD = 0x20; //定时器T1使用工作方式2
TH1 = 250; // 设置初值
TL1 = 250;
TR1 = 1; // 开始计时
PCON = 0x80; // SMOD = 1
SCON = 0x50; //工作方式1,波特率9600bps,允许接收
}
/* 发送数据 */
void send_data(unsigned char *buf)
{
unsigned char len; // 保存数据长度
unsigned char ecc; // 保存校验字节
unsigned char i;
len = 10;//strlen(buf); // 计算要发送数据的长度
ecc = len; // 开始进行校验字节计算
/* 发送数据长度 */
TI = 0;
SBUF = len; // 发送长度
while(!TI);
TI = 0;
/* 发送数据 */
for(i=0; i<len; i++)
{
ecc = ecc^(*buf); // 计算校验字节
SBUF = *buf; // 发送数据
while(!TI);
buf++;
TI = 0;
}
/* 发送校验字节 */
SBUF = ecc; // 发送校验字节
while(!TI);
TI = 0;
}
/* 延时10ms,精度较低,参数count为延时时间 */
void delay10ms(unsigned int count)
{
unsigned int i, k;
unsigned char j;
unsigned int tmp;
tmp = (int)((100*_MHZ_)/12);
for(i=0; i<count; i++)
for(j=0; j<100; j++)
for(k=0; k<tmp; k++);
}
#end
/* p2p_s.c */
/* 双机点对点通信的从机部分 */
#ifndef __P2P_S_C__
#define __P2P_S_C__
#include <p30f6014a.h>
#include <STRING.H>
_FOSC(0x0ffe5); //XT振荡,4倍频晶振.
_FWDT(WDT_OFF); //关闭看门狗定时器
_FBORPOR(PBOR_OFF & MCLR_EN); //掉电复位禁止,MCLR复位使能。
_FGS(CODE_PROT_OFF); //代码保护禁止
#define __MAX_LEN_ 64 // 数据最大长度
#define _MHZ_ 11 // 设置单片机使用的晶振频率(11.0592MHz)
/* 以下为程序协议中使用的握手信号 */
#define __RDY_ 0x06 // 主机开始通信时发送的呼叫信号
#define __BUSY_ 0x15 // 从机忙应答
#define __OK_ 0x00 // 从机准备好
#define __SUCC_ 0x0f // 数据传送成功
#define __ERR_ 0xf0 // 数据传送错误
void init_serial(); // 串口初始化
unsigned char recv_data(unsigned char *buf); // 接收数据
//void Beep_ok(); // 蜂鸣表示数据接收ok,该函数代码未给出
void delay()
{
int i, j;
for(i =1000; i>0; i--)
for(j=1000; j>0; j--);
}
void main()
{
unsigned char i = 0;
char buf[__MAX_LEN_];
unsigned char tmp = 0xff;
TRISD = 0XFF00;
LATD = 0;
/* 串口初始化 */
init_serial(); // 初始化串口
// EA = 0; // 关闭所有中断
/* 进入设备应答阶段 */
while(1)
{
/* 如果接收到的数据不是握手信号__RDY_,则继续等待 */
while(tmp != __RDY_)
{
// RI = 0;
// while(!RI);
// tmp = SBUF;
// RI = 0;
IFS1bits.U2RXIF = 0;
while(!IFS1bits.U2RXIF);
tmp = U2RXREG;
IFS1bits.U2RXIF=0;
}
/* 程序通过检测P0口数据判断当前设备状态,若P0=0xab,表示当前设备忙 */
// P0 = 0xff;
// tmp = P0;
// if(tmp == 0xab) // 如果P0口数据为0x,则当前设备忙,发送__BUSY_信号
// {
// TI = 0;
// SBUF = __BUSY_;
// while(!TI);
// TI = 0;
// continue;
// }
// TI = 0; // 否则发送__OK_信号表示可以接收数据
// SBUF = __OK_;
// while(!TI);
// TI = 0;
U2TXREG = __OK_;
while(!U2STAbits.TRMT);
/* 数据接收 */
tmp = 0xff;
while(tmp == 0xff)
{
tmp = recv_data(buf); // 校验失败返回0xff,接收成功则返回0
}
// Beep_ok(); // 蜂鸣表示数据接收成功
// LATD = 0xaa;
while(buf[i] != '\0')
{
LATD = buf[i++];
delay();
}
i = 0;
}
}
/* 初始化串口 */
void init_serial()
{
// TMOD = 0x20; //定时器T1使用工作方式2
// TH1 = 250; // 设置初值
// TL1 = 250;
// TR1 = 1; // 开始计时
// PCON = 0x80; // SMOD = 1
// SCON = 0x50; //工作方式1,波特率9600bps,允许接收
U2BRG =64; //波特率设置为9600,外部10M
U2MODEbits.PDSEL = 0;//8位数据,无奇偶校验
U2MODEbits.STSEL = 0;//一位停止位
U2STAbits.UTXISEL = 0;//发送数据就产生中断
U2STAbits.URXISEL = 0;//每当一个数据字从接收移位寄存器传输到接收缓冲器之后就产生中断
U2MODEbits.UARTEN = 1;
U2STAbits.UTXEN =1; //允许发送
IFS1bits.U2TXIF = 0;//发送使能之后,会自动将此为置1,
//如果UTXISEL = 0,当一个字从发送缓冲器传输到
//发送移位寄存器(UxTSR)时产生中断
}
/* 接收数据,注意该函数使用buf指向的缓冲区保存数据,在数据末尾使用'\0'表示数据结束
* 返回值为0,数据校验成功,返回值为0xff,数据校验失败
*/
unsigned char recv_data(unsigned char *buf)
{
unsigned char len; // 该字节用于保存数据长度
unsigned char ecc; // 该字节用于保存校验字节
unsigned char i,tmp;
/* 接收数据长度 */
// RI = 0;
// while(!RI);
// len = SBUF;
// RI = 0;
IFS1bits.U2RXIF = 0;
while(!IFS1bits.U2RXIF);
len = U2RXREG;
IFS1bits.U2RXIF = 0;
/* 使用len的值为校验字节ecc赋初值 */
ecc = len;
/* 接收数据 */
// for(i=0; i<len; i++)
// {
// while(!RI);
// *buf = SBUF; // 接收数据
// ecc = ecc^(*buf); // 进行字节校验
// RI = 0;
// buf++;
// }
for(i = 0; i<len; i++)
{
IFS1bits.U2RXIF = 0;
while(!IFS1bits.U2RXIF);
*buf = U2RXREG;
IFS1bits.U2RXIF = 0;
ecc = ecc^(*buf);
buf++;
}
*buf = 0; // 表示数据结束
/* 接收校验字节 */
// while(!RI);
// tmp = SBUF;
// RI = 0;
IFS1bits.U2RXIF = 0;
while(!IFS1bits.U2RXIF);
tmp = U2RXREG;
IFS1bits.U2RXIF = 0;
/* 进行数据校验 */
ecc = tmp^ecc;
if(ecc != 0) // 校验失败
{
*(buf-len) = 0; // 清空数据缓冲区
// TI = 0; // 发送校验失败信号
// SBUF = __ERR_;
// while(!TI);
// TI = 0;
U2TXREG = __ERR_;
while(!U2STAbits.TRMT);
return 0xff; // 返回0xff表示校验错误
}
// TI = 0; // 校验成功
// SBUF = __SUCC_;
// while(!TI);
// TI = 0;
// return 0; // 校验成功,返回0
U2TXREG = __SUCC_;
while(U2STAbits.TRMT);
return 0;
}
#endif