用MEGA8写的modbus实现了一个功能
还没有调试,请大家帮忙看看,第一次写通信程序,avr还不熟悉,不知道中断处理的如何。
主程序:
#include"485.h" #include"modbus_client.h"
extern UINT16 Get_CRC ( BYTE *, BYTE); extern void message_storage(BYTE *,BYTE,BYTE); extern EQUIPMENT_PARAMETER EQUIPMENT_PARAMETER_TABLE[MAX_EQU_NUM]; //extern uchar T_flag; //extern uchar buf_p; //extern uchar Receive_now; //在接收中断中,只要确认应答的设备地址正确就置位 // //=========================================== BYTE Receive_en; //接收使能 //=========================================== BYTE WAIT_Responsion; //等待应答:发送完一帧请求后置位,作为持续等待标志, //在接收中断中,如果接到这个设备的应答,只要地址正 //就可以清除从而结束超时等待; BYTE WAIT_Time; // //=========================================== // 全局变量结构体 //=========================================== MB_INFORMATION mb_infor; //MASTER_INFORMATION mas_infor; ADU_CONTROL adu; //=========================================== // 超时错误 //=========================================== #define MAX_CHAOSHI 3 BYTE CHAOSHI_ErrTime[MAX_EQU_NUM]; //超时错误计数器 超过MAX_CHAOSHI次就要把 //EQUIPMENT_PARAMETER_TABLE[mb_infor.EQUIPMENT_NOW].EQUIP_STATE //变为ERR //=========================================== // 帧错误 //=========================================== BYTE ZHEN_ErrTime[MAX_EQU_NUM];
int main(void) { UINT16 CRC_BUF; BYTE CRC_CHAR; MESSAGE_ERR MESSAGE_err; //================================================= // 变量初始化 //================================================= WAIT_Time = 0; Receive_en =0; memset(TxAdu_buf,0,BUFSIZE); memset(RxAdu_buf,0,BUFSIZE); memset(CHAOSHI_ErrTime,0,MAX_EQU_NUM); memset(ZHEN_ErrTime,0,MAX_EQU_NUM); // Receive_now = 0; //=========================================== MB_INFORMATION_Init(&mb_infor); // MASTER_INFORMATION_Init( &mas_infor); ADU_CONTROL_Init(&adu); PORTd_INIT(); //=========================================== cli(); comInit(); sei(); // t_485("ni hao ma?\n"); // t_485("Hello! da jia hao,wo shi tiao zao tuan zhang;\n"); while(1) { begin: //&&&&&&&&&&&&&&&&&&&&&&& // 拼装帧 发送帧 //&&&&&&&&&&&&&&&&&&&&&&& if(!EQUIPMENT_PARAMETER_TABLE[mb_infor.EQUIPMENT_NOW].EQU_ADDR/*0代表没有设备*/ && EQUIPMENT_PARAMETER_TABLE[mb_infor.EQUIPMENT_NOW].EQU_STATE/*设备无故障*/) { adu.ADULength = 0; *(adu.TxADUBuffptr + adu.ADULength) = EQUIPMENT_PARAMETER_TABLE[mb_infor.EQUIPMENT_NOW].EQU_ADDR; //地址 adu.ADULength ++; *(adu.TxADUBuffptr + adu.ADULength) = 0x03; //功能号 adu.ADULength ++; *(adu.TxADUBuffptr + adu.ADULength) = 0x00; adu.ADULength ++; *(adu.TxADUBuffptr + adu.ADULength) = EQUIPMENT_PARAMETER_TABLE[mb_infor.EQUIPMENT_NOW]. REG_ORIGINATION; //起始寄存器 adu.ADULength ++; *(adu.TxADUBuffptr + adu.ADULength) = 0x00; adu.ADULength ++; *(adu.TxADUBuffptr + adu.ADULength) = EQUIPMENT_PARAMETER_TABLE[mb_infor.EQUIPMENT_NOW].REG_NUM; //寄存器数量 adu.ADULength ++; CRC_BUF = Get_CRC ( adu.TxADUBuffptr, adu.ADULength ) ; CRC_CHAR = (BYTE)CRC_BUF; *(adu.TxADUBuffptr + adu.ADULength) = (BYTE)(CRC_BUF >> 4); //CRC校验高四位 adu.ADULength ++; *(adu.TxADUBuffptr + adu.ADULength) = CRC_BUF; //CRC校验低四位 adu.ADULength ++; *(adu.TxADUBuffptr + adu.ADULength) = '\n'; //在帧的结尾加上‘\n’做为发送结束标志 t_485(adu.TxADUBuffptr); //发送帧 adu.ADULength = 0; WAIT_Responsion = 1; //使能等待标志 OPEN_WaitResponsionClk(); //打开超时计数器T0中断 OPEN_USART1_ReINTERRUPT(); //打开接收中断 } else //如果设备不存在或设备故障转到下一台设备 { if(++mb_infor.EQUIPMENT_NOW > MAX_EQU_NUM) //查询完一遍? mb_infor.EQUIPMENT_NOW = 0; //设备编号从0开始 goto begin; } while(WAIT_Responsion) //在接收中断中如果收到当前地址选中设备的应答则清除标志,跳出循环 { if(WAIT_Time >= MAX_WAIT_TIME) //超时 { //CLOSE_WaitResponsionClk(); //关闭T0; WAIT_Time = 0; //复位WAIT_Time CHAOSHI_ErrTime[mb_infor.EQUIPMENT_NOW] ++; //超时错误计数器++ if(CHAOSHI_ErrTime[mb_infor.EQUIPMENT_NOW] >= MAX_CHAOSHI) //超过最大超时错误 { EQUIPMENT_PARAMETER_TABLE[mb_infor.EQUIPMENT_NOW].EQU_STATE = ERR; //修改设备参数表中的状态,以后不再查询该设备 CHAOSHI_ErrTime[mb_infor.EQUIPMENT_NOW] = 0; //超时错误计数器清0 } if(++mb_infor.EQUIPMENT_NOW > MAX_EQU_NUM) //设备查询过来一遍? mb_infor.EQUIPMENT_NOW = 0; //设备编号从0开始 WAIT_Responsion = 0; //重新初始化等待回应标志 goto begin; } } //&&&&&&&&&&&&&&&&&&&&&& //接收除地址外的其他字节 //&&&&&&&&&&&&&&&&&&&&&& for(;;) { while(!(UCSRA & (1<<RXC))) { if(mb_infor.T35_OUT) { mb_infor.T35_OUT = FALSE; WAIT_Time = 0; //WAIT_Time复位 goto ZHEN_OVER; } } TCNT0 = 0x00; //重新计数 WAIT_Time = 0; //中断次数清零 delay_us(50); *(adu.RxADUBuffPtr + adu.ADULength) = UDR; adu.ADULength ++; } ZHEN_OVER: CLOSE_TIMER1(); //关定时器1 //================================================================ /* 以下内容是帧处理: */ //================================================================ MESSAGE_err = message_process(adu.RxADUBuffPtr,adu.ADULength); switch(MESSAGE_err) { case CRC_ERR: ZHEN_ErrTime[mb_infor.EQUIPMENT_NOW] ++; //错误计数器++ if(ZHEN_ErrTime[mb_infor.EQUIPMENT_NOW] >= MAX_ZHENERR) //超过最大超时错误 { EQUIPMENT_PARAMETER_TABLE[mb_infor.EQUIPMENT_NOW].EQU_STATE = ERR; //修改设备参数表中的状态,以后不再查询该设备 ZHEN_ErrTime[mb_infor.EQUIPMENT_NOW] = 0; //超时错误计数器清0 } goto begin; break; case FUNC_ERR://&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& // 这里要分析错误代码 找到原因 //&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ZHEN_ErrTime[mb_infor.EQUIPMENT_NOW] ++; //错误计数器++ if(ZHEN_ErrTime[mb_infor.EQUIPMENT_NOW] >= MAX_ZHENERR) //超过最大超时错误 { EQUIPMENT_PARAMETER_TABLE[mb_infor.EQUIPMENT_NOW].EQU_STATE = ERR; //修改设备参数表中的状态,以后不再查询该设备 ZHEN_ErrTime[mb_infor.EQUIPMENT_NOW] = 0; //超时错误计数器清0 } break; case LEN_ERR: ZHEN_ErrTime[mb_infor.EQUIPMENT_NOW] ++; //错误计数器++ if(ZHEN_ErrTime[mb_infor.EQUIPMENT_NOW] >= MAX_ZHENERR) //超过最大超时错误 { EQUIPMENT_PARAMETER_TABLE[mb_infor.EQUIPMENT_NOW].EQU_STATE = ERR; //修改设备参数表中的状态,以后不再查询该设备 ZHEN_ErrTime[mb_infor.EQUIPMENT_NOW] = 0; //超时错误计数器清0 } goto begin; break; case NO_ERR: message_storage(adu.RxADUBuffPtr,mb_infor.EQUIPMENT_NOW,adu.ADULength); // //存储帧 if(++mb_infor.EQUIPMENT_NOW > MAX_EQU_NUM) //设备查询过来一遍? mb_infor.EQUIPMENT_NOW = 0; //设备编号从0开始 goto begin; break; } } }
|