美文网首页
stm32f103xxyy之LED灯

stm32f103xxyy之LED灯

作者: guanjianhe | 来源:发表于2018-05-14 09:29 被阅读0次

    先看代码

    // PB5
    void LED_Init(void)
    {
        GPIO_InitTypeDef  GPIO_InitStructure;                    //定义一个GPIO_InitTypeDef类型的结构体
    
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);    //使能PB时钟
    
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;                //选中引脚
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;         //推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //IO口速度为50MHz
        GPIO_Init(GPIOB, &GPIO_InitStructure);                   //根据设定参数初始化GPIOB.5
        GPIO_SetBits(GPIOA,GPIO_Pin_8);                          //PB.5 输出高
    }
    

    GPIO_InitTypeDef结构体定义如下,有三个参数

    typedef struct
    {
      uint16_t GPIO_Pin;             /*!< Specifies the GPIO pins to be configured.
                                          This parameter can be any value of @ref GPIO_pins_define */
    
      GPIOSpeed_TypeDef GPIO_Speed;  /*!< Specifies the speed for the selected pins.
                                          This parameter can be a value of @ref GPIOSpeed_TypeDef */
    
      GPIOMode_TypeDef GPIO_Mode;    /*!< Specifies the operating mode for the selected pins.
                                          This parameter can be a value of @ref GPIOMode_TypeDef */
    }GPIO_InitTypeDef;
    

    其中第二个参数GPIO_Speed类型如下,是个枚举类型

    typedef enum
    { 
      GPIO_Speed_10MHz = 1,  //枚举常量,值为1,代表输出速率最高为10MHz
      GPIO_Speed_2MHz,       //对不赋值的枚举常量,依次自动加1,此常量值为2 
      GPIO_Speed_50MHz       //常量值为3
    }GPIOSpeed_TypeDef;
    

    定义了3个枚举常量,即GPIO_Speed_10MHz = 1、GPIO_Speed_2MHz = 2、GPIO_Speed_50MHz = 3

    同样,GPIOMode_TypeDef也是一个枚举类型定义符,定义如下

    typedef enum
    { GPIO_Mode_AIN = 0x0,              //模拟输入模式
      GPIO_Mode_IN_FLOATING = 0x04,     //浮空输入模式
      GPIO_Mode_IPD = 0x28,             //下拉输入模式
      GPIO_Mode_IPU = 0x48,             //上拉输入模式
      GPIO_Mode_Out_OD = 0x14,          //开漏输出模式
      GPIO_Mode_Out_PP = 0x10,          //通用推挽输出模式
      GPIO_Mode_AF_OD = 0x1C,           //复用功能开漏输出
      GPIO_Mode_AF_PP = 0x18            //复用功能推挽输出
    }GPIOMode_TypeDef;
    

    接下来再看下初始化函数GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)

    void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
    {
      uint32_t currentmode = 0x00, currentpin = 0x00, pinpos = 0x00, pos = 0x00;
      uint32_t tmpreg = 0x00, pinmask = 0x00;
      /* Check the parameters */
      assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
      assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode));
      assert_param(IS_GPIO_PIN(GPIO_InitStruct->GPIO_Pin));  
      
    /*---------------------------- GPIO Mode Configuration -----------------------*/
      currentmode = ((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x0F);
      if ((((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x10)) != 0x00)
      { 
        /* Check the parameters */
        assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed));
        /* Output mode */
        currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed;
      }
    /*---------------------------- GPIO CRL Configuration ------------------------*/
      /* Configure the eight low port pins */
      if (((uint32_t)GPIO_InitStruct->GPIO_Pin & ((uint32_t)0x00FF)) != 0x00)
      {
        tmpreg = GPIOx->CRL;
        for (pinpos = 0x00; pinpos < 0x08; pinpos++)
        {
          pos = ((uint32_t)0x01) << pinpos;
          /* Get the port pins position */
          currentpin = (GPIO_InitStruct->GPIO_Pin) & pos;
          if (currentpin == pos)
          {
            pos = pinpos << 2;
            /* Clear the corresponding low control register bits */
            pinmask = ((uint32_t)0x0F) << pos;
            tmpreg &= ~pinmask;
            /* Write the mode configuration in the corresponding bits */
            tmpreg |= (currentmode << pos);
            /* Reset the corresponding ODR bit */
            if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)
            {
              GPIOx->BRR = (((uint32_t)0x01) << pinpos);
            }
            else
            {
              /* Set the corresponding ODR bit */
              if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
              {
                GPIOx->BSRR = (((uint32_t)0x01) << pinpos);
              }
            }
          }
        }
        GPIOx->CRL = tmpreg;
      }
    /*---------------------------- GPIO CRH Configuration ------------------------*/
      /* Configure the eight high port pins */
      if (GPIO_InitStruct->GPIO_Pin > 0x00FF)
      {
        tmpreg = GPIOx->CRH;
        for (pinpos = 0x00; pinpos < 0x08; pinpos++)
        {
          pos = (((uint32_t)0x01) << (pinpos + 0x08));
          /* Get the port pins position */
          currentpin = ((GPIO_InitStruct->GPIO_Pin) & pos);
          if (currentpin == pos)
          {
            pos = pinpos << 2;
            /* Clear the corresponding high control register bits */
            pinmask = ((uint32_t)0x0F) << pos;
            tmpreg &= ~pinmask;
            /* Write the mode configuration in the corresponding bits */
            tmpreg |= (currentmode << pos);
            /* Reset the corresponding ODR bit */
            if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)
            {
              GPIOx->BRR = (((uint32_t)0x01) << (pinpos + 0x08));
            }
            /* Set the corresponding ODR bit */
            if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
            {
              GPIOx->BSRR = (((uint32_t)0x01) << (pinpos + 0x08));
            }
          }
        }
        GPIOx->CRH = tmpreg;
      }
    }
    

    再看宏定义assert_param

    #ifdef  USE_FULL_ASSERT
    
    /**
      * @brief  The assert_param macro is used for function's parameters check.
      * @param  expr: If expr is false, it calls assert_failed function which reports 
      *         the name of the source file and the source line number of the call 
      *         that failed. If expr is true, it returns no value.
      * @retval None
      */
      #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
    /* Exported functions ------------------------------------------------------- */
      void assert_failed(uint8_t* file, uint32_t line);
    #else
      #define assert_param(expr) ((void)0)
    #endif /* USE_FULL_ASSERT */
    

    如果定义了宏USE_FULL_ASSERT,宏assert_param就起作用,这时候要补写函数
    void assert_failed(uint8_t* file, uint32_t line),默认是不开启的

    #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))

    如果expr的表达式值为,则为(void)0,否则调用函数assert_failed((uint8_t *)__FILE__, __LINE__)

    assert_failed函数可参考如下,函数的意思就是,如果参数出错,输出出错的文件名称和行号。

    void assert_failed(uint8_t* file, uint32_t line)
    {
        printf("file %s on line %d\r\n", file, line);
        while(1);
    }
    
    #define IS_GPIO_ALL_PERIPH(PERIPH) (((PERIPH) == GPIOA) || \
                                        ((PERIPH) == GPIOB) || \
                                        ((PERIPH) == GPIOC) || \
                                        ((PERIPH) == GPIOD) || \
                                        ((PERIPH) == GPIOE) || \
                                        ((PERIPH) == GPIOF) || \
                                        ((PERIPH) == GPIOG))
    

    相关文章

      网友评论

          本文标题:stm32f103xxyy之LED灯

          本文链接:https://www.haomeiwen.com/subject/jtnzbxtx.html