⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 f340_modbus.c

📁 单片机Modebus主站程序 MCU:C8051F340
💻 C
📖 第 1 页 / 共 2 页
字号:
	sendBuf[7]=dat>>8;sendBuf[8]=(char)dat;		//数据内容
	crcData.U16 = crc16(sendBuf,9);				//CRC
	sendBuf[9]=crcData.U8[MSB];					//CRC高字节
	sendBuf[10]=crcData.U8[LSB];					//CRC低字节
	sendCount =11;								//发送字节数
	beginSend();								//开始发送
}//-----------------------------------------------------------------------------
// sendComm0Modbus
//
// Modbus状态机,在MAIN中调用
//
//-----------------------------------------------------------------------------
void sendComm0Modbus(void)
{
	U8 i,j;
	if(FM_alarming[3]==0x0f&&menu_alarm_set[3]==-1)MB_SetAlarm|=0x20;else MB_SetAlarm&=~0x20; 	//反向回转
	if(FM_alarming[3]==0xff&&menu_alarm_set[3]==-1)MB_SetAlarm|=0x40;else MB_SetAlarm&=~0x40; 	//正向回转
	i=FM_alarming[0]|FM_alarming[2]|FM_alarming[4];j=menu_alarm_set[0]|menu_alarm_set[2];
	if(i==-1&&j==-1)MB_SetAlarm|=0x08;else MB_SetAlarm&=~0x08;									//起升向上
	i=FM_alarming[1]|FM_alarming[2]|FM_alarming[4];j=menu_alarm_set[1]|menu_alarm_set[2];
	if(i==-1&&j==-1)MB_SetAlarm|=0x10;else MB_SetAlarm&=~0x10;									//变幅向外

	if(!bMB_idle)												//空闲
	{
		if(bMB_setup)											//设置状态
		{
			if(menu_comm0_test>0&&menu_comm0_test<6)			//发送诊断
				Modbus_CommandSend(menu_comm0_test,8,0xaa);			
			else if(menu_brChange!=SetReg0)						//改变波特率
			{	Modbus_CommandSend(0,6,menu_brChange);SetReg0=menu_brChange;}
		}
		else													//工作状态
		{
			if(MB_SendNum>12)MB_SendNum=1;
			else MB_SendNum+=1;
			for(i=0;i<5;i++)
			{
				if     (menu_comm0_addr[i]=='Y'&& MB_SendNum==i+1)	//FunC:01
				{	Modbus_CommandSend(i+1,4,16);return;}		
				else if(menu_comm0_addr[i]=='Y'&& MB_SendNum==i+6)	//FunC:03
				{	Modbus_CommandSend(i+1,1, 8*4);return;}	
				else if(menu_comm0_addr[0]=='Y'&& MB_SendNum==11)	//FunC:15
				{	if(MB_c15done=='S')Modbus_DataSend(1,15,0,SignalSet);return;}		
				else if(menu_comm0_addr[0]=='Y'&& MB_SendNum==12)	//FunC:15
				{	Modbus_DataSend(1,15,16,MB_SetAlarm);return;}

			}
		}
	}
}
//-----------------------------------------------------------------------------
// beginSend
//
//开始发送
//-----------------------------------------------------------------------------
void beginSend(void)
{	
	b485Send = 1;								//设为发送
	bMB_idle = 1;								//Modbus占用
	sendPosi = 0;
	if(sendCount > 1) sendCount--;
	ACC = sendBuf[0];
	TB80 = P;
	SBUF0 = sendBuf[0];
}
//-----------------------------------------------------------------------------
// checkComm0Modbus
//
// Modbus状态机,在MAIN中调用
//
//-----------------------------------------------------------------------------
void checkComm0Modbus(void)
{
	U16 crcData;
	U16 tempData;
	if(receCount > 4)
	{
		MB_ErrorCode=0;									//Modbus错误清零
		switch(receBuf[1])
		{
			case 1:										//读取线圈状态(读取点 16位以内)
			case 2:										//读取输入状态(读取点 16位以内)
					tempData = receBuf[2]; 
					tempData += 5;						//数据个数
					if(receCount >= tempData)
					{
						if(receBuf[0]==sendBuf[0] && checkoutError==0)
						{
							crcData = crc16(receBuf,tempData-2);
							if(crcData==(receBuf[tempData-2]<<8)+receBuf[tempData-1])
								Master_readCoil();		//保存数据			
							else MB_ErrorCode=92;		//CRC错误
							MB_BroadTimer=0;MB_TimeOut=0;
							bMB_idle=0;					//释放总线
						}	
						receCount = 0;checkoutError = 0;
					}
					break;
			case 3:										//读取保持寄存器(一个或多个)
			case 4:										//读取输入寄存器(一个或多个)
					tempData =receBuf[2];
					tempData += 5;
					if(receCount >= tempData)
					{
						if(receBuf[0]==sendBuf[0] && checkoutError==0)
						{
							crcData = crc16(receBuf,tempData-2);
							if(crcData == (receBuf[tempData-2]<<8)+ receBuf[tempData-1])
								Master_readRegisters();			
							else MB_ErrorCode=92;		//CRC错误
							MB_BroadTimer=0;MB_TimeOut=0;
							bMB_idle=0;					//释放总线
						}	
						receCount = 0;checkoutError = 0;
					}
					break;
			case 5:										//强制单个线圈
			case 6:										//设置单个寄存器
			case 8:										//回送诊断校验
			case 15:									//设置多个线圈(128)
			case 16:									//设置多个寄存器(16)
					if(receCount >= 8)					//接收完成一组数据
					{
						if((receBuf[0]==sendBuf[0]) && checkoutError==0)
						{
							crcData = crc16(receBuf,6);
							if(crcData != receBuf[7]+(receBuf[6]<<8))MB_ErrorCode=92;		//CRC错误	
							else if(receBuf[1]==8){if(receBuf[5]==0xaa)MB_TestEcho=0xaa;}	//数据正确
							else if(receBuf[1]==15)MB_c15done=15;							//c15完成
							MB_BroadTimer=0;MB_TimeOut=0;
							bMB_idle=0;					//释放总线
						}						
						receCount = 0;checkoutError = 0;
					}
					break;
			default:									//非法功能处理
					if(receBuf[1]>=0x80)
					{
						MB_ErrorCode=receBuf[2];		//出错代码
						MB_BroadTimer=0;MB_TimeOut=0;
						bMB_idle=0;						//释放总线
					}
		}
	}
}
//-----------------------------------------------------------------------------
// Master_readCoil
//
//读线圈状态:读出从机数据保存到主机
//-----------------------------------------------------------------------------
void Master_readCoil(void)
{
	U8 addr;
	U8 tempAddr;
	U8 bitCount;
	UU16 tempData;
	U8 i,k;
	U8  exit = 0;
	addr = (sendBuf[2]<<8)+sendBuf[3];
	bitCount = (sendBuf[4]<<8)+sendBuf[5];
	tempAddr =addr;
	for(k=0;k<receBuf[2];k++)
	{										//字节位置
		tempData.U8[0] = receBuf[3+k];
		for(i=0;i<8;i++)
		{
			tempData.U16=tempData.U16>>1;	//位信息存在tempData.U8[1]最高位
			setCoilVal(tempAddr,tempData.U8[1]);
			tempData.U8[1] = 0;
			tempAddr++;
			if(tempAddr >= addr+bitCount){exit = 1;break;}//读完	
		}
		if(exit == 1) break;
	}
}

//-----------------------------------------------------------------------------
// Master_readRegisters
//
//读寄存器:读出从机数据保存到主机
//-----------------------------------------------------------------------------
void Master_readRegisters(void)
{
	U8 addr;
	U8 tempAddr;
	U8 byteCount;
	U16 i;
	U16 tempData = 0;	

	addr = 0;
	tempAddr = addr;
	byteCount = receBuf[2];	
	for(i=0;i<byteCount;i++,tempAddr++)
	{
		tempData = (receBuf[i*2+3]<<8) + receBuf[i*2+4];
		setRegisterVal(tempAddr,tempData);			
	}
}	
//-----------------------------------------------------------------------------
// setCoilVal
//
//设定线圈状态 返回0表示成功
//-----------------------------------------------------------------------------

U16 setCoilVal(U16 addr,U8 tempData)
{
	U16 result = 0;
	U8 tempAddr;
	U8 d,f;	
	d=1;
	tempAddr = addr/8;
	f   = addr%8;
	d = d <<f;
	if (tempData != 0) SetCoil[receBuf[0]-1][tempAddr] |= d;
	else SetCoil[receBuf[0]-1][tempAddr] &= ~d;

	return result;
}
//-----------------------------------------------------------------------------
// setRegisterVal
//
//设置寄存器值 返回0表示成功
//-----------------------------------------------------------------------------

U16 setRegisterVal(U16 addr,U16 tempData)
{
	U16 result = 0;
	SetReg[receBuf[0]-1][addr] = tempData;
	return result;
}
//-----------------------------------------------------------------------------
// End Of File
//-----------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -