📄 receivetest.c~
字号:
#include <mega8.h>
#include <delay.h>
#include <string.h>
#define led PORTD.5
#define led1 PORTD.6
#define led2 PORTD.7
#define led3 PORTB.0
#define RXB8 1
#define TXB8 0
#define UPE 2
#define OVR 3
#define FE 4
#define UDRE 5
#define RXC 7
#define FRAMING_ERROR (1<<FE)
#define PARITY_ERROR (1<<UPE)
#define DATA_OVERRUN (1<<OVR)
#define DATA_REGISTER_EMPTY (1<<UDRE)
#define RX_COMPLETE (1<<RXC)
#define DRE PORTD.2
#define DB_SENDMAXSIZE 7
#define Send_Buff_Size 128
#define Receive_Buff_Size 128
#define FunctionCode 2
#define Data_Head 0x7E
#define Data_Change 0x7D
//定义RS485总线状态,当状态为0时才允许发送数据
#define RS485_Bus_IDLE 0
#define RS485_Bus_BUSY 1
#define RS485_Receive_IDLE 0
#define RS485_Receive_RECEIVE 1
#define RS485_Receive_CHANGE 3
#define Answer_Size 8 // 定义回复包数据长度为八个字节
#define RS485_Address_Self 0x21 // 本机自己的地址
#define RS485_Address_Broad 0x00 // 广播地址
// #define Address_Broad 0x00 // 接收到的为广播地址时回复0
// #define Address_Self 0x01 // 接收到的为本机自己的地址时回复1
// #define Address_Rong 0x02 // 接收到不为本机地址也不为广播地址时回复2
#define Repeat_Send_Count 0x0A // 重发延时机制的延时时间,定为10ms
#define Check_Count 0xC8 // 检测回复包延时计数器,一次为50ms,延时200ms计数4次
#define Long_Wait_Count 0xF0 // 超时等待计数器,一次为1ms,延时250MS计数250次
#define Repeat_Send_Delay 0x01 // 重发延时状态
#define Long_Wait_Delay 0x02 // 超时等待状态
#define Send_Broad_Delay 0x03 // 回复广播包延时状态
#define Check_Delay 0x04 // 检测回复包延时状态
#define Other_Delay 0x00 // 其他中断延时状态
#define Start_Send 0x66
#define Order_Attribute 16
typedef unsigned char INT8U;
typedef char INT8S;
typedef unsigned short INT16U;
// This flag is set on USART Receiver buffer overflow
//定义RS485总线接收状态
INT8U RS485_Receive_Status;
INT8U ReSendFlag; // 重发数据标志位
INT8U ReSendCount; // 重发数据计数器
INT8U *P_RS485_Send_Buff; // 定义发送缓冲区指针
INT8U RS485_Send_Buff[Send_Buff_Size]={0x00,0x21,0x10,0x00,0x00,0x01,0x00,0x3A}; // 定义待发送数据缓冲区
INT8U RS485_Receive_Buff[Receive_Buff_Size]; // 定义接收数据缓冲区
INT8U RS485_Receive_Save[128]; // 保存接收到的数据缓冲区
INT8U RS485_Answer_Buff[8]; // 回复包接收缓冲区,回复包只为8个字节
INT8U RS485_Answer_Send_Buff[8]; // 回复数据包的发送缓冲区
INT8U Tx_Count; // 定义发送数据计数器
INT8U Receive_Count; // 定义接收数据计数器
INT8U Answer_Data_Count; // 回复包接收计数器
INT8U Tx_Send_End; // 发送完一帧数据标志位
INT8U Send_Broad_Delay_Flag; // 发送广播回复包延时标志
INT8U Repeat_Send_Data_Flag; // 重发第二次数据包标志
INT8U Send_Data_Flag; // 发送数据包(包括首发和重发标志),通过此标志去检验是否有回复包
INT8U RS485_Send_Flag; // 发送标志位
INT8U Send_Answer_Flag; // 发送回复包标志
INT8U Send_Broad_Flag; // 发送广播回复包标志
INT8U Add_Time_Flag; // 重发延时首次检测到总线不空间,对延时加3ms标志
INT8U RS485_Answer; // 回复包标志位
INT8U Send_Size; // 待发送数据的长度
INT8U Byte_Len; // 接收字节的长度,8;40;128;0
INT8U Receive_Data; // 接收的一个字节的数据
INT8U Receive_Status; // 接收数据时的状态
INT8U Receive_CheckHead; // 数据包头接收和校验
INT8U Receive_CheckData; // 数据包数据接收和校验
INT8U Send_CheckHead; // 数据包头发送和校验
INT8U Send_CheckData; // 数据包数据发送和校验
INT8U RS485_Bus_Status; // 定义485总线状态
INT8U Send_Status; // 发送数据状态
INT8U Delay_Status; // 延时中断状态
INT8U Start_Delay; // 启动延时检测回复包程序
INT8U Repeat_Send_Time; // 重发延时剩余时间计数器
INT8U Long_Wait_Time; // 超时等待剩余时间计数器
INT8U Com_Revert_Time; // 竞争回复延时剩余时间计算器
INT8U Check_Time; // 检测回复包延时剩余时间计算器
INT8U Long_Time_End; // 超时等待结束标志
INT8U UpdateFlag; // 状态更新标志
INT8U IICSendCount; // IIC发送计数器,一次通信接收8个字节
INT8U IICReceiveCount; // IIC接收计数器,一次通信接收8个字节
INT8U IICReceiveBuff[8]={0x01,0x01,0x02,0x01,0x02,0x03,0x04,0x0e}; // IIC接收缓冲区
INT8U IICSendBuff[8]; // IIC发送缓冲区
INT8U IICChecksum; // IIC接收校验和
INT8U IICCSendDataheck; // IIC发送数据的校验和
INT8U Check_Receive_Data_Flag;
INT8U RS485_Receive_End; // 485总线接收结束标志
// INT8U Buff;
// INT8U Length;
// INT8U Address;
// 竞争回复延时计数器,没计数一次延时1ms
INT8U Delay_Time_Count[]={
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,
0, 2, 4, 6, 64, 102, 98, 155, 0, 0, 0, 0, 0, 0,0,0,
0, 8, 36, 60, 66, 104, 140, 142, 166,168, 170, 172, 174, 0,0,0,
0, 10, 38, 62, 68, 84, 85, 86, 0, 0, 0, 0, 0, 0,0,0,
0, 12, 44, 100, 139, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,
0, 14, 46, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,
0, 16, 96, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,
0, 18, 94, 137, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,
0, 20, 92, 138, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,
0, 22, 40, 42, 70, 88, 90, 106, 156,158, 160, 162, 164, 0,0,0,
0, 24, 48, 72, 112, 124, 144, 143, 186,0, 0, 0, 0, 0,0,0,
0, 26, 50, 74, 114, 126, 146, 176, 188,0, 0, 0, 0, 0,0,0,
0, 28, 52, 76, 116, 128, 148, 178, 190,0, 0, 0, 0, 0,0,0,
0, 30, 54, 78, 118, 130, 150, 180, 191,0, 0, 0, 0, 0,0,0,
0, 32, 56, 80, 120, 132, 152, 182, 0, 0, 0, 0, 0, 0,0,0,
0, 34, 58, 82, 122, 134, 154, 184, 0, 0, 0, 0, 0, 0,0,0};
//---------------------------------------------------------------------------------------
//
//获取当前485接收状态
INT8U GetCurrentRS485RxStatus(void)
{
return RS485_Receive_Status;
}
//---------------------------------------------------------------------------------------
//
//设置当前485总线接收状态
void SetCurrentRS485RxStatus(INT8U status)
{
RS485_Receive_Status=status;
}
//----------------------------------------------------------------------------------------------
//
//启动发送程序
void RS485_Start_Send(void)
{
while (!(UCSRA&(1<<UDRE))); // 当数据寄存器为空时
DRE=1; // 将485转换到发送状态
UDR=0x7E; // 发送一帧的数据的开头0x7E
}
//---------------------------------------------------------------------------------------
//
// 重发延时函数
void Repeat_Delay_Program(void)
{
//Long_Time_End=0;
Repeat_Send_Time=Repeat_Send_Count; // 延时10ms
Delay_Status=Repeat_Send_Delay; // 进入重发延时中断状态
// //开中断,启动发送延时机制
// TCNT0=0xFC; // 定时1ms
// TCCR0=0x05; // 1024分频,计数39.0625次就为10ms
}
//---------------------------------------------------------------------------------------
//
//发送数据,包括首发和重发 执行这程序之前需将485引脚定义为发送状态
void RS485_Send_Subprogram(void)
{
if(ReSendFlag==1) // 判断是否为重发数据
{
ReSendFlag=0; // 重发标志清0
//将数据第二字节功能代码的第七位置位,表示为重发数据
RS485_Send_Buff[7]= RS485_Send_Buff[7] - RS485_Send_Buff[FunctionCode];
RS485_Send_Buff[FunctionCode]=RS485_Send_Buff[FunctionCode]|0x40;
RS485_Send_Buff[7]= RS485_Send_Buff[7] + RS485_Send_Buff[FunctionCode];
if(ReSendCount==1) // 第一次同第二次重发之间的超时等待
{
Long_Wait_Time=Long_Wait_Count;
Delay_Status=Long_Wait_Delay; // 进入超时等待延时中断状态
// Repeat_Send_Data_Flag=1;
// //启动定时器T00 // 超时等待350ms
// TCNT0=0x3D; // 定时50ms
// TCCR0=0x05;
// 超时等待未结束,执行其他程序
// 超时等待350ms结束,再执行重发延时
// while(Repeat_Send_Data_Flag==1)
// {
// if(Long_Time_End==0)
// {
// // Place your code here
// }
// else // 超时等待350ms结束,再执行重发延时
// {
// Long_Time_End=0;
// Repeat_Send_Data_Flag=0;
// Repeat_Delay_Program();
// }
// }
}
else
{
Repeat_Delay_Program();
}
} // 首发数据不用延时,直接发送
else
{
///
Delay_Status=Start_Send;
///
// RS485_Start_Send(); // 启动发送,即将0x7E发送到数据寄存器
}
}
//----------------------------------------------------------------------------------------------
//
// 发送点对点回复包子程序
void RS485_Answer_Subprogram(void)
{
Send_Size=8; // 发送回复包数据,固定为8个字节
P_RS485_Send_Buff=RS485_Answer_Send_Buff; // 将指针P_RS485_Send_Buff指向发送缓冲区RS485_Answer_Send_Buff首地址
Delay_Status=Start_Send;
//RS485_Start_Send(); // 启动发送
}
//----------------------------------------------------------------------------------------------
//
// 发送点对类,广播回复包子程序
void RS485_Answer_Broad_Subprogram(void)
{
Send_Size=8; // 发送回复包数据,固定为8个字节
P_RS485_Send_Buff=RS485_Answer_Send_Buff; // 将指针P_RS485_Send_Buff指向发送缓冲区RS485_Answer_Send_Buff首地址
Com_Revert_Time=Delay_Time_Count[RS485_Answer_Send_Buff[0]];
Delay_Status=Send_Broad_Delay; // 进入发送广播回复包延时中断状态
// Send_Broad_Delay_Flag=1;
// // 开定时中断
// TCNT0=0xFC; // 定时1ms
// TCCR0=0x05; // 1024分频,约计数4次为1ms
// while(Send_Broad_Delay_Flag==1)
// {
// ;// Place your code here
//
// //led3=!led3;
//
// }
// led3=0;
//
// Delay_Status=Start_Send;
// //RS485_Start_Send(); // 启动发送
}
//----------------------------------------------------------------------------------------------
//发送中断程序
interrupt [USART_TXC] void usart_tx_isr(void)
{
led3=!led3;
if(Tx_Send_End==0) // 一帧数据尚未发完
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -