背景描述:小弟用PIC16F887单片机与电脑通信,因为是485的协议,所以使用了两片芯片SN75176,一片作为接收,一片作为发送。通信协议是,电脑先发送5个字节给单片机,单片机接收并判断正确了,则会置发送标志位,然后向电脑发送数据。
问题描述:现在目前的情况是,在线调试时,发现单片机总是出现接收溢出错误,然后就再也接收不了数据(我们使用中断接收)。如果直接置发送标志位,则可以向电脑发送数据。所以,目前排除了硬件上的问题,认为是软件的问题,但是却找不出来。
请高手指点下,十分感谢!
下面是具体的程序,用在其他单片机PIC16F77,可以成功的通信。
#define RECV_INIT 0
#define RECV_ID 1
#define RECV_STATE 2
#define RECV_Sum 3
#define RECV_END 4
#define RECV_TIMEOUT 50
/********初始化**************/
void Init_UART(void)
{
ADCON1=0X07;
TRISC6=0; // output
TRISC7=1; // input
SPBRG=25; //9600
TXSTA=0b00100100;
RCSTA=0b10010000;
GIE = 1;
RCIE=1;
}
/********如果接收电脑发送的数据,若正确,则置标志位**************/
if(RCIF) // 放在中断程序里
{
ch=RCREG;
Receive_timeout=RECV_TIMEOUT;
switch(Receive_state)
{
case RECV_INIT:
if(ch==0x68)
{
Receive_state=RECV_ID;
Receive_timeout=RECV_TIMEOUT;
}
else Receive_timeout=1;
break;
case RECV_ID:
Receive_state=RECV_STATE;
Receive_buf[0]=ch; //uP ionizer ID
Data_Checksum=ch;
break;
case RECV_Sum:
Receive_state=RECV_END;
Receive_buf[2]=ch; // the received checksum
break;
case RECV_END:
if(ch==0x68)
{
if(Receive_buf[0]==Device_Address)
{
if(Receive_buf[2]==Data_Checksum)
{
Receive_Flag=1; //receive ok
// Run_state=Receive_buf[1];
}
}
}
default:
Receive_timeout=0;
Receive_state=RECV_INIT;
break;
}
/********如果接收成功,则开始向电脑发送数据**************/
if(Receive_Flag==1) // 放在main程序里
{
//增加通讯指示
WriteLCDCommand(PageAddress+3,2);
WriteLCDCommand(50,2);
for(ch=0;ch<8;ch++)WriteLCDData(0xFF,2);
//通讯开始,上传状态字 20060314
Receive_Flag=0;
RA2=1; //start to send
ch=Device_Address;
TXREG=ch; //TXREG:USART Transmit Data Register 20050313
Data_Checksum=ch;
while(!TRMT); //send the id
ch=temp1&0xff;
TXREG=ch;
Data_Checksum+=ch;
while(!TRMT); //send the VB3 data low byte
ch=(temp1>>8)&0xff;
ch |=0x80;
TXREG=ch;
Data_Checksum+=ch;
while(!TRMT); //send the VB3 data high byte
ch=temp2&0xff;
TXREG=ch;
Data_Checksum+=ch;
while(!TRMT); //send the VB2 data low byte
ch=(temp2>>8)&0xff;
ch |=0x80;
TXREG=ch;
Data_Checksum+=ch;
while(!TRMT); //send the VB2 data low byte
ch=temp3&0xff;
TXREG=ch;
Data_Checksum+=ch;
while(!TRMT); //send the VB1 data low byte
ch=(temp3>>8)&0xff;
ch |=0x80;
TXREG=ch;
Data_Checksum+=ch;
while(!TRMT); //send the VB1 data high byte
TXREG=Data_Checksum;
while(!TRMT); //send checksum
RA2=0; //switch off sending
} |