找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2744|回复: 0
打印 上一主题 下一主题
收起左侧

基于stm8L051F3单片机的无线遥控器程序设计

[复制链接]
跳转到指定楼层
楼主
使用stm8L051F3芯片,RF433频率的无线遥控器代码,支持3种按键模式


单片机源程序如下:
  1. #include "All_Includes.h"

  2. #define ACCEL_OPEN              180
  3. #define ACCEL_SHAKE             60
  4. #define ANGLE_OPEN              900     //55°* 16.4 = 900
  5. #define OPEN_TEST_TIME_GATE     25      //3s
  6. #define SHAKE_TEST_TIME_GATE    (4*60)  //4min
  7. #define SHAKE_TIME_GATE         60      //60s
  8. #define ID_ADDR                 0x4926
  9. #define CODE_MATCH              0X79
  10. #define CODE_DOWN               0X33
  11. #define CODE_UP                 0X11
  12. #define CODE_STOP                 0X55
  13. #define CODE_DRY                 0X75
  14. #define CODE_LED                 0X0F
  15. #define CODE_XD                 0X73
  16. #define CODE_HEAT                 0X76
  17. #define CODE_FLZ                 0X44



  18. uint8_t ShakeFlag       = 0;
  19. uint8_t ShakeFirstFlag  = 0;
  20. uint8_t DryFlag         = 0;//0--未检测到任何信号 1--检测到连续震动 2--检测到加速度 3--检测到开门信号
  21. uint8_t ShakeTime_1S    = 0;
  22. uint16_t TimeCount       = 0;

  23. uint16_t TestCount       = 0;
  24. uint16_t TestFlag    = 76;
  25. uint8_t TestHALF    = 0;
  26. uint8_t HALF_H_FLAG    = 1;
  27. uint8_t GO_FLAG    = 0;

  28. uint8_t TestGo = 0;

  29. uint8_t ShakeTime       = 0;
  30. uint16_t ShakeTestTime  = 0;
  31. uint8_t OpenTestTime    = 0;
  32. uint8_t Uid[4]          = {0};
  33. uint8_t KeyFlag         = 0;
  34. uint8_t UpFlag         = 1;
  35. uint8_t DnFlag         = 1;
  36. uint8_t TimeFlag = 0;



  37. void Lsi_Clk_Init(void)
  38. {
  39.     CLK_SYSCLKSourceSwitchCmd(ENABLE);            //使能时钟切换
  40.     CLK_SYSCLKSourceConfig(CLK_SYSCLKSource_LSI); //选择内部低速时钟作为时钟源
  41.     CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_1);         //设置系统时钟分频32K
  42.     while (CLK_GetSYSCLKSource() != CLK_SYSCLKSource_LSI);//等待时钟稳定
  43.     CLK_HSICmd(DISABLE);
  44. }

  45. void Hsi_Clk_Init(void)
  46. {
  47.     CLK_SYSCLKSourceSwitchCmd(ENABLE);            //使能时钟切换
  48.     CLK_SYSCLKSourceConfig(CLK_SYSCLKSource_HSI); //选择内部高速时钟作为时钟源
  49.     CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_16);         //设置系统时钟分频1M
  50.     while (CLK_GetSYSCLKSource() != CLK_SYSCLKSource_HSI);//等待时钟稳定
  51. }


  52. void Rtc_Init(void)
  53. {
  54.     CLK_PeripheralClockConfig(CLK_Peripheral_RTC, ENABLE);//RTC时钟门控使能
  55.     CLK_RTCClockConfig(CLK_RTCCLKSource_LSI, CLK_RTCCLKDiv_1);
  56.     RTC_WakeUpClockConfig(RTC_WakeUpClock_RTCCLK_Div16);
  57.     RTC_SetWakeUpCounter(200);          //80ms
  58.     RTC_WakeUpCmd(ENABLE);
  59.         
  60.     PWR_FastWakeUpCmd(ENABLE);  //快速唤醒使能
  61.     PWR_UltraLowPowerCmd(ENABLE);//超低功耗
  62.     RTC_ITConfig(RTC_IT_WUT, ENABLE);
  63. }
  64.   
  65. void Init_All(void)
  66. {
  67.     Hsi_Clk_Init(); //初始化时钟
  68.     Time4_Init();
  69.     Gpio_Init();
  70.     //MPU6050_Init();
  71. }

  72. /*STM8L处于HALT状态,6050处于1HZ检测状态*/
  73. void Enter_Halt(void)
  74. {
  75.     //MPU6050_Init_1HZ();
  76.     //Gpio_Init_LowPower();
  77.     Lsi_Clk_Init();
  78.     PWR_UltraLowPowerCmd(ENABLE);//超低功耗
  79.     //MPU6050INT_Port->CR2 |= MPU6050INT_PINS;     //开中断
  80.     enableInterrupts();
  81.     halt();   
  82. }

  83. /*STM8L处于AWU状态,6050处于40HZ检测状态*/
  84. void Enter_AWU(void)
  85. {
  86.     MPU6050_Init_40HZ();
  87.     Gpio_Init_LowPower();
  88.     Lsi_Clk_Init();
  89.     Rtc_Init();
  90.     PWR_UltraLowPowerCmd(ENABLE);//超低功耗
  91.     halt();
  92. }

  93. int16_t fabs(int16_t x)
  94. {
  95.     if(x > 0)
  96.     {
  97.         return x;
  98.     }
  99.     else
  100.     {
  101.         return -x;
  102.     }
  103. }

  104. uint16_t fabs_2(int16_t x,int16_t y)
  105. {
  106.     if(x > y)
  107.     {
  108.         return (uint16_t)((int32_t)x-(int32_t)y);
  109.     }
  110.     else
  111.     {
  112.         return (uint16_t)((int32_t)y-(int32_t)x);
  113.     }
  114. }

  115. void GetStm8Id(uint8_t* uid)
  116. {  
  117.     uid[0]  = *(uint8_t*)(ID_ADDR+4);
  118.     uid[1]  = *(uint8_t*)(ID_ADDR+6);
  119.     uid[2]  = *(uint8_t*)(ID_ADDR+8);
  120.     uid[3]  = *(uint8_t*)(ID_ADDR+9);

  121.     //uid[0]  = 0x76;
  122.     //uid[1]  = 0x44;
  123.     //uid[2]  = 0x77;
  124.     //uid[3]  = 0x61;//6,9
  125. }

  126. void KeyDeal(uint8_t code , uint8_t key_pins )
  127. {
  128.     disableInterrupts();
  129.     //KeyFlag = 0;
  130.     TimeCount = 0;

  131.     if(0 == (KEY_PORT_B->IDR & key_pins))//按键为0表示有按键按下
  132.     {
  133.         Delay100uS(100);
  134.         if(0 == (KEY_PORT_B->IDR & key_pins))//延时10ms消抖
  135.         {
  136.             SysLED_High;
  137.             Send_RF433_Data_3Time(code);
  138.             Delay100uS(100);
  139.             SysLED_Low;
  140.         }
  141.      }
  142.     enableInterrupts();
  143. }

  144. /*******************************************
  145. 1s调用一次
  146. 1s内有2次以上震动就算检测到震动信号,否则算为静止时间,连续静止5s以上重新进入低功耗模式
  147. 连续检测到5次以上震动信号就算检测到甩干信号
  148. *******************************************/
  149. void ShakeMonitor(void)
  150. {
  151.     if(ShakeTime_1S >= 2)//1s内2次
  152.     {
  153.         ShakeTime_1S = 0;
  154.         ShakeTime++;
  155.         if(ShakeTime >= SHAKE_TIME_GATE)
  156.         {
  157.             DryFlag   = 1;
  158.             ShakeTime = 0;
  159.             return;
  160.         }
  161.     }
  162.     ShakeTestTime ++;
  163.     if((ShakeTestTime >= 40 && ShakeTime <= 5)
  164.        || ShakeTestTime >= SHAKE_TEST_TIME_GATE)//(40s内5s,4min内60s)进入低功耗
  165.     {
  166.         ShakeFlag     = 0;
  167.         ShakeTime_1S  = 0;
  168.         ShakeTime     = 0;
  169.         ShakeTestTime = 0;   
  170.     }   
  171. }

  172. /*******************************************
  173. 100ms调用一次
  174. 未检测到甩干信号时检测甩干信号
  175. 检测到甩干信号后定时唤醒检测开门状态
  176. *******************************************/
  177. void ShakeProcess(void)
  178. {
  179.     int16_t acce_x_aver = 0;
  180.     int16_t acce_y_aver = 0;
  181.     int16_t acce_z_aver = 0;
  182.     uint16_t acce_x_change = 0;
  183.     uint16_t acce_y_change = 0;
  184.     uint16_t acce_z_change = 0;
  185.     static int16_t acce_x_before = 0;
  186.     static int16_t acce_y_before = 0;
  187.     static int16_t acce_z_before = 0;
  188.    
  189.     int16_t gyro_x_aver = 0;
  190.     int16_t gyro_y_aver = 0;
  191.     int16_t gyro_z_aver = 0;
  192.     static int32_t Angle_x = 0;
  193.     static int32_t Angle_y = 0;
  194.     static int32_t Angle_z = 0;
  195.    
  196.     MPU6050INT_Port->CR2 &= ~MPU6050INT_PINS;  //关闭中断
  197.     I2C_IOInit();
  198.     MPU6050ReadAcc(&acce_x_aver,&acce_y_aver,&acce_z_aver);
  199.    
  200.     if(1 == ShakeFirstFlag)
  201.     {   
  202.         DryFlag         = 0;
  203.         ShakeTestTime   = 0;
  204.         ShakeTime_1S    = 0;
  205.         ShakeTime       = 0;
  206.         OpenTestTime    = 0;
  207.         ShakeFirstFlag  = 0;
  208.         acce_x_before = acce_x_aver;
  209.         acce_y_before = acce_y_aver;
  210.         acce_z_before = acce_z_aver;
  211.     }
  212.     acce_x_change = fabs_2(acce_x_aver,acce_x_before);
  213.     acce_y_change = fabs_2(acce_y_aver,acce_y_before);
  214.     acce_z_change = fabs_2(acce_z_aver,acce_z_before);
  215.    
  216.     acce_x_before = acce_x_aver;
  217.     acce_y_before = acce_y_aver;
  218.     acce_z_before = acce_z_aver;

  219.     if(0 == DryFlag) //要检测连续震动信号
  220.     {
  221.         if(ACCEL_SHAKE < acce_x_change || ACCEL_SHAKE < acce_y_change || ACCEL_SHAKE < acce_z_change)//震动
  222.         {
  223.             ShakeTime_1S++;
  224.         }
  225.         TimeCount++;
  226.         if(TimeCount >= 10)
  227.         {
  228.             TimeCount = 0;
  229.             ShakeMonitor();
  230.         }
  231.     }
  232.     else if(1 == DryFlag)//检测到连续震动之后需要检测开门信号
  233.     {
  234.         if(ACCEL_OPEN < acce_x_change || ACCEL_OPEN < acce_y_change || ACCEL_OPEN < acce_z_change)//开门
  235.         {
  236.             DryFlag = 2;
  237.             Angle_x = 0;
  238.             Angle_y = 0;
  239.             Angle_z = 0;
  240.         }
  241.     }
  242.     else if(2 == DryFlag)//检测到瞬间加速度值大于开门加速度
  243.     {
  244.         MPU6050_Init_Active();
  245.         
  246.         MPU6050ReadGyro(&gyro_x_aver,&gyro_y_aver,&gyro_z_aver);
  247.         Angle_x = Angle_x + gyro_x_aver/6; //150ms
  248.         Angle_y = Angle_y + gyro_y_aver/6;
  249.         Angle_z = Angle_z + gyro_z_aver/6;

  250.         if(ANGLE_OPEN < fabs(Angle_x) || ANGLE_OPEN < fabs(Angle_y) || ANGLE_OPEN < fabs(Angle_z))
  251.         {
  252.             DryFlag = 0;
  253.             ShakeFirstFlag = 0;
  254.             ShakeFlag = 0;
  255.             disableInterrupts();
  256.             Send_RF433_Data_3Time(CODE_DOWN);
  257.             enableInterrupts();
  258.             return;
  259.         }

  260.         OpenTestTime++;
  261.         if(OpenTestTime >= OPEN_TEST_TIME_GATE)//超过一定时间检测到角度变化值小则重新检测加速度
  262.         {
  263.             OpenTestTime = 0;
  264.             DryFlag = 1;
  265.         }
  266.     }
  267. }

  268. uint8_t itoa(int32_t num,uint8_t *str,int8_t radix)
  269. {
  270.     uint8_t index[]= "0123456789ABCDEF";
  271.     uint32_t unum;
  272.     int8_t i=0,j,k;

  273.     if(num < 0)
  274.     {
  275.         unum=(uint32_t)(-num);
  276.         str[i++] = '-';
  277.     }
  278.     else
  279.     {   
  280.       unum = (uint32_t)num;
  281.     }
  282.    
  283.     do
  284.     {
  285.         str[i++] = index[unum%radix];
  286.         unum /= radix;
  287.     }while(unum);
  288.     str[i]='\0';
  289.    
  290.     /*逆序*/
  291.     if(str[0]=='-')
  292.     {
  293.       k=1;/*十进制负数*/
  294.     }
  295.     else
  296.     {
  297.       k=0;
  298.     }
  299.    
  300.     int8_t temp;
  301.     for(j=k;j<=(i-1)/2;j++)
  302.     {
  303.         temp = str[j];
  304.         str[j] = str[i-1+k-j];
  305.         str[i-1+k-j] = temp;
  306.     }
  307.     return i;
  308. }

  309. void main(void)
  310. {   
  311.     disableInterrupts();
  312.     Init_All();
  313.     SysLED_High;
  314.     //Delay100uS(10000);
  315.     SysLED_Low;
  316.     GetStm8Id(Uid);
  317.     //Enter_Halt();  
  318.    
  319.     enableInterrupts();
  320.     //Enter_Halt();
  321.     Send_RF433_Data_3Time(CODE_MATCH);
  322.    
  323.     while(1)
  324.     {   
  325.         //Hsi_Clk_Init();
  326.         //RTC_ITConfig(RTC_IT_WUT, DISABLE);
  327.         

  328.         switch(KeyFlag)
  329.         {   
  330.         case 1 : //上升
  331.             Delay100uS( TimeCount );
  332.             if(0 == (KEY_PORT_B->IDR & (KEY_PINS_UP | KEY_PINS_DN )))
  333.             {
  334.                
  335.                 KeyDeal( CODE_MATCH , (KEY_PINS_UP | KEY_PINS_DN) );
  336.                 TimeCount = 0;
  337.             }
  338.             else if ( KeyFlag )
  339.             {
  340.                 KeyDeal( CODE_UP, KEY_PINS_UP );
  341.                 TimeFlag ++;               
  342.             }
  343.             
  344.             if ( KEY_PORT_B->IDR & KEY_PINS_UP )
  345.             {
  346.                 Send_RF433_Data( 0X1E );
  347.                 KeyFlag = 0;
  348.             }
  349.             
  350.             if ( TimeFlag >= 60 )//发送60次报文,时间约10s,
  351.             {
  352.                 KeyFlag = 0;
  353.                 TimeFlag = 0;
  354.             }
  355.             break;
  356.         case 2: //下降
  357.           Delay100uS( TimeCount );
  358.             if(0 == (KEY_PORT_B->IDR & (KEY_PINS_UP | KEY_PINS_DN )))
  359.             {               
  360.                 KeyDeal( CODE_MATCH , (KEY_PINS_UP | KEY_PINS_DN) );
  361.                 TimeCount = 0;
  362.             }
  363.             else if ( KeyFlag )
  364.             {
  365.                 KeyDeal( CODE_DOWN, KEY_PINS_DN );
  366.                 TimeFlag ++;
  367.             }

  368.             
  369.             if ( KEY_PORT_B->IDR & KEY_PINS_DN )
  370.             {
  371.                 Send_RF433_Data( 0X3E );
  372.                 KeyFlag = 0;
  373.             }
  374.             
  375.             if ( TimeFlag >= 60 ) //发送60次后停止
  376.             {
  377.                 KeyFlag = 0;
  378.                 TimeFlag = 0;               
  379.             }
  380.             break;
  381.          case 3: //风干
  382.             KeyDeal( CODE_DRY , KEY_PINS_DRY );
  383.             KeyFlag = 0;
  384.             break;
  385.          case 4: //照明
  386.             KeyDeal( CODE_LED , KEY_PINS_LED );
  387.             //Send_RF433_Data_3Time(0x79);
  388.             KeyFlag = 0;
  389.             break;
  390.          case 5: //消毒
  391.             KeyDeal( CODE_XD , KEY_PINS_XD );
  392.             KeyFlag = 0;
  393.             break;
  394.          case 6: //烘干
  395.             KeyDeal( CODE_HEAT , KEY_PINS_HEAT );
  396.             KeyFlag = 0;
  397.             break;
  398.          case 7: //负离子
  399.             KeyDeal( CODE_FLZ , KEY_PINS_FLZ );
  400.             KeyFlag = 0;
  401.             break;   
  402.          default:
  403.            //Enter_Halt(); //没有按键的情况下,进入低功耗
  404.            break;
  405.         }
  406.     }
  407. }
复制代码

所有资料51hei提供下载:
YK001 V1.0.7z (635.9 KB, 下载次数: 43)


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表