PIC单片机RS485程序


#include


#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{
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();
}
}


相关主题
相关文档
最新文档