打印
[STM32F1]

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

[复制链接]
楼主: junpeng324
手机看帖
扫描二维码
随时随地手机跟帖
81
junpeng324|  楼主 | 2017-11-12 22:38 | 只看该作者 回帖奖励 |倒序浏览
旋钮调节
#include "ADC.h"
u8 i; u32 ad,dianya;
void adc_init()  //ADC初始化
{
  GPIO_InitTypeDef GPIO_InitStructure;
        ADC_InitTypeDef ADC_InitStructure;
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO|RCC_APB2Periph_ADC1,ENABLE);
       
        //ADC管脚初始化配置
  GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;      //ADC123 通道1 PA1
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;         //模拟输入
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
        GPIO_Init(GPIOA,&GPIO_InitStructure);
       
        //ADC初始化
        ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;     //ADC1与ADC2工作在独立模式
        ADC_InitStructure.ADC_ScanConvMode = DISABLE;          //单次单通道模式
        ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;    //单次模式
        ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //软件触发启动规则通道模数转换
        ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;  //右对齐
        ADC_InitStructure.ADC_NbrOfChannel = 1;
        ADC_Init(ADC1, &ADC_InitStructure);
       
        ADC_RegularChannelConfig(ADC1,ADC_Channel_1,1,ADC_SampleTime_239Cycles5);
        //指定ADC的规则组通道,设置转化顺序和采样时间
       
        ADC_Cmd(ADC1,ENABLE);       

        ADC_ResetCalibration(ADC1);//重置指定ADC的校准寄存器
        while(ADC_GetResetCalibrationStatus(ADC1));//获取ADC重置校验位的状态
       
        ADC_StartCalibration(ADC1);//开始指定ADC的校准状态
        while(ADC_GetCalibrationStatus(ADC1));//获取ADC的校准状态

        ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能或失能ADC的软件转换启动功能
}
void xuanniu_dat()  //旋钮数据处理
{
          for(i=0;i<50;i++)             
                {
                        ADC_SoftwareStartConvCmd(ADC1, ENABLE);
                        while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));
                        ad=ad+ADC_GetConversionValue(ADC1);                 
                }
                ad=ad/50;
}
void xuanniu_deal()  //旋钮处理
{
   if(dianya!=ad)
                {
                        led_adc_flag=1;
                        dianya=ad;
                        tiaoguang(dianya/2);
                }

}




使用特权

评论回复
82
junpeng324|  楼主 | 2017-11-12 22:42 | 只看该作者
旋钮调节部分我们使用了电位器调节,来改变灯的亮度,通过ADC检测电位器变化的电压以此来改变PWM的值。

使用特权

评论回复
83
vsunl| | 2017-11-13 16:38 | 只看该作者
不错,很强大

使用特权

评论回复
84
junpeng324|  楼主 | 2017-11-13 22:08 | 只看该作者
感谢支持,相互学习

使用特权

评论回复
85
junpeng324|  楼主 | 2017-11-13 22:14 | 只看该作者
#include "pwm.h"
void pwm_init()
{
        GPIO_InitTypeDef GPIO_InitStructure;   //声明一个结构体变量,用来初始化GPIO
  TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//声明一个结构体变量,用来初始化定时器
  TIM_OCInitTypeDef TIM_OCInitStructure;//根据TIM_OCInitStruct中指定的参数初始化外设TIMx


        /* 开启时钟 */
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);


        /*  配置GPIO的模式和IO口 */
        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
        GPIO_Init(GPIOA,&GPIO_InitStructure);


        //TIM3定时器初始化
        TIM_TimeBaseInitStructure.TIM_Period = 7200;           //不分频,PWM 频率=72000/900=8Khz//设置自动重装载寄存器周期的值
        TIM_TimeBaseInitStructure.TIM_Prescaler = 0;//设置用来作为TIMx时钟频率预分频值,100Khz计数频率
        TIM_TimeBaseInitStructure.TIM_ClockDivision = 0;//设置时钟分割:TDTS = Tck_tim
        TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;        //TIM向上计数模式
        TIM_TimeBaseInit(TIM5, & TIM_TimeBaseInitStructure);




        //PWM初始化          //根据TIM_OCInitStruct中指定的参数初始化外设TIMx
        TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;
        TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//PWM输出使能
        TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;


        TIM_OC1Init(TIM5,&TIM_OCInitStructure);
        //注意此处初始化时TIM_OC2Init而不是TIM_OCInit,否则会出错。因为固件库的版本不一样。


        TIM_OC1PreloadConfig(TIM5, TIM_OCPreload_Enable);//使能或者失能TIMx在CCR2上的预装载寄存器
       
        TIM_Cmd(TIM5,ENABLE);//使能或者失能TIMx外设
        TIM_SetCompare1(TIM5, 0);
}
void led_on()         //开灯
{
TIM_SetCompare1(TIM5, 2000);
currentDataPoint.valueLamp_Size=200;
}
void led_off()       //关灯
{
TIM_SetCompare1(TIM5, 0);
currentDataPoint.valueLamp_Size=0;
}
void tiaoguang(u16 zkb)      //调光
{
TIM_SetCompare1(TIM5, zkb);
currentDataPoint.valueLamp_Size=zkb/10;
  if(zkb==0)
        {
         currentDataPoint.valueLamp_Power=0;
        }
        else
        {
          currentDataPoint.valueLamp_Power=1;
        }
}


使用特权

评论回复
86
junpeng324|  楼主 | 2017-11-13 22:15 | 只看该作者
#ifndef _pwm_H
#define _pwm_H
#include "stm32f10x.h"
#include "gizwits_protocol.h"
extern dataPoint_t currentDataPoint;
void pwm_init(void);
void led_on(void);
void led_off(void);
void tiaoguang(u16 zkb);


#endif

使用特权

评论回复
87
junpeng324|  楼主 | 2017-11-14 22:32 | 只看该作者
用于报警的蜂鸣器
#include "beep.h"
void BEEP_Init()          //端口初始化
{
        GPIO_InitTypeDef GPIO_InitStructure;        //声明一个结构体变量,用来初始化GPIO
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);   /* 开启GPIO时钟 */
  /*  配置GPIO的模式和IO口 */
        GPIO_InitStructure.GPIO_Pin=BZ;                //选择你要设置的IO口
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;                  //设置推挽输出模式
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;          //设置传输速率
        GPIO_Init(GPIOB,&GPIO_InitStructure);          /* 初始化GPIO */
        GPIO_SetBits(GPIOB,BZ);
}
void BUZZ(u8 k)    //蜂鸣器
{
  if(k==1)
         {
           GPIO_ResetBits(GPIOB,BZ);  //开蜂鸣器
         }
         else
        {
           GPIO_SetBits(GPIOB,BZ);    //关蜂鸣器
        }
}


使用特权

评论回复
88
junpeng324|  楼主 | 2017-11-14 22:33 | 只看该作者
需要用到的延时函数
#include "delay.h"

/*******************************************************************************
* 函 数 名         : delay_us
* 函数功能                   : 延时函数,延时us
* 输    入         : i
* 输    出         : 无
*******************************************************************************/
void delay_us(u32 i)
{
        u32 temp;
        SysTick->LOAD=9*i;                 //设置重装数值, 72MHZ时
        SysTick->CTRL=0X01;                 //使能,减到零是无动作,采用外部时钟源
        SysTick->VAL=0;                            //清零计数器
        do
        {
                temp=SysTick->CTRL;                   //读取当前倒计数值
        }
        while((temp&0x01)&&(!(temp&(1<<16))));         //等待时间到达
        SysTick->CTRL=0;        //关闭计数器
        SysTick->VAL=0;                //清空计数器
}

/*******************************************************************************
* 函 数 名         : delay_ms
* 函数功能                   : 延时函数,延时ms
* 输    入         : i
* 输    出         : 无
*******************************************************************************/
void delay_ms(u32 i)
{
        u32 temp;
        SysTick->LOAD=9000*i;          //设置重装数值, 72MHZ时
        SysTick->CTRL=0X01;                //使能,减到零是无动作,采用外部时钟源
        SysTick->VAL=0;                        //清零计数器
        do
        {
                temp=SysTick->CTRL;           //读取当前倒计数值
        }
        while((temp&0x01)&&(!(temp&(1<<16))));        //等待时间到达
        SysTick->CTRL=0;        //关闭计数器
        SysTick->VAL=0;                //清空计数器
}

/*******************************************************************************
* 函 数 名         : RCC_HSE_Configuration
* 函数功能                   : 自定义系统时钟,可以通过修改PLL时钟源和倍频系数实现时钟调整
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void RCC_HSE_Configuration() //自定义系统时间(可以修改时钟)
{
        RCC_DeInit(); //将外设RCC寄存器重设为缺省值
        RCC_HSEConfig(RCC_HSE_ON);//设置外部高速晶振(HSE)
        if(RCC_WaitForHSEStartUp()==SUCCESS) //等待HSE起振
        {
                RCC_HCLKConfig(RCC_SYSCLK_Div1);//设置AHB时钟(HCLK)
                RCC_PCLK1Config(RCC_HCLK_Div2);//设置低速AHB时钟(PCLK1)
                RCC_PCLK2Config(RCC_HCLK_Div1);//设置高速AHB时钟(PCLK2)
                RCC_PLLConfig(RCC_PLLSource_HSE_Div2,RCC_PLLMul_9);//设置PLL时钟源及倍频系数
                RCC_PLLCmd(ENABLE); //使能或者失能PLL
                while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET);//检查指定的RCC标志位设置与否,PLL就绪
                RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);//设置系统时钟(SYSCLK)
                while(RCC_GetSYSCLKSource()!=0x08);//返回用作系统时钟的时钟源,0x08:PLL作为系统时钟
        }
}


使用特权

评论回复
89
junpeng324|  楼主 | 2017-11-14 22:35 | 只看该作者
云端联网按键设置函数
#include "Hal_key/hal_key.h"
#include <stm32f10x.h>
#include <math.h>
#include "key/key.h"


extern keysTypedef_t keys;
extern u8 tempflag,zuozi_time_flag;
uint8_t                 keyCountTime;
static uint8_t          keyTotolNum = 0;

//TIM2中断函数
void TIM2_IRQHandler(void)
{
         static u16 i;
         if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)  
    {
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
        keyHandle((keysTypedef_t *)&keys);
    }
                     i++;
                if(i==1000)   //1s对温湿度,光照值,可燃气体检测,坐姿距离进行上传
                {
                  i=0;tempflag=1;zuozi_time_flag=1;
                }
               
}

/**
* @brief 定时器初始化

* 使用定时器TIM2 用来监测按键状态
* @param none
* @return none
*/
void timer2Init(void)
{
    u16 arr = 7199; //重装初值
    u16 psc = 9; //预分频
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //时钟使能

    //定时器TIM2初始化
    TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重载寄存器周期的值
    TIM_TimeBaseStructure.TIM_Prescaler = psc; //设置用来作为TIMx时钟频率的预分频值
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位0

    TIM_ITConfig(TIM2, TIM_IT_Update,ENABLE ); //使能指定的TIM2中断,允许更新中断

    //中断优先级NVIC设置
    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;  //TIM2中断
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //优占优先级0级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;  //从优先级2级
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
    NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器
    TIM_Cmd(TIM2, ENABLE);  //使能TIMx
}

/**
* @brief Read the GPIO state
* @param [in] keys 按键功能全局结构体指针
* @return uint16_t型的GPIO状态值
*/
uint16_t getKey(keysTypedef_t *keyS)
{
    uint8_t i = 0;
    uint16_t readKey = 0;              //必要,初始化

    //GPIO Cyclic scan
    for(i = 0; i < keys.keyTotolNum; i++)
    {
        if(!GPIO_ReadInputDataBit((GPIO_TypeDef*)keyS->singleKey.keyPort,keyS->singleKey.keyGpio))
        {
            G_SET_BIT(readKey, keyS->singleKey.keyNum);
        }
    }

    return readKey;
}


/**
* @brief Read the KEY value
* @param [in] keys 按键功能全局结构体指针
* @return uint16_t型的按键状态值
*/
uint16_t readKeyValue(keysTypedef_t *keyS)
{
    static uint8_t keyCheck = 0;
    static uint8_t keyState = 0;
    static uint16_t keyLongCheck = 0;
    static uint16_t keyPrev = 0;      //上一次按键

    uint16_t keyPress = 0;
    uint16_t keyReturn = 0;

    keyCountTime ++;

    if(keyCountTime >= (DEBOUNCE_TIME / KEY_TIMER_MS))          //keyCountTime 1MS+1  按键消抖10MS
    {
        keyCountTime = 0;
        keyCheck = 1;
    }
    if(1 == keyCheck)
    {
        keyCheck = 0;
        keyPress = getKey(keyS);
        switch (keyState)
        {
            case 0:
                if(keyPress != 0)
                {
                    keyPrev = keyPress;
                    keyState = 1;
                }
                break;

            case 1:
                if(keyPress == keyPrev)
                {
                    keyState = 2;
                    keyReturn= keyPrev | KEY_DOWN;
                }
                else                //按键抬起,是抖动,不响应按键
                {
                    keyState = 0;
                }
                break;

            case 2:

                if(keyPress != keyPrev)
                {
                    keyState = 0;
                    keyLongCheck = 0;
                    keyReturn = keyPrev | KEY_UP;
                    return keyReturn;
                }
                if(keyPress == keyPrev)
                {
                    keyLongCheck++;
                    if(keyLongCheck >= (PRESS_LONG_TIME / DEBOUNCE_TIME))    //长按3S有效
                    {
                        keyLongCheck = 0;
                        keyState = 3;
                        keyReturn= keyPress | KEY_LONG;
                        return keyReturn;
                    }
                }
                break;

            case 3:
                if(keyPress != keyPrev)
                {
                    keyState = 0;
                }
                break;
        }
    }
    return  NO_KEY;
}

/**
* @brief 按键回调函数

* 在该函数内完成按键状态监测后调用对应的回调函数
* @param [in] keys 按键功能全局结构体指针
* @return none
*/
void keyHandle(keysTypedef_t *keyS)
{
    uint8_t i = 0;
    uint16_t key_value = 0;

    key_value = readKeyValue(keyS);

    if(!key_value) return;

    //Check short press button
    if(key_value & KEY_UP)
    {
        //Valid key is detected
        for(i = 0; i < keyS->keyTotolNum; i++)
        {
            if(G_IS_BIT_SET(key_value, keyS->singleKey.keyNum))
            {
                //key callback function of short press
                if(keyS->singleKey.shortPress)
                {
                    keyS->singleKey.shortPress();

                }
            }
        }
    }

    //Check short long button
    if(key_value & KEY_LONG)
    {
        //Valid key is detected
        for(i = 0; i < keyS->keyTotolNum; i++)
        {
            if(G_IS_BIT_SET(key_value, keyS->singleKey.keyNum))
            {
                //key callback function of long press
                if(keyS->singleKey.longPress)
                {
                    keyS->singleKey.longPress();

                }
            }
        }
    }
}

/**
* @brief 单按键初始化

* 在该函数内完成单个按键的初始化,这里需要结合STM32 GPIO寄存器配置设置参数
* @param [in] keyRccPeriph APB2_peripheral
* @param [in] keyPort Peripheral_declaration
* @param [in] keyGpio GPIO_pins_define
* @param [in] short_press 短按状态的回调函数地址
* @param [in] long_press 长按状态的回调函数地址
* @return 单按键结构体指针
*/
keyTypedef_t keyInitOne(uint32_t keyRccPeriph, GPIO_TypeDef * keyPort, uint32_t keyGpio, gokitKeyFunction shortPress, gokitKeyFunction longPress)
{
    static int8_t key_total = -1;

    keyTypedef_t singleKey;

    //Platform-defined GPIO
    singleKey.keyRccPeriph = keyRccPeriph;
    singleKey.keyPort = keyPort;
    singleKey.keyGpio = keyGpio;
    singleKey.keyNum = ++key_total;

    //Button trigger callback type
    singleKey.longPress = longPress;
    singleKey.shortPress = shortPress;

    keyTotolNum++;

    return singleKey;
}

/**
* @brief 按键驱动初始化

* 在该函数内完成所有的按键GPIO初始化,并开启一个定时器开始按键状态监测
* @param [in] keys 按键功能全局结构体指针
* @return none
*/
void keyParaInit(keysTypedef_t *keys)
{
    uint8_t temI = 0;

    if(NULL == keys)
    {
        return ;
    }

    keys->keyTotolNum = keyTotolNum;

    //Limit on the number keys (Allowable number: 0~12)
    if(KEY_MAX_NUMBER < keys->keyTotolNum)
    {
        keys->keyTotolNum = KEY_MAX_NUMBER;
    }

    for(temI = 0; temI < keys->keyTotolNum; temI++)
    {
        GPIO_InitTypeDef GPIO_InitStructure;
        RCC_APB2PeriphClockCmd(keys->singleKey[temI].keyRccPeriph, ENABLE);

        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;

        GPIO_InitStructure.GPIO_Pin = keys->singleKey[temI].keyGpio;
        GPIO_Init(keys->singleKey[temI].keyPort, &GPIO_InitStructure);
    }

    //初始化周期为1MS定时器
    timer2Init();
}


使用特权

评论回复
90
junpeng324|  楼主 | 2017-11-14 22:36 | 只看该作者
ESP8266串口部分

#include "stm32f10x_rcc.h"
#include "Hal_Usart/hal_uart.h"

#ifdef __GNUC__
// With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf set to 'Yes') calls __io_putchar()
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */


/**
* @brief 串口GPIO初始化

* @param none
* @return none
*/
void uartGpioInit(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

#if defined (Open_UART1)
    USART1_GPIO_Cmd(USART1_GPIO_CLK, ENABLE);
    USART1_AFIO_Cmd(USART1_AFIO_CLK, ENABLE);
    USART1_CLK_Cmd(USART1_CLK, ENABLE);

    GPIO_InitStructure.GPIO_Pin = USART1_TxPin;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(USART1_GPIO_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = USART1_RxPin;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(USART1_GPIO_PORT, &GPIO_InitStructure);
#endif

#if defined (Open_UART2)
    USART2_GPIO_Cmd(USART2_GPIO_CLK, ENABLE);
    USART2_CLK_Cmd(USART2_CLK, ENABLE);
    USART2_AFIO_Cmd(USART2_AFIO_CLK, ENABLE);

    GPIO_InitStructure.GPIO_Pin = USART2_TxPin;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(USART2_GPIO_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = USART2_RxPin;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(USART2_GPIO_PORT, &GPIO_InitStructure);
#endif

#if defined (Open_UART3)
    USART3_GPIO_Cmd(USART3_GPIO_CLK, ENABLE);
    USART3_CLK_Cmd(USART3_CLK, ENABLE);
    USART3_AFIO_Cmd(USART3_AFIO_CLK, ENABLE);
    GPIO_PinRemapConfig(GPIO_PartialRemap_USART3,ENABLE);

    GPIO_InitStructure.GPIO_Pin = USART3_TxPin;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(USART3_GPIO_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = USART3_RxPin;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(USART3_GPIO_PORT, &GPIO_InitStructure);
#endif
}

/**
* @brief 串口配置初始化

* @param none
* @return none
*/
void uartConfig(void)
{
    USART_InitTypeDef USART_InitStructure;
#if defined (Open_UART1)
    USART_InitStructure.USART_BaudRate = 115200;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART1, &USART_InitStructure);

    USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
    USART_Cmd(USART1, ENABLE);
    USART_ClearFlag(USART1, USART_FLAG_TC); /*清空发送完成标志,Transmission Complete flag */
#endif

#if defined (Open_UART2)
    USART_InitStructure.USART_BaudRate = 9600;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART2, &USART_InitStructure);

    USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);
    USART_Cmd(USART2, ENABLE);
    USART_ClearFlag(USART2, USART_FLAG_TC); /*清空发送完成标志,Transmission Complete flag */
#endif

#if defined (Open_UART3)
    USART_InitStructure.USART_BaudRate = 115200;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART3, &USART_InitStructure);

    USART_ITConfig(USART3,USART_IT_RXNE,ENABLE);
    USART_Cmd(USART3, ENABLE);
    USART_ClearFlag(USART3, USART_FLAG_TC); /*清空发送完成标志,Transmission Complete flag */
#endif

}

/**
* @brief 串口NVIC初始化

* @param none
* @return none
*/
void nvicConfiguration(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
#if defined (Open_UART1)
    /*使能串口中断,并设置优先级*/
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
#endif

#if defined (Open_UART2)
    /*使能串口中断,并设置优先级*/
    NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
#endif

#if defined (Open_UART3)
    /*使能串口中断,并设置优先级*/
    NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
#endif
}

/**
* @brief UART1写操作
*
* @param data     : 数据
*
* @return : none
*/
void uart1SendData(uint8_t data)
{
    USART_SendData(USART1,data);
    //Loop until the end of transmission
    while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}

/**
* @brief 串口初始化函数
* @param none
* @return none
*/
void uartxInit(void)
{
    uartGpioInit();
    uartConfig();
    nvicConfiguration();
}

/**
* @brief printf打印重定向
* @param none
* @return none
*/
PUTCHAR_PROTOTYPE
{
    //Place your implementation of fputc here , e.g. write a character to the USART
    USART_SendData(USART1,(u8)ch);
    //Loop until the end of transmission
    while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
    return ch;
}


使用特权

评论回复
91
kelly1989| | 2017-11-15 08:03 | 只看该作者
功能太棒了,就是太复杂了

使用特权

评论回复
92
junpeng324|  楼主 | 2017-11-15 23:06 | 只看该作者
kelly1989 发表于 2017-11-15 08:03
功能太棒了,就是太复杂了

这样才好得将啊

使用特权

评论回复
93
junpeng324|  楼主 | 2017-11-15 23:14 | 只看该作者
看门狗代码
#include "hal_watchdog.h"


/**
* @brief 看门狗初始化接口


*Tout=((4×2^prer) ×rlr) /40 = ((4 * 2^4) * 625) / 40 = 1000ms = 1s


*prer 为看门狗时钟预分频值(IWDG_PR 值),范围为0~7


*rlr 为看门狗的重装载值(IWDG_RLR 的值)


*1s内喂狗,看门狗就可以不复位 , 看门狗时钟不标准的40kHz


* @param timeoutS : 复位时间,单位是秒
* @return none
*/
void watchdogInit(uint8_t timeoutS)//宏
{
#ifdef  WATCHDOG
    uint8_t prer = 4;
    uint16_t rlr = timeoutS * 625;
    IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); /* 使能对寄存器IWDG_PR和IWDG_RLR的写操作*/
    IWDG_SetPrescaler(prer);    /*设置IWDG预分频值:设置IWDG预分频值*/
    IWDG_SetReload(rlr);     /*设置IWDG重装载值*/
    IWDG_ReloadCounter();    /*按照IWDG重装载寄存器的值重装载IWDG计数器*/
    IWDG_Enable();        /*使能IWDG*/
#endif
}


/**
* @brief 看门狗喂狗接口


* @param  none
* @return none
*/
void watchdogFeed(void)
{
#ifdef  WATCHDOG
    IWDG->KR=0xaaaa;
#endif
}


使用特权

评论回复
94
junpeng324|  楼主 | 2017-11-15 23:17 | 只看该作者
#include "key.h"
#include "gizwits_protocol.h"
extern dataPoint_t currentDataPoint;
u8 mode_flag,zuozi_flag;
/*******************************************************************************
* 函 数 名         : key_init
* 函数功能                   : 按键端口初始化函数          
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void key_init()          
{
        GPIO_InitTypeDef GPIO_InitStructure;          //声明一个结构体变量,用来初始化GPIO
  /* 开启GPIO时钟 */
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE,ENABLE);


        /*  配置GPIO的模式和IO口 */
        GPIO_InitStructure.GPIO_Pin=K_DOWN|K_RIGHT;
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;        //上拉输入
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
        GPIO_Init(GPIOE,&GPIO_InitStructure);


}
void keyscan()
{
  if(k_down==0)  //模式切换
        {
                delay_ms(10);
                if(k_down==0)
                {
                        if(mode_flag==1)
                        {
                          mode_flag=0;
                                currentDataPoint.valueLamp_Auto_Control=0;
                        }
                        else
                        {
                         mode_flag=1;
                         currentDataPoint.valueLamp_Auto_Control=1;
                        }
                }
                while(!k_down);
        }
        if(k_right==0)  //启动坐姿测量
        {
                delay_ms(10);
                if(k_right==0)
                {
                  if(zuozi_flag==1)
                        {
                          zuozi_flag=0;
                        }
                        else
                        {
                          zuozi_flag=1;
                        }
                }
                while(!k_right);
        }
       
}


使用特权

评论回复
95
junpeng324|  楼主 | 2017-11-15 23:31 | 只看该作者
可燃气体检测
#include "mq2.h"
void mq2_init()          
{
        GPIO_InitTypeDef GPIO_InitStructure;          
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
  GPIO_InitStructure.GPIO_Pin=mq;
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;       
        GPIO_Init(GPIOE,&GPIO_InitStructure);
}
u8 qitijiance()   //气体检测 有可燃气体时蜂鸣器响
{
   if(MQ==0)
         {
           delay_ms(100);
                 if(MQ==0)
                 {
                  delay_ms(100);
                        BUZZ(1);
                         return 1;
                 }
         }
         else
         {
           BUZZ(0);
                 return 0;
         }
}




使用特权

评论回复
96
caijie001| | 2017-11-15 23:35 | 只看该作者
不错的作品,帮顶

使用特权

评论回复
97
junpeng324|  楼主 | 2017-11-16 22:42 | 只看该作者
caijie001 发表于 2017-11-15 23:35
不错的作品,帮顶

相互学习哈,共同进步。

使用特权

评论回复
98
lishutong| | 2017-11-17 07:56 | 只看该作者
功能确实复杂

使用特权

评论回复
99
junpeng324|  楼主 | 2017-11-18 22:23 | 只看该作者

越复杂越容易得奖。

使用特权

评论回复
100
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; //求出秒

}












































使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则