STM32学习笔记——1

GPIO的初始化(以LED为例)

bsp_led.c文件:

GPIO_InitTypeDef GPIO_InitStructure;

/*开启LED相关的GPIO外设时钟*/

RCC_APB2PeriphClockCmd( LED1_GPIO_CLK | LED2_GPIO_CLK | LED3_GPIO_CLK, ENABLE);

/*选择要控制的GPIO引脚*/

GPIO_InitStructure.GPIO_Pin = LED1_GPIO_PIN;

/*设置引脚模式为通用推挽输出*/

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   

/*设置引脚速率为50MHz */   

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

/*调用库函数,初始化GPIO*/

GPIO_Init(LED1_GPIO_PORT, &GPIO_InitStructure);

/*选择要控制的GPIO引脚*/

GPIO_InitStructure.GPIO_Pin = LED2_GPIO_PIN;

/*调用库函数,初始化GPIO*/

GPIO_Init(LED2_GPIO_PORT, &GPIO_InitStructure);

/*选择要控制的GPIO引脚*/

GPIO_InitStructure.GPIO_Pin = LED3_GPIO_PIN;

/*调用库函数,初始化GPIOF*/

GPIO_Init(LED3_GPIO_PORT, &GPIO_InitStructure);

bsp_led.h文件中预先宏定义增加可读性,方便修改

#define LED1_GPIO_PORT   GPIOB               /* GPIO端口 */

#define LED1_GPIO_CLK RCC_APB2Periph_GPIOB /* GPIO端口时钟 */

#define LED1_GPIO_PIN GPIO_Pin_5         /* 连接到SCL时钟线的GPIO */

初始化结构体参数

stm32f103x_gpio.h文件中

typedef struct

{

  uint16_t GPIO_Pin;            

  GPIOSpeed_TypeDef GPIO_Speed;

  GPIOMode_TypeDef GPIO_Mode;   

}GPIO_InitTypeDef;

初始化结构体中有三个成员。其中GPIO_Speed和GPIO_Mode是枚举变量

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;

输出的四种模式配置时第四位都为1

typedef enum

{

  GPIO_Speed_10MHz = 1,

  GPIO_Speed_2MHz,       //枚举常量2

  GPIO_Speed_50MHz      //枚举常量3

}GPIOSpeed_TypeDef;

GPIO_Pin有以下设置值:

 16位整型,每一个端口的宏定义仅有一位是1,其他位都是0。

GPIOx->GPIO_Pin = GPIO_Pin_x

配置寄存器

位操作方式修改寄存器:

GPIO->CRL &=~(uint32_t)(1111<<4*3);#清空Pin3的四个控制位

GPIO->CRL |=~(uint32_t)(0011<<4*3);#配置Pin3的四个控制位

GPIO->CRL &=~(uint32_t)(1111<<4*4);#清空Pin4的四个控制位

GPIO->CRL |=~(uint32_t)(0011<<4*4);#配置Pin4的四个控制位

配置GPIOx低8位引脚的寄存器GPIOx_CRL。

四位一组共有八组,所以在清空Pin3的控制位时要使用(1111<<4*3) (乘4)

 

 配置MODEy[1:0]:

00:输入模式(复位后的状态)

01:输出模式,最大速度10MHz

10:输出模式,最大速度2MHz

11:输出模式,最大速度50MHz

配置CNFy[1:0]:
if (MODEy[1:0] == 00)

00:模拟输入模式

01:浮空输入模式

10:上拉/下拉输入模式

11:保留

else

00:通用推挽输出模式

01:通用开漏输出模式

10:复用功能推挽输出模式

11:复用功能开漏输出模式

理解ST库的本质:

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);

  #将GPIO_Mode的低4位暂存

  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; #备份原CRL寄存器中的值

    for (pinpos = 0x00; pinpos < 0x08; pinpos++)

    {

      pos = ((uint32_t)0x01) << pinpos; #1左移0-7位

      /* Get the port pins position */

      currentpin = (GPIO_InitStruct->GPIO_Pin) & pos;

      if (currentpin == pos) 

      {

#表示pos引脚需要配置

        pos = pinpos << 2; #pinpos的值从0-7

        /* Clear the corresponding low control register bits */

        pinmask = ((uint32_t)0x0F) << pos; #把控制这个引脚的4个寄存器位清零

        tmpreg &= ~pinmask;#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; #将前面处理后的暂存值写入到CRL寄存器之中

  }

/*---------------------------- 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()的意义在于将用户输入的三个参数转换成

GPIOx->CRL = 0x44333444; #某一个32位整数来配置寄存器

GPIO地址映射

stm32f103x.h文件中

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;

 

 

 

  

Cortex-M3的地址映射:Cortex-M3y有32根地址线,所以它的寻址空间大小为4GB。ARM公司设计时,预先把这4GB的寻址空间大致的分配好了。它把从0x40000000至0x5FFFFFFF(512MB)的地址分配给片上外设。通过把片上外设的寄存器映射到这个地址区,就可以简单地以访问内存地方式,访问这些外设的寄存器,从而控制外设的工作。这样,片上外设可以使用C语言来操作。

 

类比C51单片机汇编语言:

MOV A, #X ;数据X->A

MOV DPTR, #7FFFH ;指向DAC0832(x),7FFFH也就成为了DAC0832(x)的地址

MOVX @DPTR, A ;该段代码使芯片引脚输出(01111111)B,使能外设

stm32f10x.h这个文件中的重要内容就是把STM32的所有寄存器进行地址映射。如同51单片机的<reg52.h>头文件一样,stm32f10x.h像一个大表格,我们在使用的时候就是通过宏定义进行类似查表操作,

#define GPIO_BASE (APB2PERIPH_BASE + 0x1000)

#define APB2PERIPH (PERIPH_BASE + 0x10000)

#define PERIPH_BASE ((uint32_t)0x40000000)

PERIPH_BASE的宏展开为0x40000000就是Cortex-M3分配给片上外设512MB寻址空间中的第一个地址,所以中文意思就是外设基地址。

APB2PERIPH_BASE的宏展开使外设基地址再加上偏移地址0x10000,即为0x40010000。STM32芯片有AHB总线、APB2总线和APB1总线,挂载在这些总线上的外设有特定的地址范围。

像GPIO、串口1、ADC及部分定时器是挂载在APB2的总线上,挂载到APB2总线上的外设地址空间从0x40010000至0x40013FFF地址。这里的第一个地址,也就是0x40010000,称为APB2PERIPH_BASE(APB2总线外设基地址)。

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据引用内容,STM32C8T6是一款通用增强型的48脚单片机,具有64K闪存和LQFP封装。它适用于工业级温度范围-40~85度。下面是一些关于STM32C8T6学习笔记: 1. 学习资料:可以从ST官方网站下载STM32C8T6的数据手册和参考手册,这些手册包含了该单片机的详细信息和使用方法。 2. 开发环境:为了开始学习STM32C8T6,你需要安装相应的开发环境。ST官方提供了一款免费的集成开发环境(IDE)——STM32CubeIDE,它可以帮助你进行代码编写、调试和下载。 3. 编程语言:STM32C8T6可以使用多种编程语言进行开发,包括C语言和汇编语言。C语言是最常用的编程语言,它可以通过STM32CubeIDE进行编写和调试。 4. 引脚配置:在使用STM32C8T6之前,你需要了解每个引脚的功能和配置。数据手册中有一张引脚功能表,可以帮助你了解每个引脚的用途和配置方法。 5. 时钟配置:STM32C8T6具有多个时钟源和时钟分频器,你需要根据自己的需求配置正确的时钟。时钟配置对于外设的正常工作非常重要。 6. 中断和定时器:STM32C8T6支持中断和定时器功能,这些功能可以帮助你实现各种任务和功能。你可以通过配置中断和定时器来实现外设的响应和定时操作。 7. 外设驱动:STM32C8T6具有丰富的外设,包括GPIO、UART、SPI、I2C等。你可以根据自己的需求选择合适的外设,并学习如何配置和驱动这些外设。 8. 调试和下载:在开发过程中,你可以使用STM32CubeIDE提供的调试功能来调试你的代码。一旦代码调试完成,你可以使用ST-Link或其他下载器将代码下载到STM32C8T6上运行。 希望以上笔记对你学习STM32C8T6有所帮助!如果你有任何进一步的问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值