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(); //这块要注意!!不能放在大循环,因为会导致没有时间响应主机命令!!
}