/*------------------------------Modbus.c--------------------------*/
#include "PRJ.h"
#include "p30f6014a.h"
#include "stdio.h"
#include "DFT.h"
#include "Freq.h"
#include "control.h"
#include "ModBus.h"
#define R485C PORTGbits.RG14
//#define R485C PORTGbits.RG12 //for profibus test
#define TRUE 1
#define FALSE 0
unsigned char temp4[80];
unsigned int send_no; //发送数据个数
unsigned int Send_data[12]={'t','e','s','t','\r','\n','1','2','3','4','\r','\n'}; //发送的数组
/* ****************************************************************
** 函 数 名: Uart_Initial()
** 功能描述: 通用异步收发器UART初始化
*************************************************************** */
/*通用异步收发器UART初始化
*/
void Uart_Initial()
{
IFS0bits.U1TXIF=0; //发送中断标志位清零
IFS0bits.U1RXIF=0; //接收中断标志位清零
IPC2bits.U1TXIP=1; //发中断优先级:1级
IEC0bits.U1TXIE=0; //UART1发送中断使能
//IEC0bits.U1RXIE=TRUE;
//IEC0bits.U1RXIE=FALSE;
IEC0bits.U1RXIE=TRUE;
U1MODE=0x8000; //UART使能,8位数据,无奇偶校验
U1STA=0x0400; //当一个字符被传输到发送移位寄存器(发送缓冲器中至
//U1STA=0x0000; //少还有一个字符)产生中断,当接收到一个字符时,中
//断标志位置位
//U1BRG=0X34; //U1BRG=Fcy/(16*波特率)-1,此处波特率为9600
U1BRG=0X33;
//U1BRG=0X06;
//U1STA=0x0400;
return;
}
#define uchar unsigned char
uchar rxd_get[20]={0x64,0x03,0x00,0x04,0x00,0x01};
uchar rxd_cnt=0;
uchar rxd_flag=FALSE;
uchar rxd_tms=0;
uchar rxd_id=0x64;
void uart_err_todo(void)
{
if(U1STAbits.OERR==1)
{
U1STAbits.OERR=0;
}
}
void uart_get(void)//1ms cycle called
{
rxd_tms++;
if(rxd_tms>5)//dt=5ms,帧同步
{
rxd_tms=0;
rxd_cnt=0;
}
if(rxd_flag==FALSE)
{
while(U1STAbits.URXDA==1)
{
rxd_tms=0;
IFS0bits.U1RXIF=0;
rxd_get[rxd_cnt++]=U1RXREG;
if(rxd_get[0]!=rxd_id)
{rxd_cnt=0;}
if(rxd_cnt>7)//get 8 byte
{
rxd_cnt=0;
rxd_flag=TRUE;
}//if()
}//while()
}//if()
}//end
//-------------------------------------------
//3.CRC16算法
//-------------------------------------------
#define U16 unsigned int
#define U8 unsigned char
U16 CRC16(U8 *p,U8 n)
{
U16 temp=0xffff;
U16 crc_result;
U8 i,j;
for(j=0;j<n;j++)
{
temp^=(*p);
for(i=0;i<8;i++)
{
/*
temp>>=1;
if(STATUSbits.C==1)
{temp^=0xa001;}*/
if((temp&0x0001)==0x0000)
{temp>>=1;}
else
{temp>>=1;
temp^=0xa001;
}
}
p++;
}
crc_result=(temp/256)+(temp%256)*256;
return(crc_result);
}
//------------------------------------------
//
//------------------------------------------
#define uint unsigned int
uchar txd_buff[8];
extern signed int I_sys;//=0;
extern signed char pf_2nd;//pf real is 0.98
extern uchar relay_state;//=0x00;
void uart_echo(void)//100ms cycle called
{
uchar i;
uint crc_temp,reg_addr;
if(rxd_flag==TRUE)
{
//send
/*
for(i=0;i<8;i++)
{
U1TXREG=rxd_get[i];
while(IFS0bits.U1TXIF==0);
IFS0bits.U1TXIF=0;
}
*/
//crc test
crc_temp=CRC16(rxd_get,6);
if((crc_temp/256==rxd_get[6])&&\
(crc_temp%256==rxd_get[7])&&\
(rxd_get[1]==0x03))
{
reg_addr=(uint)rxd_get[2]*256+rxd_get[3];
/*
switch(reg_addr)
{
case 1://电压
txd_buff[4]=VL_2nd/256;
txd_buff[5]=VL_2nd%256;
break;
case 2://电流
txd_buff[4]=I_sys/256;
txd_buff[5]=I_sys%256;
break;
case 3://功率因数
txd_buff[4]=pf_2nd/256;
txd_buff[5]=pf_2nd%256;
break;
case 4://投切状态
txd_buff[4]=relay_state/256;
txd_buff[5]=relay_state%256;
break;
case 5://
break;
case 6://
break;
default:break;
}
*/
txd_buff[0]=rxd_id;
txd_buff[1]=0x03;
txd_buff[2]=0x00;
txd_buff[3]=0x01;
crc_temp=CRC16(txd_buff,6);
txd_buff[6]=crc_temp/256;
txd_buff[7]=crc_temp%256;
//_20ms_timer_clr();
//while(_20ms_timer()==FALSE);
//*
for(i=0;i<8;i++)
{
U1TXREG=txd_buff[i];
while(IFS0bits.U1TXIF==0);
IFS0bits.U1TXIF=0;
}
//*/
}
rxd_flag=FALSE;
}
}
//----------------------------------------
//for @30000# format get
//----------------------------------------
#define uint8 unsigned char
#define uint16 unsigned int
uint16 FS_SET=50;//300~30,000Hz
void FS_SET_Update(void)
{
uint16 temp;
temp=(uint16)(rxd_get[1]-'0')*10000;
temp=temp+(uint16)(rxd_get[2]-'0')*1000;
temp=temp+(uint16)(rxd_get[3]-'0')*100;
temp=temp+(uint16)(rxd_get[4]-'0')*10;
temp=temp+(uint16)(rxd_get[5]-'0');
if(temp<=30000)
{
FS_SET=temp;
//Update F sample
//printf()
PR4=(uint16)(250000.0/(float)temp);
printf("FS_SET=%d,PR4 Set=%d\r\n",FS_SET,PR4);
}
else
{printf("FS_SET Not Update\r\n");}
}
//
uint8 SIND_Get_Flag=FALSE;
uint8 SIND_Get_State=0;
uint8 GetTemp;
extern void modbus_recieve(void);
///
void __attribute__((__interrupt__)) _U1RXInterrupt()
{
/*
//while(U1STAbits.URXDA==1)
// {
//IFS0bits.U1RXIF=0;
rxd_get[rxd_cnt++]=U1RXREG;
if(rxd_cnt>9)
{rxd_cnt=0;
rxd_flag=TRUE;
}
// }
*/
if(SIND_Get_Flag==FALSE)
{
GetTemp=U1RXREG;
modbus_recieve();
switch(SIND_Get_State)
{
case 0:if(GetTemp=='@')
{rxd_cnt=0;
rxd_get[rxd_cnt++]=GetTemp;
SIND_Get_State=1;
}
break;
case 1:if(GetTemp=='#')
{//rxd_cnt=0;
rxd_get[rxd_cnt++]=GetTemp;
rxd_get[rxd_cnt++]='\0';
rxd_cnt=0;
SIND_Get_State=0;
SIND_Get_Flag=TRUE;
}
else
{
rxd_get[rxd_cnt++]=GetTemp;
}
break;
}
}
IFS0bits.U1RXIF=0;
}
extern uint8 SIND_Get_Flag;//=FALSE;
extern uchar rs485_com_adr;//=0;//rs485 通讯地址
extern uint IL_real_uart;
extern uint relay_state_2nd;//=0x0fff;
extern unsigned int ct_ratio;//CT 变比
extern unsigned int Iq_set;
extern unsigned int dt_interval;//控制时间间隔
extern unsigned int pf_th;//功率因数上限
extern unsigned int uh_th;//电容运行电压上限
extern unsigned int swn;//补偿路数
void command_001_back(void)
{
//VL_2nd=380;
//IL_real_uart=2500;
//relay_state_2nd=7;
printf("\r\n");
//0.
printf("@%03d 001",(uint16)rs485_com_adr);
//1.
printf(" %03d",VL_2nd);
//2.
printf(" %04d",IL_real_uart);
//printf(" %-04d")
//pf_2nd=56;
//3.
// pf_sign_2nd=IND;
if(pf_sign_2nd==IND)
{
printf(" +%-04.2f",pf_2nd/100.0);
}
else
{
printf(" -%-04.2f",(pf_2nd/100.0));
}
// */
// pf_2nd=80;
// printf(" %-04.2f",-(pf_2nd/100.0));
//printf(" %-0d#\r\n",relay_state_2nd);
printf(" %05d",relay_state_2nd);
//-----------------------------------------------
//2017.11.6 add part
//-----------------------------------------------
//4.ct_set
printf(" %05d",ct_ratio);
//5.iq_step
printf(" %04d",Iq_set);
//C:\quick_v5_2017.10.30\control.h:8: extern unsigned int Iq_set;
//6.dt
printf(" %05d",dt_interval);
//7.pf_th
printf(" %-04.2f",pf_th/100.0);
//8.uh_th
printf(" %04d",uh_th);
//9.sw_sum
printf(" %04d",swn);
printf("#\r\n");
}
//2020 modbus code
///
int cnt_1ms_end=0;
int GET_EN=TRUE;
int pp_save=0;
unsigned char modbus_get_buff[100];
extern uint8 GetTemp;
//帧数据接收函数
void modbus_recieve(void)
{
cnt_1ms_end=0;//
if(GET_EN==TRUE)
{
modbus_get_buff[pp_save]=GetTemp;
if(pp_save<99)
{pp_save++;}
}
}
unsigned char modbus_send_buff[100];
unsigned char modbus_reg_data[20];//
void modbus_reg_data_init(void)
{
int i;
for(i=0;i<20;i++)
{modbus_reg_data[i]=i;}
}
void modbus_reg_update(void)
{
/*
0 380是当前电网电压
1 2500是当前系统的电流
2 小于100,例如98 代表0.98 大于100,代表容性,例如198,代表功率因数是-0.98
3 7代表当前投切状态,转化成12位的二进制数,0000 0000 0000 0111
“1”代表投入,“0”代表未投入
4 00100 CT变比 100:5
5 0020 单组电容电流
6 00020 动作时间间隔单位ms,20ms
7 0.90 补偿功率因数上限
8 0420过电压保护阀值
9 0012补偿总路数,12路
*/
/*
VL_2nd=100;
IL_real_uart=100;
pf_2nd=98;
relay_state_2nd=0xfff;
ct_ratio=100;
Iq_set=30;
dt_interval=100;
pf_th=98;
uh_th=100;
swn=10;
*/
//1 电网电压
modbus_reg_data[0]=VL_2nd>>8;
modbus_reg_data[1]=VL_2nd&0xff;
//2 电网侧电流
modbus_reg_data[2]=IL_real_uart>>8;
modbus_reg_data[3]=IL_real_uart&0xff;
//3.功率因数
if(pf_sign_2nd==IND)//感性
{
modbus_reg_data[4]=(unsigned int)pf_2nd>>8;
modbus_reg_data[5]=(unsigned int)pf_2nd&0xff;
}
else
{
modbus_reg_data[4]=(unsigned int)(pf_2nd+100)>>8;
modbus_reg_data[5]=(unsigned int)(pf_2nd+100)&0xff;
}
//4 当前投切状态
modbus_reg_data[6]=relay_state_2nd>>8;
modbus_reg_data[7]=relay_state_2nd&0xff;
//5 CT变比比率 100,代表(500:5 或者100:1)
modbus_reg_data[8]=ct_ratio>>8;
modbus_reg_data[9]=ct_ratio&0xff;
//6 单组电容电流
modbus_reg_data[10]=Iq_set>>8;
modbus_reg_data[11]=Iq_set&0xff;
//7 动作时间间隔
modbus_reg_data[12]=dt_interval>>8;
modbus_reg_data[13]=dt_interval&0xff;
// 8 0.90 补偿功率因数上限
modbus_reg_data[14]=pf_th>>8;
modbus_reg_data[15]=pf_th&0xff;
//9 420过电压保护阀值
modbus_reg_data[16]=uh_th>>8;
modbus_reg_data[17]=uh_th&0xff;
//10 0012补偿总路数,12路
modbus_reg_data[18]=swn>>8;
modbus_reg_data[19]=swn&0xff;
Nop();
Nop();
}
///
//帧数据发送函数
void modbus_byte_send(unsigned char n)
{
int i;
for(i=0;i<n;i++)
{
//modbus_send_buff[i]=i;
U1TXREG=modbus_send_buff[i]; // 返送接收到的数
}
}
#define FRAME_TIME 200 //20ms
void modbus_echo(void)
{
unsigned char x=100;
int i=0;
unsigned int reg_addr=0;
unsigned int num_data=0;
unsigned char CRC_L,CRC_H;
unsigned int crc16,crc16_get;
//IEC0bits.U1TXIE=1;
//U1STAbits.UTXEN=1;//发送使能!!!
IEC0bits.U1TXIE=1;U1STAbits.UTXEN=1;
if((cnt_1ms_end>FRAME_TIME)&&(pp_save>7))
{
GET_EN=FALSE;
cnt_1ms_end=0;
R485C=1;
Nop();Nop();Nop();Nop();
Nop();Nop();Nop();Nop();
reg_addr=((unsigned int)modbus_get_buff[2]<<8)+modbus_get_buff[3];
num_data=((unsigned int)modbus_get_buff[4]<<8)+modbus_get_buff[5];
crc16_get=((unsigned int)modbus_get_buff[6]<<8)+modbus_get_buff[7];
crc16=CRC16(modbus_get_buff,6);
Nop();
/
if(modbus_get_buff[0]==rs485_com_adr)//地址判断
{
if(modbus_get_buff[1]==0x03)//功能代码判断
{
if((reg_addr<10)&&(num_data<=10)&&(crc16_get==crc16))//地址 数据 CRC 校验
{
//todo:modbus 数据准备与发送
modbus_send_buff[0]=rs485_com_adr;
modbus_send_buff[1]=0x03;
modbus_send_buff[2]=num_data*2;//数据字节个数
for(i=0;i<num_data;i++)
{
modbus_send_buff[3+2*i]=modbus_reg_data[reg_addr*2];
modbus_send_buff[3+2*i+1]=modbus_reg_data[reg_addr*2+1];
reg_addr++;
}
//add crc data
CRC_L=CRC16(modbus_send_buff,3+num_data*2)>>8;
CRC_H=CRC16(modbus_send_buff,3+num_data*2)&0xff;
modbus_send_buff[3+num_data*2]=CRC_L;
modbus_send_buff[3+num_data*2+1]=CRC_H;
//send
modbus_byte_send(5+num_data*2);
Nop();
Nop();
}
}
}
//modbus_byte_send(50);
pp_save=0;
/
Nop();Nop();Nop();Nop();
Nop();Nop();Nop();Nop();
R485C=0;
GET_EN=TRUE;
}
}
///
void UartGetReturn(void)
{
uint8 com_addr,com_command;
if(SIND_Get_Flag==TRUE)
{
com_addr=(rxd_get[1]-'0')*100+(rxd_get[2]-'0')*10+(rxd_get[3]-'0');
com_command=(rxd_get[4]-'0')*100+(rxd_get[5]-'0')*10+(rxd_get[6]-'0');
// if(com_addr==rs485_com_adr)
if(1)
{
switch(com_command)
{
case 1:
R485C=1;
Nop();Nop();Nop();Nop();
Nop();Nop();Nop();Nop();
//printf("%s",rxd_get);
//printf("\r\n");
//printf("----------------\r\n");
command_001_back();
//printf("command valid!\r\n");
R485C=0;
Nop();Nop();Nop();Nop();
Nop();Nop();Nop();Nop();
break;
default:
R485C=1;
Nop();Nop();Nop();Nop();
Nop();Nop();Nop();Nop();
//printf("%s",rxd_get);
//printf("\r\n");
//printf("----------------\r\n");
printf("command no valid!\r\n");
R485C=0;
Nop();Nop();Nop();Nop();
Nop();Nop();Nop();Nop();
break;
}
/*
R485C=1;
Nop();Nop();Nop();Nop();
Nop();Nop();Nop();Nop();
printf("%s",rxd_get);
printf("\r\n");
printf("----------------\r\n");
R485C=0;
Nop();Nop();Nop();Nop();
Nop();Nop();Nop();Nop();
*/
}
/*
R485C=1;
Nop();Nop();Nop();Nop();
Nop();Nop();Nop();Nop();
printf("%s",rxd_get);
printf("\r\n");
printf("----------------\r\n");
R485C=0;
Nop();Nop();Nop();Nop();
Nop();Nop();Nop();Nop();
*/
SIND_Get_Flag=FALSE;
}
}
void __attribute__((__interrupt__)) _U1TXInterrupt()
{
while(U1STAbits.TRMT ==0); //当为0时,表明移位寄存器没空
IFS0bits.U1TXIF=0; //发送中断标志位清零
}
void io_init(void)
{
TRISGbits.TRISG14=0;
Nop();
R485C=1;
Nop();
R485C=0;
Nop();
}
void Send1Byte(void)
{
unsigned char i;
printf("**************************************************************\r\n");
printf("* 电能质量分析结果 * \r\n");
printf("**************************************************************\r\n");
printf("频率f=%6.3f(Hz)\r\n",(1000000.0)/(float)FreqTerm);
printf("功率Pa=%8.2f(W),Pb=%8.2f(W),Pc=%8.2f(W)\r\n",Pa,Pb,Pc);
printf("功率因数cosFA=%5.2f,cosFB=%5.2f,cosFC=%5.2f\r\n",cosFA,cosFB,cosFC);
printf("有效值(有名值):\r\n");
printf("Va=%d(V),Vb=%d(V),Vc=%d(V)\r\n",Va_rms,Vb_rms,Vc_rms);
printf("Ia=%f(A),Ib=%f(A),Ic=%f(A)\r\n",Ia_rms/100.0,Ib_rms/100.0,Ic_rms/100.0);
printf("--------------------------------------------------------------\r\n");
printf("谐波总畸变率:\r\n");
printf("-------------------------------------------------------------\r\n");
printf("THD is: Va_THD=%d%%%,Vb_THD=%d%%,Vc_THD=%d%%\r\n",Va_THD,Vb_THD,Vc_THD);
printf("THD is: Ia_THD=%d%%%,Ib_THD=%d%%,Ic_THD=%d%%\r\n",Ia_THD,Ib_THD,Ic_THD);
printf("-------------------------------------------------------------\r\n");
printf("谐波含量(百分值)\r\n");
for(i=1;i<32;i++)
{
printf("%2dst----Va=%d%%,Vb=%d%%,Vc=%d%%,Ia=%d%%,Ib=%d%%,Ic=%d%%",\
i,Va_dft_pu[i],Vb_dft_pu[i],Vc_dft_pu[i],\
Ia_dft_pu[i],Ib_dft_pu[i],Ic_dft_pu[i]);
printf("\r\n");
printf("-------------------------------------------------------------\r\n");
}
printf("**************************************************************\r\n");
printf("* The End of the Report * \r\n");
printf("**************************************************************\r\n");
}
unsigned char print_cnt=0;
void UartSend(void)
{
unsigned char i;
switch(print_cnt)
{case 0:
printf("**************************************************************\r\n");
printf("* 电能质量分析结果 * \r\n");
printf("**************************************************************\r\n");
break;
case 1:
printf("频率f=%6.3f(Hz)\r\n",(1000000.0)/(float)FreqTerm);
printf("功率Pa=%8.2f(W),Pb=%8.2f(W),Pc=%8.2f(W)\r\n",Pa,Pb,Pc);
break;
case 2:
printf("功率因数cosFA=%5.2f,cosFB=%5.2f,cosFC=%5.2f\r\n",cosFA,cosFB,cosFC);
printf("有效值(有名值):\r\n");
break;
case 3:
printf("Va=%d(V),Vb=%d(V),Vc=%d(V)\r\n",Va_rms,Vb_rms,Vc_rms);
printf("Ia=%f(A),Ib=%f(A),Ic=%f(A)\r\n",Ia_rms/100.0,Ib_rms/100.0,Ic_rms/100.0);
break;
case 4:
printf("--------------------------------------------------------------\r\n");
printf("谐波总畸变率:\r\n");
printf("-------------------------------------------------------------\r\n");
break;
case 5:
printf("THD is: Va_THD=%d%%%,Vb_THD=%d%%,Vc_THD=%d%%\r\n",Va_THD,Vb_THD,Vc_THD);
printf("THD is: Ia_THD=%d%%%,Ib_THD=%d%%,Ic_THD=%d%%\r\n",Ia_THD,Ib_THD,Ic_THD);
break;
case 6:
printf("-------------------------------------------------------------\r\n");
printf("谐波含量(百分值)\r\n");
break;
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
case 16:
case 17:
case 18:
case 19:
case 20:
case 21:
case 22:
case 23:
case 24:
case 25:
case 26:
case 27:
case 28:
case 29:
case 30:
case 31:
case 32:
case 33:
case 34:
case 35:
case 36:
case 37:
i=print_cnt-6;
printf("%2dst----Va=%d%%,Vb=%d%%,Vc=%d%%,Ia=%d%%,Ib=%d%%,Ic=%d%%",\
i,Va_dft_pu[i],Vb_dft_pu[i],Vc_dft_pu[i],\
Ia_dft_pu[i],Ib_dft_pu[i],Ic_dft_pu[i]);
printf("\r\n");
printf("-------------------------------------------------------------\r\n");
// }
break;
case 38:
printf("**************************************************************\r\n");
printf("* The End of the Report * \r\n");
printf("**************************************************************\r\n");
break;
default:print_cnt=0;break;
}
print_cnt++;
if(print_cnt>38){print_cnt=0;}
}