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

📄 c8051f340-modbus.c

📁 用新华龙的C8051F340单片机
💻 C
📖 第 1 页 / 共 2 页
字号:
//modbus通信协议实现
//

#include <c8051f340.h>            
#include <intrins.h>
//-----------------------------------------------------------------------------
// Global CONSTANTS
//-----------------------------------------------------------------------------
#define BaudRate       19200//9600,14400,19200,38400,56000可选        
#define SYSCLK         12000000    
//#define BAUDRATE     9600         
//#define SYSCLK       11059200     
sbit GREEN = P2^2;
sbit RED   = P2^1;
sbit PF    = P2^0;
//-----------------------------------------------------------------------------
// Function PROTOTYPES
//-----------------------------------------------------------------------------

#define u16 unsigned int
#define u8 unsigned char
#define   MAXNByte  15   //最大字节数
//#define  time0      30000
#define  MAXREG     100   //最大寄存器数量

//void SYSCLK_Init (void);
void PORT_Init (void);   //IO口初始化
void UART0_Init (void);   //uart0初始化

void readRegisters(void) ;//读寄存器,功能码03
void beginSend(void) ;    //发送子程序
void presetMultipleRegisters(void);//设置多个寄存器,功能码16
void FLASH_ByteWrite(u16 addr, u8 byte);//flash写
void FLASH_PageErase (u16 addr);        //flash页擦写
//void Receive_timeout(void);             //超时子程序
u16 crc_chk(u8 *dat,u8 length);         //CRC校验
u8 FLASH_ByteRead (u16 addr);           //flash读
//void presetSingleRegisters(void);       //设置单个寄存器,功能码06
void send_err(u8 err,u8 err_code);       //发送错误
void Timer0_Init(void);                  //定时器0初始化
void PCA_Init();
u16 flag;
u8 temp;
u8 count_receiveNByte;//接收字节数
u8 mod_buf[20];       //modubs 数据接收缓冲区
u8 sendBuf[20];       //发送缓冲区
u8 sendCount;         //发送字节数
u8 localAddr = 3;     //单片机控制板的地址
//u16 Receivetimeout;    //定时初值
//bit ReceiveBit;    

//unsigned int  code  baud_code[8] = {};
/*?????*/
/*void delay(unsigned int m)
{
 unsigned int n;
 n=0;
 while(n < m)
 {n++;}
 return;
}  */
//-----------------------------------------------------------------------------
// MAIN Routine
//-----------------------------------------------------------------------------

void main(void)
{
   u16 dat;
   u16 tempData;
   u16 crcData;
   PCA0MD    &= ~0x40;                    
   OSCICN    |= 0x03; 

   //SYSCLK_Init ();                     
    PORT_Init ();                       
    UART0_Init (); 
    PCA_Init();                    
// 	Timer0_Init();
    EA=1;
    ES0=1;
	PS0=1;
	GREEN=1;     
    RED=0;
 while(1){
  if (mod_buf[0]==localAddr)
  { 
     if(count_receiveNByte>4) 
	{


    switch(mod_buf[1])
	{
       case 0x03:
	                    if(count_receiveNByte>=8)
	      		 	    { 
				          crcData = crc_chk(mod_buf,6);  //CRC校验
                          dat=mod_buf[7];
                          if(crcData==mod_buf[6]+(dat<<8)) //CRC校验结果比较
                        
                              readRegisters();         // 如果检验正确,那么就回应数据
							  count_receiveNByte=0;     //接受数据指针归零   
						 
                         }
                    break;
                    
                 
/*    	case 0x06:
               if(count_receiveNByte>=8)
	      		 	{ 
				     crcData = crc_chk(mod_buf,6);  //CRC校验
					 dat=mod_buf[7];
                   if(crcData==mod_buf[6]+(dat<<8)) //CRC校验结果比较
                     
 		            presetSingleRegisters();
                    count_receiveNByte=0;     //接受数据指针归零  
 			       }
                   break;*/
	    case 0x10:
		           dat=mod_buf[4];
                   tempData = (dat<<8) + mod_buf[5];
                   tempData = tempData * 2; //数据个数
                   tempData += 9;
                if(count_receiveNByte >= tempData)
                 {
                  
                     crcData = crc_chk(mod_buf,tempData-2);
                     dat=mod_buf[tempData-1];
                    if(crcData == (dat<<8)+ mod_buf[tempData-2])
                      
		                presetMultipleRegisters();
						count_receiveNByte=0;     //接受数据指针归零   
					
				 }
				  break; 
		 default:
                  break; 
	 }
				

   }
   
         
  }
  else
    count_receiveNByte=0;     //接受数据指针归零
  _nop_();
//    Receive_timeout();
   PCA0CPH4 = 0x00;
 }
}

//-----------------------------------------------------------------------------
// SYSCLK_Init
//-----------------------------------------------------------------------------
//
// This routine initializes the system clock to use an 22.1184MHz crystal
// as its clock source.
//
//void SYSCLK_Init (void)
//{
//   int i;                              

//   OSCXCN = 0x67;                     
 //  for (i=0; i < 256; i++) ;         

//   while (!(OSCXCN & 0x80)) ;          

//   OSCICN = 0x88;                     
//}

//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
//
// Configure the Crossbar and GPIO ports
//

void PCA_Init()
{
    PCA0CN     =  0x40;                // PCA counter enable
    PCA0MD    &= ~0x40 ;               // Watchdog timer disabled-clearing bit 6
    PCA0MD    &=  0xF1;                // timebase selected - System clock / 12
    PCA0CPL4   =  0xFF;                // Offset value
    PCA0MD  |= 0x40;
    PCA0L    = 0x00;               	   // Set lower byte of PCA counter to 0  
    PCA0H    = 0x00; 
}

void PORT_Init (void)
{
   XBR0    = 0x01;                      //UART TX0, RX0连到端口引脚P0.4和P0.5
   XBR1    = 0x40;
   XBR2    = 0x00;                     //UART1的I/O不连到端口引?
   P0MDOUT |= 0x01;                    //TX0输出为推挽方式
   P2MDOUT |= 0x3f;                   
   P1MDOUT |= 0xff;
//   P0SKIP  |= 0xc0;
}

//-----------------------------------------------------------------------------
// UART0_Init
//-----------------------------------------------------------------------------
//
// Configure the UART0 using Timer1, for <baudrate> and 8-N-1.
//
void UART0_Init (void)
{
    SCON0   = 0x50;                    
    TMOD    = 0x20;                    
	if(BaudRate > 38400)                 
	{
		CKCON  = 0x08;                      //定时器使用系统时钟
		TH1    = 256-SYSCLK/2/BaudRate;
	}
	if(BaudRate <= 38400) 
	{
		CKCON  = 0x01;                      //定时器时钟用系统时钟的4分频
		TH1    = 256-SYSCLK/4/2/BaudRate;
	}
   TL1=TH1;
   TR1    = 1;                        
   CKCON |= 0x01;                      //定时器时钟用系统时钟的4分频
   PF=0;
}

/*void Timer0_Init(void)
{
 TMOD |= 0x01;        // 定时器0: 方式1,16位定时器
 TF0=0;        
 TR0=1;// TR0
 CKCON |= 0x10;        // 
 TH0 = 0xf1; //256 -((60*SYSCLK/1000/12)/256);
 TL0 = 0xc2;//256 -((60*SYSCLK/1000/12)%256);
 ET0=1;
}

void timer0() interrupt 1 using 2 //定时器中断
{   
    TF0=0;
    TR0=0;
    TH0=0xf1;    //3.646ms interrupt
    TL0=0xc2;
    flag++;
	if(flag==15)
	 {
	   flag=0;
       if(count_receiveNByte<=2)    //超时后,若接收缓冲区有数则判断为收到一帧
       {
              count_receiveNByte=0;     //接受数据指针归零   ;
       }
	  }
	TR0=1;
}
/***********************************************************
CRC校验
***************************************************************/
u16 crc_chk(u8 *pData,u8 nLen)
{
u16 temp=0xffff,temp1,i,j;
 for(i=0;i<nLen;i++)
    {
    temp^=*(pData+i);
	for(j=0;j<8;j++)
		{
		temp1=temp;
		temp>>=1;
		if(temp1&0x0001)
			temp^=0xa001;
        }
    }
return(temp);
}

/*功能码03读*/
void readRegisters(void)
{
   u16 addr;
   u16 tempAddr;
// u16 result;
   u16 crcData;
   u8 readCount;
   u8 byteCount;

// u8  finsh; //
   u8 i;
   u16 tempData = 0; 
   tempData=mod_buf[2];
   addr = (tempData<<8) + mod_buf[3];
   tempAddr = addr ;//& 0xfff; 
   //addr = mod_buf[3];
   //tempAddr = addr;

 //readCount = (receBuf[4]<<8) + receBuf[5]; 
   readCount  = mod_buf[5];
   if(readCount<MAXREG)
   {

⌨️ 快捷键说明

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