标题:
基于stm8L051F3单片机的无线遥控器程序设计
[打印本页]
作者:
gandonjun
时间:
2019-12-30 13:59
标题:
基于stm8L051F3单片机的无线遥控器程序设计
使用stm8L051F3芯片,RF433频率的无线遥控器代码,支持3种按键模式
51hei.png
(13.46 KB, 下载次数: 48)
下载附件
2019-12-30 15:54 上传
单片机源程序如下:
#include "All_Includes.h"
#define ACCEL_OPEN 180
#define ACCEL_SHAKE 60
#define ANGLE_OPEN 900 //55°* 16.4 = 900
#define OPEN_TEST_TIME_GATE 25 //3s
#define SHAKE_TEST_TIME_GATE (4*60) //4min
#define SHAKE_TIME_GATE 60 //60s
#define ID_ADDR 0x4926
#define CODE_MATCH 0X79
#define CODE_DOWN 0X33
#define CODE_UP 0X11
#define CODE_STOP 0X55
#define CODE_DRY 0X75
#define CODE_LED 0X0F
#define CODE_XD 0X73
#define CODE_HEAT 0X76
#define CODE_FLZ 0X44
uint8_t ShakeFlag = 0;
uint8_t ShakeFirstFlag = 0;
uint8_t DryFlag = 0;//0--未检测到任何信号 1--检测到连续震动 2--检测到加速度 3--检测到开门信号
uint8_t ShakeTime_1S = 0;
uint16_t TimeCount = 0;
uint16_t TestCount = 0;
uint16_t TestFlag = 76;
uint8_t TestHALF = 0;
uint8_t HALF_H_FLAG = 1;
uint8_t GO_FLAG = 0;
uint8_t TestGo = 0;
uint8_t ShakeTime = 0;
uint16_t ShakeTestTime = 0;
uint8_t OpenTestTime = 0;
uint8_t Uid[4] = {0};
uint8_t KeyFlag = 0;
uint8_t UpFlag = 1;
uint8_t DnFlag = 1;
uint8_t TimeFlag = 0;
void Lsi_Clk_Init(void)
{
CLK_SYSCLKSourceSwitchCmd(ENABLE); //使能时钟切换
CLK_SYSCLKSourceConfig(CLK_SYSCLKSource_LSI); //选择内部低速时钟作为时钟源
CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_1); //设置系统时钟分频32K
while (CLK_GetSYSCLKSource() != CLK_SYSCLKSource_LSI);//等待时钟稳定
CLK_HSICmd(DISABLE);
}
void Hsi_Clk_Init(void)
{
CLK_SYSCLKSourceSwitchCmd(ENABLE); //使能时钟切换
CLK_SYSCLKSourceConfig(CLK_SYSCLKSource_HSI); //选择内部高速时钟作为时钟源
CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_16); //设置系统时钟分频1M
while (CLK_GetSYSCLKSource() != CLK_SYSCLKSource_HSI);//等待时钟稳定
}
void Rtc_Init(void)
{
CLK_PeripheralClockConfig(CLK_Peripheral_RTC, ENABLE);//RTC时钟门控使能
CLK_RTCClockConfig(CLK_RTCCLKSource_LSI, CLK_RTCCLKDiv_1);
RTC_WakeUpClockConfig(RTC_WakeUpClock_RTCCLK_Div16);
RTC_SetWakeUpCounter(200); //80ms
RTC_WakeUpCmd(ENABLE);
PWR_FastWakeUpCmd(ENABLE); //快速唤醒使能
PWR_UltraLowPowerCmd(ENABLE);//超低功耗
RTC_ITConfig(RTC_IT_WUT, ENABLE);
}
void Init_All(void)
{
Hsi_Clk_Init(); //初始化时钟
Time4_Init();
Gpio_Init();
//MPU6050_Init();
}
/*STM8L处于HALT状态,6050处于1HZ检测状态*/
void Enter_Halt(void)
{
//MPU6050_Init_1HZ();
//Gpio_Init_LowPower();
Lsi_Clk_Init();
PWR_UltraLowPowerCmd(ENABLE);//超低功耗
//MPU6050INT_Port->CR2 |= MPU6050INT_PINS; //开中断
enableInterrupts();
halt();
}
/*STM8L处于AWU状态,6050处于40HZ检测状态*/
void Enter_AWU(void)
{
MPU6050_Init_40HZ();
Gpio_Init_LowPower();
Lsi_Clk_Init();
Rtc_Init();
PWR_UltraLowPowerCmd(ENABLE);//超低功耗
halt();
}
int16_t fabs(int16_t x)
{
if(x > 0)
{
return x;
}
else
{
return -x;
}
}
uint16_t fabs_2(int16_t x,int16_t y)
{
if(x > y)
{
return (uint16_t)((int32_t)x-(int32_t)y);
}
else
{
return (uint16_t)((int32_t)y-(int32_t)x);
}
}
void GetStm8Id(uint8_t* uid)
{
uid[0] = *(uint8_t*)(ID_ADDR+4);
uid[1] = *(uint8_t*)(ID_ADDR+6);
uid[2] = *(uint8_t*)(ID_ADDR+8);
uid[3] = *(uint8_t*)(ID_ADDR+9);
//uid[0] = 0x76;
//uid[1] = 0x44;
//uid[2] = 0x77;
//uid[3] = 0x61;//6,9
}
void KeyDeal(uint8_t code , uint8_t key_pins )
{
disableInterrupts();
//KeyFlag = 0;
TimeCount = 0;
if(0 == (KEY_PORT_B->IDR & key_pins))//按键为0表示有按键按下
{
Delay100uS(100);
if(0 == (KEY_PORT_B->IDR & key_pins))//延时10ms消抖
{
SysLED_High;
Send_RF433_Data_3Time(code);
Delay100uS(100);
SysLED_Low;
}
}
enableInterrupts();
}
/*******************************************
1s调用一次
1s内有2次以上震动就算检测到震动信号,否则算为静止时间,连续静止5s以上重新进入低功耗模式
连续检测到5次以上震动信号就算检测到甩干信号
*******************************************/
void ShakeMonitor(void)
{
if(ShakeTime_1S >= 2)//1s内2次
{
ShakeTime_1S = 0;
ShakeTime++;
if(ShakeTime >= SHAKE_TIME_GATE)
{
DryFlag = 1;
ShakeTime = 0;
return;
}
}
ShakeTestTime ++;
if((ShakeTestTime >= 40 && ShakeTime <= 5)
|| ShakeTestTime >= SHAKE_TEST_TIME_GATE)//(40s内5s,4min内60s)进入低功耗
{
ShakeFlag = 0;
ShakeTime_1S = 0;
ShakeTime = 0;
ShakeTestTime = 0;
}
}
/*******************************************
100ms调用一次
未检测到甩干信号时检测甩干信号
检测到甩干信号后定时唤醒检测开门状态
*******************************************/
void ShakeProcess(void)
{
int16_t acce_x_aver = 0;
int16_t acce_y_aver = 0;
int16_t acce_z_aver = 0;
uint16_t acce_x_change = 0;
uint16_t acce_y_change = 0;
uint16_t acce_z_change = 0;
static int16_t acce_x_before = 0;
static int16_t acce_y_before = 0;
static int16_t acce_z_before = 0;
int16_t gyro_x_aver = 0;
int16_t gyro_y_aver = 0;
int16_t gyro_z_aver = 0;
static int32_t Angle_x = 0;
static int32_t Angle_y = 0;
static int32_t Angle_z = 0;
MPU6050INT_Port->CR2 &= ~MPU6050INT_PINS; //关闭中断
I2C_IOInit();
MPU6050ReadAcc(&acce_x_aver,&acce_y_aver,&acce_z_aver);
if(1 == ShakeFirstFlag)
{
DryFlag = 0;
ShakeTestTime = 0;
ShakeTime_1S = 0;
ShakeTime = 0;
OpenTestTime = 0;
ShakeFirstFlag = 0;
acce_x_before = acce_x_aver;
acce_y_before = acce_y_aver;
acce_z_before = acce_z_aver;
}
acce_x_change = fabs_2(acce_x_aver,acce_x_before);
acce_y_change = fabs_2(acce_y_aver,acce_y_before);
acce_z_change = fabs_2(acce_z_aver,acce_z_before);
acce_x_before = acce_x_aver;
acce_y_before = acce_y_aver;
acce_z_before = acce_z_aver;
if(0 == DryFlag) //要检测连续震动信号
{
if(ACCEL_SHAKE < acce_x_change || ACCEL_SHAKE < acce_y_change || ACCEL_SHAKE < acce_z_change)//震动
{
ShakeTime_1S++;
}
TimeCount++;
if(TimeCount >= 10)
{
TimeCount = 0;
ShakeMonitor();
}
}
else if(1 == DryFlag)//检测到连续震动之后需要检测开门信号
{
if(ACCEL_OPEN < acce_x_change || ACCEL_OPEN < acce_y_change || ACCEL_OPEN < acce_z_change)//开门
{
DryFlag = 2;
Angle_x = 0;
Angle_y = 0;
Angle_z = 0;
}
}
else if(2 == DryFlag)//检测到瞬间加速度值大于开门加速度
{
MPU6050_Init_Active();
MPU6050ReadGyro(&gyro_x_aver,&gyro_y_aver,&gyro_z_aver);
Angle_x = Angle_x + gyro_x_aver/6; //150ms
Angle_y = Angle_y + gyro_y_aver/6;
Angle_z = Angle_z + gyro_z_aver/6;
if(ANGLE_OPEN < fabs(Angle_x) || ANGLE_OPEN < fabs(Angle_y) || ANGLE_OPEN < fabs(Angle_z))
{
DryFlag = 0;
ShakeFirstFlag = 0;
ShakeFlag = 0;
disableInterrupts();
Send_RF433_Data_3Time(CODE_DOWN);
enableInterrupts();
return;
}
OpenTestTime++;
if(OpenTestTime >= OPEN_TEST_TIME_GATE)//超过一定时间检测到角度变化值小则重新检测加速度
{
OpenTestTime = 0;
DryFlag = 1;
}
}
}
uint8_t itoa(int32_t num,uint8_t *str,int8_t radix)
{
uint8_t index[]= "0123456789ABCDEF";
uint32_t unum;
int8_t i=0,j,k;
if(num < 0)
{
unum=(uint32_t)(-num);
str[i++] = '-';
}
else
{
unum = (uint32_t)num;
}
do
{
str[i++] = index[unum%radix];
unum /= radix;
}while(unum);
str[i]='\0';
/*逆序*/
if(str[0]=='-')
{
k=1;/*十进制负数*/
}
else
{
k=0;
}
int8_t temp;
for(j=k;j<=(i-1)/2;j++)
{
temp = str[j];
str[j] = str[i-1+k-j];
str[i-1+k-j] = temp;
}
return i;
}
void main(void)
{
disableInterrupts();
Init_All();
SysLED_High;
//Delay100uS(10000);
SysLED_Low;
GetStm8Id(Uid);
//Enter_Halt();
enableInterrupts();
//Enter_Halt();
Send_RF433_Data_3Time(CODE_MATCH);
while(1)
{
//Hsi_Clk_Init();
//RTC_ITConfig(RTC_IT_WUT, DISABLE);
switch(KeyFlag)
{
case 1 : //上升
Delay100uS( TimeCount );
if(0 == (KEY_PORT_B->IDR & (KEY_PINS_UP | KEY_PINS_DN )))
{
KeyDeal( CODE_MATCH , (KEY_PINS_UP | KEY_PINS_DN) );
TimeCount = 0;
}
else if ( KeyFlag )
{
KeyDeal( CODE_UP, KEY_PINS_UP );
TimeFlag ++;
}
if ( KEY_PORT_B->IDR & KEY_PINS_UP )
{
Send_RF433_Data( 0X1E );
KeyFlag = 0;
}
if ( TimeFlag >= 60 )//发送60次报文,时间约10s,
{
KeyFlag = 0;
TimeFlag = 0;
}
break;
case 2: //下降
Delay100uS( TimeCount );
if(0 == (KEY_PORT_B->IDR & (KEY_PINS_UP | KEY_PINS_DN )))
{
KeyDeal( CODE_MATCH , (KEY_PINS_UP | KEY_PINS_DN) );
TimeCount = 0;
}
else if ( KeyFlag )
{
KeyDeal( CODE_DOWN, KEY_PINS_DN );
TimeFlag ++;
}
if ( KEY_PORT_B->IDR & KEY_PINS_DN )
{
Send_RF433_Data( 0X3E );
KeyFlag = 0;
}
if ( TimeFlag >= 60 ) //发送60次后停止
{
KeyFlag = 0;
TimeFlag = 0;
}
break;
case 3: //风干
KeyDeal( CODE_DRY , KEY_PINS_DRY );
KeyFlag = 0;
break;
case 4: //照明
KeyDeal( CODE_LED , KEY_PINS_LED );
//Send_RF433_Data_3Time(0x79);
KeyFlag = 0;
break;
case 5: //消毒
KeyDeal( CODE_XD , KEY_PINS_XD );
KeyFlag = 0;
break;
case 6: //烘干
KeyDeal( CODE_HEAT , KEY_PINS_HEAT );
KeyFlag = 0;
break;
case 7: //负离子
KeyDeal( CODE_FLZ , KEY_PINS_FLZ );
KeyFlag = 0;
break;
default:
//Enter_Halt(); //没有按键的情况下,进入低功耗
break;
}
}
}
复制代码
所有资料51hei提供下载:
YK001 V1.0.7z
(635.9 KB, 下载次数: 43)
2019-12-30 15:56 上传
点击文件名下载附件
下载积分: 黑币 -5
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1