Files
RS485_10VRLY/Source/SYSTEM/control_rly.c
yeyangwen 1eb7209c0a feat:提交0_10V温控继电器固件
fea:第一次发布固件
2026-04-02 16:33:59 +08:00

608 lines
13 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "includes.h"
ZERO_CTRL_RLY c_rly;
void Relay_Init(void)
{
memset(&c_rly,0, sizeof(ZERO_CTRL_RLY));
EEPROM_Init();
GPT_IO_Init(GPT_CHB_PB00);
GPT_Configure(GPTCLK_EN,GPT_PCLK,GPT_IMMEDIATE,0);
GPT_WaveCtrl_Configure(GPT_INCREASE,GPT_SWSYNDIS,GPT_IDLE_LOW,GPT_PRDLD_PEND,GPT_OPM_CONTINUOUS,GPT_BURST_DIS,GPT_CKS_PCLK,GPT_CG_CHAX,GPT_CGFLT_00,GPT_PRDLD_ZERO);
GPT_Period_CMP_Write(10000,0,0);
GPT_WaveLoad_Configure(GPT_WAVEA_IMMEDIATE,GPT_WAVEB_SHADOW,GPT_AQLDA_ZERO,GPT_AQLDB_ZERO);
GPT_WaveOut_Configure(GPT_CHB,GPT_CASEL_CMPA,GPT_CBSEL_CMPA,2,0,1,1,0,0,0,0,0,0);
GPT_Start();
GPT_ConfigInterrupt_CMD(ENABLE,GPT_INT_PEND);
//真-继电器
GPIO_Init(GPIOA0,12,Output);
GPIO_Init(GPIOA0,13,Output);
RLY_1_CLOSE;
RLY_2_CLOSE;
c_rly.rly_control = 0x01; //继电器控制标志位
}
/*****************************************
* @brief 和校验
* @param data: 校验数据
* @param len: 数据长度
* @retval 和校验值
******************************************/
U8_T CheckSum(U8_T *data,U16_T len)
{
U16_T data_sum = 0;
for(U16_T i = 0;i<len;i++)
{
data_sum += data[i];
}
return data_sum;
}
U8_T CheckSum3(U8_T *data,U16_T len,U16_T n)
{
U16_T data_sum = 0;
for(U16_T i = 0;i<len;i++)
{
if(n != i){
data_sum += data[i];
}
}
return data_sum;
}
/*****************************************
* @brief 和校验取反
* @param data: 校验数据
* @param len: 数据长度
* @retval 和校验值
******************************************/
U8_T CheckSum_Check(U8_T *data,U16_T len)
{
U16_T data_sum = 0;
for(U16_T i = 0;i<len;i++)
{
data_sum += data[i];
}
return ~data_sum;
}
U8_T CheckSum_Overlook_Check(U8_T *data, U16_T len, U16_T check_id)
{
U8_T data_sum = 0;
for(U8_T i = 0;i<len;i++)
{
if(check_id != i) data_sum += data[i];
}
return ~data_sum;
}
//选择输出电压0 - 10000mV
U8_T Change_OUTV(U16_T VolOut)
{
if(VolOut > 10000) return 0x01;
GPT0->CMPA = VolOut;
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_SYS_STATUS,"CMPA:%d",VolOut);
#endif
return 0x00;
}
/********************************************************************
*@brief 由继电器状态判断当前风速输出PWM波
* @param
* @retval None
* */
void BLV_VolOut_Ctrl(void)
{
c_rly.wind = WIND_STOP;
if(c_rly.rly_state[WINDRLY_HIGH] == Control_ON) // 优先级高>中>抵 , 若同时被控制多个风速继电器,则将按照优先级打开继电器
{
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_SYS_STATUS,"WIND_HIGH");
#endif
c_rly.wind = WIND_HIGH;
//c_rly.rly_state[WINDRLY_MID] = Control_OFF;
//c_rly.rly_state[WINDRLY_LOW] = Control_OFF;
}else if(c_rly.rly_state[WINDRLY_MID] == Control_ON)
{
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_SYS_STATUS,"WIND_MID");
#endif
c_rly.wind = WIND_MID;
//c_rly.rly_state[WINDRLY_LOW] = Control_OFF;
}else if(c_rly.rly_state[WINDRLY_LOW] == Control_ON)
{
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_SYS_STATUS,"WIND_LOW");
#endif
c_rly.wind = WIND_LOW;
}
Dbg_Println(DBG_BIT_SYS_STATUS,"VolOut_Ctrl wind:%d",c_rly.wind);
if(c_rly.wind == WIND_STOP){
Change_OUTV(c_rly.wind_STOP_vol);
}else if(c_rly.wind == WIND_LOW){
Change_OUTV(c_rly.wind_LOW_vol);
}else if(c_rly.wind == WIND_MID){
Change_OUTV(c_rly.wind_MID_vol);
}else if(c_rly.wind == WIND_HIGH){
Change_OUTV(c_rly.wind_HIGH_vol);
}
}
/********************************************************************
*@brief 产生继电器控制,直接控制两个实体继电器状态
* @param rly_id:继电器id
* @param state继电器要改变的状态
* @retval None
* */
void BLV_RLY_Ctrl_Purpose(U8_T rly_id,U8_T state)
{
if(rly_id >= RLY_MAX) return;
switch(state)
{
case Control_ON:
if(c_rly.rly_state[rly_id] != Control_ON)
{
c_rly.rly_state[rly_id] = Control_ON;
if(rly_id == CTRL_RLY1){
RLY_1_OPEN;
}else if(rly_id == CTRL_RLY2){
RLY_2_OPEN;
}
}
break;
case Control_OFF:
if(c_rly.rly_state[rly_id] != Control_OFF)
{
c_rly.rly_state[rly_id] = Control_OFF;
if(rly_id == CTRL_RLY1){
RLY_1_CLOSE;
}else if(rly_id == CTRL_RLY2){
RLY_2_CLOSE;
}
}
break;
case Cnotrol_RES:
if(c_rly.rly_state[rly_id] != Control_OFF)
{
c_rly.rly_state[rly_id] = Control_OFF;
if(rly_id == CTRL_RLY1){
RLY_1_CLOSE;
}else if(rly_id == CTRL_RLY2){
RLY_2_CLOSE;
}
}else if(c_rly.rly_state[rly_id] != Control_ON)
{
c_rly.rly_state[rly_id] = Control_ON;
if(rly_id == CTRL_RLY1){
RLY_1_OPEN;
}else if(rly_id == CTRL_RLY2){
RLY_2_OPEN;
}
}
break;
}
}
//继电器动作处理
void BLV_RLY_Task(void)
{
if(c_rly.rly_control != 0x01)return;
for(U8_T i = 0;i<RLY_MAX;i++)
{
if(c_rly.rly_ctrl_state[i] == RLY_OFF)
{
BLV_RLY_Ctrl_Purpose(i,Control_OFF);
}
else if(c_rly.rly_ctrl_state[i] == RLY_ON)
{
BLV_RLY_Ctrl_Purpose(i,Control_ON);
}else if(c_rly.rly_ctrl_state[i] == RLY_RES)
{
BLV_RLY_Ctrl_Purpose(i,Cnotrol_RES);
}
c_rly.rly_ctrl_state[i] = NO_CTRL;
}
BLV_VolOut_Ctrl(); //风速判断输出pwm
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_SYS_STATUS,"BLV_RLY_Task");
#endif
c_rly.rly_control = 0x00;
}
U8_T BLV_CMD_SN(U8_T sn)
{
U8_T rely_sn = (sn & 0x0f);
if(rely_sn <0x0F)
{
rely_sn += 1;
}else{
rely_sn = 0x00;
}
return rely_sn;
}
//1、主机下发设置继电器状态
U8_T BLV_A9RLY_CMD_SET_Processing(U8_T *data,U16_T len)
{
if(len < 9) return 0x01;
U8_T t = 0x00;
U8_T SendData[30];
U16_T SendLen = 0x00;
U16_T RLY_STATE = 0x00;
// if(len >= 9)
{
RLY_STATE =(data[SEND_PARA] + (data[SEND_PARA+1]<<8));
c_rly.rly_control = 0x01; //继电器控制标志
for(U8_T i = 0;i<RLY_MAX;i++)
{
t = ((RLY_STATE>>(2*i)) & 0x03);
if(t == NO_CTRL){
c_rly.rly_ctrl_state[i] = NO_CTRL; //默认状态,不用处理
}else if(t == RLY_OFF){
c_rly.rly_ctrl_state[i] = RLY_OFF;
}else if(t == RLY_ON){
c_rly.rly_ctrl_state[i] = RLY_ON;
}else if(t == RLY_RES){
c_rly.rly_ctrl_state[i] = RLY_RES;
}
}
}
//BLV_RLY_Task();
c_rly.SN = (data[1]&0x0F);
//回复
SendData[SendLen++] = g_Dip.addr;
SendData[SendLen++] = c_rly.SN; //SN
SendData[SendLen++] = data[2];
SendData[SendLen++] = data[0];
SendData[SendLen++] = 0x00; //len
SendData[SendLen++] = 0x00; //sum
SendData[SendLen++] = CMD_SET_RLYSTATE_REPLY; //回复CMD
SendLen = 0x07;
SendData[SEND_LEN] = SendLen; //len
SendData[SEND_SUM] = CheckSum_Check(SendData,SendLen);
Set_GroupSend(SendData,SendLen,1,BUSSend_WaitTime1,20); //组包
return 0x00;
}
//2、读取继电器状态的回复
void BLV_A9RLY_CMD_READ_Processing(U8_T *data,U16_T len)
{
U8_T SendData[30];
U16_T SendLen = 0x00;
U8_T RLY_State2 = 0x00;
for(U8_T i = 0;i<RLY_MAX;i++)
{
if(c_rly.rly_state[i] == Control_ON)
{
RLY_State2 |= (0x01<<i);
}
}
c_rly.SN = (data[1]&0x0F);
//回复
SendData[SendLen++] = g_Dip.addr;
SendData[SendLen++] = c_rly.SN;
SendData[SendLen++] = data[2];
SendData[SendLen++] = data[0];
SendData[SendLen++] = 0x00; //len
SendData[SendLen++] = 0x00; //sum
SendData[SendLen++] = CMD_READ_RLYSTATE_REPLY; //回复CMD
SendData[SendLen++] = RLY_State2;
SendData[SendLen++] = 0x00;
SendData[SendLen++] = 0x00;
SendLen = 0x0A;
SendData[SEND_LEN] = 0x0A; //len
SendData[SEND_SUM] = CheckSum_Check(SendData,SendLen);
Set_GroupSend(SendData,SendLen,1,BUSSend_WaitTime1,20); //组包
}
//3、设置各个风速档位的电压输出值
U8_T BLV_WINDOUT_CMD_SET_Processing(U8_T *data,U16_T len)
{
if(len < 15) return 0x01;
U8_T save_flag = 0x00;
U8_T SendData[30];
U16_T SendLen = 0x00;
U16_T SetVol = 0x00;
// if(len >= 15)
{
for(U8_T i = 0x00; i < 0x04; i++)
{
SetVol = (data[(SEND_PARA+(i*2))] + (data[(SEND_PARA+(i*2+1))]<<8 ));
if(SetVol <= 10000){
switch(i){
case 0x00:
if(c_rly.wind_STOP_vol != SetVol){
c_rly.wind_STOP_vol = SetVol;
save_flag++;
}
break;
case 0x01:
if(c_rly.wind_LOW_vol != SetVol){
c_rly.wind_LOW_vol = SetVol;
save_flag++;
}
break;
case 0x02:
if(c_rly.wind_MID_vol != SetVol){
c_rly.wind_MID_vol = SetVol;
save_flag++;
}
break;
case 0x03:
if(c_rly.wind_HIGH_vol != SetVol){
c_rly.wind_HIGH_vol = SetVol;
save_flag++;
}
break;
}
}
}
}
if(save_flag != 0x00)
{
EEPROM_WritePara(); //保存flash
}
BLV_VolOut_Ctrl();
c_rly.SN = (data[1]&0x0F);
//回复
SendData[SendLen++] = g_Dip.addr;
SendData[SendLen++] = c_rly.SN;
SendData[SendLen++] = data[2];
SendData[SendLen++] = data[0];
SendData[SendLen++] = 0x00; //len
SendData[SendLen++] = 0x00; //sum
SendData[SendLen++] = CMD_SET_WINDOUTVOL_REPLY; //回复CMD
SendLen = 0x07;
SendData[SEND_LEN] = SendLen; //len
SendData[SEND_SUM] = CheckSum_Check(SendData,SendLen);
Set_GroupSend(SendData,SendLen,1,BUSSend_WaitTime1,20); //组包
return 0x00;
}
//4、读取各个风速档位的电压输出值
U8_T BLV_WINDOUT_CMD_READ_Processing(U8_T *data,U16_T len)
{
U8_T SendData[30];
U16_T SendLen = 0x00;
c_rly.SN = (data[1]&0x0F);
//回复
SendData[SendLen++] = g_Dip.addr;
SendData[SendLen++] = c_rly.SN;
SendData[SendLen++] = data[2];
SendData[SendLen++] = data[0];
SendData[SendLen++] = 0x00; //len
SendData[SendLen++] = 0x00; //sum
SendData[SendLen++] = CMD_READ_WINDOUTVOL_REPLY; //回复CMD
SendData[SendLen++] = (c_rly.wind_STOP_vol & 0xFF);
SendData[SendLen++] = (c_rly.wind_STOP_vol >> 8) & 0xFF;
SendData[SendLen++] = (c_rly.wind_LOW_vol & 0xFF);
SendData[SendLen++] = (c_rly.wind_LOW_vol >> 8) & 0xFF;
SendData[SendLen++] = (c_rly.wind_MID_vol & 0xFF);
SendData[SendLen++] = (c_rly.wind_MID_vol >> 8) & 0xFF;
SendData[SendLen++] = (c_rly.wind_HIGH_vol & 0xFF);
SendData[SendLen++] = (c_rly.wind_HIGH_vol >> 8) & 0xFF;
SendLen = 0x0F;
SendData[SEND_LEN] = SendLen; //len
SendData[SEND_SUM] = CheckSum_Check(SendData,SendLen);
Set_GroupSend(SendData,SendLen,1,BUSSend_WaitTime1,20); //组包
return 0x00;
}
//5、设置端口模式
U8_T BLV_DEVPROT_CMD_SET_Processing(U8_T *data,U16_T len)
{
if(len != 0x08) return 0x01;
U8_T SendData[30];
U16_T SendLen = 0x00;
if((data[SEND_PARA] == ACTIVE_PORT)||((data[SEND_PARA] == POLLING_PORT)))
{
if(data[SEND_PARA] != c_rly.dev_port){
c_rly.dev_port = data[SEND_PARA];
EEPROM_WritePara(); //保存flash
}
}else{
return 0x02;//设置的端口不合法
}
c_rly.SN = (data[1]&0x0F);
//回复
SendData[SendLen++] = g_Dip.addr;
SendData[SendLen++] = c_rly.SN;
SendData[SendLen++] = data[2];
SendData[SendLen++] = data[0];
SendData[SendLen++] = 0x00; //len
SendData[SendLen++] = 0x00; //sum
SendData[SendLen++] = CMD_SET_DEVPORT_REPLY; //回复CMD
SendLen = 0x07;
SendData[SEND_LEN] = SendLen; //len
SendData[SEND_SUM] = CheckSum_Check(SendData,SendLen);
Set_GroupSend(SendData,SendLen,1,BUSSend_WaitTime1,20); //组包
return 0x00;
}
//6、读取端口模式
U8_T BLV_DEVPROT_CMD_READ_Processing(U8_T *data,U16_T len)
{
U8_T SendData[30];
U16_T SendLen = 0x00;
c_rly.SN = (data[1]&0x0F);
//回复
SendData[SendLen++] = g_Dip.addr;
SendData[SendLen++] = c_rly.SN;
SendData[SendLen++] = data[2];
SendData[SendLen++] = data[0];
SendData[SendLen++] = 0x00; //len
SendData[SendLen++] = 0x00; //sum
SendData[SendLen++] = CMD_READ_DEVPORT_REPLY; //回复CMD
SendData[SendLen++] = c_rly.dev_port; //端口模式
SendData[SendLen++] = Project_FW_Version; //软件版本号
SendData[SendLen++] = Project_HW_Version; //硬件版本号
SendLen = 0x0A;
SendData[SEND_LEN] = SendLen; //len
SendData[SEND_SUM] = CheckSum_Check(SendData,SendLen);
Set_GroupSend(SendData,SendLen,1,BUSSend_WaitTime1,20); //组包
return 0x00;
}
U8_T BLV_RLY_RS485_Pro(U8_T *RecData, U16_T Len)
{
U8_T ret = 0x00;
if(Len < 0x07)
{
Dbg_Println(DBG_BIT_SYS_STATUS,"Data Len Err");
return 0x01;
}
if(RecData[4] != Len)
{
Dbg_Println(DBG_BIT_SYS_STATUS,"Len Check Err");
return 0x01;
}
if(RecData[2] != A9EXPANDTYPE) //A9继电器设备类型
{
Dbg_Println(DBG_BIT_SYS_STATUS,"Type Check Err");
return 0x02;
}
if(RecData[3] != g_Dip.addr) //地址校验
{
Dbg_Println(DBG_BIT_SYS_STATUS,"Addr Check Err ");
return 0x03;
}
if( CheckSum_Overlook_Check(RecData,Len,SEND_SUM) != RecData[SEND_SUM] ) //和校验
{
Dbg_Println(DBG_BIT_SYS_STATUS,"Sum Check Err: %02x,%02x",RecData[SEND_SUM],CheckSum_Overlook_Check(RecData,Len,SEND_SUM));
Dbg_Print_Buff(DBG_BIT_SYS_STATUS,"Sum Check Err: ",RecData,Len);
return 0x05;
}
if((RecData[SEND_SN]&0x0F) == c_rly.SN)
{
Dbg_Println(DBG_BIT_SYS_STATUS,"SN is Equal: %02x",c_rly.SN);
return 0x00;
}
switch(RecData[0x06])
{
#if DBG_LOG_EN
Dbg_Println(DBG_BIT_SYS_STATUS,"BLV_RLY_RS485 CMD:%02x",RecData[0x06]);
#endif
case CMD_SET_RLYSTATE:
BLV_A9RLY_CMD_SET_Processing(RecData,Len);
break;
case CMD_READ_RLYSTATE:
BLV_A9RLY_CMD_READ_Processing(RecData,Len);
break;
case CMD_SET_WINDOUTVOL:
BLV_WINDOUT_CMD_SET_Processing(RecData,Len);
break;
case CMD_READ_WINDOUTVOL:
BLV_WINDOUT_CMD_READ_Processing(RecData,Len);
break;
case CMD_SET_DEVPORT:
BLV_DEVPROT_CMD_SET_Processing(RecData,Len);
break;
case CMD_READ_DEVPORT:
BLV_DEVPROT_CMD_READ_Processing(RecData,Len);
break;
}
}
void CTRL_LEDStatus_Task(void)
{
static U32_T Ctrl_LED_tick = 0x00;
if(SysTick_1ms - Ctrl_LED_tick >= 500)
{
Ctrl_LED_tick = SysTick_1ms;
REVERISE_STATUS;
}
}