前景介绍
本人曾独立开发风扇灯产品,故在此将相关程序进行总结与分享,与大家一起学习交流。
这里大致介绍下风扇灯这款产品,风扇灯即在传统吊扇上集成了灯光照明的功能,可以通过射频遥控以及APP的WIFI控制,主控芯片接收到射频信号后进行解码,(注:解码程序见本人的博客分享MM32射频解码)解码后解析出遥控码中的操作码并进行相应的操作,调光与控制风扇电机状态等。其中LED调光通过定时器的PWM实现,电机控制通过对电控芯片下发操作码实现。下面将介绍各部分原理及程序。
LED调光
LED调光,自然而然联想到PWM调光,通过改变脉冲宽度实现无极调光。原理许多博客都有介绍与讲解,此处不再赘述。关于定时器的配置程序如下。
//TIM配置
void TIM_Light_Configuration()
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
//时钟初始化
TIM_DeInit(TIM1);
TIM_DeInit(TIM14);
/*
APB2负责AD,I/O,高级TIM,串口1
APB1负责DA,USB,SPI,I2C,CAN,串口2345,普通TIM
*/
/* TIMx clock enable */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB ,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1 |RCC_APB2Periph_TIM14,ENABLE);
//TIM1的PWM功能配置
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0 | GPIO_Pin_1; //TIM1_CH1N TIM1_CH2N TIM1_3N
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//配置指定管脚的复用功能
GPIO_PinAFConfig(GPIOB, GPIO_PinSource0,GPIO_AF_2); //TIM1_CH2N
GPIO_PinAFConfig(GPIOB, GPIO_PinSource1,GPIO_AF_0); //TIM14_CH1
// GPIO_PinAFConfig(GPIOB, GPIO_PinSource13,GPIO_AF_2); //TIM1_CH3N WIFI指示灯
TIM_TimeBaseStructure.TIM_Period = 1000-1; //预装载arr
TIM_TimeBaseStructure.TIM_Prescaler = 3; //预分频2k PWM频率
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; //重复寄存器,用于自动更新PWM占空比
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
TIM_TimeBaseInit(TIM14, &TIM_TimeBaseStructure);
/*
TIM_OCInitTypeDef.TIM_OCMode = TIM_OCMode_PWM1:
当计时器值小于比较器设定值时TIMX输出脚此时输出有效高电平,反之为低电平
TIM_OCInitTypeDef.TIM_OCMode = TIM_OCMode_PWM2:
当计时器值大于比较器设定值时TIMX输出脚此时输出有效高电平,反之为低电平
*/
//PWM设置
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OCInitStructure.TIM_Pulse = 0; //CCR,设置占空比
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //正向通道有效
TIM_OC1Init(TIM14, &TIM_OCInitStructure); //黄灯
//PWM设置
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OCInitStructure.TIM_Pulse = 0; //CCR,设置占空比
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable; //正向通道无效
//高级定时器参数
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low; //互补端极性
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; //反向通道有效
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; //死区后输出状态
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset; //死区后互补端输出状态
TIM_OC2Init(TIM1, &TIM_OCInitStructure); //白灯
//预装载
TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);
TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable);
//Ê使能TIMx在ARR上的预装载寄存器
TIM_ARRPreloadConfig(TIM1, ENABLE);
TIM_ARRPreloadConfig(TIM14, ENABLE);
/* TIM1 counter enable */
TIM_Cmd(TIM1, ENABLE);
TIM_Cmd(TIM14, ENABLE);
/* TIM1 Main Output Enable */
TIM_CtrlPWMOutputs(TIM1, ENABLE);
TIM_CtrlPWMOutputs(TIM14, ENABLE);
}
通过改变TIM的捕获/比较寄存器即可实现脉宽改变,实现TIM的PWM调光。该部分功能函数如下:
/*******************************************************************************************
函数信息:void Yellow_Pulse(u8 Light)
功能描述:
输入参数:Light为灯光亮度等级,0-10亮度依次降低
输出参数:
备注:
********************************************************************************************/
void Yellow_Pulse(u8 Light)
{
TIM_SetCompare1(TIM14, 10*(Light)); //黄灯
}
/*********************************************************************************************
函数信息:void White_Pulse(u8 Light)
功能描述:
输入参数:Light为灯光亮度等级,0-10亮度依次降低
输出参数:
备注:
**************************************************************************************/
void White_Pulse(u8 Light)
{
TIM_SetCompare2(TIM1, 10*(Light)); //白灯
}
MM32下发电控指令
根据产品需求,MM32作为主控芯片,需要完成射频信号解码,以及与电控芯片通信并下发控制指令。电控主要操作有,电机(风扇)转速档位加减,正反转以及自然风选择。首先将控制指令定义如下表。
相关解释:
- 检测码:0001000011101111 周期2s(风扇运转过程中持续发送,不受射频遥控影响)未接收到电控指令时未始终未高电平;
- 信号1,信号周期为2.24ms,高电平占1.62ms,低电平占0.62ms;
- 信号0:信号周期为1.24ms,高电平占0.62ms,低电平占0.62ms;
- 码头的同步码:依次为低电平9ms,高电平4.5ms,低电平0.62ms。
其中检测码用于检测电控芯片与主控MCU(MM32)之间通信的正常稳定,若当风扇电机运转后未在指定时间(2s)内接收到检测码,则电控芯片处于安全考虑将使风扇电机停转。
操作码及地址码宏定义
根据上面的操作码表,将操作码定义如下:
/*地址码宏定义*/
#define Oper_Addr ((uint32_t)0x10EF0000)
/*操作码VSP宏定义*/
/*正转*/
#define Gear_One_Z (Oper_Addr + 0xF50A)
#define Gear_Two_Z (Oper_Addr + 0xF10E)
#define Gear_Three_Z (Oper_Addr + 0xED12)
#define Gear_Four_Z (Oper_Addr + 0xEA15)
#define Gear_Five_Z (Oper_Addr + 0xE619)
#define Gear_Six_Z (Oper_Addr + 0xE21D)
#define Gear_Seven_Z (Oper_Addr + 0xDE21)
#define Gear_Eight_Z (Oper_Addr + 0xDB24)
#define Gear_Nine_Z (Oper_Addr + 0xD728)
#define Gear_Ten_Z (Oper_Addr + 0xD32C)
/*反转*/
#define Gear_One_F (Oper_Addr + 0x758A)
#define Gear_Two_F (Oper_Addr + 0x728D)
#define Gear_Three_F (Oper_Addr + 0x708F)
#define Gear_Four_F (Oper_Addr + 0x6D92)
#define Gear_Five_F (Oper_Addr + 0x6B94)
#define Gear_Six_F (Oper_Addr + 0x6897)
#define Gear_Seven_F (Oper_Addr + 0x6699)
#define Gear_Eight_F (Oper_Addr + 0x639C)
#define Gear_Nine_F (Oper_Addr + 0x619E)
#define Gear_Ten_F (Oper_Addr + 0x5EA1)
/*停止*/
#define Stop (Oper_Addr + 0xFF00)
/*自然风*/
#define Breeze (Oper_Addr + 0xF10E)
/*检测码*/
#define Test (Oper_Addr + 0x00FF)
/*操作码宏定义Oper_Code_Get */
#define Off ((uint8_t)0x11) /*关机*/
#define Reverse ((uint8_t)0x21) /*正反转*/
#define Speed_Plus ((uint8_t)0x31) /*加速*/
#define Speed_Minus ((uint8_t)0x30) /*减速*/
#define Natural ((uint8_t)0x41) /*自然风*/
#de