zoukankan      html  css  js  c++  java
  • 台灯改造【智能台灯】

      2020年春节,由于受疫情的限制,另外博主也是疫情的重灾区-湖北省襄阳市,一方面响应国家的号召“在家不论跑就是最大的贡献”,另一方也是在家闲不住,于是又准备捣鼓捣鼓前两年改造的台灯,前两年在家改造的台灯,改造完后就去上学去了,今年回来,经爸妈的反馈,在实际使用过程中,还是不好用,但之前的程序没有存档,于是乎,又重新列出了,台灯的几个功能:

    1、台灯分两个功能模式:自动模式和手动模式;

    2、自动模式----白天自动熄灯;晚上检测到人体后开灯,若人体在一定时间内移动,则灯一直开灯不熄灭,当超过一定时间后,人体不移动或未检测到人体,则灯自动熄灭;---这一场景功能主要是方便晚上起夜上厕所;灯的亮度可调目前分为10个级别;-------这一场景功能主要是晚上上突然开启强光,眼睛会花眼;

    3、自动模式----定时时间可调,分为2min,3min,4min,5min四中定时时间可调整;

    4、手动模式---手动模式不论是白天还是黑夜都可以开启灯光,切灯光亮度可调10个亮度等级;------这一场景功能主要应用是有时白天需要使用台灯,或晚上看书或做别的事情,若灯光太亮,可以手动调节;

    5、双电源自动切换----平时台灯插电,台灯使用的时电源适配器的供电,当出现停电状况,自动切换到锂电池供电;-----这一场景功能主要是我这边有时会停电,家里很不方便,自己也有好多18650电池,正好利用起来;

    6、锂电池自动充电 -----当检测到锂电池电源过低时,启用自动充电给台灯内的电池充电,保证电池处于有电状态,以此应急停电;

    7、USB充电------台灯另外一个功能也可以当做一个充电宝,目前手上有十几节电池,目前使用的是12节18650电池,一节容量2200mA,所以总容量大概                   12x2200mA=26400mA;使用的模块是充电宝拆出来的模块,USB输出标称为5V1A;

    8、按键功能------使用原有台灯按键,按键功能目前定义如下:单击---调节亮度;双击----关闭台灯;长按-----模式切换(自动模式和手动模式);

    以上是自己目前想出来的几个主要功能,单片机使用的还是较为熟悉的STC12C5A60S2---DIP-40封装,电源基准使用的是从电脑电源电路板上拆的WL431,查了很多资料,没有查出和TL431是什么区别,还是没有查出来,于是自己完全按照TL431管脚实验了下,结果脚位相同,可是使用;MOS管使用的是F9540N和AO3400,使用双适配器5V供电,一路适配器输出电压给电路使用,一路专门给锂电池充电使用;

    电路图如下:

    由于是使用的充电宝改进的,存在一个问题就是,目前市面上大部分使用的充电宝方案为DW01、8025A单片机和MT5032,会出现一个弊端就是无法使用小电流模式下升压至5V,由于查了许多资料,最终锁定在MT5032这颗升压IC上,经测量发现MT5032管脚的EN使能端是连接在一颗SOP-14芯片上,猜想为一颗单片机,于是,把此管脚切开,直接和VCC接起来即1、2管脚连接起来,直接使能,可以解决这个问题,MT5032大致资料如下:

    程序如下:

    主程序main.c:

     1 /*
     2  智能台灯 20200215完结
     3  By-----Li
     4 */
     5 #include "main.h"
     6 #include "config.h"
     7 #include "gpio.h"
     8 #include "timer.h"
     9 #include "uart.h"
    10 #include "adc.h"
    11 #include "interrupt.h"
    12 #include "user_timer.h"
    13 #include "user_auto_contorl.h"
    14 #include "pwm.h"
    15 #include "user_funtion_ui.h"
    16 #include "user_key.h"
    17 #include <stdio.h>
    18 #include "delay.h"
    19 
    20 void main()
    21 {
    22   gpio_init();                    // GPIO 电平初始化
    23     pwm0_init();          // PWM初始化
    24   Timer_Init();                  // 定时器初始化
    25   user_timer_init();    //  初始化时间数组
    26 #ifdef USER_TEST
    27     InitUart();          // 串口初始化
    28 #endif
    29     InitADC();           // ADC初始化
    30     user_key_init();             //  按键检测初始化
    31     user_ui_init();       //初始化灯光亮度    
    32     while(1)
    33     {
    34         add_system_time();                                    //添加系统时间
    35         user_key_scan(USER_KEY_SCAN_PIN );  //按键扫描
    36         auto_contorl_bat_battery();                //电池电压充电管理
    37         user_ui();                                   //灯光功能
    38     }
    39 }

    主程序头文件main.h

     1 #ifndef _MAIN_H_
     2 #define _MAIN_H_
     3 #include <STC12C5A60S2.H>
     4 
     5 #define USER_KEY_SCAN_PIN  P11  //按键输入管脚
     6 
     7 
     8 void main();
     9 
    10 #endif

    灯光功能函数user_funtion_ui.c

      1 #include "user_funtion_ui.h"
      2 #include "user_auto_contorl.h"
      3 #include "pwm.h"
      4 #include "user_key.h"
      5 #include "user_timer.h"
      6 #include "eeprom.h"
      7 #include <stdio.h>
      8 #include "delay.h"
      9 
     10 static uint16_t USER_HUMMAN_REACTION_TIME =LED_TIMMING_TWO_MIN ;//灯光定时时长
     11 static bit  led_mode_flag = 0 ;                                                         //LED灯光模式标志位
     12 uint8_t pwm_adj_data = 0 ;                                                                          //LED灯光亮度数据
     13 extern  bit battery_flag  ;                                                                         //充电标志位
     14 
     15 
     16 /*
     17 Function Name : user_ui_init
     18 Function :灯光模式初始化
     19 Header:读取灯光亮度数据,设置定时时长
     20 */
     21 void user_ui_init()
     22 {
     23          EA=1;
     24     V_BAT_SITCH_PIN =0 ;
     25   pwm_adj_data =  read_eeprom(0x0000);  //读取灯光亮度数据
     26   pwm_adj_data =  read_eeprom(0x0000);  //读取灯光亮度数据
     27     clear_time_cnt(ADC_PRINTF_TIME_NUMBER);   // 清除检测电池电压间隔时间
     28     clear_time_cnt(USER_HUMMAN_REACTION_NUMBER);  //清除LED灯亮的时间
     29 //    check_woman_time();                                     //设置灯光定时时长
     30 }
     31 
     32 /*
     33 Function Name : user_ui
     34 Function :灯光功能主函数
     35 */
     36 
     37 void user_ui()
     38 {    
     39     static bit led_key_switch_flag = 0 ;              // 双击灯光控制标志位
     40     static bit auto_time_counts_flag = 0 ;    
     41     
     42         check_woman_time();                                     //设置灯光定时时长
     43      if(return_key_state() == KEY_TWO_ACTION )  //双击触发
     44      {
     45          led_key_switch_flag = ~led_key_switch_flag;
     46 #ifdef USER_TEST
     47             printf( "双击操作发生!!
    " );
     48             printf( "自动模式定时=%d
    ",USER_HUMMAN_REACTION_TIME);
     49 #endif
     50             rest_key_state();                                       //释放按键
     51      }
     52      if(battery_flag != 1 )
     53         {
     54                 if(return_key_state() == KEY_LONG_PRESS_ACTION )  //长按触发
     55                 {
     56                          rest_key_state();                   //释放按键
     57                     led_mode_flag = ~led_mode_flag;
     58 //                       led_mode_flag++;
     59 //                      if(led_mode_flag>=2)
     60 //                        {
     61 //                          led_mode_flag = 0;
     62 //                        }
     63 //                        clean_iap(0x0100 );                                      //擦除EEROM数据
     64 //                        write_eeprom(0x0100, led_mode_flag);   //写入灯光模式 数据    
     65                         
     66                       led_key_switch_flag = 0 ;                         //每次切换模式,灯都处于打开状态!!
     67                         if(led_mode_flag == 0 )
     68                         {
     69                                 clear_time_cnt(USER_HUMMAN_REACTION_NUMBER);  //清除LED灯亮的时间
     70                               auto_time_counts_flag = 0 ;
     71 
     72                         }
     73                 }
     74             
     75              if( led_mode_flag )  //手动模式调光
     76                 {       
     77                          if( return_key_state() == KEY_CLICK_ACTION )
     78                          {
     79                              rest_key_state();                               //释放按键
     80                              if(led_key_switch_flag )
     81                              {
     82                                led_key_switch_flag = ~led_key_switch_flag; 
     83 #ifdef USER_TEST
     84                                  printf( "打开手动灯光
    ");
     85 #endif
     86                              }
     87                              else
     88                              {
     89                                     pwm_adj_data +=PWM_LED_STEP_LUMINANCE  ; //灯光步进亮度
     90                                     if(pwm_adj_data>PWM_SET_MIN_LUMINANCE)  
     91                                     {
     92                                         pwm_adj_data = PWM_SET_MAX_LUMINANCE ;
     93                                     }
     94                                     clean_iap(0x0000 );                                    //擦除EEROM数据
     95                                     write_eeprom(0x0000, pwm_adj_data);   //写入EEROM数据
     96 #ifdef USER_TEST
     97                                     printf( "手动灯光亮度值增加
    ");
     98 #endif
     99                              }
    100                          }
    101                          if(led_key_switch_flag)  //双击手动关灯
    102                          {
    103                             pwm_updata( 0xFF );                  //打开灯光
    104                             USER_LED( LED_ALL_OFF );  //关闭指示灯
    105                          }
    106                          else
    107                          {
    108                             USER_LED( LED_MODE_USER );  //手动模式指示灯
    109                               pwm_updata( pwm_adj_data );  //打开灯光
    110                          }
    111                 }
    112                 else     //自动模式调光
    113                 {
    114                         if(check_time_arrive( USER_HUMMAN_REACTION_NUMBER,USER_HUMMAN_REACTION_TIME) ) //检查定时时间是否到达
    115                         {
    116                             if(auto_time_counts_flag!=1)
    117                             {
    118                                 auto_time_counts_flag = 1 ;
    119                                 pwm_updata( 0xFF );
    120                               led_key_switch_flag = 0 ;
    121 #ifdef USER_TEST
    122                               printf( "自动定时时间到!!
    " );
    123 #endif
    124                             }
    125                         }
    126                         else
    127                         {
    128 //                              printf( "时间未到
    " );
    129                             
    130                              if(return_key_state() == KEY_CLICK_ACTION )  //单击
    131                              {
    132                                    rest_key_state();   //释放按键  
    133                                     if(led_key_switch_flag)
    134                                     {
    135                                       led_key_switch_flag = ~led_key_switch_flag; 
    136 #ifdef USER_TEST
    137                                         printf( "打开自动灯光
    ");
    138 #endif
    139                                     }
    140                                     else
    141                                     {
    142                                             pwm_adj_data +=PWM_LED_STEP_LUMINANCE  ;  //灯光步进亮度
    143                                             if(pwm_adj_data>PWM_SET_MIN_LUMINANCE)
    144                                             {
    145                                                 pwm_adj_data = PWM_SET_MAX_LUMINANCE ;
    146                                             }
    147                                             clean_iap(0x0000 );                                    //擦除EEROM数据
    148                                             write_eeprom(0x0000, pwm_adj_data);   //写入EEROM数据
    149 #ifdef USER_TEST
    150                                             printf( "自动灯光亮度增加
    ");
    151 #endif
    152                                     }
    153                                  
    154                              }
    155                                  if(led_key_switch_flag)               //双击手动关灯
    156                                  {
    157                                      pwm_updata( 0xFF );                  //打开灯光
    158                                        USER_LED( LED_ALL_OFF);     //关闭指示灯
    159                                  }
    160                                  else
    161                                  {
    162                                        USER_LED( LED_MODE_AUTO );  //自动模式指示灯
    163                                      pwm_updata( pwm_adj_data );  //打开灯光
    164                                  }
    165                         
    166                         }
    167                         if( HUMMAN_REACTION_PIN == 0 )//若检测到人体,则清除时间,重新开始计时!
    168                          {
    169 #ifdef USER_TEST
    170 //                              printf( "检测到人体
    " );
    171 #endif
    172                              auto_time_counts_flag = 0 ;
    173                              clear_time_cnt(USER_HUMMAN_REACTION_NUMBER); //清除时间
    174                          }
    175                 }
    176         }
    177         else
    178         {
    179                 pwm_updata( 0xFF );        
    180         }
    181 }
    182 
    183 /*
    184 Function Name : USER_LED
    185 Function :灯光模式指示灯
    186 Header:红----手动模式 ; 蓝----自动模式
    187 */
    188 void USER_LED(uint8_t mode_flag)  
    189 {
    190     switch( mode_flag)
    191     {
    192       case 0 :
    193                         USER_CONTORL_B_LED_MODE = LED_INDICATOR_ON ;
    194                         AUTO_CONTORL_R_LED_MODE = LED_INDICATOR_OFF ;
    195        break;
    196         case 1 :
    197                         USER_CONTORL_B_LED_MODE = LED_INDICATOR_OFF ;
    198                         AUTO_CONTORL_R_LED_MODE = LED_INDICATOR_ON ;
    199         break;
    200         case 2:
    201                         USER_CONTORL_B_LED_MODE = LED_INDICATOR_OFF ;
    202                         AUTO_CONTORL_R_LED_MODE = LED_INDICATOR_OFF ;
    203         break;
    204         default : break;
    205      
    206     }
    207 
    208 }
    209 
    210 /*
    211 Function Name : check_woman_time
    212 Function :设置灯光定时时间  
    213 Header:设置定时时长:
    214 1:1 = 2min
    215 1:0 = 4min
    216 0:1 = 3min
    217 1:0 = 5min
    218 */
    219 void check_woman_time()  //设置灯光定时时间
    220 {
    221     static uint16_t time_temp = LED_TIMMING_TWO_MIN ;
    222     time_temp = USER_HUMMAN_REACTION_TIME; //保存上次定时值
    223   if( SET_CHECK_WOMAN_0_TIME_PIN)
    224     {
    225       if( SET_CHECK_WOMAN_1_TIME_PIN )
    226              USER_HUMMAN_REACTION_TIME = LED_TIMMING_TWO_MIN ;  //2 min
    227          else
    228              USER_HUMMAN_REACTION_TIME = LED_TIMMING_FOUR_MIN ;  //4 min
    229     
    230     }
    231     else
    232     {
    233       if( SET_CHECK_WOMAN_1_TIME_PIN )
    234              USER_HUMMAN_REACTION_TIME = LED_TIMMING_THREE_MIN ;  //3 min
    235          else
    236              USER_HUMMAN_REACTION_TIME = LED_TIMMING_FIVE_MIN ;  //5 min    
    237     }
    238     if(time_temp != USER_HUMMAN_REACTION_TIME )  //若定时值发生变化
    239     {
    240         clear_time_cnt(USER_HUMMAN_REACTION_NUMBER);  //清除LED灯亮的时间
    241     
    242     }
    243 //    clear_time_cnt(USER_HUMMAN_REACTION_NUMBER);  //清除LED灯亮的时间
    244 //    clear_time_cnt(ADC_PRINTF_TIME_NUMBER);   // 清除检测电池电压间隔时间
    245 
    246 }

    灯光功能函数头文件user_funtion_ui.h

     1 #ifndef _user_funtion_ui_h_
     2 #define _user_funtion_ui_h_
     3 
     4 #include "config.h"
     5 
     6 #define USER_CONTORL_B_LED_MODE  P21 //自动模式指示灯
     7 #define AUTO_CONTORL_R_LED_MODE  P24//手动模式指示灯
     8 
     9 #define SET_CHECK_WOMAN_0_TIME_PIN              P22  //设置人体检测时间
    10 #define SET_CHECK_WOMAN_1_TIME_PIN       P23
    11 
    12 #define PWM_LED_STEP_LUMINANCE 20  //灯光步进亮度
    13 #define PWM_SET_MIN_LUMINANCE  200  //灯光最小亮度
    14 #define PWM_SET_MAX_LUMINANCE  0   //最大亮度
    15 
    16 #define LED_INDICATOR_OFF  1
    17 #define LED_INDICATOR_ON   0
    18 #define LED_ALL_OFF        2
    19 
    20 #define LED_MODE_USER  1
    21 #define LED_MODE_AUTO  0
    22 
    23 #define LED_TIMMING_TWO_MIN     24000    //2min
    24 #define LED_TIMMING_THREE_MIN   36000    // 3min
    25 #define LED_TIMMING_FOUR_MIN   48000    // 4min
    26 #define LED_TIMMING_FIVE_MIN   60000    // 5min
    27 
    28 void check_woman_time() ; //设置灯光定时时间
    29 
    30 void USER_LED(uint8_t mode_flag);
    31 
    32 void user_ui_init();
    33 
    34 void user_ui();
    35 
    36 #endif

    电池管理功能user_auto_contorl.c

     1 #include "user_auto_contorl.h"
     2 #include "config.h"
     3 #include "user_timer.h"
     4 #include "adc_smoothing.h"
     5 #include "eeprom.h"
     6 #include "pwm.h"
     7 #include <stdio.h>
     8 
     9 bit battery_flag = 0 ; ////充电标志位
    10 
    11 
    12 
    13 /*
    14 Function Name : auto_contorl_bat_battery
    15 Function :自动控制电池充电
    16 */
    17 void auto_contorl_bat_battery()  //自动控制电池充电
    18 {
    19   float ADC_V_BAT = 0;
    20     uint16_t  v_ref ,v_bat;
    21         
    22     if(check_time_arrive( ADC_PRINTF_TIME_NUMBER,ADC_PRINTF_TIME) )//采集电池电压间隔
    23         {
    24             clear_time_cnt(ADC_PRINTF_TIME_NUMBER);
    25             v_bat =  GetResult(V_BAT_INTPUT_CH);  //读取电池电压转换AD后的值
    26             v_ref = GetResult(V_REF_INTPUT_CH);   //读取TL431基准+2.5V电压转换AD后的值
    27 //            ADC_V_BAT = v_bat * 2.5f / v_ref; //计算出实际电池电压
    28             ADC_V_BAT = v_bat *REFERENCE_VOLTAGE / v_ref; //计算出实际电池电压
    29             
    30             if(ADC_V_BAT <= V_BAT_MIN_VOLTAGE )  //电池电压过低,且未充电,则关闭LED灯,保护电池过放!!
    31             {
    32                 battery_flag = 1 ;        //充电标志位
    33                 V_BAT_SITCH_PIN = 1 ; //开启充电功能
    34 #ifdef USER_TEST
    35                  printf( "电压状态=1
    " );
    36 #endif
    37             }
    38             else if((ADC_V_BAT>V_BAT_MIN_VOLTAGE )&&( ADC_V_BAT <= V_BAT_START_BATTERY_VOLTAGE ) ) // 电池到达最低临界值,开始充电!
    39             {
    40 #ifdef USER_TEST
    41                  printf( "电压状态=2
    " );
    42 #endif
    43                 battery_flag = 0 ;        //充电标志位
    44                     V_BAT_SITCH_PIN =1;  //开启充电功能
    45                 battery_flag =0;
    46             }
    47             else if(( ADC_V_BAT >V_BAT_START_BATTERY_VOLTAGE )&&(ADC_V_BAT <= V_BAT_OVER_BATTERY_VOLTAGE ))
    48             {
    49               battery_flag = 0 ;
    50 #ifdef USER_TEST
    51                  printf( "电压状态=3
    " );
    52 #endif
    53 //                    V_BAT_SITCH_PIN =1;  //开启充电功能
    54             }
    55             else   //电池电压充电到达最大电压,关闭充电!
    56             {
    57 #ifdef USER_TEST
    58                  printf( "电池状态=4
    ");
    59 #endif
    60               V_BAT_SITCH_PIN =0;  //关闭充电功能
    61               battery_flag = 0 ;
    62             }
    63 #ifdef USER_TEST
    64           printf( "电池电压值=%f
    ", ADC_V_BAT );
    65             
    66 //        if(P25 ==1 )
    67 //        {
    68 //                 printf( "充电器插上状态
    " );
    69 //        
    70 //        }
    71 //        else
    72 //                 printf( "充电器无电压
    " );
    73 //    }
    74             
    75 #endif
    76         }
    77 
    78 }

    电池管理功能头文件user_auto_contorl.h

     1 #ifndef _user_auto_contorl_h_
     2 #define _user_auto_contorl_h_
     3 
     4 #define V_BAT_INTPUT_CH   0X04   //电池电压采集通道
     5 #define V_REF_INTPUT_CH   0X06   //TL431基准电压采集通道
     6 #define REFERENCE_VOLTAGE 2.4f   //基准电压 +2.5V
     7 
     8 
     9 /*------------ 电池电压 ------------------*/
    10 #define V_BAT_MIN_VOLTAGE                       3.30f   //电池最低保护电压
    11 #define V_BAT_START_BATTERY_VOLTAGE             3.70f   // 电池开始充电电压
    12 #define V_BAT_OVER_BATTERY_VOLTAGE              4.20f     // 电池结束充电电压
    13 ////////////////////////////////////////////////////
    14 
    15 #define HUMMAN_REACTION_PIN   P10   //人体感应和光敏开关
    16 #define LED_PIN    P13              //灯光控制
    17 #define V_BAT_SITCH_PIN   P20        //充电控制
    18 
    19 
    20 void auto_contorl_bat_battery();  //自动控制电池充电
    21 
    22 
    23 
    24 
    25 
    26 #endif
     3 #ifndef _config_h_
    #define _config_h_
    4 #include <STC12C5A60S2.H> 6 7 8 #define USER_TEST 9 10 #define FOSC 11059200L 11 #define BAUD 9600 12 13 14 15 16 17 ///////////////// 灯光亮度档位 /////////////////// 18 //#define LED_OFF 255 19 //#define LED_PWM_ONE_DATA 191 20 //#define LED_PWM_TWO_DATA 127 21 //#define LED_PWM_THREE_DATA 64 22 //#define LED_PWM_FOUR_DATA 0 23 24 25 ////////////////////// timer_number /////////////////////// 26 #define USER_TIMER_AMOUNT 4 27 28 #define USER_HUMMAN_REACTION_NUMBER 0 //人体感应编号 29 #define ADC_PRINTF_TIME_NUMBER 1 30 #define KEY_TRIGGER_TIMER_NUMBER 2 31 #define KEY_TWO_TRIGGER_TIME_NUMBER 3 32 33 ////////////////////// key_timer ////////////////////// 34 //#define USER_HUMMAN_REACTION_TIME 10000 // 灯光定时时间 35 #define ADC_PRINTF_TIME 1000 //5S 电池检测间隔 36 #define KEY_TRIGGER_TIMER 5 //20ms 消抖时间 37 #define KEY_TWO_TRIGGER_TIME 50 //250MS 双击时间阀值 38 #define KEY_LONG_PRESS_TIME 400 //2s 长按时间阀值 39 40 //#define KEY_LONG_PRESS_TIME 4000 // 4000 x 500us = 2s 41 42 43 44 45 46 47 48 49 50 51 ///////////////////////////////////////////////// 52 53 #define OFF 0 54 #define ON 1 55 56 57 #define BIT0 0x01 58 #define BIT1 0x02 59 #define BIT2 0x04 60 #define BIT3 0x08 61 #define BIT4 0x10 62 #define BIT5 0x20 63 #define BIT6 0x40 64 #define BIT7 0x80 65 66 67 #ifndef uint8_t 68 #define uint8_t unsigned char 69 #endif 70 71 #ifndef uint16_t 72 #define uint16_t unsigned int 73 #endif 74 75 #ifndef uint32_t 76 #define uint32_t unsigned long 77 #endif 78 79 #endif

    电池电压滤波adc_smoothing.c

     1 #include "adc_smoothing.h"
     2 #include "adc.h"
     3 
     4 
     5 /*
     6 Function Name : GetResult
     7 Function :ADC滤波
     8 Header:采用掐头去尾方法,把最大值和最小值去掉,取平均值
     9 */
    10 unsigned int GetResult(unsigned char ch)
    11 {
    12         unsigned int ADC_min, ADC_max, ADC_tmp, ADC_result, ADC;
    13         unsigned char i, j;
    14         
    15         ADC = 0;
    16         for(j = 0; j < 16; j++)
    17         {
    18                 ADC_result = 0;
    19                 ADC_min = ADC_max = GetADCResult(ch);
    20                 for(i = 0; i < 8; i++)
    21                 {
    22                         ADC_tmp = GetADCResult(ch);
    23                         if(ADC_tmp < ADC_min)
    24                         {
    25                                 ADC_result += ADC_min;
    26                                 ADC_min = ADC_tmp;
    27                         }
    28                         else if(ADC_tmp > ADC_max)
    29                         {
    30                                 ADC_result += ADC_max;
    31                                 ADC_max = ADC_tmp;
    32                         }
    33                         else
    34                         {
    35                                 ADC_result += ADC_tmp;
    36                         }
    37                 }
    38                 
    39                 ADC_result /= 8;
    40                 ADC += ADC_result;
    41         }
    42         ADC /= 16;
    43         
    44         return ADC;
    45 }

    电池电压滤波adc_smoothing.h

    1 #ifndef _adc_smoothing_h_
    2 #define _adc_smoothing_h_
    3 
    4 #include "config.h"
    5 
    6 unsigned int GetResult(unsigned char ch);
    7 
    8 #endif

    定时器timer.c

     1 #include "timer.h"
     2 #include "config.h"
     3 
     4 #include <STC12C5A60S2.H>
     5 
     6 
     7 
     8 
     9 void Timer_Init()
    10 {
    11     TMOD |= BIT0;//16位定时器,模式1
    12     
    13       TH0=(65536-5000)/256;        // 5000us
    14     TL0=(65536-5000)%256;
    15 
    16             
    17        ET0=1; 
    18        TR0=1;
    19     
    20 //    AUXR=0X94;           //辅助寄存器开启定时器T2,启动定时器T2,配置T0,T2时钟为 1T模式 (比STC15C5A 1T 模式快 20%)    
    21 
    22 //      EA=1;
    23 
    24 
    25 
    26 
    27 }

    定时器头文件timer.h

    1 #ifndef _TIMER_H_
    2 #define _TIMER_H_
    4 
    5 void Timer_Init();

    模数转换adc.c

     1 #include "adc.h"
     2 #include <STC12C5A60S2.H>
     3 #include "intrins.h"
     4 
     5 /*Define ADC operation const for ADC_CONTR*/
     6 #define ADC_POWER   0x80            //ADC power control bit
     7 #define ADC_FLAG    0x10            //ADC complete flag
     8 #define ADC_START   0x08            //ADC start control bit
     9 #define ADC_SPEEDLL 0x00            //420 clocks
    10 #define ADC_SPEEDL  0x20            //280 clocks
    11 #define ADC_SPEEDH  0x40            //140 clocks
    12 #define ADC_SPEEDHH 0x60            //70 clocks
    13 
    14 void InitADC()
    15 {
    16         P1ASF = 0x50; //P14,P16为AD输入
    17         ADC_RES = 0;
    18         ADC_CONTR = ADC_POWER|ADC_SPEEDL;
    19 }
    20 
    21 unsigned int GetADCResult(unsigned char ch)
    22 {
    23         unsigned int AD_result;
    24         ADC_RES = 0;
    25         ADC_RESL = 0;
    26         ADC_CONTR = ADC_POWER | ADC_SPEEDL | ch | ADC_START;
    27         _nop_();                        //Must wait before inquiry
    28         _nop_();
    29         _nop_();
    30         _nop_();
    31         _nop_();
    32         _nop_();
    33         _nop_();
    34         _nop_();
    35 
    36         while (!(ADC_CONTR & ADC_FLAG));//Wait complete flag
    37         
    38         ADC_CONTR &= ~ADC_FLAG;         //Close ADC
    39         AD_result = ADC_RES;
    40         AD_result <<= 2;
    41         AD_result += ADC_RESL; 
    42 
    43     return AD_result;             //Return ADC result 10bit
    44 }

    模数转换头文件adc.h

     1 #ifndef _adc_h_
     2 #define _adc_h_
     3 
     4 
     5 #include "config.h"
     6 
     7 void InitADC();
     8 unsigned int GetADCResult(unsigned char ch);
     9 
    10 //unsigned int GetResult(unsigned char ch);
    11 
    12 
    13 
    14 
    15 
    16 
    17 
    18 #endif

    串口通讯(测试)uart.c

     1 #include "uart.h"
     2 #include "config.h"
     3 
     4 #ifdef USER_TEST
     5 
     6 /*----------------------------
     7 Initial UART
     8 ----------------------------*/
     9 void InitUart()
    10 {
    11       TMOD |= BIT5;                    //T1 as 8-bit auto reload
    12 //    TMOD = 0x20;                    //T1 as 8-bit auto reload
    13     SCON = 0x5a;                    //8 bit data ,no parity bit
    14     TH1 = TL1 = -(FOSC/12/32/BAUD); //Set Uart baudrate
    15     TR1 = 1;                        //T1 start running
    16 }
    17 #endif
    18 ///*----------------------------
    19 //Send one byte data to PC
    20 //Input: dat (UART data)
    21 //Output:-
    22 //----------------------------*/
    23 //void SendData(uint8_t dat)
    24 //{
    25 //    while (!TI);                    //Wait for the previous data is sent
    26 //    TI = 0;                         //Clear TI flag
    27 //    SBUF = dat;                     //Send current data
    28 //}

    串口通讯(测试)uart.h

    1 #ifndef _uart_h_
    2 #define _uart_h_
    3 #include "config.h"
    4 
    5 void InitUart();
    6 void SendData(uint8_t  dat);
    7 
    8 
    9 #endif

    脉宽调制pwm.c

     1 #include "pwm.h"
     2 #include <STC12C5A60S2.H>
     3 //#include <STC15F2K60S2.H>
     4 
     5 #include "config.h"
     6 
     7 /*
     8   PCA时钟频率由CCON中的 CPS2,CPS1,CPS0决定,FOSC分频系数
     9   PWM频率 = PCA时钟频率/256;(8位PWM)
    10   eg:
    11     FOSC = 24000000HZ;
    12     CPS2:CPS1:CPS0 = 1:0:0    FOSC不分频,为FOSC时钟频率,即  PCA时钟=FOSC=24000000HZ;
    13     PWM频率 = 24000000/256 = 93KHz
    14     
    15     占空比控制由 CCAP1L和CCAP1H控制,CL和CCAP1L比较,CL>=CCAP1L时,PWM口输出1(高电平),反之亦然。
    16     eg:
    17     当工作在8位模式时,
    18      CCAP1L = CCAP1H =0x7F;  占空比位50%
    19 
    20     
    21 */
    22 
    23 void pwm0_init()
    24 {
    25          CMOD = 0X08 ;                //选择系统时钟 
    26          CCON= 0x00;
    27          CL= 0x00;
    28          CH= 0x00;
    29          PCA_PWM0= 0x00;         
    30          CCAPM0= 0x42;                 //8位PWM,无中断
    31          CCAP0L = CCAP0H =0x00;
    32 //         CCON= 0x40;                     //允许PAC计数
    33       CR = 1 ;
    34 }
    35 
    36 void pwm_updata(uint16_t pwm_data)
    37 {
    38 //            uint16_t pwm_temp;
    39 //            pwm_data = 100-pwm_data;
    40 //            pwm_temp = pwm_data<<8;
    41 //            pwm_temp =(uint8_t)(pwm_temp/100);
    42 //            CCAP1L = CCAP1H =pwm_temp;
    43             CCAP0L = CCAP0H =   pwm_data;
    44 
    45 }

    脉宽调制pwm.h

     1 #ifndef _pwm_h_
     2 #define _pwm_h_
     3 
     4 //#include "user_config.h"
     5 #include "config.h"
     6 void pwm0_init();
     7 
     8 void pwm_updata(uint16_t pwm_data);
     9 
    10 #endif

    eerom.c

     1 #include <STC12C5A60S2.H>
     2 #include "eeprom.h"
     3 #include "delay.h"
     4 
     5 #define CMD_READ  1  //IAP字节读命令
     6 #define CMD_PROGRAM  2  //IAP字节编程
     7 #define CMD_ERASE   3 //IAP扇区擦除命令
     8 
     9 #define ENABLE_IAP 0X82   //SYSCLK<12MHz
    10 #define IAP_ADDRESS   0X0000
    11 
    12 void iap_idle()
    13 {
    14   IAP_CONTR = 0X00 ; //关闭IAP功能
    15     IAP_CMD = 0 ;    //清除指令待机
    16     IAP_TRIG = 0X00 ;   //清空触发器寄存器
    17     IAP_ADDRH =0X80; //将地址设置到非IAP地址
    18     IAP_ADDRL=0X00;
    19  
    20 
    21 }
    22 
    23 uint8_t  read_eeprom( uint16_t read_adder)
    24 { 
    25     uint8_t read_eerom_tmp_data;
    26      IAP_CONTR = ENABLE_IAP ;  //使能IAP
    27         IAP_CMD = CMD_READ;        //读eeprom命令
    28         IAP_ADDRL = read_adder;
    29         IAP_ADDRH = read_adder>>8;     //首地址高位
    30         IAP_TRIG = 0x5a;   //启动命令
    31         IAP_TRIG = 0xa5;
    32       delay_1us(10);
    33       read_eerom_tmp_data =IAP_DATA;
    34            iap_idle();
    35    return  read_eerom_tmp_data;
    36  }
    37 
    38 void write_eeprom(uint16_t write_adder,uint8_t write_dat)
    39 { 
    40 /*
    41 1 IAP_DATA  数据寄存器,从此处读,向此处写入
    42 2 IAP_ADDRH 数据地址
    43   IAP_ADDRL
    44 3 IAP_CMD
    45   00 无操作
    46   01 读
    47   02 编程
    48   03 擦除
    49 4 IAP_TRIG 
    50   当IAPEN(IAP_CONTR.7)=1时,
    51   依次写入5A、A5,IAP才启动命令
    52 5 IAP_CONTR
    53   .7    0禁止操作  1允许操作
    54   .6    0从应用程序启动 1从ISP程序启动
    55   .5  0不操作      1单片机自复位
    56   .4    地址失效并发送了操作命令引得操作失败,则为1
    57   .3  空
    58   .2.1.0  选100,系统频率>=6MHz
    59 6 PCON  .5  为1,则电压偏低,需软件清零
    60  读一字节  2个时钟
    61  写一字节  55us
    62  扇区擦除  21ms
    63 */
    64    IAP_CONTR =   ENABLE_IAP ;  //使能IAP
    65      IAP_CMD =  CMD_PROGRAM;//编程
    66      
    67          IAP_ADDRL = write_adder;
    68         IAP_ADDRH = write_adder>>8;     //首地址高位
    69       IAP_DATA = write_dat;
    70         IAP_TRIG = 0x5a;   //启动命令
    71         IAP_TRIG = 0xa5;
    72         delay_1us(10);
    73         iap_idle();
    74     
    75 }
    76 
    77 void clean_iap(uint16_t clean_adder)   //擦除扇区
    78 {
    79    IAP_CONTR =   ENABLE_IAP ;  //使能IAP
    80     IAP_CMD=CMD_ERASE;
    81       IAP_ADDRH=clean_adder>>8;
    82       IAP_ADDRL=clean_adder;
    83          IAP_TRIG = 0x5a;   //启动命令
    84         IAP_TRIG = 0xa5;
    85     delay_1us(10);
    86     iap_idle();
    87 
    88 
    89 }
    90     

    eerom.h

     1 #ifndef _eeprom_h_
     2 #define _eeprom_h_
     3 
     4 #include "config.h"
     5 void iap_idle();
     6 
     7 uint8_t  read_eeprom( uint16_t read_adder);
     8 
     9 void write_eeprom(uint16_t write_adder,uint8_t write_dat);
    10 
    11 void clean_iap(uint16_t clean_adder)  ; //擦除扇区
    12 
    13 #endif

    delay.c

     1 #include "delay.h"
     2 
     3 
     4 
     5 //void delay(unsigned char ms)
     6 //{
     7 //    unsigned int x, y;
     8 //    for (x=ms; x>0; x--)      
     9 //    for (y=110; y>0; y--);    
    10 
    11 //}
    12 
    13 
    14 void delay_1us(unsigned int us)
    15  {
    16     unsigned int x, y;
    17     for (x=us; x>0; x--)      
    18     for (y=500; y>0; y--);    
    19  } 

    delay.h

     1 #ifndef _delay_h_
     2 #define _delay_h_
     3 
     4 void delay(unsigned char ms);
     5 
     6 void delay_1us(unsigned int us);
     7 
     8 
     9 
    10 
    11 
    12 #endif

    中断interrupt.c

     1 #include "interrupt.h"
     2 #include "user_timer.h"
     3 #include "adc.h"
     4 
     5 //#include "user_key.h"
     6 //#include "key.h"
     7 
     8 #include "config.h"
     9 
    10 
    11 extern uint16_t timer0_time_cnt;
    12 
    13 
    14                                               
    15 void timer0(void) interrupt 1     //定时器T0中断函数入口         //500us进一次中断  10usX100=1000us=1ms    f=1/1ms=1Khz
    16 {    
    17       TH0=(65536-5000)/256;        // 5000us
    18     TL0=(65536-5000)%256;
    19 
    20              timer0_time_cnt ++ ;    //自定义定时查询使用
    21 }

    中断interrupt.h

    1 #ifndef _INTERRUPT_H_
    2 #define _INTERRUPT_H_
    3 
    4 //#include <STC12C5A60S2.H>
    5 
    6 
    7 #endif

    gpio.c

     1 #include "gpio.h"
     2 #include "config.h"
     3 
     4 
     5 void gpio_init()
     6 {
     7     P1M0 &= ~(BIT0|BIT1) ;   // P10 ,P11 设置为输入
     8     P1M1 |=  (BIT0|BIT1) ;
     9     
    10     
    11     P1M0 |=  BIT3 ;   // P13 设置为推挽输出
    12     P1M1 &= ~BIT3 ;
    13     
    14     P1M0 &= ~(BIT4|BIT6); // P14,P16设置为高阻态
    15     P1M1 |= (BIT4|BIT6);
    16     
    17     
    18     P2M0 |=  (BIT0|BIT1|BIT4) ;   // P20,P21,P24 设置为推挽输出
    19     P2M1 &= ~(BIT0|BIT1|BIT4)  ;
    20     
    21 //    P2M0 &= ~BIT5 ;   // P25 设置为输入
    22 //    P2M1 |=  BIT5 ;
    23     
    24 }

    gpio.h

    1 #ifndef _GPIO_H_
    2 #define _GPIO_H_
    3 
    4 void gpio_init();
    5 
    6 
    7 #endif

    按键user_key.c

      1 #include "user_key.h"
      2 #include "config.h"
      3 #include "user_timer.h"
      4 #include <stdio.h>
      5 
      6 static  uint8_t idata key_event_flag = 0;
      7 static uint8_t key_event = 0 ;
      8 
      9 
     10 void user_key_init()
     11 {
     12   key_event_flag = KEY_NOT_ACTION ;
     13 }
     14 
     15 
     16 unsigned char  user_key_scan_even( bit KEY )
     17 {
     18       static  bit key_state = 1 ;                   
     19       static uint8_t key_step = 0;
     20 //      static uint8_t key_event;
     21        key_state = KEY ;
     22     
     23 #if Key_Default_State
     24       key_state  = key_state ;
     25     
     26 #else
     27        key_state  = !key_state ;                   // 按键未被触发时电平
     28 #endif
     29     
     30     
     31      
     32     switch( key_step)
     33     {
     34         case 0:
     35             if( key_state )                                                    // 第0步,按键未被触发
     36             {
     37                        key_event = KEY_NOT_ACTION ; //无操作
     38                 clear_time_cnt(KEY_TRIGGER_TIMER_NUMBER);                           // 清除消抖时间
     39             }
     40             else                                    
     41                 key_step++;                                                       // 按键触发 ,进入第1步
     42             break;
     43             
     44         case 1:
     45             if( key_state )                                                     // 再次确认按键是否按下 ,
     46                 key_step--;                                                   // 若没有,则返回第0步
     47             else                                                              // 如确认按键按下
     48             {
     49                 if(check_time_arrive(KEY_TRIGGER_TIMER_NUMBER, KEY_TRIGGER_TIMER))  // 检查按键按下时间,是否超过设定消抖时间 ,若超过
     50                 {
     51                     clear_time_cnt(KEY_TRIGGER_TIMER_NUMBER);                        // 清除消抖时间
     52                                     
     53                     key_step++;                                                // 进入 第2步
     54                        } 
     55             }
     56             break;
     57                         
     58         case 2:
     59             if( key_state )                                                    // 若超过设定消抖时间后,按键弹起
     60             {
     61                 clear_time_cnt(KEY_TRIGGER_TIMER_NUMBER);                            // 清除消抖时间
     62                 key_step++;                                                    // 进入第3部
     63                  }
     64            else                                                            // 若超过设定消抖时间后,按键还未被释放
     65             {
     66                 if(check_time_arrive(KEY_TRIGGER_TIMER_NUMBER, KEY_LONG_PRESS_TIME)) //检查按键按下时间是否超过 长按设定时间 ,若超过
     67                 {
     68                     key_event = KEY_LONG_PRESS_ACTION;                    // 发生长按 动作
     69                     key_step += 2;                                            // 进入第4步
     70                 }
     71             }
     72             break;
     73         case 3:
     74             if( key_state )                                                    // 按键被释放
     75             {
     76                 if(check_time_arrive(KEY_TRIGGER_TIMER_NUMBER, KEY_TRIGGER_TIMER)) // 检查释放时间是否满足 消抖时间 ,若满足
     77                 {
     78                                             key_event = KEY_CLICK_ACTION;                        // 则发生 单击 动作
     79                                             key_step = 0;                                            // 返回 第 0 步
     80                       }
     81             }
     82             else                                                            // 若按键释放时间 未满足 消抖时间 ,则
     83             {
     84                 clear_time_cnt(KEY_TRIGGER_TIMER_NUMBER);                          // 清除消抖时间
     85                 key_step--;                                                    // 返回 第3步 ,继续判断按键按下时间,
     86                 }
     87             break;
     88         case 4:
     89             if( key_state)                                                    // 长按 按键释放后
     90             {
     91                 if(check_time_arrive(KEY_TRIGGER_TIMER_NUMBER, KEY_TRIGGER_TIMER)) //检查长按按键 释放 时间是否满足 按键消抖时间 
     92                 {
     93                     key_event = KEY_LONG_RELEASE_ACTION;               // 则 发生 长按 动作
     94                     key_step = 0;                                           // 返回 第 0 步
     95                 }
     96             }
     97             break;
     98         default:
     99             break;
    100     }
    101         
    102         return key_event;
    103 }
    104 
    105 void user_key_scan( bit KEY )
    106 {
    107     uint8_t key_temp;
    108       static uint8_t key_step = 0;
    109    key_temp = user_key_scan_even( KEY);  //获取单击、长按
    110    switch( key_step )
    111      {
    112        case 0:
    113          {
    114            if(key_temp == KEY_CLICK_ACTION ) //单击动作
    115              {
    116                 key_step = 1 ; 
    117                     clear_time_cnt(KEY_TWO_TRIGGER_TIME_NUMBER);  //清除时间
    118              }
    119              else   //其他按键类型,直接返回
    120              {
    121                key_event_flag = key_temp ; 
    122                  key_event = 0 ;
    123              }
    124          };break;
    125          
    126          case 1 :
    127          {
    128            if(key_temp == KEY_CLICK_ACTION ) //单击动作
    129              {
    130                key_event_flag = KEY_TWO_ACTION ; //双击动作
    131                                 key_step = 0 ;
    132 
    133              }
    134              else if( check_time_arrive(KEY_TWO_TRIGGER_TIME_NUMBER , KEY_TWO_TRIGGER_TIME ))
    135              {
    136                key_event_flag = KEY_CLICK_ACTION ; 
    137                                key_step = 0 ;
    138              }
    139          };break;
    140          default : break;
    141      }
    142 }
    143 
    144 uint8_t return_key_state() //返回按键 事件值  
    145 {
    146    return key_event_flag ;
    147 
    148 }
    149 
    150 
    151 void rest_key_state()   //按键释放
    152 {
    153   key_event_flag = KEY_NOT_ACTION ;
    154 }

    按键user_key.h

     1 #ifndef _USER_KEY_
     2 #define _USER_KEY_
     3 #include "config.h"
     4 
     5 #define Key_Default_State   1      //按键未触发状态  【 1:高电平     0: 低电平 】
     6 
     7 #define KEY_NOT_ACTION            0       // 按键无动作        
     8 #define KEY_CLICK_ACTION          1       // 单击动作
     9 #define KEY_LONG_PRESS_ACTION     3       // 长按动作 ----> 长按按键触发状态
    10 #define KEY_LONG_RELEASE_ACTION   4       // 长按动作 ----> 长按按键释放
    11 
    12 #define KEY_TWO_ACTION 5           //双击
    13 
    14 void user_key_init();
    15 unsigned char  user_key_scan_even( bit KEY );
    16 
    17 void user_key_scan(bit KEY);
    18 uint8_t return_key_state();
    19 void rest_key_state();
    20 
    21 
    22 
    23 
    24 #endif

    时间user_timer.c

     1 #include "user_timer.h"
     2 #include "config.h"
     3 #include "interrupt.h"
     4 
     5 uint16_t timer0_time_cnt = 0 ;
     6 
     7 static   uint16_t  user_timer_array[USER_TIMER_AMOUNT] = {0};
     8 static   uint16_t  timeout_control_array[USER_TIMER_AMOUNT] = {0};
     9 
    10 void user_timer_init(void)        // 数组初始化
    11 {
    12     uint8_t i = 0;
    13     for(i = 0; i < USER_TIMER_AMOUNT; i++)
    14     {
    15         user_timer_array[i] = 0;
    16         timeout_control_array[i] = 0;
    17     }
    18 }
    19 
    20 /*********************
    21     function:    
    22         The system reference time is added to the user time array.
    23     parameter:
    24         null
    25     return:
    26         null
    27 *********************/
    28 void add_system_time(void)                  // 添加 时间 (放主循环)
    29 {
    30     uint8_t i = 0  ;
    31     uint16_t temp ;
    32     
    33     temp = timer0_time_cnt;
    34     timer0_time_cnt = 0;
    35     
    36     for(i = 0; i < USER_TIMER_AMOUNT; i++)
    37     {
    38         if(user_timer_array[i] <= timeout_control_array[i])
    39             user_timer_array[i] += temp;
    40 
    41     }
    42 }
    43 
    44 
    45 
    46 /*********************
    47     function:    
    48         Clear the user time count.
    49     parameter:
    50         USER_TIMER0_CNT ...... USER_TIMERN_CNT or user typedef name
    51     return:
    52         null
    53 *********************/
    54 void clear_time_cnt(uint8_t time_number)        // 清除时间
    55 {
    56     if(USER_TIMER_AMOUNT > time_number)
    57         user_timer_array[time_number] = 0;
    58 }
    59 
    60 
    61 /*********************
    62     function:    
    63         time if arrived
    64     parameter:
    65         <time_number>
    66             USER_TIMER0_CNT ...... USER_TIMERN_CNT or user typedef name
    67         <time>
    68             check time
    69     return:
    70         null
    71 *********************/ 
    72 
    73 
    74 
    75 
    76 uint8_t check_time_arrive(uint8_t time_number, uint16_t time)  // 检查设定时间,是否到达
    77 {
    78     if(USER_TIMER_AMOUNT > time_number)
    79     {
    80         timeout_control_array[time_number] = time;
    81         
    82         if(time <= user_timer_array[time_number])
    83           {
    84             
    85             return 1;
    86         }
    87         else
    88             return 0;
    89   }
    90     return 0;
    91 }

    时间user_time.h

     1 #ifndef _USER_TIMER_
     2 #define _USER_TIMER_
     3 
     4 #include "config.h"
     5 
     6 void user_timer_init(void);
     7 void add_system_time(void);                  // 添加 时间 (放主循环)
     8 
     9 void clear_time_cnt(uint8_t time_number);        // 清除时间
    10 
    11 uint8_t check_time_arrive(uint8_t time_number, uint16_t time);
    12 
    13 #endif

    管脚分配如下:

    P10 ------ 光敏、人体感应(1--无触发, 0---- 触发)
    P11 ------ 按键

    P13 ----- PWM 灯光亮度调节

    P14 ------ 电池电压输入
    P16 ------ TL431 +2.5V 基准输入

    P20 ------ 充电控制 1--- 开 ; 0---- 关

    P21 ------ 灯光模式指示LED(蓝灯)
    P24 ------ 灯光指示模式LED(红灯)

    P22,P23 -------- 人体检测时间 【 1:1 -- 3分钟; 0:1 --- 6分钟; 1:0 -- 9分钟; 0:0 -- 12分钟; 】

    来几张照片:

    文末,在此希望这次疫情赶快去,祝愿中国加油,湖北加油,武汉加油!!!!!!!!!!!!!!!!!!!

     
  • 相关阅读:
    mysql零碎问题合集
    mysql 纵表转横表 需要用join不能直接where连接
    eclipse导出可执行jar包 报main function not found错误
    shell脚本将mysql查询结果制作成csv格式
    linux shell中把句子中的单词提取作为变量值 主要是使用了数组
    linux下文件字符编码转换
    Banner使用
    recyclerview的博客网址需要的权限
    okhttp权限
    Okhttp代码
  • 原文地址:https://www.cnblogs.com/UPUPDay2152/p/12313106.html
Copyright © 2011-2022 走看看