你怎么在中断里面 Send...
看你程序处理的感觉很复杂,
本人应用的部分代码 共享下: <3 4 6 16号命令>
struct
{
union
{
u8 buf[5+(NumOfIR+NumOfHR)*2 ];
struct {// 3/4号 命令
u8 addr; //地址
u8 cmd; //命令
u16 shift; //偏移地址
u16 number; //寄存器数量
u16 crc; //校验
}msg_3_4;
struct{//16号命令
u8 addr; //地址
u8 cmd; //命令
u16 shift; //偏移地址
u16 number; //寄存器数量
u8 bytecnt; //字节数量
u16 *data; //数据
//u16 crc;
}msg_16;
//.....其他指令定义
}Buf;
u8 rcS; //超时计数
u16 rcIndex; //数据指针
bool rcOK; //接收完成
}uartRMsg; //接收缓冲区
//检测超时函数 供定时器中断调用-1ms一次
// t为超时时间
__inline void Chk_TimeOut(u8 t)
{
if(!uartRMsg.rcOK && (uartRMsg.rcIndex>=8) && (++uartRMsg.rcS >=t) ) //超时之后,开始重新解码
uartRMsg.rcOK = true;
}
//接收函数, 供USART中断调用
__inline void Recieve_MSG(char ch)
{
uartRMsg.rcS = 0; //如果接收到数据,则清除超市检测计数,
if(!uartRMsg.rcOK)
{
uartRMsg.Buf.buf[uartRMsg.rcIndex ++] = ch; //赋值
if(uartRMsg.rcIndex>=8 && uartRMsg.Buf.msg.cmd!=16)// 16号命令接收到的数据长度不是 固定的
uartRMsg.rcOK = true;
}
}
//供主函数调用
void MSGTransfer(void)
{
if(!uartRMsg.rcOK) return;
// if(uartRMsg.rcIndex<8) return;
if((uart_Address==uartRMsg.Buf.msg.addr) || (uartRMsg.Buf.msg.addr==0))//设备地址
{
WORD crc = CRC16(uartRMsg.Buf.buf ,
(uartRMsg.Buf.msg.cmd!=16)? 6 : (uartRMsg.Buf.msg_16_1.bytecnt + 7));
if(crc.Value != ((uartRMsg.Buf.msg.cmd!=16)? \
Message_R3R4.crc : \
(*(u16*)((u8*)uartRMsg.Buf.buf + uartRMsg.Buf.msg_16_1.bytecnt + 7 ))) )
{//CRC校验错误
uartRMsg.rcOK = false;
uartRMsg.rcIndex = 0;
return;
}
// if(uartRMsg.Buf.msg.addr==0) //广播地址
// {
// return;
// }
u16 shift,number;
shift = DATA_CHG_INT16(Message_R3R4.shift);
number= DATA_CHG_INT16(Message_R3R4.number);
SendBuf[0] = Message_R3R4.addr;
SendBuf[1] = Message_R3R4.cmd;
switch(Message_R3R4.cmd & 0xff ) //modbus命令
{
case 0: //
break;
case 1: //读取线圈状态
break;
case 2: //读取输入状态
break;
case 3: //读取保持寄存器(标定数据)
case 4: //读取输入寄存器(采样数据)
SendBuf[2] = number*2;
if((shift + number) <= ((Message_R3R4.cmd==3)?NumOfHR:NumOfIR))
{
u8 *p = (u8*)(((Message_R3R4.cmd==3)?DatasOfBD.buf  atasOfDT.buf) + shift*2);
for(int i=0; i< number; i++) //读取信息
{
SendBuf[3+ 2*i ] = p[2*i+1];
SendBuf[3+ 2*i+1] = p[2*i ];
}
crc.Value = 0xffff;
crc = CRC16(crc, SendBuf, 3 + number*2) ;
SendBuf[3 + number*2]=crc.cV[0] ;
SendBuf[4 + number*2]=crc.cV[1] ;
SendMessage(5 + number*2) ;
}
break;
case 5: //强制单线圈
break;
case 6: //强制单个寄存器
DatasOfBD.Datas[shift] = number;
EE.WriteByte(EE_BD_START + shift*2 + 0, DatasOfBD.buf[2*shift+0]);
EE.WriteByte(EE_BD_START + shift*2 + 1, DatasOfBD.buf[2*shift+1]);
for(int i=2;i<8;i++)
SendBuf = uartRMsg.Buf.buf;
SendMessage(8);
break;
case 16: //预置多个寄存器
if(shift + number < NumOfHR)
{
u16 *p = (u16*)((u8*)uartRMsg.Buf.buf + 7); //数据起始地址
for(int i=0; i<number; i++)
{
DatasOfBD.Datas[shift+i] = DATA_CHG_INT16(p);
EE.WriteByte(EE_BD_START + (shift+i)*2 + 0, DatasOfBD.buf[2*(shift+i)+0]);
EE.WriteByte(EE_BD_START + (shift+i)*2 + 1, DatasOfBD.buf[2*(shift+i)+1]);
}
for(int i=2; i<6;i++)
SendBuf = uartRMsg.Buf.buf;
crc = CRC16(SendBuf, 6) ;
SendBuf[6]=crc.cV[0] ;
SendBuf[7]=crc.cV[1] ;
SendMessage(8);
}
break;
default:
break;
}
}
uartRMsg.rcOK = false;
uartRMsg.rcIndex = 0;
}
仅供参考 |