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

📄 mini.c

📁 485通讯程序
💻 C
字号:
#include  <htc.h>
#include  "pic18f4520.h"


#define DE RC5 //接MAX485 DE脚,为1时发送,为0时接收
static    unsigned char     rc_buff[4];    //接收缓存
static    unsigned char     tx_buff[6];    //发送缓存
static    unsigned char     *P;            //缓存数组指针
static    unsigned char     rclenth;       //接收字节长度
static    unsigned char     txlenth;	   //发送字节长度
static    unsigned char     rctime;        //接收计时
static    unsigned char     CRC_NUM; 	   //CRC校验字节长度
static    unsigned char     CRC_HIG; 	   //CRC校验高字节
static    unsigned char     CRC_LOW; 	   //CRC校验低字节


static    volatile  unsigned char flag        @ 0x1a9; //标志位字节
static    volatile  bit  send_last_flag	      @ (unsigned) &flag*8+0;  //发送完成标志

void ini(void)        //定时器及USART的初始化 
{
        INTCON=0b00000000; //GIE and PEIE disable;TO and INT enable;IntFlag cleared
        PIE1=0b00100110;   //TMER2中断,异步串行接收中断
        PIR1=0;
        PIR2=0;
        PR2=249;    	   //PR2=124;        
        T2CON=4;           //TMR2ON=1;
        SPBRG = 25;	   // 9600 = 4M / ( 16 * ( 52+1 ) ) HIGH
        RCSTA = 0x90;
        TXSTA = 0x06;		     	
	DE=0; 		   //MAX485处于接收
        CREN=1;		   // 允许接收
        INTCON=0b11000000; //开启中断
        flag=0; //清标志位
}



void portset(void)    //端口设置
{
        TRISA=0b00010111;     //本来打算接几个LED作为接收各种数据的标志
        TRISB=0b00000111;
        TRISC=0b10010100;
        PORTB=0;
	PORTC=0b00001000;
	PORTA=0;
}

void crc_check(void)  //CRC校验
{
  unsigned char temp;  
  unsigned char i;
  unsigned char c;
  unsigned char TT;
  unsigned int crc=0xffff;
	for(c=0;c<CRC_NUM;c++)
	{
		temp=P[c];
		crc=crc^temp;
		for(i=0;i<8;i++)
		{
			TT=crc&1;
			crc=crc>>1;
			crc=crc&0x7fff;
			if (TT==1)
				crc=crc^0xa001;
			crc=crc&0xffff;
		}
	}
  CRC_LOW=crc&0x00ff;
  CRC_HIG=crc>>8;

}

      
/*异步串口发送初始化,打开发送中断,485发送*/
void ur_send_init(void)
{
	DE=1; //开启485发送
	asm("nop");
	asm("nop");
        TXREG=tx_buff[0];
        txlenth=1;
	TXEN=1;
	TXIE=1;
} 

/*串口的接收处理
判断命令:0X05  查询
          0x07  开关
          0x08  广播方式,开关所有MC120
*/
void urcom_rC_deel(void)
{	
	unsigned char i;
	
	  
	 if(rc_buff[0]==1)
        	{		
			switch(rc_buff[1])     
			{
				case 2 :
				 	if(rclenth!=4) 
			         		return;	
			         	
     	                       	 		
		            		for(i=0;i<=5;i++)
		            			tx_buff[i]=0;
		            		CREN=0;      	  
     	                       	 	RCIE=0;  //禁止接收
		            		tx_buff[0]=0;
		                	tx_buff[1]=1;
	                                tx_buff[2]=2;
	                                tx_buff[3]=3;
	                               
                                	CRC_NUM=4;
                                	P=tx_buff;
                                	crc_check();
                                	
                                	tx_buff[4]=CRC_LOW;
                                	tx_buff[5]=CRC_HIG;		                
		                	ur_send_init(); 		     
		          	break;		
				case 3:
			     		if(rclenth!=4) 
			         		return;	
			     
			     		for(i=0;i<=5;i++)
		            			tx_buff[i]=0; //清零发送缓存
		            		CREN=0;     	  
     	                        	RCIE=0;	 //禁止接收,屏蔽接收中断		          
		                	tx_buff[0]=4;
		                	tx_buff[1]=5;
	                        	tx_buff[2]=6;
	                        	tx_buff[3]=7;
	                    		
                                        CRC_NUM=4; //CRC
                               		P=tx_buff;
                               		crc_check(); 
                               		tx_buff[4]=CRC_LOW;
                               		tx_buff[5]=CRC_HIG;		          
         	              		ur_send_init(); 	            	 
		          	break;
				default : 
		       		rclenth=0;	
                       		rctime=0;
                       		CREN = 1;
                       		RCIE=1; 
                       		DE=0;
                       		break;				
	}
      } 
}

/*接收处理*/   	    
void  ur_recieve(void)
{
 	 if(rclenth>3&&rctime>30) // 接收完成 ,接收字节小于3或接受时间过长认为无数据
       {        	   
	   CRC_NUM=rclenth-2; //除去高低CRC验证字节
	   P=rc_buff;         //指向接收缓冲区
	   crc_check();		 	   
	   if (rc_buff[rclenth-1]==CRC_HIG&&rc_buff[rclenth-2]==CRC_LOW )
	   {
                 urcom_rC_deel(); //最后为CRC校验被认为接收正确              	                        		             
           }
           rclenth=0;
           rctime=0;        
       }
}  

/* interrupt service routine*/
void interrupt isr(void)
{    
	        if(TMR2IF)
    		{  
    			TMR2IF=0;
    			if(rctime<50) 
       				rctime++;
       			if(send_last_flag)
       			{
       	  			if(TRMT) //发送缓冲为空
       	 			{
       		 			TXEN=0;     	  	
     	  	 			TXIE=0;      	  
     	  	 			CREN=1;     	  
     	     				RCIE=1;
     	     				DE=0; 
     	     				send_last_flag=0;       	
       	  			}       	
       			}
 		} 
    	
     		else if(TXIF)          //发送中断
     		{
			if(txlenth>=CRC_NUM+2)       //发送最后一个字节
     	  		{     	  	
     	  			TXIE=0;          //禁止发送中断
     	  			send_last_flag=1;//发送最后一个字节标志;
 			}     	
     			else
     	  		{
     	    			TXREG=tx_buff[txlenth];
     	    			txlenth++;     	  	
     	  		}
     		} 
    		else if(RCIF)
    		{
    	 		rctime=0;
    			if ( OERR == 0 )			// 无溢出错误
		  	{ 	
				rc_buff[rclenth] = RCREG;	// 读发送来的数据	
				rclenth ++;
				if ( rclenth>5 )
					rclenth=0;			 
				
		  	}
			else
			{
				CREN = 0;
				asm("nop");
				CREN = 1;
			}
		}
   		else
   		{
       			INTCON=0b00000000;  //GIE and PEIE disable;TO and INT enable;IntFlag cleared
        		PIE1=0b00100110;   //允许TMER2中断,异步串行接收中断
        		PIR1=0;
      			PIR2=0;
        		PR2=250;        //PR2=124;        
        		T2CON=4;        //TMR2ON=1;
       			SPBRG = 25;	// 9600 = 4M / ( 16 * ( 25+1 ) ) 
			RCSTA = 0x90;
			TXSTA = 0x06;
			DE=0;		    	
			CREN=1;			
			INTCON=0b11000000; 
    		} 
}

void main(void) //主程序
{
	portset(); 	
	ini();

	while(1)       //死循环,等待接收
    {    
	ur_recieve();        
    }
}

⌨️ 快捷键说明

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