📄 server.c
字号:
#include "i2c.h"
#include "server.h"
u8 UDPAsk[] = "FFFFF"; //返回的应答
u8 UDPData[] = "FFFFFFFFFFFFFFFFFFFF"; //返回的数据(0x72指令)
extern u8 Cmd71_SetFlg; //0x71指令标识符
extern u8 Cmd77_SetFlg; //0x77指令设置标记(设置IP地址)
extern u8 Cmd79_SetFlg; //0x79指令标识符
extern u8 InputState[20][12]; //推子模块状态(临时场景信息)
extern u8 HotFireSet[4]; //热线地址
extern u8 HotFireClear; //"热线"按键屏蔽功能
extern u8 OutputSet[20]; //输出通道设置
extern u8 OutputGainSet[7]; //输出通道增益设置(最后还包含一个字节SyncMode)
extern u8 SyncMode; //同步模式
extern u8 KeyDataBK[20]; //存储原来按键值
extern u8 AddVoltage[5][4]; //话筒输入板加幻想电压(5个输入板,A/B/C/D四路)
extern u8 TabTotal; //节目列表总字节数(Tablen * 6 Byte)
extern u8 PlayTable[40][6]; //播放列表
extern u8 IPAddress[12]; //IP地址
extern u8 EffectTest[13]; //效果测试(0x74)
extern u8 EffectData[4][12]; //效果设置(0x75)
extern u8 EffectAddr[20][3]; //恢复效果(0x7A)(话筒输入板地址,效果编号,是否测试)
extern u8 ScenNum; //场景编号
extern u8 ScenKeyBK; //场景按键
extern u8 SceneSetFlag; //场景设置标记(为了使按下"场景"键时,只发送一次)
extern u16 TuiziAddr[5];
extern u16 InputAddr[5];
extern u16 OutputAddr[5];
extern CanTxMsg TxMessage;
/**
* @brief Initialize the server application.
* @param None
* @retval None
*/
void server_init(void)
{
struct udp_pcb *upcb;
/* Create a new UDP control block */
upcb = udp_new();
/* Bind the upcb to the UDP_PORT port */
/* Using IP_ADDR_ANY allow the upcb to be used by any local interface */
udp_bind(upcb, IP_ADDR_ANY, UDP_SERVER_PORT);
/* Set a receive callback for the upcb */
udp_recv(upcb, udp_server_callback, NULL);
}
/**
* @brief This function is called when an UDP datagrm has been received on the port UDP_PORT.
* @param arg : user supplied argument (udp_pcb.recv_arg)
* @param upcb: the udp_pcb which received data
* @param p : the packet buffer that was received
* @param addr: the remote IP address from which the packet was received
* @param port: the remote port from which the packet was received
* @retval None
*/
void udp_server_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, struct ip_addr *addr, u16_t port)
{
u16 j;
u8 u,k;
u8 ins = 0; //指令字节
u8 len = 0; //有效数据长度
// u8 add = 0; //有效数据总和
u8 check = 0; //校验码
u8 askdata[5] = {0}; //指令回复数据
u8 revdata[512]={0}; //接收的数据
u8 *pt = (u8 *)p->payload;
////////////////////////////////////////////
// #define DATALEN p->len
//
// printf("\nThe receive data :\n");
// for(j=0;j<DATALEN;j++)
// {
// printf("0x%X ",*pt);
// pt++;
// }
// printf("\n");
// pt = (u8 *)p->payload;
////////////////////////////////////////////
//开始处理网络接收的数据
if(*pt == 0x55) //第一个字节:start起始标识符
{
askdata[0] = 0x55;
pt++;
ins = *pt; //第二个字节:指令字节
askdata[1] = *pt;
if(ins == 0x71) //0x71指令,数据长度超过255字节,故未用第三字节表示有效数据长度
{
pt++;
for(j=0;j<272;j++)
{
revdata[j] = *pt;
pt++;
}
// printf("\nThe last data is = 0x%X\n",*pt);
// printf("The len is = %d\n\n",j);
askdata[2] = 0xFA;
askdata[3] = askdata[0]+askdata[1]+askdata[2];
if(*pt == 0xEE)
askdata[4] = 0xEE;
}
else if(ins == 0x79) //场景
{
pt++;
ScenNum = *pt; //场景编号
pt++;
for(j=0;j<312;j++)
{
revdata[j] = *pt;
pt++;
}
// printf("\nThe last data is = 0x%X\n",*pt);
// printf("The len is = %d\n\n",j);
askdata[2] = 0xFA;
askdata[3] = askdata[0]+askdata[1]+askdata[2];
if(*pt == 0xEE)
askdata[4] = 0xEE;
}
else
{
pt++;
len = *pt; //第三个字节:有效数据长度
pt++;
for(j=0;j<len;j++) //接收有效数据
{
revdata[j] = *pt;
// add += *pt;
pt++;
}
// check = 0x55+ins+len+add;
// if(check == *pt)
askdata[2] = 0xFA;
// else
// askdata[2] = 0xF4;
askdata[3] = askdata[0]+askdata[1]+askdata[2]; //校验和(CheckSum)
pt++;
if(*pt == 0xEE)
askdata[4] = 0xEE;
}
}
for(j=0;j<5;j++)
UDPAsk[j] = askdata[j];
//若接收正确,则根据不同指令,处理接收的数据
if((askdata[0] == 0x55)&&(askdata[2] == 0xFA)&&(askdata[4] == 0xEE))
{
switch(ins)
{
//*** 设置调音台数据 ***//
case (0x71):
if(ScenKeyBK) //"场景"按键有效
{
I2C_EE_BufferWrite(revdata,EEP_TempScene_Address,271); //临时场景
}
else //"场景"按键未按下时(临时场景)
{
Cmd71_SetFlg = 1;
I2C_EE_ByteWrite(Cmd71_SetFlg,EEP_Cmd71_Address);
I2C_EE_BufferWrite(revdata,EEP_TempScene_Address,271); //临时场景
u=0;k=0;
for(j=0;j<240;j++) //输入通道状态设置数据
{
InputState[k][u] = revdata[j];
u++;
if(u%12==0)
{
k++;
u=0;
}
}
for(u=0,j=240;j<244;j++) //热线设置数据
{
HotFireSet[u] = revdata[j];
u++;
}
for(u=0,j=244;j<264;j++) //输出通道状态设置数据
{
OutputSet[u] = revdata[j];
u++;
}
for(u=0,j=264;j<271;j++) //输出通道增益设置数据
{
OutputGainSet[u] = revdata[j];
u++;
}
SyncMode = OutputGainSet[6];//同步模式 revdata[270];
// printf("(0).SyncMode = 0x%X\n",SyncMode);
//上位机每设置一次临时场景,都会保存"效果设置"信息
for(j=0;j<20;j++)
{
if(InputState[j][7] == 0x03) //与推子模块绑定的是否是话筒输入板
EffectAddr[j][0] = InputState[j][8];//保存话筒输入板地址
else
EffectAddr[j][0] = 0; //未用话筒输入板绑定,没有地址
}
for(k=0,j=0;j<40;j++)
{
revdata[j++] = EffectAddr[k++][0];
revdata[j] = 0; //默认都未设置效果
}
I2C_EE_PageWrite(revdata,EEP_EffectAddr_Address,40);//保存话筒输入板地址
if(HotFireSet[2]) //处理"热线"按键
{
for(j=0;j<20;j++)
if(HotFireSet[2] == InputState[j][8])break;
HotFireClear = (((InputState[j][0]>>4)& 0x0F)-1)*4 + ((InputState[j][0]& 0x0F)-0x0A);
}
else
HotFireClear = 0xFF;
//刷新"设置"按键
TxMessage.RTR = CAN_RTR_DATA;
TxMessage.IDE = CAN_ID_STD;
TxMessage.DLC = 4;
if(TuiziAddr[0] != 0) //地址1推子
{
for(j=0;j<4;j++)
{
if((InputState[j][7] & 0x0F)!= 0x03)
KeyDataBK[j] &= ~(1<<3);
if(HotFireClear == j)
KeyDataBK[j] &= ~(1<<1);
TxMessage.Data[j] = KeyDataBK[j];
}
TxMessage.StdId = 0x101;
while(((CAN1->TSR>>26)& 0x07) == 0);
CAN_Transmit(CAN1, &TxMessage);
}
if(TuiziAddr[1] != 0) //地址2推子
{
for(k=0,j=4;j<8;j++)
{
if((InputState[j][7] & 0x0F)!= 0x03)
KeyDataBK[j] &= ~(1<<3);
if(HotFireClear == j)
KeyDataBK[j] &= ~(1<<1);
TxMessage.Data[k++] = KeyDataBK[j];
}
TxMessage.StdId = 0x201;
while(((CAN1->TSR>>26)& 0x07) == 0);
CAN_Transmit(CAN1, &TxMessage);
}
if(TuiziAddr[2] != 0) //地址3推子
{
for(k=0,j=8;j<12;j++)
{
if((InputState[j][7] & 0x0F)!= 0x03)
KeyDataBK[j] &= ~(1<<3);
if(HotFireClear == j)
KeyDataBK[j] &= ~(1<<1);
TxMessage.Data[k++] = KeyDataBK[j];
}
TxMessage.StdId = 0x301;
while(((CAN1->TSR>>26)& 0x07) == 0);
CAN_Transmit(CAN1, &TxMessage);
}
if(TuiziAddr[3] != 0) //地址4推子
{
for(k=0,j=12;j<16;j++)
{
if((InputState[j][7] & 0x0F)!= 0x03)
KeyDataBK[j] &= ~(1<<3);
if(HotFireClear == j)
KeyDataBK[j] &= ~(1<<1);
TxMessage.Data[k++] = KeyDataBK[j];
}
TxMessage.StdId = 0x401;
while(((CAN1->TSR>>26)& 0x07) == 0);
CAN_Transmit(CAN1, &TxMessage);
}
if(TuiziAddr[4] != 0) //地址5推子
{
for(k=0,j=16;j<20;j++)
{
if((InputState[j][7] & 0x0F)!= 0x03)
KeyDataBK[j] &= ~(1<<3);
if(HotFireClear == j)
KeyDataBK[j] &= ~(1<<1);
TxMessage.Data[k++] = KeyDataBK[j];
}
TxMessage.StdId = 0x501;
while(((CAN1->TSR>>26)& 0x07) == 0);
CAN_Transmit(CAN1, &TxMessage);
}
//设置推子模块数据
TxMessage.RTR = CAN_RTR_DATA;
TxMessage.IDE = CAN_ID_STD;
TxMessage.DLC = 8;
if(TuiziAddr[0] != 0) //地址1推子
{
TxMessage.StdId = TuiziAddr[0];
for(j=0;j<4;j++)
{
TxMessage.Data[0] = (InputState[j][7]<<4)|(j+1); //高4位信号格式,低4位数据包编号
TxMessage.Data[1] = InputState[j][8];
for(u=2;u<8;u++)
TxMessage.Data[u] = InputState[j][u-1];
while(((CAN1->TSR>>26)& 0x07) == 0);
CAN_Transmit(CAN1, &TxMessage);
}
}
if(TuiziAddr[1] != 0) //地址2推子
{
TxMessage.StdId = TuiziAddr[1];
for(j=4;j<8;j++)
{
TxMessage.Data[0] = (InputState[j][7]<<4)|(j-3); //高4位信号格式,低4位数据包编号
TxMessage.Data[1] = InputState[j][8]; //输入模块地址
for(u=2;u<8;u++)
TxMessage.Data[u] = InputState[j][u-1]; //6字节汉字码
while(((CAN1->TSR>>26)& 0x07) == 0);
CAN_Transmit(CAN1, &TxMessage);
}
}
if(TuiziAddr[2] != 0) //地址3推子
{
TxMessage.StdId = TuiziAddr[2];
for(j=8;j<12;j++)
{
TxMessage.Data[0] = (InputState[j][7]<<4)|(j-7); //高4位信号格式,低4位数据包编号
TxMessage.Data[1] = InputState[j][8];
for(u=2;u<8;u++)
TxMessage.Data[u] = InputState[j][u-1];
while(((CAN1->TSR>>26)& 0x07) == 0);
CAN_Transmit(CAN1, &TxMessage);
}
}
if(TuiziAddr[3] != 0) //地址4推子
{
TxMessage.StdId = TuiziAddr[3];
for(j=12;j<16;j++)
{
TxMessage.Data[0] = (InputState[j][7]<<4)|(j-11); //高4位信号格式,低4位数据包编号
TxMessage.Data[1] = InputState[j][8];
for(u=2;u<8;u++)
TxMessage.Data[u] = InputState[j][u-1];
while(((CAN1->TSR>>26)& 0x07) == 0);
CAN_Transmit(CAN1, &TxMessage);
}
}
if(TuiziAddr[4] != 0) //地址5推子
{
TxMessage.StdId = TuiziAddr[4];
for(j=16;j<20;j++)
{
TxMessage.Data[0] = (InputState[j][7]<<4)|(j-15); //高4位信号格式,低4位数据包编号
TxMessage.Data[1] = InputState[j][8];
for(u=2;u<8;u++)
TxMessage.Data[u] = InputState[j][u-1];
while(((CAN1->TSR>>26)& 0x07) == 0);
CAN_Transmit(CAN1, &TxMessage);
}
}
//加幻相电压
for(k=0;k<5;k++)
for(j=0;j<4;j++)
AddVoltage[k][j] = 0; //清零
for(j=0;j<20;j++)
{
if(InputState[j][7] == 0x03) //与推子模块绑定的是否是话筒输入板
{
u = ((InputState[j][8]>>4)& 0x0F)-0x01;
k = (InputState[j][8]& 0x0F)-0x0A;
if((u>=0x05)||(k>=0x04))continue;
if(InputState[j][10]== 0x01) //加幻相电压
{
AddVoltage[u][k] = 1;
}
else //不加幻相电压
AddVoltage[u][k] = 0;
}
}
//设置输入通道数据
TxMessage.RTR = CAN_RTR_DATA;
TxMessage.IDE = CAN_ID_STD;
TxMessage.DLC = 1;
if(InputAddr[0] != 0)
{
TxMessage.Data[0] = (AddVoltage[0][0]|(AddVoltage[0][1]<<1)|
(AddVoltage[0][2]<<2)|(AddVoltage[0][3]<<3))& 0x0F;
TxMessage.StdId = InputAddr[0];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -