#include <stc12c5a.h>
#include <string.h>
#include "uart.h"
#include "delay.h"
#include "lcd1602.h"
#include "arraykey.h"
//定义发送数据包的状态,0为发送数据包,1为回复数据包
#define REPLY 1
#define SEND 0
//定义该机的编号,主机为255,两个从机的编号为8和2
#define Master_MCU
#define MCU_ID 255
#define LEFT_MCU_ID 8
#define RIGHT_MCU_ID 2
//数据包指针,目标,源和数据起始点
#define DESTMCU 3
#define SOURMCU 4
#define DATASTART 5
/***************************************全局变量**************************************/
unsigned char index = 0;
/*************************************显示的字符串************************************/
unsigned char stringReceive[]="Received:MCU#001";
unsigned char stringReceived[]=" ";
unsigned char code stringSend[]="Sending data to:";
unsigned char code stringSent[]=" Send Success ";
unsigned char stringSendMCU[]=" MCU #001 ";
unsigned char code stringTransmit[]=" Transmitting ";
unsigned char code stringTransmitted[]="Transmit Success";
unsigned char stringTransmitMCU[]="MCU #000 to #000";
unsigned char code welcomestring[]=" M-S Com System ";
unsigned char code welcomestringMaster[]=" Master MCU ";
unsigned char code SendUIstring[]=" Send Data: ";
unsigned char InputString[]=" ";
/************************************数据包格式定义**********************************/
unsigned char DataPacket[25];
//数据包格式:
//00-02:起始标志("B&S")
//03:目标机ID
//04:源机ID
//05-20:16个字节的数据(ACK包数据第一字节为0xAA)
//21-23:结束符("END")
//注意:数据包里的数据不应该有任何一个0x00,否则发送时会认为这是数据包的结束!
unsigned char code StartFlag[] = "B&S"; //起始标志符
unsigned char code EndFlag[] = "END"; //结束标志符
/***************************************函数声明*************************************/
void SendDataPacket(bit);
void Check_New_Message(void);
void DataPacketInit(void);
void ProcessPacket(unsigned char);
void SendUI(void);
void WelcomeDisplay(void);
void SendDisplay(void);
void TransmitDisplay(void);
void ReceiveDisplay(void);
void SuccessDisplay(void);
/************************************************************************************/
void main()
{
delay1ms(255); //消除开机造成的抖动
Uart1Init();
Uart2Init();
DataPacketInit();
LCD1602_init();
WelcomeDisplay();
EA = 1;
while(1)
{
Check_New_Message();
if(KeyDown())
{
SendUI();
}
}
}
/************************************************************************************/
//用于发送的用户界面函数
/************************************************************************************/
void SendUI()
{
bit flag = 0;
unsigned char i,Key;
DataPacketInit(); //初始化数据包
DataPacket[SOURMCU] = MCU_ID; //将源机设置成自己的编号
for(i=0;i<16;i++)
InputString[i] = ' '; //初始化显示的字符串
i = 0; //清空i,用于按下次数的统计
LCD1602_display(SendUIstring,InputString);
while(!flag)
{
Key = KeyDown(); //获取按键状态
if(!Key) //获取到0则为没有任何按键按下,直接跳过后续判断
continue;
else if(Key<11) //按下0-9时(按下1为1,2为2。。。按下0为10)
{
if(i<16) //满16个后不能再继续输入
{
Key = (Key%10)+'0'; //取这个数的ASCII码
InputString[i] = Key; //数据包和显示的字符串都更新
DataPacket[DATASTART+i] = Key;
i++;
LCD1602_display2(InputString); //进行显示
}
}
else if(Key == 11) //按下发送至左侧从机的键时
{
DataPacket[DESTMCU] = LEFT_MCU_ID; //数据包的目标机部分填上左侧从机的ID
SendDataPacket(SEND); //发送数据包
SendDisplay(); //显示已发送
flag = 1; //标志设为1,退出循环
}
else if(Key == 12) //按下发送至右侧从机的键时
{
DataPacket[DESTMCU] = RIGHT_MCU_ID; //数据包的目标机部分填上右侧从机的ID
SendDataPacket(SEND);
SendDisplay();
flag = 1;
}
else //按下其他键时,是取消的作用
{
WelcomeDisplay(); //显示开机界面
flag = 1; //退出
}
}
}
/************************************************************************************/
//发送数据包的函数
/************************************************************************************/
void SendDataPacket(bit reply)
{
if(!reply)
{
if(DataPacket[DESTMCU] == LEFT_MCU_ID) //往数据包目标机发送出去
UART1_SendString(DataPacket);
else if(DataPacket[DESTMCU] == RIGHT_MCU_ID)
UART2_SendString(DataPacket);
}
else
{
DataPacket[DATASTART] = 0xAA; //ACK回应
if(DataPacket[SOURMCU] == LEFT_MCU_ID) //往数据包源机发送回去,目标机发现这是个ACK包,不会理会目标机源机是什么,因此不需要改动
UART1_SendString(DataPacket);
else if(DataPacket[SOURMCU] == RIGHT_MCU_ID)
UART2_SendString(DataPacket);
}
}
/************************************************************************************/
//检查是否有数据包收到的函数
/************************************************************************************/
void Check_New_Message()
{
//strstr是检测子串函数,如果在该字符串内有出现该子串,返回子串第一次出现的指针,如果没有则返回NULL
if(strstr(Uart2_Buf,"END")!=NULL) //在串口2缓冲区内检查到了数据包结束标志,说明收到了一个数据包
{
Uart2_Buf[UART2_Int] = '\0'; //将缓冲区当前字节设置为数组结束,否则后面处理数据包会出现死循环
ProcessPacket(2); //交由处理数据包函数进行处理
}
if(strstr(Uart1_Buf,"END")!=NULL) //在串口1缓冲区内检查到了数据包结束标志,说明收到了一个数据包
{
Uart1_Buf[UART1_Int] = '\0';
ProcessPacket(1);
}
}
/************************************************************************************/
//处理收到数据包的函数
/************************************************************************************/
void ProcessPacket(unsigned char source)
{
unsigned char *tempString;
switch(source) //根据源机的不同而对不同的缓冲区进行操作
{
case 1:
tempString = strstr(Uart1_Buf,"B&S"); //检测数据包起始标志符的位置,获得一个指针,但是数据还在缓冲区里!
strncpy(DataPacket,tempString,24); //把数据复制下来,只复制24个字节
CLR_Buf1(); //清空缓冲区
break;
case 2:
tempString = strstr(Uart2_Buf,"B&S");
strncpy(DataPacket,tempString,24);
CLR_Buf2();
break;
default:
break;
}
DataPacket[24] = '\0'; //设置数组结束符
if(DataPacket[DATASTART] == 0xAA) //如果获得的是ACK包,直接显示发送完成/转发完成
SuccessDisplay();
else if(DataPacket[DESTMCU] == MCU_ID) //如果是收到一个数据包(目标MCU为自己),则显示内容并回复ACK
{
ReceiveDisplay();
SendDataPacket(REPLY);
}
else //如果是收到一个需要中转的数据包(目标MCU不为自己),则转发并显示
{
TransmitDisplay();
SendDataPacket(SEND); //先发出数据包再回复,回复会修改数据包内容
SendDataPacket(REPLY);
}
}
/************************************************************************************/
//初始化数据包的函数
/************************************************************************************/
void DataPacketInit()
{
unsigned char i;
for(i=0;i<3;i++) //写入标志符
{
DataPacket[i] = StartFlag[i];
DataPacket[i+21] = EndFlag[i];
}
for(i=0;i<16;i++) //清空数据区,不能写0,而是写入空格,传输也是以字符的形式传输而不是传输数字本身
{
DataPacket[DATASTART+i] = ' ';
}
DataPacket[24] = '\0'; //数组结束
}
/************************************************************************************/
//显示相关的函数
/************************************************************************************/
void WelcomeDisplay()
{
LCD1602_display(welcomestring,welcomestringMaster);
}
void SuccessDisplay()
{
if(DataPacket[SOURMCU] == MCU_ID)
LCD1602_display1(stringSent);
else
LCD1602_display1(stringTransmitted);
}
void SendDisplay()
{
stringSendMCU[11] = DataPacket[DESTMCU] + '0';
LCD1602_display(stringSend,stringSendMCU);
}
void TransmitDisplay()
{
stringTransmitMCU[7] = DataPacket[SOURMCU] + '0';
stringTransmitMCU[15] = DataPacket[DESTMCU] + '0';
LCD1602_display(stringTransmit,stringTransm