ST MCU Finder
安装免费手机应用,
寻找理想的ST MCU

[STM32F1] 基于STM32芯片的一款智能台灯

[复制链接]
楼主: junpeng324
 楼主 | 2017-11-18 22:44 | 显示全部楼层
#include "rtc.h"
const uint8_t RtcLeapMonth[12]   = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const uint8_t RtcCommonMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
/* 定义一个全局变量保存时钟 */
RTC_TimeTypeDef RTC_Time;


/* 声明内部函数 */
static uint8_t RTC_CheckLeapYear(uint16_t year);
static uint8_t RTC_SetTime(RTC_TimeTypeDef *time);
static void RTC_NVIC_Config(void);
static void RTC_GetTime(void);


/****************************************************************************
* Function Name  : RTC_SetClock
* Description    : 设置时钟
* Input          : *time:要设置的时钟值
* Output         : None
* Return         : None
****************************************************************************/


void RTC_SetClock(RTC_TimeTypeDef *time)
{   
    RTC_EnterConfigMode();                    //允许配置       
    RTC_WaitForLastTask();                          //等待最近一次对RTC寄存器的写操作完成
    RTC_SetTime(time);                        //设置时间       
    RTC_ExitConfigMode();                     //退出配置模式  
    RTC_GetTime();         //更新时间
}


/****************************************************************************
* Function Name  : RTC_Config
* Description    : 初始化时钟,并初始化内部的时钟信息
* Input          : time:要初始化的时钟
* Output         : None
* Return         : 0:初始化成功;0xFF:初始化失败
****************************************************************************/


int8_t RTC_Config(RTC_TimeTypeDef *time)
{
    uint32_t timeCount;


    if(BKP_ReadBackupRegister(BKP_DR1) != 0x5050)
    {
        /* 使能PWR电源时钟和BKP备份区域外设时钟 */   
                RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);


        PWR_BackupAccessCmd(ENABLE);        //使能后备寄存器访问
                BKP_DeInit();                        //复位备份区域        
                RCC_LSEConfig(RCC_LSE_ON);            //设置外部低速晶振(LSE),使用外设低速晶振


        /* 检查指定的RCC标志位设置与否,等待低速晶振(LSE)就绪 */
            while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
                {
                    timeCount++;
            if(timeCount > 0x00FFFFF)
            {
                break;
            }
                }


        /* 外部晶振错误,返回设置失败 */
        if(timeCount > 0x00FFFFF)
        {
            return 0xFF;            
        }


        RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);   //设置RTC时钟(RTCCLK),选择LSE作为RTC时钟   
                    RCC_RTCCLKCmd(ENABLE);                          //使能RTC时钟
        RTC_WaitForLastTask();                          //等待最近一次对RTC寄存器的写操作完成
                    RTC_WaitForSynchro();                                  //等待RTC寄存器同步  
                    RTC_ITConfig(RTC_IT_SEC, ENABLE);                      //使能RTC秒中断
                    RTC_WaitForLastTask();                          //等待最近一次对RTC寄存器的写操作完成


                                RTC_EnterConfigMode();                    //允许配置       
                                RTC_SetPrescaler(32767);                  //设置RTC预分频的值
                                RTC_WaitForLastTask();                          //等待最近一次对RTC寄存器的写操作完成
                                RTC_SetTime(time);                        //设置时间       
                                RTC_ExitConfigMode();                     //退出配置模式  
                                BKP_WriteBackupRegister(BKP_DR1, 0X5050); //向指定的后备寄存器中写入用户程序数据
                                }
                                else
                                {
                                                RTC_WaitForSynchro();                   //等待最近一次对RTC寄存器的写操作完成
                                RTC_ITConfig(RTC_IT_SEC, ENABLE);  //使能RTC秒中断
                                RTC_WaitForLastTask();                   //等待最近一次对RTC寄存器的写操作完成
                                }


                                RTC_NVIC_Config();     //RCT中断分组设置,开启中断                                                         
                        RTC_GetTime();         //更新时间


                                return 0;
}


/****************************************************************************
* Function Name  : RTC_IRQHandler
* Description    : RTC时钟的中断函数,用来跟新时间,或者闹钟
* Input          : None
* Output         : None
* Return         : None
****************************************************************************/


void RTC_IRQHandler(void)
{                 
        if (RTC_GetITStatus(RTC_IT_SEC) != RESET)     //秒钟中断
        {                                                       
                  RTC_GetTime();                            //更新时间
           
        }


        if(RTC_GetITStatus(RTC_IT_ALR)!= RESET)       //闹钟中断
        {
                RTC_ClearITPendingBit(RTC_IT_ALR);              //清闹钟中断                    
          }
                                                                                                        
        RTC_ClearITPendingBit(RTC_IT_SEC|RTC_IT_OW);  //清闹钟中断
        RTC_WaitForLastTask();                                                //等待最近一次对RTC寄存器的写操作完成                                             
}


/****************************************************************************
* Function Name  : RTC_NVIC_Config
* Description    : RTC中断的设置
* Input          : None
* Output         : None
* Return         : None
****************************************************************************/


static void RTC_NVIC_Config(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;


        NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;                        //RTC全局中断
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;        //抢占优先级设置
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;                //响应优先级设置
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                        //使能该通道中断


        NVIC_Init(&NVIC_InitStructure);   //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
}


/****************************************************************************
* Function Name  : RTC_SetTime
* Description    : 设置RTC时钟的计数器初始值
* Input          : time:设置的初始值(注:年份设置从2000到2100年之间)
* Output         : None
* Return         : 0:设置成功;0xFF:设置失败
****************************************************************************/


static uint8_t RTC_SetTime(RTC_TimeTypeDef *time)
{
    uint8_t  leapYear = 0;
    uint16_t i;
    uint32_t secondCount = 0;
   
    /* 确定写入的时间不超过年限 */
    if((time->year < 2000) || (time->year > 2100)) //从2000年到2100年,一共100年
    {
        return 0xFF;             //超过时限返回失败
    }
   
    /* 将所有的年份秒数相加 */
    for(i = RTC_BASE_YEAR; i<time->year; i++)
    {
        if(RTC_CheckLeapYear(i) == 0)          //如果年份是闰年
        {
            secondCount += RTC_LEEP_YEAR_SECOND;     
        }
        else
        {
            secondCount += RTC_COMMON_YEAR_SECOND;   
        }   
    }
   
   
    /* 检测写入年份是闰年还是平年 */
    if(RTC_CheckLeapYear(time->year) == 0) //如果是闰年
    {
        leapYear = 1;                     //标记为闰年            
    }
    else
    {
        leapYear = 0;                     //标记为平年   
    }
    /* 所有月份秒数相加 */
    for(i=1; i<time->month; i++)
    {
        if(leapYear == 1)
        {
            secondCount += RtcLeapMonth[i - 1] * RTC_DAY_SECOND;     
        }
        else
        {
            secondCount += RtcCommonMonth[i - 1] * RTC_DAY_SECOND;
        }      
    }
   
    /* 所有的日期秒数相加 */
    for(i=1; i<time->day; i++)
    {
        secondCount += RTC_DAY_SECOND;
    }
   
    /* 小时的秒数 */
    secondCount += RTC_HOUR_SECOND * time->hour;
   
    /* 分钟的秒数 */
    secondCount += 60 * time->minit;
   
    /* 加上秒数 */
    secondCount += time->second;


    /* 使能PWR电源时钟和BKP备份区域外设时钟 */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
        PWR_BackupAccessCmd(ENABLE);          //使能RTC和后备寄存器访问
        RTC_SetCounter(secondCount);          //设置RTC计数器的值
   
    RTC_WaitForLastTask();                  //等待最近一次对RTC寄存器的写操作完成         


        return 0;                         //设置成功返回0
}


/****************************************************************************
* Function Name  : RTC_CheckLeapYear
* Description    : 检测年份是否是闰年
* Input          : year:检测的年份
* Output         : None
* Return         : 0:是闰年;0xFF:是平年
****************************************************************************/


static uint8_t RTC_CheckLeapYear(uint16_t year)
{
    /* 闰年有两种计算方式,第一种是能被四整除且不能被100整除, */
    /* 第二种是能被100整除且能被400整除 */


    if((year % 100) == 0) //能被100整除的,且能被400整除是闰年
    {
        if((year % 400) == 0)
        {
            return 0;     //是闰年
        }
        else
        {
            return 0xFF;  //是平年
        }   
    }
    else                  //不能被100整除,但能被4整除是闰年
    {
        if((year % 4) == 0)
        {
            return 0;     //是闰年
        }
        else
        {
            return 0xFF;  //是平年
        }
    }
}


/****************************************************************************
* Function Name  : RTC_GetTime
* Description    : 读取RTC计数器的值,并将其转化为日期
* Input          : None
* Output         : None
* Return         : None
****************************************************************************/

static void RTC_GetTime(void)
{
    uint8_t leapYear = 0, i = 0;
    uint32_t secondCount = 0;
    uint32_t day;


    /* 读取时钟计数器的值 */
    secondCount =  RTC->CNTH;
    secondCount <<= 16;
    secondCount |= RTC->CNTL;
   
    day = secondCount / RTC_DAY_SECOND;           //求出天数
    secondCount = secondCount % RTC_DAY_SECOND;   //求出剩余秒数


    RTC_Time.year = RTC_BASE_YEAR;


    /* 求出星期几 */
    RTC_Time.week = (day + 6) % 7;         //因为2000年1月1日是星期六所以加6


    /* 求出年份 */
    while(day >= 365)
    {
        if(RTC_CheckLeapYear(RTC_Time.year) == 0)   //是闰年
        {
            day -= 366;                    //闰年有366天   
        }
        else
        {
            day -= 365;                    //平年有365天
        }


        RTC_Time.year++;
    }


    /* 求出月份 */
    if(RTC_CheckLeapYear(RTC_Time.year) == 0)
    {
        leapYear = 1;                        //如果是闰年标记
    }


    i = 0;
    RTC_Time.month = 1;
    while(day >= 28)
    {        
        if(leapYear == 1)
        {
            if(day < RtcCommonMonth) //天数不够一个月
            {
                break;
            }
            day -= RtcLeapMonth;     //减去闰年该月的天数
        }
        else
        {
            if(day < RtcCommonMonth) //天数不够一个月
            {
                break;
            }
            day -= RtcCommonMonth;   //减去平年该月的天数
        }
        RTC_Time.month++;               //月份加1
        i++;                            //月份数组加1
    }


    /* 求出天数 */
    RTC_Time.day = day + 1;             //月份剩下的天数就是日期(日期从1号开始)


    RTC_Time.hour = secondCount / RTC_HOUR_SECOND;       //求出小时
    RTC_Time.minit = secondCount % RTC_HOUR_SECOND / 60; //求出分钟
    RTC_Time.second = secondCount % RTC_HOUR_SECOND %60; //求出秒

}












































 楼主 | 2017-11-18 22:46 | 显示全部楼层
RTC数字时钟底层代码,支持年月日,掉电不丢失。
 楼主 | 2017-11-18 22:47 | 显示全部楼层
#include "smg.h"
u8 smgduan[12]={0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07,
             0x7f, 0x6f,0x40,0x00};//0~F 数码管段选数据
void smg_init()
{
        GPIO_InitTypeDef GPIO_InitStructure;  //声明一个结构体变量,用来初始化GPIO
        /* 开启GPIO时钟 */
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC,ENABLE);

       
        /*  配置GPIO的模式和IO口 */
        GPIO_InitStructure.GPIO_Pin=smg_duan;          //选择你要设置的IO口
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
        GPIO_Init(GPIOC,&GPIO_InitStructure);                /* 初始化GPIO */
       
        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7;          //选择你要设置的IO口
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
        GPIO_Init(GPIOA,&GPIO_InitStructure);                /* 初始化GPIO */
}
void smg_display(u16 shi,u16 fen,u16 miao)        //数码管时钟显示
{       
                 GPIO_SetBits(GPIOA,GPIO_Pin_6);
          GPIO_Write(GPIOC,(u16)(smgduan[shi/10]));
          GPIO_ResetBits(GPIOA,GPIO_Pin_6);
          
          GPIO_SetBits(GPIOA,GPIO_Pin_7);
          GPIO_Write(GPIOC, (u16)(0xfe));
          GPIO_ResetBits(GPIOA,GPIO_Pin_7);
          delay_us(200);
   
    GPIO_SetBits(GPIOA,GPIO_Pin_6);
          GPIO_Write(GPIOC,(u16)(smgduan[shi%10]));
          GPIO_ResetBits(GPIOA,GPIO_Pin_6);
          
               
          GPIO_SetBits(GPIOA,GPIO_Pin_7);
          GPIO_Write(GPIOC, (u16)(0xfd));
          GPIO_ResetBits(GPIOA,GPIO_Pin_7);
          delay_us(200);
          
          if(miao%2)
                {
          GPIO_SetBits(GPIOA,GPIO_Pin_6);
          GPIO_Write(GPIOC,(u16)(smgduan[10]));
          GPIO_ResetBits(GPIOA,GPIO_Pin_6);
          }
                else
                {
                GPIO_SetBits(GPIOA,GPIO_Pin_6);
          GPIO_Write(GPIOC,(u16)(smgduan[11]));
          GPIO_ResetBits(GPIOA,GPIO_Pin_6);
                }
          GPIO_SetBits(GPIOA,GPIO_Pin_7);
          GPIO_Write(GPIOC, (u16)(0xfb));
          GPIO_ResetBits(GPIOA,GPIO_Pin_7);
          delay_us(200);
               
                GPIO_SetBits(GPIOA,GPIO_Pin_6);
          GPIO_Write(GPIOC,(u16)(smgduan[fen/10]));
          GPIO_ResetBits(GPIOA,GPIO_Pin_6);
          
          GPIO_SetBits(GPIOA,GPIO_Pin_7);
          GPIO_Write(GPIOC, (u16)(0xf7));
          GPIO_ResetBits(GPIOA,GPIO_Pin_7);
          delay_us(200);
               
                GPIO_SetBits(GPIOA,GPIO_Pin_6);
          GPIO_Write(GPIOC,(u16)(smgduan[fen%10]));
          GPIO_ResetBits(GPIOA,GPIO_Pin_6);
          
          GPIO_SetBits(GPIOA,GPIO_Pin_7);
          GPIO_Write(GPIOC, (u16)(0xef));
          GPIO_ResetBits(GPIOA,GPIO_Pin_7);
          delay_us(100);
               
                if(miao%2)
                {
                GPIO_SetBits(GPIOA,GPIO_Pin_6);
          GPIO_Write(GPIOC,(u16)(smgduan[10]));
          GPIO_ResetBits(GPIOA,GPIO_Pin_6);
          }
                else
                {
                GPIO_SetBits(GPIOA,GPIO_Pin_6);
          GPIO_Write(GPIOC,(u16)(smgduan[11]));
          GPIO_ResetBits(GPIOA,GPIO_Pin_6);
                }
          GPIO_SetBits(GPIOA,GPIO_Pin_7);
          GPIO_Write(GPIOC, (u16)(0xdf));
          GPIO_ResetBits(GPIOA,GPIO_Pin_7);
          delay_us(100);
               
                GPIO_SetBits(GPIOA,GPIO_Pin_6);
          GPIO_Write(GPIOC,(u16)(smgduan[miao/10]));
          GPIO_ResetBits(GPIOA,GPIO_Pin_6);
          
          GPIO_SetBits(GPIOA,GPIO_Pin_7);
          GPIO_Write(GPIOC, (u16)(0xbf));
          GPIO_ResetBits(GPIOA,GPIO_Pin_7);
          delay_us(100);
               
                GPIO_SetBits(GPIOA,GPIO_Pin_6);
          GPIO_Write(GPIOC,(u16)(smgduan[miao%10]));
          GPIO_ResetBits(GPIOA,GPIO_Pin_6);
          
          GPIO_SetBits(GPIOA,GPIO_Pin_7);
          GPIO_Write(GPIOC, (u16)(0x7f));
          GPIO_ResetBits(GPIOA,GPIO_Pin_7);
          delay_us(100);
               
                GPIO_SetBits(GPIOA,GPIO_Pin_6);
          GPIO_Write(GPIOC,(u16)(smgduan[11]));
          GPIO_ResetBits(GPIOA,GPIO_Pin_6);
          
          GPIO_SetBits(GPIOA,GPIO_Pin_7);
          GPIO_Write(GPIOC, (u16)(0x7f));
          GPIO_ResetBits(GPIOA,GPIO_Pin_7);
          delay_us(100);
}

void sfr_display(u16 ds)        //数码管距离显示
{       
                 GPIO_SetBits(GPIOA,GPIO_Pin_6);
          GPIO_Write(GPIOC,(u16)(smgduan[10]));
          GPIO_ResetBits(GPIOA,GPIO_Pin_6);
          GPIO_SetBits(GPIOA,GPIO_Pin_7);
          GPIO_Write(GPIOC, (u16)(0xfe));
          GPIO_ResetBits(GPIOA,GPIO_Pin_7);
          delay_us(200);
   
    GPIO_SetBits(GPIOA,GPIO_Pin_6);
          GPIO_Write(GPIOC,(u16)(smgduan[10]));
          GPIO_ResetBits(GPIOA,GPIO_Pin_6);
          GPIO_SetBits(GPIOA,GPIO_Pin_7);
          GPIO_Write(GPIOC, (u16)(0xfd));
          GPIO_ResetBits(GPIOA,GPIO_Pin_7);
          delay_us(200);
          
          
          GPIO_SetBits(GPIOA,GPIO_Pin_6);
          GPIO_Write(GPIOC,(u16)(smgduan[0]));
          GPIO_ResetBits(GPIOA,GPIO_Pin_6);
          GPIO_SetBits(GPIOA,GPIO_Pin_7);
          GPIO_Write(GPIOC, (u16)(0xfb));
          GPIO_ResetBits(GPIOA,GPIO_Pin_7);
          delay_us(200);
               
                GPIO_SetBits(GPIOA,GPIO_Pin_6);
          GPIO_Write(GPIOC,(u16)(smgduan[ds/100]));
          GPIO_ResetBits(GPIOA,GPIO_Pin_6);
          GPIO_SetBits(GPIOA,GPIO_Pin_7);
          GPIO_Write(GPIOC, (u16)(0xf7));
          GPIO_ResetBits(GPIOA,GPIO_Pin_7);
          delay_us(200);
               
                GPIO_SetBits(GPIOA,GPIO_Pin_6);
          GPIO_Write(GPIOC,(u16)(smgduan[ds%100/10]));
          GPIO_ResetBits(GPIOA,GPIO_Pin_6);
          GPIO_SetBits(GPIOA,GPIO_Pin_7);
          GPIO_Write(GPIOC, (u16)(0xef));
          GPIO_ResetBits(GPIOA,GPIO_Pin_7);
          delay_us(100);
               
       
       
                GPIO_SetBits(GPIOA,GPIO_Pin_6);
          GPIO_Write(GPIOC,(u16)(smgduan[ds%10]));
          GPIO_ResetBits(GPIOA,GPIO_Pin_6);
          GPIO_SetBits(GPIOA,GPIO_Pin_7);
          GPIO_Write(GPIOC, (u16)(0xdf));
          GPIO_ResetBits(GPIOA,GPIO_Pin_7);
          delay_us(100);
               
                GPIO_SetBits(GPIOA,GPIO_Pin_6);
          GPIO_Write(GPIOC,(u16)(smgduan[10]));
          GPIO_ResetBits(GPIOA,GPIO_Pin_6);
          GPIO_SetBits(GPIOA,GPIO_Pin_7);
          GPIO_Write(GPIOC, (u16)(0xbf));
          GPIO_ResetBits(GPIOA,GPIO_Pin_7);
          delay_us(100);
               
                GPIO_SetBits(GPIOA,GPIO_Pin_6);
          GPIO_Write(GPIOC,(u16)(smgduan[10]));
          GPIO_ResetBits(GPIOA,GPIO_Pin_6);
          GPIO_SetBits(GPIOA,GPIO_Pin_7);
          GPIO_Write(GPIOC, (u16)(0x7f));
          GPIO_ResetBits(GPIOA,GPIO_Pin_7);
          delay_us(100);
               
                GPIO_SetBits(GPIOA,GPIO_Pin_6);
          GPIO_Write(GPIOC,(u16)(smgduan[11]));
          GPIO_ResetBits(GPIOA,GPIO_Pin_6);
          GPIO_SetBits(GPIOA,GPIO_Pin_7);
          GPIO_Write(GPIOC, (u16)(0x7f));
          GPIO_ResetBits(GPIOA,GPIO_Pin_7);
          delay_us(100);
}

 楼主 | 2017-11-18 22:48 | 显示全部楼层
基于数字时钟的数码管代码,八位共阳极数码管。
 楼主 | 2017-11-27 22:25 | 显示全部楼层
手势控制部分如下图,用四个光电开关组成。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
 楼主 | 2017-11-27 22:26 | 显示全部楼层
手势控制原理
通过四个光电开关采集挥手的速度:
左——右:
                      挥手速度较快时,亮度增加较大,
                       挥手速度较慢时亮度增加较慢
                       最亮时不再变化。
右——左:
                       挥手速度较快时,亮度减弱较大,
                       挥手速度较慢时亮度减弱较慢
                       最暗时不再变化。
 楼主 | 2017-11-27 22:27 | 显示全部楼层
如图曲线是手势控制原理

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
 楼主 | 2017-11-27 22:28 | 显示全部楼层
#include "shoushi.h"
/*******************************************************
  手势控制:通过TIM4定时器捕获,分别捕捉4个通道低电平持续时间
  通道1~通道4对应GPIO管脚 :PB6~PB9
********************************************************/
u8 ch1_sta,ch2_sta,ch3_sta,ch4_sta;     //输入捕获状态
u16 ch1_val,ch2_val,ch3_val,ch4_val;    //输入捕获值
u32 sj1,sj2,sj3,sj4;                    //四个通道捕获低电平持续时间
u8 fx_flag;                             //方向标志位

static u32 sj_av;   
static u8  sj1_flag,sj2_flag,sj3_flag,sj4_flag;
static u8  fx1_flag,fx2_flag,fx3_flag,fx4_flag;
 楼主 | 2017-11-27 22:29 | 显示全部楼层
void shoushi_init()       //手势初始化   
{
        TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
        TIM_ICInitTypeDef TIM4_ICInitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;


        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);         //使能TIM4时钟

  TIM_TimeBaseInitStructure.TIM_Period = 0xffff;         //设定计数器自动重装值        
        TIM_TimeBaseInitStructure.TIM_Prescaler = 719;   //以100khz的频率计数 一次即是10us
        TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;          //不分割
        TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up ;         //TIM向上计数模式
        TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStructure);//根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
       
        TIM4_ICInitStructure.TIM_Channel = TIM_Channel_1; //选择输入端 IC1映射到TI1上
        TIM4_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling; //下降沿捕获
        TIM4_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上
        TIM4_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //配置输入分频,不分频
        TIM4_ICInitStructure.TIM_ICFilter = 0x00; //IC1F=0000 配置输入滤波器 不滤波
        TIM_ICInit(TIM4, &TIM4_ICInitStructure); //初始化TIM5输入捕获通道1       
       
        TIM4_ICInitStructure.TIM_Channel = TIM_Channel_2; //选择输入端 IC1映射到TI1上
        TIM4_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling; //下降沿捕获
        TIM4_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上
        TIM4_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //配置输入分频,不分频
        TIM4_ICInitStructure.TIM_ICFilter = 0x00; //IC1F=0000 配置输入滤波器 不滤波
        TIM_ICInit(TIM4, &TIM4_ICInitStructure); //初始化TIM5输入捕获通道1       
       
        TIM4_ICInitStructure.TIM_Channel = TIM_Channel_3; //选择输入端 IC1映射到TI1上
        TIM4_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling; //下降沿捕获
        TIM4_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上
        TIM4_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //配置输入分频,不分频
        TIM4_ICInitStructure.TIM_ICFilter = 0x00; //IC1F=0000 配置输入滤波器 不滤波
        TIM_ICInit(TIM4, &TIM4_ICInitStructure); //初始化TIM5输入捕获通道1       
       
        TIM4_ICInitStructure.TIM_Channel = TIM_Channel_4; //选择输入端 IC1映射到TI1上
        TIM4_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling; //下降沿捕获
        TIM4_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上
        TIM4_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //配置输入分频,不分频
        TIM4_ICInitStructure.TIM_ICFilter = 0x00; //IC1F=0000 配置输入滤波器 不滤波
        TIM_ICInit(TIM4, &TIM4_ICInitStructure); //初始化TIM5输入捕获通道1       
       
       
        //中断分组初始化
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
        NVIC_InitStructure.NVIC_IRQChannel=TIM4_IRQn;        //打开TIM4的全局中断
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;        //抢占优先级为0
        NVIC_InitStructure.NVIC_IRQChannelSubPriority=1; //响应优先级为1
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;          //使能
  NVIC_Init(&NVIC_InitStructure);
       
        TIM_Cmd(TIM4,ENABLE);
        TIM_ITConfig(TIM4, TIM_IT_Update|TIM_IT_CC1, ENABLE );       
  TIM_ITConfig(TIM4, TIM_IT_Update|TIM_IT_CC2, ENABLE );       
        TIM_ITConfig(TIM4, TIM_IT_Update|TIM_IT_CC3, ENABLE );       
        TIM_ITConfig(TIM4, TIM_IT_Update|TIM_IT_CC4, ENABLE );       
}
 楼主 | 2017-11-27 22:30 | 显示全部楼层
void TIM4_IRQHandler()          //定时器4输入捕获中断函数
{
        if((ch1_sta&0X80)==0)   //还未成功捕获
        {
                if (TIM_GetITStatus(TIM4, TIM_IT_Update)!= RESET)       
                {
                        if(ch1_sta&0X40)     //已经捕获到低电平了
                        {
                                if((ch1_sta&0x3f)==0x3f)//低电平太长了
                                {       
                                        ch1_sta|=0x80;             //标记成功捕获了一次
                                        ch1_val=0xffff;               
                                }
                                else
                                {
                                        ch1_sta++;       
                                }
                        }
                }       
        }
        if (TIM_GetITStatus(TIM4, TIM_IT_CC1) != RESET) //捕获1发生捕获事件
        {
                if(ch1_sta&0X40) //捕获到一个上升沿
                {
                        ch1_sta|=0X80; //标记成功捕获到一次下降沿
                        ch1_val=TIM_GetCapture1(TIM4); //获得TIMx输入捕获1的值
                        TIM_OC1PolarityConfig(TIM4,TIM_ICPolarity_Falling); //设置为下降沿捕获       
                }
                else              //捕获到了下降沿
                {
                        ch1_sta=0; //清空
                        ch1_val=0;
                        TIM_SetCounter(TIM4,0);
                        ch1_sta|=0X40; //标记捕获到了下降沿
                        TIM_OC1PolarityConfig(TIM4,TIM_ICPolarity_Rising); //设置为上升沿捕获
                }       
        }
       
       
        if((ch2_sta&0X80)==0)//还未成功捕获
        {
                if (TIM_GetITStatus(TIM4, TIM_IT_Update)!= RESET)       
                {
                        if(ch2_sta&0X40) //已经捕获到低电平了
                        {
                                if((ch2_sta&0x3f)==0x3f)//低电平太长了
                                {       
                                        ch2_sta|=0x80;             //标记成功捕获了一次
                                        ch2_val=0xffff;               
                                }
                                else
                                {
                                        ch2_sta++;       
                                }
                        }
                }       
        }
        if (TIM_GetITStatus(TIM4, TIM_IT_CC2) != RESET) //捕获1发生捕获事件
        {
                if(ch2_sta&0X40) //捕获到一个上升沿
                {
                        ch2_sta|=0X80; //标记成功捕获到一次下降沿
                        ch2_val=TIM_GetCapture2(TIM4); //获得TIMx输入捕获1的值
                        TIM_OC2PolarityConfig(TIM4,TIM_ICPolarity_Falling); //设置为下降沿捕获       
                }
                else              //捕获到了下降沿
                {
                        ch2_sta=0; //清空
                        ch2_val=0;
                        TIM_SetCounter(TIM4,0);
                        ch2_sta|=0X40; //标记捕获到了下降沿
                        TIM_OC2PolarityConfig(TIM4,TIM_ICPolarity_Rising); //设置为上升沿捕获
                }       
        }
       
        if((ch3_sta&0X80)==0)//还未成功捕获
        {
                if (TIM_GetITStatus(TIM4, TIM_IT_Update)!= RESET)       
                {
                        if(ch3_sta&0X40) //已经捕获到低电平了
                        {
                                if((ch3_sta&0x3f)==0x3f)//低电平太长了
                                {       
                                        ch3_sta|=0x80;             //标记成功捕获了一次
                                        ch3_val=0xffff;               
                                }
                                else
                                {
                                        ch3_sta++;       
                                }
                        }
                }       
        }
        if (TIM_GetITStatus(TIM4, TIM_IT_CC3) != RESET) //捕获1发生捕获事件
        {
                if(ch3_sta&0X40) //捕获到一个上升沿
                {
                        ch3_sta|=0X80; //标记成功捕获到一次下降沿
                        ch3_val=TIM_GetCapture3(TIM4); //获得TIMx输入捕获1的值
                        TIM_OC3PolarityConfig(TIM4,TIM_ICPolarity_Falling); //设置为下降沿捕获       
                }
                else              //捕获到了下降沿
                {
                        ch3_sta=0; //清空
                        ch3_val=0;
                        TIM_SetCounter(TIM4,0);
                        ch3_sta|=0X40; //标记捕获到了下降沿
                        TIM_OC3PolarityConfig(TIM4,TIM_ICPolarity_Rising); //设置为上升沿捕获
                }       
        }
       
        if((ch4_sta&0X80)==0)//还未成功捕获
        {
                if (TIM_GetITStatus(TIM4, TIM_IT_Update)!= RESET)       
                {
                        if(ch4_sta&0X40) //已经捕获到低电平了
                        {
                                if((ch4_sta&0x3f)==0x3f)//低电平太长了
                                {       
                                        ch4_sta|=0x80;             //标记成功捕获了一次
                                        ch4_val=0xffff;               
                                }
                                else
                                {
                                        ch4_sta++;       
                                }
                        }
                }       
        }
        if (TIM_GetITStatus(TIM4, TIM_IT_CC4) != RESET) //捕获1发生捕获事件
        {
                if(ch4_sta&0X40) //捕获到一个上升沿
                {
                        ch4_sta|=0X80; //标记成功捕获到一次下降沿
                        ch4_val=TIM_GetCapture4(TIM4); //获得TIMx输入捕获1的值
                        TIM_OC4PolarityConfig(TIM4,TIM_ICPolarity_Falling); //设置为下降沿捕获       
                }
                else              //捕获到了下降沿
                {
                        ch4_sta=0; //清空
                        ch4_val=0;
                        TIM_SetCounter(TIM4,0);
                        ch4_sta|=0X40; //标记捕获到了下降沿
                        TIM_OC4PolarityConfig(TIM4,TIM_ICPolarity_Rising); //设置为上升沿捕获
                }       
        }
TIM_ClearITPendingBit(TIM4, TIM_IT_CC1|TIM_IT_CC2|TIM_IT_CC3|TIM_IT_CC4|TIM_IT_Update); //清除中断标志位
}
 楼主 | 2017-11-27 22:31 | 显示全部楼层
关于手势数据处理的下次再分享,也是整个手势扫描的核心代码。
 楼主 | 2017-11-27 22:31 | 显示全部楼层
明天接着分享,各位晚安了,
 楼主 | 2017-11-28 11:56 | 显示全部楼层
void shoushi_dat()  //手势数据处理
{
if((ch1_sta&0x80))
                 {
                         fx1_flag=1;
                         fx_flag=1;
                         sj1_flag=1;         //通道1数据获取完成
                         sj1=ch1_sta&0x3f;       
                         sj1=sj1*65536;                  
                         sj1=sj1+ch1_val;
//                 printf("ch1:%d ms\r\n",sj1/100);   //打印通道1数据
                         ch1_sta=0;        
                        }
        if((ch2_sta&0x80))         
                {
                        fx2_flag=1;
                        sj2_flag=1;         //通道2数据获取完成
            sj2=ch2_sta&0x3f;
      sj2=sj2*65536;
      sj2=sj2+ch2_val;
//      printf("ch2:%d ms\r\n",sj2/100);   //打印通道2数据
      ch2_sta=0;
                        }
         if((ch3_sta&0x80))          
                {
            fx3_flag=1;
                        sj3_flag=1;         //通道3数据获取完成
                        sj3=ch3_sta&0x3f;
      sj3=sj3*65536;
      sj3=sj3+ch3_val;
//      printf("ch3:%d ms\r\n",sj3/100);    //打印通道3数据
      ch3_sta=0;
                 }
        if((ch4_sta&0x80))         
                {
            fx4_flag=1;
                        fx_flag=4;
                        sj4_flag=1;         //通道4数据获取完成
                        sj4=ch4_sta&0x3f;
      sj4=sj4*65536;
      sj4=sj4+ch4_val;
//      printf("ch4:%d ms\r\n",sj4/100);     //打印通道4数据
      ch4_sta=0;        
                }
                if((sj1_flag==1)&&(sj2_flag==1)&&(sj3_flag==1)&&(sj4_flag==1))
                {
                           led_shoushi_flag=1;                
                     sj1_flag=sj2_flag=sj3_flag=sj4_flag=0;       //清空各通道获取数据完成标志位
                           sj_av=(sj1+sj2+sj3+sj4)/4;                   //求取平均值
//                         printf("ch av:%d ms\r\n",sj_av/100);         //打印平均值
                }
}       
 楼主 | 2017-11-28 11:57 | 显示全部楼层
void shoushi_deal()   //手势处理
{
          static u8 fx_succese_flag,kk;
    static  u16 lx,zj_lx;
          u8 lx_flag;     
        //方向判断函数   用于防误差操作
        if((fx1_flag==1)&&(fx2_flag==1)&& (fx3_flag==1)&& (fx4_flag==1))  //方向有效
    {
                     fx1_flag=fx2_flag=fx3_flag=fx4_flag=0;    //从新捕获方向
                           fx_succese_flag=1;
         lx_flag=1;                       
                           kk=fx_flag;           //保存此时方向
                }
  else   //方向无效
                {
                   if(fx_succese_flag==1)     //再次方向无效
                         {
                             kk=kk;
                         }
       else                       //第一次方向无效
                   TIM_SetCompare1(TIM5, 0);
                }
             
 楼主 | 2017-11-28 11:57 | 显示全部楼层
/***************************************************************************
                通过大量手势摆动数据显示 我们根据手势的速度对灯光亮度进行了相关处理
模式1:
                         1.通过四个光电门的平均时间处于0~50ms范围:
                                                                                                                                                                                 从左至右亮度值服从该函数 y=-0.2x+2000;
                                                                                                                                                                            
                         2.通过四个光电门的平均时间大于50ms
                                                                                                                                                                                  从左至右亮度以一个微弱的亮度值
                   3.手势从右至左时   任意速度  灯灭
               
模式2:
                   1.从左至右 :挥手速度快  灯光亮度增加快
                                挥手速度慢  灯光亮度增加慢
                                到达最亮时  灯光亮度不再改变
               
                   2.从右至左: 挥手速度快  灯光亮度减弱的快
                                挥手速度慢  灯光亮度减弱的慢
                                到达最暗时  灯光亮度不再改变
 楼主 | 2017-11-28 11:57 | 显示全部楼层
模式1  根据速度来控制灯光的亮度
            函数: y=-0.2x+2000;
       
  *********************************************/
//   if(sj_av>=5000)
//         {
//            tiaoguang(100);           //速度过慢时微微点亮
//         }
//         if((sj_av>0)&&(sj_av<5000))  //函数 y=-0.2x+2000
//         {
//             lx=2000-((sj_av*4)/10);
//                   if(kk==4)
//                                 led_off();
//                         if(kk==1)
//                         {
//                      tiaoguang(lx);
//                         }
//         }
/*******************************************
 楼主 | 2017-11-28 11:58 | 显示全部楼层
模式2   根据左右挥动的速度作为增量和减量来控制灯光
                 y=-0.2x+1000
                                                     
*******************************************/
     
                if(sj_av>=5000)     //速度较慢时 保持原有亮度
                {
                   tiaoguang(lx);   
                }
                if((sj_av>0)&&(sj_av<5000))
                {
                   if(kk==4)        //右至左
                         {
                          
                                 zj_lx=1000-((sj_av*2)/10);
                                 if(lx_flag==1)
                                        {
                                                lx_flag=0;
                                          lx-=zj_lx;
                                        }
                                        if((lx<0)|(lx>2000))
                                        {
                                          lx=0;  
                                        }
                                        if(app_sucess==1)
                                        {
                                          app_sucess=0;
                                               
                                                lx=currentDataPoint.valueLamp_Size*10-zj_lx;
                                                tiaoguang(lx);
                                        }
                                        if(app_sucess==0)
                                        {
                                          tiaoguang(lx);
                                        }
                        }
                         if(kk==1)        //左至右
                         {
                            zj_lx=1000-((sj_av*2)/10);
                                  if(lx_flag==1)
                                        {
                                                lx_flag=0;
                                          lx+=zj_lx;
                                        }
                                        if(lx>=2000)
                                        {
                                                 lx=2000;
                                        }
                                        if(app_sucess==1)
                                        {
                                                app_sucess=0;
                                          lx=currentDataPoint.valueLamp_Size*10+zj_lx;
                                                tiaoguang(lx);
                                        }
                                        if(app_sucess==0)
                                        {
                                          tiaoguang(lx);
                                        }
                         }
         }
}
| 2017-11-30 14:30 | 显示全部楼层
不错不错
| 2017-11-30 21:09 | 显示全部楼层
这台灯老霸道了,买不起啊,哈哈
| 2017-11-30 23:40 | 显示全部楼层
这是个杂合体的产品,很有趣
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式
我要创建版块 申请成为版主

论坛热帖

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