📄 comm485.c
字号:
/********************************************************************************
485总线是一种常用的工业控制总线,支持多机通信,最长通信距离可达1500米,信号抗干扰能力强。
函数功能:用485实现dsPIC30F和PIC16系列的通信,上位机位dsPIC30F
*********************************************************************************/
void __attribute__((__interrupt__)) _U2RXInterrupt(void) //串口2接收中断
{
IFS1bits.U2RXIF=0;
RecvDataBuf[RecvDataLen++]=U2RXREG;
if(HOST_ADDRESS==RecvDataBuf[0])
{
U2STAbits.ADDEN=0;
}
if(RecvDataLen-1==RecvDataBuf[1])
{
if(Check_Sum(RecvDataBuf,RecvDataLen))
{
CheckMessageOK=1;
U2STAbits.ADDEN=1;
RecvDataLen=0;
}
else
{
CheckMessageOK=0;
U2STAbits.ADDEN=1;
RecvDataLen=0;
}
}
}
void RS485_Init(void)
{
U2BRG=(FCY/16/BAUDRATE)-1; //设置波特率为9600
U2MODEbits.UARTEN=0; //暂时关闭串口
U2MODEbits.PDSEL=3; //九位数据,无奇偶校验位
U2MODEbits.STSEL=0; //一个停止位
U2MODEbits.ABAUD=1;
U2STAbits.UTXISEL=1; //发送缓冲器空时,产生中断
U2STAbits.UTXEN=0; //暂时禁止发送
U2STAbits.URXISEL=0;
U2STAbits.ADDEN=1; //地址检测模式使能
U2RXREG=0X0000; //清发送缓冲和接受缓冲
U2TXREG=0X0000;
IFS1bits.U2TXIF = 0;
IFS1bits.U2RXIF = 0; //清除中断标志
IEC1bits.U2TXIE = 0;
IEC1bits.U2RXIE = 1; //开启串口中断
IPC6bits.U2TXIP = 6;
IPC6bits.U2RXIP = 6; //发送接受优先级3级
}
void Send_Message(unsigned char Address) //发送数据函数
{
unsigned int i;
//RECV_DISABLE;
//SEND_ENABLE;
PORTG=0x0003;
// U2TXREG.UTX8=1; //&&&&&检测能不能写进地址
U2TXREG=(1<<8)|Address;
//U2TXREG=0x0155;
//while(!U2STA.TRMT);
for(i=1000;i>0;i--); //等待发送完毕,※※※延时是否合适
for(i=1000;i>0;i--);
for(i=9000;i>0;i--);
PORTG=0x0000;
//RECV_ENABLE;
//SEND_DISABLE;
}
unsigned char Check_Sum(unsigned char *CheckData,unsigned char Len) //校验和函数
{
unsigned char i;
unsigned char AddSum;
for(i=1;i<Len;i++)
{
// CheckData+=1;
AddSum+=RecvDataBuf[i];
}
flag=RecvDataBuf[4];
if(0==AddSum) {return 1;}
else {return 0;}
}
/********************************************************************************
函数功能:用485实现dsPIC30F和PIC16系列的通信,下位机为PIC16系列
*********************************************************************************/
void initial(void) //初始化函数
{
GIE=0;
TRISD7=0; //置RD7为输出
RD7=1;
TRISD6=0; //置RD6为输出
RD6=1;
PCFG2=1;
PCFG1=1;
PCFG0=1;
TRISA=0x00; //定义A口RA2为输出
CSRC=1; //内部时钟源
SYNC=0; //异步通信方式
BRGH=1; //高速
SPBRG=0x81; //波特初值9600
SPEN=1; //允许RC6,RC7为USART引脚
TX9=1; //选择9位数据位
TXIF=0; //不受软件控制
TXEN=1; //发送使能
CREN=1; //允许连续接收
SREN=1; //允许单字节接收
ADDEN=1; //九位通信状态使能
RCIE=1; //接收中断使能
RCIF=0; //接收中断标志
RX9=1; //接收9位数据
PEIE=1; //外设中断允许
GIE=1; //开全局中断
}
void interrupt USART_RECEIVE_ISR(void) //接收中断服务函数
{
if(RCIF==1)
{
RCIF=0;
RecvAddress=RCREG;
if(SLAVE_ADDRESS==RecvAddress)
{
Delay(500);
SendDataLen=strlen(SendDataBuf)/2;
Send_Data(HOST_ADDRESS,SendDataLen,SendDataBuf);
if(RD7) RD7=0; //发光管闪烁指示,表示正在发送数据
else RD7=1; //测试点
}
}
}
void Send_Data(unsigned char Address,unsigned char DataLen,unsigned char *PointerDataBuf) //发送数据函数
{
unsigned char i;
unsigned char CheckSum=0;
SEND_ENABLE;
TX9D=1;
Send_Byte(Address);
TX9D=0;
Send_Byte(DataLen+2);
CheckSum+=DataLen+2;
for(i=0;i<DataLen;i++)
{
TX9D=0;
Send_Byte(*(PointerDataBuf+i));
CheckSum+=*(PointerDataBuf+i);
}
TX9D=0;
Send_Byte(0-CheckSum);
Delay(1500);
RECV_ENABLE;
}
void Send_Byte(unsigned char Data) //发送数据
{
TXREG=Data;
while(TXIF==0);
TXIF=0;
Delay(500);
}
/********************************************************************************
注意事项:
1.硬件连接应注意阻抗匹配
2.ADDEN位的设置应仔细阅读手册,以确保通信无误
3.16位与8位通信注意数据格式
有问题请高手赐教,laosi_laosi@126.com
*********************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -