📄 modbus_client.c
字号:
#include "modbus_client.h"
#ifndef _PGM
#define _PGM
#include <avr/pgmspace.h>
#endif
//=========================================
// 返回CRC校验结果
//=========================================
extern unsigned int Get_CRC(BYTE *,BYTE);
//=========================================
// 缓冲区
//=========================================
extern ADU_CONTROL adu;
extern MB_INFORMATION mb_infor;
extern BYTE WAIT_Time,Receive_en,WAIT_Responsion;
//========================================================================
// 设备参数表
//========================================================================
EQUIPMENT_PARAMETER EQUIPMENT_PARAMETER_TABLE[MAX_EQU_NUM]=
{
{0X09,0,OK,0,0x15},
//1、地址 2、类型 3、状态 4、起始寄存器 5、寄存器数量(十六位,两个字节)
{0x02,1,OK,0,0x0f},
{0x11,0,OK,0,0x15}/*,
{0x00,0,OK,0,0},
{0x00,0,OK,0,0}*/
};
//==========================================================================
// 定时计数器1溢出中断函数
//==========================================================================
ISR(SIG_OVERFLOW1)
{
TCNT1 = 0xf70c;
//4M时0.5个字符-0.000573s产生一个中断
mb_infor.TO_times ++;
if(mb_infor.TO_times == 3)mb_infor.T15_OUT = TRUE;
//1.5ms延时到
if(mb_infor.TO_times == 7)
{
mb_infor.T35_OUT = TRUE;
//3.5ms延时到
CLOSE_TIMER1();
//关定时器
}
}
//==========================================================================
// 定时计数器0溢出中断函数
//==========================================================================
ISR(SIG_OVERFLOW0)
{
WAIT_Time ++;
if(WAIT_Time >= MAX_WAIT_TIME)
{
//WAIT_Time = MAX_WAIT_TIME;
CLOSE_WaitResponsionClk();
//关T0中断
OPEN_USART1_ReINTERRUPT();
//关接收中断
}
else
TCNT0 = 0x00;
//重新装入计数器初值
}
//==========================================================================
// USART接收中断函数
//==========================================================================
ISR(SIG_UART_RECV)
//串口接受中断
{
BYTE Rdata;
Rdata = UDR;
if(Rdata == EQUIPMENT_PARAMETER_TABLE[mb_infor.EQUIPMENT_NOW].EQU_ADDR)
//是当前等待帧
{
WAIT_Responsion = 0;
//结束超时判断
Receive_en = 1;
//使能接收
adu.ADULength = 0;
*(adu.RxADUBuffPtr + adu.ADULength) = Rdata;
//为了CRC计算方便,还是要在缓冲区存储整个PDU帧
adu.ADULength ++;
CLOSE_USART1_ReINTERRUPT();
//关接收中断
OPEN_TIMER1();
//开定时器T1
}
// delay_us(40); //退出时启动定时器
}
//===========================================================================
// 初始化函数
//===========================================================================
//modbus状态
void MB_INFORMATION_Init(MB_INFORMATION *MBi)
{
MBi -> EQUIPMENT_NOW = 0;
//初始化时,从第0台设备开始
// MBi -> MODBUS_STATE = (enum _MODBUS_STATE)0;
MBi -> T15_OUT = FALSE;
MBi -> T35_OUT = FALSE;
MBi -> TO_times = 0;
}
void ADU_CONTROL_Init(ADU_CONTROL *adu)
{
adu -> Address = 0;
adu -> TxADUBuffptr = TxAdu_buf;
adu -> RxADUBuffPtr = RxAdu_buf;
adu -> ADULength = 0;
adu -> FrameOK = FALSE;
}
//================================================================================
// 接收帧的处理;
// 参数: 1.要处理帧的指针 2.要处理帧的长度
//================================================================================
MESSAGE_ERR message_process(BYTE *Message,BYTE len)
{
unsigned int CRC_data,RX_crc;
RX_crc = *(adu.RxADUBuffPtr + adu.ADULength - 2)/*CRC高位*/*256 +
*(adu.RxADUBuffPtr + adu.ADULength - 1)/*CRC低位*/;
CRC_data = Get_CRC (adu.RxADUBuffPtr,adu.ADULength - 2);
//计算CRC校验
if(CRC_data == RX_crc)
//CRC校验正确
{
if(bit_is_clear(*(adu.RxADUBuffPtr + 1),7))
//功能码返回正确?
{
if(*(adu.RxADUBuffPtr + 2) == adu.ADULength - 5) //
{
return NO_ERR;
}
else
return LEN_ERR;
}
else
return FUNC_ERR;
}
else
return CRC_ERR;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -