1.频率

/**根据需要的频率,求得单次高低电平的周期,再以50%占空比输出。**/
//设定开关频率 相当于 模拟输出一个pwm波,eg:100hz 50%

void led_frequency_ctrl(void)
{      
  period = 1/frequency*1000;  //1
  
  if(CheckDelay((uint32_t*)&time_f)==0)
  {
    Set_Delay_Time(period,(uint32_t*)&time_f);  //1
  }  
  if(time_f <= period/2)  //2
  {
    PAout(1) = 1;
    MP_ModBus1.Hold_Reg[2] = 0;
  }
  else
  {
    PAout(1) = 0;
    MP_ModBus1.Hold_Reg[2] = 1;
  }
}


/**之后再1ms调用**/
static void Task_1ms(void)
{ 
  DelayTimeCount_ms((uint32_t*)&time_f); //!!!
  TimeCountReceive(&U_D_Uart2);
}

2.modbus主从机主要代码

注:主机只需要发什么功率什么频率以及读取已经处理好的监控值,真正控制处理灯的是从机。

例如:

第三功能,需要只在开灯情况下读取监控值,那么就让从机只在开灯状态才存入就好,这样主机获取的都是开灯状态下的值,不需要自己在判断。

再例如:

设定频率,主机只需要告诉从机,你要以多大频率开关灯,从机得知后自主转换控制频率。而不是之前,主机亲自控制每一次开关达到控制频率效果,复杂而且通信量很大出错率也高。

/**主机**/
/**实现3/4个功能:1.灯开关频率设定 2.功率设定 3.读取监控值**/



#include "md_data_set.h"

struct all_ctrl  struct_ctrl;
struct pid_para  pid_dev;
uint16_t v_detection = 0;
uint16_t p_monitor = 0;
uint16_t led_on_off_time = 0;
uint16_t setp_time = 0;


void power_ctrl_init(void)
{
  struct_ctrl.powerset = &power_ctrl;
  struct_ctrl.set_power_ok = 0;
}

/*************************************************************************/
void led_on_off_poll(void)
{
  static uint8_t x = 0;
  switch(x)
  {
    case 0:
    {
      if(CheckDelay(&led_on_off_time)==0)
      {
        SetLedEnable();
        Set_Delay_Time(300,&led_on_off_time);
        x++;        
      }      
    }break;
    case 1:
    {
      if(struct_ctrl.powerset->LEDUpdate == 1)
      {
        struct_ctrl.powerset->LEDUpdate = 0; 
      }
      x = 0;
    }break;
    default:
    {
       x = 0;
    }break;
  } 
}
/*************************************************************************/
void power_set_poll(void)
{
  static uint8_t State = 0;
  switch(State)
  {
    case 0:
    {
      if(CheckDelay(&setp_time)==0)
      {
        SetPowerEnable();
        struct_ctrl.set_power_ok = 0;
        Set_Delay_Time(1100,&setp_time);
        State++;        
      }      
    }break;
    case 1:
    {
      if(struct_ctrl.powerset->DataUpdate == 1)
      {
        struct_ctrl.powerset->DataUpdate = 0;
        struct_ctrl.set_power_ok = 1;      
        
      }   
      State = 0;
    }break;
    default:
    {
       State = 0;
    }break;
  } 
}
/*************************************************************************/
void read_poll(void)
{
  static uint8_t State = 0;
  switch(State)
  {
    case 0:
    {
       ReadPowerEnable();
       State++;
    }break;
    case 1:
    {
      if(struct_ctrl.powerset->PowerDataUpdate == 1)
      {
         struct_ctrl.powerset->PowerDataUpdate = 0;
         v_detection = struct_ctrl.powerset->MMD.Hold_Reg[3];
         p_monitor = struct_ctrl.powerset->MMD.Hold_Reg[4];         
      }  
      State = 0;
    }break;
    default:
    {
       State = 0;
    }break;
  }
}
/*************************************************************************/
void commit_scope_poll(void)
{
    rev_string_fuction();    
    if(uart_3.flag_v == 1)
    {
      McuSendData(UartVisSco, (int16_t *)&struct_ctrl.powerset->MMD.Hold_Reg[3]);
    }
    if(uart_3.flag_p == 1)
    {
      McuSendData(UartVisSco, (int16_t *)&struct_ctrl.powerset->MMD.Hold_Reg[4]);
    }
}




/**从机主要代码**/


#include "data_trans.h"

uint16_t PowerSet = 0;  //modbus master set
uint16_t PowerOut = 0;  //pwm
uint16_t time_f = 0;
float frequency = 0; //led on/off

double v_detection = 0.00f;
double power_monitor = 0.00f;
float  period = 0;

void registers_init(void)
{
  time_f = 0;
  PAout(1) = 0;
  frequency = 0;
  MP_ModBus1.Hold_Reg[0] = 0; //hz
  MP_ModBus1.Hold_Reg[1] = 0; //powerout 
 ///MP_ModBus1.Hold_Reg[2] = 0; //on is 1,off is 0 //这块没必要,是错误的想法,详见上面解析
  MP_ModBus1.Hold_Reg[3] = 0; //v_m
  MP_ModBus1.Hold_Reg[4] = 0; //p_m
}

/******************************************************/
void get_v_detection(void)
{
  uint16_t temp_0;
  float v0;
  
  temp_0 = ADC_ConvertedValue[0];
  v_detection = (float)temp_0/4096*3.3;
  v0 = v_detection*1000;
  MP_ModBus1.Hold_Reg[3] = (uint16_t)v0;
}
void get_power_monitor(void)
{
  uint16_t temp_1;
  float p1;
  
  temp_1 = ADC_ConvertedValue[1];
  power_monitor = (float)temp_1/4096*3.3;
  p1 = power_monitor*1000;
  MP_ModBus1.Hold_Reg[4] = (uint16_t)p1;
}
/******************************************************/
void led_frequency_ctrl(void)
{      
  period = 1/frequency*1000;
  
  if(CheckDelay((uint32_t*)&time_f)==0)
  {
    Set_Delay_Time(period,(uint32_t*)&time_f);  
  }  
  if(time_f <= period/2)
  {
    PAout(1) = 1;
    MP_ModBus1.Hold_Reg[2] = 0;
  }
  else
  {
    PAout(1) = 0;
    MP_ModBus1.Hold_Reg[2] = 1;
  }
}
/******************************************************/
void SetPowerOut(uint16_t Pset)
{
  __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_4,Pset);
}
/******************************************************/
void modbus_slave_poll(void)
{
  static uint8_t State = 0;
  switch(State)
  {
      case 0:
      {
         frequency = MP_ModBus1.Hold_Reg[0];
         State++;
      }break;
      case 1:
      {  
          PowerSet = MP_ModBus1.Hold_Reg[1];
          SetPowerOut(PowerSet); 
          State++;
      }break;
      case 2:
      {
        State = 0;
      }break;
      
      default:
      {
         State = 0;
      };
  }
}

/******************************************************/
/******************************************************/
/******************************************************/
static void Task_1ms(void)
{ 
   DelayTimeCount_ms((uint32_t*)&time_f);
   TimeCountReceive(&U_D_Uart2);
}
static void Task_2ms(void)
{
  if(MP_ModBus1.Hold_Reg[2]==1)  //处理led开时候读取监控数据
  {
    get_v_detection();
    get_power_monitor(); 
  }
}
static void Task_5ms(void)
{
	
}
static void Task_10ms(void)
{
	modbus_slave_poll();    //这块要注意!!不能放在大循环,因为会导致没有时间响应主机命令!!
}