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

📄 modbus.c

📁 使用Atmel88芯片实现RS485通讯,Modbus通讯协议.在IVR_AVR环境中编译,文件完整.
💻 C
字号:
//modbus.c         
#include <iom48v.h>        
#include <macros.h>            
#include "main.h"            
#include "modbus.h"         
#include "timer2.h"  
#include "led.h"

#define LocalAddr 0x01          
#define TRUE 1                                   
#define FLASE 0                               
volatile uchar sendPosi,sendCount;             
uchar receCount;                    
volatile uchar GetCntTemp;                  
 uchar sendBuf[16];                          
 uchar receBuf[16];                           
volatile uchar checkoutError;	//校验结果     
 uchar receTimeOut;				//接收超时     
                 
uchar GetKeyValue;
uint crc_result;

 uint testVarAnalog;
 uint testVarPoint;
 uint testVarInputUp;
 uint testVarInputDown;
				 
// UART0 initialize
// desired baud rate: 9600
// actual: baud rate:9615 (0.2%)
void uart0_init(void)
{
  UCSR0B = 0x00; //disable while setting baud rate
  UCSR0A = 0x02;		// 0x02;
  UCSR0C = 0x3E; //奇校验 2个停止位. 
  UBRR0L = 0x67; //set baud rate lo.
  UBRR0H = 0x00; //set baud rate hi.
// UCSR0B = 0xB8; //bit3 send enable.
  UCSR0B = 0b10010000;             
// UCSR0B &= ~BIT(TXCIE0); //RXCIE0 清零.
// UCSR0B &= ~BIT(TXEN0);  //TXEN0 清零.
}//void uart0_init(void)


void beginSend(void)
{
//sendEnable();    //设为发送.
	sendPosi = 0;
	if(sendCount > 1)
	    sendCount--;
//	TX9D = ParityBit(sendBuf[0]);
	UDR0 = sendBuf[0];
	//UCSR0B |= BIT(UDRIE0);       //  TXIE = 1;       //使能发送中断. 
	UCSR0B |= BIT(TXCIE0);
	UCSR0B |= BIT(TXEN0);		   //  TXEN = 1;		//使能发送
//	TXIE = 1;     
//	CREN = 1;
//	RCIE = 1;
//	CREN = 0;
//	RCIE = 0;
}//void beginSend(void)

/*
void singleKeyTranmit(void)
{
	sendBuf[0] = 0x12;	 
	sendBuf[1] = 0x34;	 
	sendBuf[2] = 0x56; 
	sendBuf[3] = 0x78; 
	sendBuf[4] = 0x90; 
	sendCount = 5;   //发送字节长 
	beginSend(); 
} 
*/


//单键值处理 
void singleKeyTranmit(void) 
{ 
	sendBuf[0] = 0xff;	
	sendBuf[1] = 0xaa;	
	sendBuf[2] = 0x55;	                //0x55 校验确认回复. 
   	crc_result = CRC16(sendBuf,3);	
    sendBuf[3] = (uchar)(crc_result&0x00ff);      // Lo byte. 
	sendBuf[4] = (uchar)((crc_result&0xff00)>>8); // Hi byte. 
//--------
	sendCount = 5;   
//----------
	beginSend();   
}  
 
 
// 从站接受信息帧处理 
void ReceiveFrameDisFun(void) 
{
 	if(receCount>4)
	{	 
		 		switch(receBuf[1])     	    //byte 2: Command byte.
				{	
					case 0:	
				 		  	break;
					case 1:	
							break;
					case 3: //请求变量
					 
					    if(receCount >= 8)
						{	
						  //PORTC ^= 0x02;    
						
     						if(receBuf[0]==LocalAddr && checkoutError==0) 
							{
								if(RecFrameCheck(&receBuf[0],receCount))
								{ //校验正确
				                     readRegisters();
									 LedShowLink = 1717;
								}  
							}
		    				receCount = 0;	
			    			checkoutError = 0;	
						}
				 
							break;
					
					case 5:
							break;
					
					case 0xaa:
						// PORTC ^= 0x02;        
						if(receCount >= 5)         
						{              
						//   PORTC ^= 0x02;       
							if(receBuf[0]==LocalAddr && checkoutError==0) 
							{
							 //  PORTC ^= 0x02;
								if( RecFrameCheck(receBuf,5) )     
								{//校验正确							
								//	PORTC ^= 0x02;												
					 				GetKeyValue = receBuf[2]; 
					  	     		LedShowLink = GetKeyValue;	
					   			singleKeyTranmit(); 
						 		}	                        
							} //if(receBuf[0]==LocalAddr && checkoutError==0) 
						receCount = 0;	
						checkoutError = 0;	
					    } 
							break;
                                 
					default:
					    	break;	 	// 错误功能码处理.
				}	//switch(receBuf[1]) 
	}	//	if(receCount>4)
	NOP();	
}  //void ReceiveFrameDisFun(void)


uchar RecFrameCheck(uchar *p_CheckData,uchar GetCntTempBuf)
{	
	uint CRCWord;	
	CRCWord = *(p_CheckData+(GetCntTempBuf-1)) + 
					(*(p_CheckData+(GetCntTempBuf-2))<<8); 
//	CRCWord = *(p_CheckData+(GetCntTempBuf-2)) + 
//				(*(p_CheckData+(GetCntTempBuf-1))<<8); 				
	if(CRCWord == CRC16(p_CheckData,GetCntTempBuf-2))	 
	{
		return TRUE;
	}
	else
	{
		return FLASE;
	}
}//uchar RecFrameCheck(uchar *p_CheckData,uchar GetCntTempBuf)	




//
MyWord CRC16(MyByte *data,int iLength)
{   
 	MyByte CRC16Lo,CRC16Hi;
    MyByte CL,CH;
 	MyByte SaveHi,SaveLo;
	int i,Flag;
    
	CRC16Lo = 0xff;
	CRC16Hi = 0xff;
	CL = 0x01;
	CH = 0xa0;
	for(i=0; i<iLength; i++)
	{
		CRC16Lo = CRC16Lo ^ data[i];
		for( Flag=0; Flag<=7; Flag++)
		{
			SaveHi = CRC16Hi;
			SaveLo = CRC16Lo;
			CRC16Hi = CRC16Hi>>1;
			CRC16Lo = CRC16Lo>>1;

			if((SaveHi&0x01) == 0x01)
			   CRC16Lo = CRC16Lo|0x80;

			if((SaveLo&0x01) == 0x01)
			{
				CRC16Hi = CRC16Hi ^ CH; //
				CRC16Lo = CRC16Lo ^ CL; //
			}
		}
	}
	return(CRC16Hi<<8 | CRC16Lo);
}//MyWord CRC16(MyByte *data,int iLength).


//读寄存器
void readRegisters(void)
{
	uint addr;
	uint  tempAddr;
	uint  result;
	uint  crcData;
	uchar readCount;
	uchar byteCount;
	uchar finsh;	//1完成  0出错
	uint  i;
  	uint  tempData = 0;	
	
    //起始地址 40001 (0x9c41)   
	addr = (receBuf[2]<<8) + receBuf[3];
	
	//tempAddr = addr & 0xfff;
	//addr = receBuf[3];
	tempAddr = addr;
	
    readCount = (receBuf[4]<<8) + receBuf[5];	//要读的个数
	//readCount = receBuf[5];
	
	byteCount = readCount * 2;
	
	for(i=0;i<byteCount;i+=2,tempAddr++)
	{
		getRegisterVal(tempAddr,&tempData);
		sendBuf[i+3] = tempData >> 8;
		sendBuf[i+4] = tempData & 0xff;
	}
	
	sendBuf[0] = 0xff;
	sendBuf[1] = 3;
	sendBuf[2] = byteCount;
	byteCount += 3;
	crcData = CRC16(sendBuf,byteCount);
	sendBuf[byteCount] = crcData >> 8;
	byteCount++;
	sendBuf[byteCount] = crcData & 0xff;
//----------
  	sendCount = byteCount + 1;
//	sendCount = 7;
//----------
	beginSend();
}//void readRegisters(void)


//取寄存器值 返回0表示成功
uint getRegisterVal(uint addr,uint *p_tempData)
{
	uint  result = 0;
	uint  tempAddr;

//	tempAddr = addr & 0xfff;
	addr = addr - 40000;	
	switch(addr)                 //(tempAddr)          // & 0xff)
	{
		case 0:
				break;
		case 1:
			 	*p_tempData = testVarAnalog;	// 模拟量当前值.	
				break;
		case 2:		
		    	*p_tempData = testVarPoint;   // 小数点位置.
				break;		
		case 3:
			 	*p_tempData = testVarInputUp; //  上限.
				break;		
		case 4:
	        	*p_tempData = testVarInputDown;// 下限. 
				break;		
		case 5:
				break;
		case 6:
				break;			
		case 7:
				break;		
		case 8:
				break;		
		case 9:
				break;  
		case 10:
				break;
		case 11:
				break;
		case 12:
				break;
		case 13:
				break;
		case 14:
				break;
		case 15:
				break;
		case 16:
				//*tempData = testRegister;
				break;
		default:
				break;
	}
	return result;
}//uint16 getRegisterVal(uint16 addr,uint16 &data)
 

 
 

⌨️ 快捷键说明

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