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

📄 modbus.c

📁 C51 MODBUS 实现
💻 C
字号:




/*************************************************************************************/
#ifdef		MODBUS_COMM
	//MODBUS 命令定义
	#define		REGISTERREAD		0x03        //读出存储寄存器的内容
	#define		REGISTERWRITEONBYTE 0x06        //改写一个特定的寄存器的数据
	#define		REGISTERWRITE		0x10        //连续写入多个存储寄存器
	#define		COMMTEST			0x08        //通讯测试

	//MODBUS 寄存器地址定义
	//1.系统参数及通讯参数
	#define		Device_Code			0x00		//设备识别号
	#define		Device_Comm_Sel		0x01		//设备通讯模式寄存器
	#define		Device_Comm_Pr		0x02		//设备通讯参数(通讯地址,通讯速率)
	#define		Device_Tcp_Iph		0x03		//TCP 通讯IP地址高字节寄存器
    #define		Device_Tcp_Ipl		0X04		//TCP 通讯IP地址低字节寄存器
 	#define		Device_Tcp_Maskh	0X05		//TCP 通讯子网掩码地址高字节寄存器
	#define		Device_Tcp_Maskl	0X06		//TCP 通讯子网掩码地址低字节寄存器
	#define		Device_Tcp_Gateh	0X07		//TCP 通讯网关地址高字节寄存器
	#define	    Device_Tcp_Gatel	0X08		//TCP 通讯网关地址低字节寄存器
	//2.系统时间
	#define		Minute_Second		0x09		//分,秒
	#define		Day_Hour			0x0a		//日,小时
	#define		Year_Month			0x0b		//年,月
	#define		Bak					0X0c		//预留备用寄存器 oc-oh
 	//其他寄存器
    #define		Anomalous_Staus		0x10		//异常状态寄存器
	//3.机器实时运行参数
	#define		Ux_Volt			    0x20		//系统电压
	#define		Uc_Volt				0x21		//机端电压
	#define		Ut_Volt				0x22		//调差电压
	#define		Ilc_Value			0x23		//励磁电流
	#define		Cos_Value			0x24		//功率因数
	#define		Q_Value				0x25		//无功功率
	#define		Fre_Jd				0x26		//机端频率
	#define		Alf_Value			0x27		//触发相位角
	#define		Ug_Volt				0x28		//给定电压
	#define		Ilg_Value			0x29		//给定电流
	#define		Cosg_Value			0x2a		//给定功率因数
	#define		Qg_Value			0x2b		//给定无功
	#define		Alfg_Value			0x2c		//给定ALF角度
	#define		Bak 				0x2d		//预留备用寄存器   2d-2f
	//4.机器开入开出状态寄存器
	#define		Switch_In			0x30		//开入输入变量	
	#define		Switch_Out			0x31		//开入输入变量
	//5.机器实时运行状态寄存器		
	#define		Run_Staus			0x32		//机器实时运行状态寄存器	
	#define		Run_Bak				0x33		//状态备用寄存器   33-3f
	//6.励磁设置参数寄存器
	#define		P_Set						0x40	//PID参数P寄存器
	#define		I_Set						0x41	//PID参数I寄存器
	#define		D_Set						0x42	//PID参数D寄存器
	#define		Kq_Set						0x43	//无功功率比例参数寄存器
	#define		Ile_Set						0x44	//励磁电流比例参数寄存器
	#define		Ct_Set						0x45	//CT 变比参数寄存器
	#define		Pt_Set						0x46	//PT 变比参数寄存器
	#define		Tc_Set						0x47	//调差系数寄存器
	#define		LcIncDec_Set				0x48	//增减励寄存器
	#define		AutoStartStop_Set			0x49	//自动开机停机寄存器
	#define		RunMode_Set					0x4a	//运行模式寄存器
	#define		UxTron_Set					0x4b	//网跟控制寄存器	
	#define		Excitation_Set				0x4c	//高低起励寄存器
	#define		MkActive_Set				0x4d	//灭磁开关寄存器
	#define		Excitation_Suppression_Set 	0x4e	//起励灭磁寄存器
	#define		Bak_Set						0x4f	//预留备用寄存器		
   //	#define

//全局变量定义:
//UART2 缓冲单元
unsigned char xdata 	UART2_ReceiveBuffer[UART_DATAPACK_SIZE];	  	//接收缓冲单元
unsigned char 			UART2_ReceiveCount = 0;		//接收的字节数
unsigned char 			UART_SendNum = 0;			//发送的字节数	
unsigned char xdata		UART_SendOk	 = 0;			//已经发送的字节数 
unsigned char xdata 	UART2_ReceiveBuffer[UART_SENDPACK_SIZE];		//发送缓冲单元

//扩展缓冲单元
unsigned char xdata 	SPI_ReceiveBuffer[SPI_DATAPACK_SIZE];	  	//接收缓冲单元
unsigned char 			SPI_ReceiveCount = 0;						//接收的字节数
unsigned char 			SPI_SendNum = 0;							//发送的字节数	
unsigned char xdata		SPI_SendOk	 = 0;							//已经发送的字节数
unsigned char xdata 	SPI_SendBuffer[SPI_SENDPACK_SIZE];			//发送缓冲单元 
//本身地址
unsigned int            My_Addr
//液晶缓冲单元
unsigned char xdata 	Yj_ReceiveBuffer[];		    //接收缓冲单元
unsigned char xdata 	Yj_SendBuffer[];		   	//发送缓冲单元
//液晶接收处理标志位
unsigned int			Yj_ReceiveFlag;			//液晶接收缓冲单元中是否有数据要求液晶进行处理标志位
unsigned int			Yj_SendFlag;				//液晶发送缓冲单元中是否有数据要求液晶进行处理标志位

//----------------------------SPI发送程序--------------------------------//
unsigned char  SPISendComm(unsigned char *buf,unsigned char len)
{
	unsigned int  timeout=0;

	if (len > SPI_SENDPACK_SIZE)		//长度大于UART长度,出错
		return -1;

	if (SPI_SendOk != 0)				//已经发送的字节数不为0
	{
		while (SPI_SendOk != 0)
		{
			timeout++;
			if (timeout >= 3000)
			{
				SPI_SendOk = 0;		//已经发送的字节数清0
				SPI_SendNum = 0;		//发送的字节数清0
				return 1;
			}
		}
		return 1;
	}

	memcpy(SPI_SendBuffer,buf,len);
	SPI_SendNum = len;
	void WriteData(SPI_SendBuffer,channelA, buf,len);
	ES = 1;
	SPI_SendOk=1;
	return 0;													//modify								
}


//-----------------------------串口发送程序-------------------------------//
unsigned char  UARTSendComm(unsigned char *buf,unsigned char len)
{
	unsigned int  timeout=0;

	if (len > UART_SENDPACK_SIZE)
		return -1;

	if (UART_SendOk != 0)
	{
		while (UART_SendOk != 0)
		{
			timeout++;
			if (timeout >= 3000)
			{
				UART_SendOk = 0;
				UART_SendNum = 0;
				return 1;
			}
		}
		return 1;
	}

	memcpy(UART_SendBuffer,buf,len);
	UART_SendNum = len;
	S2BUF=UART_SendBuffer[0];
	ES = 1;
	UART_SendOk=1;
	return 0;													//modify								
}


/************************************************************************************** 
* 名称:GetCommData
* 说明:判断液晶接收数据的正确性
* 功能:7eH 外部与MCU通讯;feH液晶与MCU通讯;My_AddrH外部通讯(0X20之前,外部与液晶通讯;之后,外部与MCU通讯)
* 调用:
* 输入: UART2_ReceiveBuffer,SPI_ReceiveBuffer
* 返回值:7eH返回值为2;feH返回值1;My_Addr返回值0
* ************************************************************************************/
unsigned char GetCommData(unsigned char *len)
{
	unsigned char comm;
	unsigned char length[2];
	unsigned char tempaddr;
	unsigned char ret;
	unsigned char receivecount;			//接收的字节数
	unsigned char receivebuffer[];     //接收到的数据

	ret = -1;
	*len = 0;

	if (receivecount >= 8)                     //接收的字节数
 	{
		tempaddr =  receivebuffer[0];
		if ( (tempaddr != My_Addr) && (tempaddr != 0x7e) && (tempaddr != 0xfe) )
	   		return  ret;
				 	  
		comm =  receivebuffer[1];
		switch (comm)
		{
			case REGISTERWRITE:
				 *(unsigned int*)(length+0) = 9 + (*(unsigned int*)( receivebuffer+4) *2);//接收到数据字节数
				 if (*(unsigned int*)(length+0) < MAXREADLENGTH )//接收到的字节数小于最大字节长度
				 	if (CrcCmp16( receivebuffer,length[1]) ==0)//CRC校验
					{
						if (tempaddr == 0x7e)
							ret = 2;
					    if (tempaddr == 0xfe)
							ret = 1;
						if (tempaddr == My_Addr)
							ret = 0;
						*len = length[1];
						return ret;
				     }
				   break;

			case REGISTERREAD:
			case COMMTEST:
		    case REGISTERWRITEONBYTE:
				 if (CrcCmp16( receivebuffer,8) ==0)       //接受到字节数是8个,CRC校验
				 {
			 			if (tempaddr == 0x7e)
							ret = 2;
					    if (tempaddr == 0xfe)
							ret = 1;
						if (tempaddr == My_Addr)
							ret = 0;
						*len = 0x08;
						return ret;

				 }
				 break;
	   }
	}
	return ret;
}


/*************************************************************************************
*名称:SendDataToMCU
*说明:液晶把接收到的串口2数据发给MCU;
*功能:把调节器地址替换成7e,重新进行CRC校验,发送给MCU
*调用:
*输入:UART2_ReceiveBuffer
*输出

⌨️ 快捷键说明

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