历史上的今天
返回首页

历史上的今天

今天是:2024年12月03日(星期二)

正在发生

2021年12月03日 | STM32 LED跑马灯-库函数

2021-12-03 来源:eefocus

一,GPIO知识回顾

1,四种输入模式:

    输入浮空

    输入上拉

    输入下拉

    模拟输入


2,四种输出模式:

    开漏输出

    开漏复用输出

    推挽输出

    推挽复用输出


3,三种最大输出速度

    2MHz 

    10MHz 

    50MHz


每组GPIO共16个IO口,含下7个寄存器


GPIOx_CRL  : 端口配置低寄存器

GPIOx_CRH  : 端口配置高寄存器

GPIOx_IDR  : 端口输入寄存器

GPIOx_ODR  : 端口输出寄存器

GPIOx_BSRR : 端口位设置/清除寄存器

GPIOx_BRR  : 端口位清除寄存器

GPIOx_LCKR : 端口配置锁存寄存器


二,LED硬件连接:

这里写图片描述

LED0连接PB5引脚

LED1连接PE5引脚


三,LED跑马灯实现流程

1,使能GPIO时钟

     使用IO口前先要使能相应的GPIO时钟


2,初始化IO口 GPIO_Init()

     配置IO口的引脚工作方式(最大速度,输入/输出模式)


3,操作IO口输出高低电平

     控制响应IO口输出高电平或低电平


四,源码分析

1,GPIO初始化函数

stm32f10x_gpio.h头文件中找到GPIO_Init函数声明


void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);

1

stm32f10x_gpio.c中找到GPIO_Init函数的实现


/**

  * @brief  Initializes the GPIOx peripheral according to the specified

  *         parameters in the GPIO_InitStruct.

  * @param  GPIOx: where x can be (A..G) to select the GPIO peripheral.

  * @param  GPIO_InitStruct: pointer to a GPIO_InitTypeDef structure that

  *         contains the configuration information for the specified GPIO peripheral.

  * @retval None

  */

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;

  }

}


GPIO_Init函数两个入参为GPIO_TypeDef和GPIO_InitTypeDef两个结构体指针


GPIO_TypeDef参数:

stm32f10x.h中找到GPIO_TypeDef结构体声明


/**

  * @brief General Purpose I/O

  * 定义了GPIO的7个寄存器

  */

typedef struct

{

  __IO uint32_t CRL;    // 端口配置低寄存器

  __IO uint32_t CRH;    // 端口配置高寄存器

  __IO uint32_t IDR;    // 端口输入寄存器

  __IO uint32_t ODR;    // 端口输出寄存器

  __IO uint32_t BSRR;   // 端口位设置/清除寄存器

  __IO uint32_t BRR;    // 端口位清除寄存器

  __IO uint32_t LCKR;   // 端口配置锁存寄存器

} GPIO_TypeDef;


GPIO_TypeDef有效性判断:


/** @defgroup GPIO_Exported_Types

  * GPIOA->GPIOG

  */


#define IS_GPIO_ALL_PERIPH(PERIPH) (((PERIPH) == GPIOA) ||

                                    ((PERIPH) == GPIOB) ||

                                    ((PERIPH) == GPIOC) ||

                                    ((PERIPH) == GPIOD) ||

                                    ((PERIPH) == GPIOE) ||

                                    ((PERIPH) == GPIOF) ||

                                    ((PERIPH) == GPIOG))


GPIO_InitTypeDef参数:

stm32f10x_gpio.h中找到GPIO_InitTypeDef结构体声明


/**

  * @brief  GPIO Init structure definition

  * GPIO_InitTypeDef结构体-设置IO口,速度,工作模式

  */

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_InitStruct->GPIO_Speed有效性校验


/** 

  * @brief  Output Maximum frequency selection  

  */


typedef enum

  GPIO_Speed_10MHz = 1,

  GPIO_Speed_2MHz, 

  GPIO_Speed_50MHz

}GPIOSpeed_TypeDef;

#define IS_GPIO_SPEED(SPEED) (((SPEED) == GPIO_Speed_10MHz) || ((SPEED) == GPIO_Speed_2MHz) ||

                              ((SPEED) == GPIO_Speed_50MHz))


GPIO_InitStruct->GPIO_Mode有效性校验


/**

  * @brief  Configuration Mode enumeration

  * 八种输入/输出模式

  */


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;


#define IS_GPIO_MODE(MODE) (((MODE) == GPIO_Mode_AIN) ||  

                            ((MODE) == GPIO_Mode_IN_FLOATING) ||

                            ((MODE) == GPIO_Mode_IPD) ||

                            ((MODE) == GPIO_Mode_IPU) ||

                            ((MODE) == GPIO_Mode_Out_PP) ||

                            ((MODE) == GPIO_Mode_AF_OD) ||  

                            ((MODE) == GPIO_Mode_AF_PP))


GPIO_InitStruct->GPIO_Pin有效性校验


/** @defgroup GPIO_pins_define

  * GPIO_Pin_0->GPIO_Pin_15

  */

#define GPIO_Pin_0                 ((uint16_t)0x0001)  /*!< Pin 0 selected */

推荐阅读

史海拾趣

骅讯(Cmedia)公司的发展小趣事

为了进一步提升品牌影响力和市场竞争力,骅讯积极寻求与知名品牌的合作。通过与音频市场上的主要品牌建立合作关系,骅讯成功将其先进的音频技术应用于各种音频产品中,为消费者带来了更为优质的音频体验。这种合作模式不仅促进了骅讯技术的推广和应用,也为其带来了更为广阔的市场空间。

Gennum ( Semtech )公司的发展小趣事
在连接元件时,避免导线裸露部分相互接触或接触到金属物体,以防止短路。
Discrete Semiconductor Industries公司的发展小趣事

“绿源科技”是一家致力于绿色环保的Discrete Semiconductor Industries公司。该公司注重环保理念在产品研发和生产过程中的应用,积极推广绿色制造和循环经济。通过采用环保材料和工艺,绿源科技成功开发出了一系列低能耗、低污染的半导体产品。这些产品不仅满足了市场的需求,还为环境保护做出了积极贡献。同时,绿源科技还积极参与各种环保公益活动,推动行业向更加绿色、可持续的方向发展。

Cableform Inc公司的发展小趣事

进入21世纪,电子行业迎来了快速发展的黄金时期。为了适应市场需求的变化,Cableform Inc不断加大研发投入,致力于技术创新。公司成功开发出了一系列具有自主知识产权的电磁控制产品,涵盖了从直流电机控制到高精度磁铁控制等多个领域。这些技术创新不仅提升了公司的核心竞争力,也为客户提供了更加高效、可靠的解决方案。

正泰公司的发展小趣事

正泰公司始建于1984年,初期以低压电器业务为主。随着公司业务的不断拓展,正泰逐渐将业务范围扩展至智慧能源系统领域。在这一过程中,公司深入践行“产业化、科技化、国际化、数字化、平台化”战略举措,形成了“绿色能源、智能电气、智慧低碳”三大板块。正泰的低压电器产品长期保持国内领先地位,品牌认知度和客户粘性极强,为公司后续的发展奠定了坚实的基础。

General Diode Corp公司的发展小趣事
检查冷却系统是否正常运行,清理散热片上的灰尘和杂物;若冷却风扇损坏,则需更换新的风扇。

问答坊 | AI 解惑

PLC工程中注意的问题

西门子PLCS7200系列,当PLC断电处于RUN状态时,此时若PLC通电,则PLC会自动运行,这种情况可能会造成设备的损坏甚至现场人员的伤亡,所以应加以处理, 利用特殊位继电器SM0.3可以避免这种情况的发生, …

查看全部问答>

如何能编好单片机的程序(13)

2、书写Debug版和Release版的程序 ---------------- 程序在开发过程中必然有许多程序员加的调试信息。我见过许多项目组,当程序开发结束时,发动群众删除程序中的调试信息,何必呢?为什么不像VC++那样建立两个版本的目标代码?一个是debug版本的 ...…

查看全部问答>

BGA封装的元器件,如何扇出?

如下图: 这是BGA布线规则中的图,VIA 分别朝左上、左下、右上、右下方向打,但是为什么在内部打不了过孔啊?还有就是只要修改一个过孔的尺寸,整个的过孔都改了,这怎么回事啊? [ 本帖最后由 静若幽兰 于 2010-5-14 18:13 编辑 ]…

查看全部问答>

[笔记].在Quartus II中使用JTAG模式固化程序到EPCS中的方法.[Quartus II]

范例 流水灯 图1 流水灯范例 实现步骤 步骤1: 在Quartus II中,单击File->Convert Programming Files..。打开编程文件转换程序,如图2所示。   图2 编程文件转换程序界面 在此界面中。在Programming file&nb ...…

查看全部问答>

ZLG/FS文件系统读SD卡数据的OSFileRead函数怎么用

uint32 OSFileRead(void *Buf, uint32 Size, HANDLE Handle); Buf是保存读到的数据的指针,size是要读的字节数,Handle是文件句柄,返回值是实际读到的字节数。 我是这样用的: char *FileNameRead = \"A:\\\\toRead.txt\"; char ReadFileDat ...…

查看全部问答>

与或式化简

例:f’= f⊕起跳状态 + /Q6/Q5/Q4/Q3/Q2/Q1 = Q6⊕Q5⊕/Q6/Q5/Q4/Q3Q2Q1 + /Q6/Q5/Q4/Q3/Q2/Q1 = (Q6⊕Q5)/(/Q6/Q5/Q4/Q3Q2Q1) + / (Q6⊕Q5) /Q6/Q5/Q4/Q3Q2Q1 + /Q6/Q5/Q4/Q3/Q2/Q1 =(Q6/Q5+ /Q6Q5)(Q6+Q5+Q4+Q3+/Q2+/Q1) + (/Q6+ Q5) ( ...…

查看全部问答>

PDA串口丢数据问题

115200下,PC端给PDA发送数据,每100ms发送530bytes,有时会有数据丢失。 调用ClearCommError发现输入缓冲区中才60多个bytes,肯定还没满,状态返回CE_OVERRUN,硬件溢出了,天。有没有别的办法,除了改驱动,加流控。 读写我是有单独线程来完成 ...…

查看全部问答>

STM32的程序的烧写?运行?调试?调试脚本相关问题

STM32的启动方式了解 但是对其的调试方式和储存介质一直糊涂 目前知道 调试可以在 片内的FLASH 和 RAM来进行,不知我用FSMC外挂的SRAM 可以不? 我将一段代码COPY到外部SRAM ,然后跳过去,没好使,不知是跳的问题 还是跳过去不能运行? ...…

查看全部问答>

msp430 编译器

请问我见过一个程序,连启动代码也是自己写的,他是用什么样的编译器…

查看全部问答>