0

0

0

修罗

站点介绍

只有了解事实才能获得真正的自由

STM32F103ZE点亮LED灯(二)

修罗 2025-08-18 907 5条评论 stm32

首页 / 正文

STM32F103ZE点亮LED灯(二)

1. 宏定义优化

ST公司提前把每个外设寄存器的地址提前给我们用宏定义的方式定义在stm32f10x.h文件中,我们只需要直接使用即可。

  • 外设基址定义, 比如:
#define PERIPH_BASE           ((uint32_t)0x40000000)
#define APB2PERIPH_BASE       (PERIPH_BASE + 0x10000)
#define GPIOA_BASE            (APB2PERIPH_BASE + 0x0800)
#define RCC_BASE              (AHBPERIPH_BASE + 0x1000)
  • 寄存器结构体映射, 例如 GPIO:
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;

#define GPIOA               ((GPIO_TypeDef *) GPIOA_BASE)

这样我们就可以写:

GPIOA->ODR |= (1 << 0);   // 设置 PA0 输出高电平
  • 位定义(宏), 比如 RCC 里的时钟使能位:
#define RCC_APB2ENR_IOPAEN   ((uint32_t)0x00000004)

这样就不用记住 0x40021018 了。

  • 因此,之前的点LED1代码可以修改为:
#include "stm32f10x.h"

int main(void)
{
    RCC->APB2ENR = 4;
    GPIOA->CRL = 3;
    GPIOA->ODR = 0xfffe;
    while (1)
    {
    }
}

2. 特定位修改优化

​ 在STM32中一个寄存器是32位的,我们在编写代码的时候只是需要给某位或某几位赋值。由于STM32不支持位寻址,所以在前面的操作中,我们其实是修改了所有位。这是非常不合理的,也许其他位在其他地方有赋值,我们重新赋值势必会覆盖了其他值,带来的后果也是很严重的。

​ 把代码进化为下面的形式:

#include "stm32f10x.h"

int main(void)
{
    /* 开启GPIOA的时钟 第2位置1*/
    RCC->APB2ENR |= (0x1 << 2);

    /* GPIOA_CRL的最后4位置 0011 */
    GPIOA->CRL &= ~(0x1 << 3);
    GPIOA->CRL &= ~(0x1 << 2);
    GPIOA->CRL |= 0x1 << 1;
    GPIOA->CRL |= 0x1 << 0;

    /* GPIOA_ODR的第0位置0 */
    GPIOA->ODR &= ~(0x1 << 0);

    while (1)
    {
    }
}

3. 使用宏定义中移位后的值

​ 上次优化中,我们是给寄存器“或等”和“与等”了一些值,这些值都是通过相应的“移位”操作得到的。比如要操作第2位,就需要把0x1左移2位得到。我们需要查找手册才能知道要移位几。也是很不方便。

​ 其实ST公司也把我们需要的移位后的值给提前计算好了,用宏定义的方式供我们使用。

​ 比如前面的开启时钟,已经定义了好了这个值。正好就是1<<2

#define  RCC_APB2ENR_IOPAEN                  ((uint32_t)0x00000004)

​ 利用ST公司提前预定义的这些值,可以进一步进化代码为下面的形式:

#include "stm32f10x.h"

int main(void)
{
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;

    GPIOA->CRL &= ~GPIO_CRL_CNF0_1;
    GPIOA->CRL &= ~GPIO_CRL_CNF0_0;
    GPIOA->CRL |= GPIO_CRL_MODE0_1;
    GPIOA->CRL |= GPIO_CRL_MODE0_0;

    GPIOA->ODR &= ~GPIO_ODR_ODR0;

    while (1)
    {
    }
}

评论(5)

  1. 1 游客 2025-09-01 11:26 回复

    1

  2. 1 游客 2025-09-01 12:04 回复

    1

  3. @@uQJVd 游客 2025-09-01 12:05 回复

    1

  4. 1 游客 2025-09-01 12:07 回复

    1

  5. 1 游客 2025-09-01 12:08 回复

    1


最新评论

  • https://www.studyglobus.com/author/carroll34a5552/

    Ценники на вывоз мусора сейчас космос, любые лайфхаки по экономии в тему.

  • Richardgrold

    1xbet onlayn kazino platforması ilə vaxtınızı daha səmərəli və maraqlı keçirin. Saytın canlı kazino bölməsi istifadəçilərə fərqli bir dünya təklif edir. Burada canlı dilerli kazino oyunlarının hər bir növünü sınaqdan keçirə bilərsiniz. Krupyelərin peşəkarlığı oyunun dinamikasını və marağını artırır. Müntəzəm olaraq yenilənən oyun siyahısı cansıxıcılığa yol vermir. Hesabınızı artırmaq üçün onlarla fərqli və etibarlı üsul mövcuddur. Qazanılan pullar cəmi bir neçə dəqiqə ərzində şəxsi hesabınıza köçürülür. Aktiv fəaliyyətinizə görə fərdi bonuslar və hədiyyələr qazana bilərsiniz. Dəstək xidməti həm çat, həm də e-poçt vasitəsilə kömək göstərir. 1xbet ailəsinə qoşulun və böyük uduşlar üçün ilk addımı atın. onlayn kazino

  • 砂岩白丘

    我一直梦想, 看到你们相册那样的地方。真棒。

  • 城市地標

    我喜欢, 这里分享真实经验。你的项目 就是 属于这里的。请继续。

  • 宗教地標

    我热爱这样的想法, 去那么多国家。真的很鼓舞。

  • 觀景高地

    能感受到热爱。继续保持 感受。

  • 最佳季節

    我关注这样的资源, 写得很实在。你的网站 就是 属于这里的。加油。

  • 1

    1

  • 1

    1

  • -1' OR 2+158-158-1=0+0+0+1 or 'TKCTZnRa'='

    1

日历

2026年07月

   1234
567891011
12131415161718
19202122232425
262728293031 

文章目录

推荐关键字: Linux webpack js 算法 MongoDB laravel JAVA jquery javase redis