📄 receivetest.c~
字号:
RS485_Answer=1;
}
else
{
RS485_Answer_Set();
RS485_Answer_Subprogram(); // 调用发送点对点回复包子程序
led2=!led2;
Check_Receive_Data_Flag=1;
}
}
else if( (Address_Flag==RS485_Address_Broad)||( Address_Flag==( RS485_Address_Self & 0xF0)))
{
// 广播类型数据包回复标志
RS485_Answer_Set();
// 发送回复包标志清0
RS485_Answer_Broad_Subprogram(); // 调用发送点对广播回复包子程序
//RS485_Answer_Subprogram();
led2=!led2;
Check_Receive_Data_Flag=1;
}
}
}
}
//----------------------------------------------------------------------------------------------
//
//串行接收处理函数
void RS485_Receive_Process(INT8U RecData)
{
Receive_Status=GetCurrentRS485RxStatus();
switch(Receive_Status)
{
case RS485_Receive_IDLE:
if(RecData==Data_Head) // 在空闲状态下接收到数据,判断是否数据包起始字节
{
SetCurrentRS485RxStatus(RS485_Receive_RECEIVE); // RS485总线状态改为接收状态
Receive_Count=0; // 接收计数器清0
// Receive_CheckHead=0; // 准备进行对接收到的数据头进行和校验,简单累加和
// Receive_CheckData=0; // 准备进行对接收到的数据进行和校验,简单累加和
RS485_Bus_Status = RS485_Bus_BUSY; // 接收到0x7E时总线状态为忙,不能发送数据
}
break;
case RS485_Receive_RECEIVE:
if(RecData==Data_Change)
{
SetCurrentRS485RxStatus(RS485_Receive_CHANGE); // RS485总线状态改为转移状态
break;
}
if(RecData==Data_Head)
{
if(Receive_Count>0) // 当接收到0x7E且接收计数器大于0,接收结束
{
RS485_Data_Handle(); // 调用数据处理程序
SetCurrentRS485RxStatus(RS485_Receive_IDLE); // 将485接收状态改为空闲状态
RS485_Bus_Status=RS485_Bus_IDLE;
//RS485_Receive_Save_Data();
RS485_Receive_End=1;
// RS485_Receive_Save_Data();
Receive_Count=0; // 接收完毕,将接收数据计数器清0
}
// else
// {
// SetCurrentRS485RxStatus(RS485_Receive_IDLE); // 将485接收状态改为空闲状态
// RS485_Bus_Status=RS485_Bus_IDLE; // 接收完毕(无论正确与否,无论数据还是回复包)485总线状态设置为空闲状态,
// }
break;
}
RS485_Receive_Buff[Receive_Count]= RecData;
// if(Receive_Count<7)
// {
// Receive_CheckHead += RS485_Receive_Buff[Receive_Count]; // 更新累加数据头和校验信息
// }
//
// else if(Receive_Count>7)
// {
// Receive_CheckData += RS485_Receive_Buff[Receive_Count]; // 更新累加数据和校验信息
// }
Receive_Count++; // 接收计数器加1
break;
case RS485_Receive_CHANGE:
RS485_Receive_Buff[Receive_Count]= RecData^0x20;
// if(Receive_Count<7)
// {
// Receive_CheckHead += RS485_Receive_Buff[Receive_Count]; // 更新累加数据头和校验信息
// }
// else if(Receive_Count>7)
// {
// Receive_CheckData += RS485_Receive_Buff[Receive_Count]; // 更新累加数据和校验信息
// }
SetCurrentRS485RxStatus(RS485_Receive_RECEIVE); // 转换之后将485改为接收状态,接收下一字节数据
Receive_Count++; // 接收计数器加1
break;
default:
break;
}
}
//----------------------------------------------------------------------------------------------
//
//接收中断程序
interrupt [USART_RXC] void usart_rx_isr(void)
{
// INT8U Receive_Data;
led=!led;
Receive_Data=UDR;
RS485_Receive_Process(Receive_Data);
}
//----------------------------------------------------------------------------------------------
//
// 定时器0中断程序
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
switch(Delay_Status)
{
case Start_Send:
{
Delay_Status=Other_Delay; // 中断延时结束,返回其他状态
RS485_Start_Send();
}
break;
case Repeat_Send_Delay: // 重发延时10ms,1ms中断一次
if(Repeat_Send_Time>0) // 延时尚未结束
{
if(RS485_Bus_Status == RS485_Bus_BUSY) // 检测到总线为不空闲,
{
if(Add_Time_Flag==1) // 首次不空闲时将加3ms延时
{
Repeat_Send_Time=Repeat_Send_Time+3;
Add_Time_Flag=0;
}
break;
}
else // 总线状态为空闲时,将延时计数器减1
{
Repeat_Send_Time=Repeat_Send_Time-1;
Add_Time_Flag=1;
}
break;
}
else // 延时结束,
{
if(RS485_Bus_Status == RS485_Bus_BUSY) // 延时结束,发送前检测到总线不为空闲,重新执行延时程序
{
Repeat_Delay_Program(); // 调用重发延时函数,继续执行重发延时
break;
}
else // 总线为空闲,即开始发送数据
{
ReSendCount++; // 重发计数器加1
Delay_Status=Start_Send;
}
}
break;
case Long_Wait_Delay: // 重发之间的超时等待延时350ms,50ms中断一次
if(Long_Wait_Time>0)
{
Long_Wait_Time=Long_Wait_Time-1;
break;
}
else
{
Delay_Status=Repeat_Send_Delay;
}
break;
case Send_Broad_Delay: // 对广播包竞争回复延时,1ms中断一次
if(Com_Revert_Time>0) // 延时未结束
{
if(RS485_Bus_Status == RS485_Bus_BUSY) // 检测到总线为不空闲,
{
if(Add_Time_Flag==1) // 首次不空闲时将加3ms延时
{
Com_Revert_Time=Com_Revert_Time+3;
Add_Time_Flag=0;
}
break;
}
else // 检测到总线为空闲
{
Add_Time_Flag=1;
if(RS485_Answer==0) // 还没有收到回复包,计数器将减1
{
Com_Revert_Time=Com_Revert_Time-1;
break;
}
else // 已经收到回复包,放弃对广播包的回复
{
Delay_Status=Other_Delay; // 中断延时结束,返回其他状态
break;
}
}
}
else // 表示竞争回复延时结束
{
if(RS485_Bus_Status == RS485_Bus_BUSY) // 延时结束,发送前检测到总线不为空闲,重新执行延时程序
{
Com_Revert_Time=Delay_Time_Count[ RS485_Answer_Send_Buff[0]]; // 竞争回复延时间计数长度
}
else // 总线为空闲,即开始发送数据
{
Delay_Status=Start_Send; // 中断延时结束,返回其他状态
led3=0;
}
}
break;
case Check_Delay: // 检测是否接收到回复包延时200ms,50ms中断一次
if(Check_Time>0) // 200ms延时未结束,继续延时
{
Check_Time=Check_Time-1;
break;
}
else // 200ms延时结束
{
Send_Data_Flag=0;
Delay_Status=Other_Delay; // 中断延时结束,返回其他状态
if(RS485_Answer==0) // 定时中断50ms后如果没有回复包标志,将重发数据
{
if(ReSendCount<2) // 重发数据小于2次时;
{
RS485_Send_Flag=1; // 启动发送标志位
ReSendFlag=1; // 启动重发标志
break;
}
else // 重发超过两次;
{
ReSendCount=0; // 重发次数计数器清0
}
}
else
{
// RS485_Answer=0; // 接收到回复包,将重发计数器清0
ReSendCount=0; // 重发次数计数器清0
}
}
break;
default :
// TCCR0=0x00; // 关闭定时中断
break;
}
}
//----------------------------------------------------------------------------------------------
//
// 2 Wire bus interrupt service routine
interrupt [TWI] void twi_isr(void)
{
// Place your code here
INT8U IICStatus;
IICStatus = TWSR;
IICStatus &= 0xF8;
switch(IICStatus)
{
//从机接收
case 0x60: // 接收到自身SLA+W,返回ACK,并清除INT位
case 0x68: //自己作为主机的时候仲裁失败,并收到自身的SLA+W,返回ACK了。这种情况不会出现
IICSendCount=0;
IICChecksum=0;
TWCR |= 0xC0;
break;
//从机发送
case 0xA8:
case 0xB0:
case 0xB8:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -