文章目录

  • 一、STM32F103系列芯片地址映射和寄存器映射原理
    • 1、什么是寄存器
    • 2、地址映射和寄存器映射
    • 3、寄存器地址查找
  • 二、GPIO端口初始化设置
    • 1、GPIO简介
    • 2、配置时钟
    • 3、输入输出端口设置
  • 三、点亮LED流水灯
    • 1、电路连接
    • 2、在keil中新建项目
    • 3、程序烧录
  • 四、STM32CubeMX生成代码使用HAL库点亮流水灯
    • 1、安装STM32
    • 2、安装HAL库
    • 3、在STM32CubeMX中新建项目
    • 4、Keil下替换代码
    • 5、程序烧录
    • 6、keil中调试
  • 五、总结

一、STM32F103系列芯片地址映射和寄存器映射原理

1、什么是寄存器

寄存器是CPU内部用来存放数据的一些小型存储区域,用来暂时存放参与运算的数据和运算结果。其实寄存器就是一种常用的时序逻辑电路,但这种时序逻辑电路只包含存储电路。寄存器的存储电路是由锁存器或触发器构成的,因为一个锁存器或触发器能存储1位二进制数,所以由N个锁存器或触发器可以构成N位寄存器。寄存器是中央处理器内的组成部分。寄存器是有限存储容量的高速存储部件,它们可用来暂存指令、数据和位址。

2、地址映射和寄存器映射

为了保证CPU执行指令时可正确访问存储单元,需将用户程序中的逻辑地址转换为运行时由机器直接寻址的物理地址,这一过程称为地址映射。

寄存器映射是在存储器映射的基础上进行的。存储器本身不具有地址信息,它的地址是由芯片厂商或用户分配,给存储器分配地址的过程就称为存储器映射。在存储器的区域单元中,每一个单元对应不同的功能,当我们控制这些单元时就可以驱动外设工作。我们可以找到每个单元的起始地址,然后通过 C 语言指针的操作方式来访问这些单元,如果每次都是通过这种地址的方式来访问,不仅不好记忆还容易出错,这时我们可以根据每个单元功能的不同,以功能为名给这个内存单元取一个别名,这个别名就是我们经常说的寄存器,这个给已经分配好地址的有特定功能的内存单元取别名的过程就叫寄存器映射。

3、寄存器地址查找

想要知道某个寄存器的地址需要查看数据手册,然后根据手册中提供的信息稍加计算,在STM32中给不同的寄存器分配了不同的地址。具体操作参考文章https://blog.csdn.net/geek_monkey/article/details/86291377

二、GPIO端口初始化设置

1、GPIO简介

GPIO 是通用输入输出端口的简称,是 STM32 可控制的引脚,STM32 芯片 的 GPIO引脚与外部设备连接起来,从而实现与外部通讯、控制以及数据采集的功能。
最基本的输出功能是由 STM32 控制引脚输出高、低电平,实现开关控制,如把 GPIO 引脚接入到 LED 灯,那就可以控制 LED 灯的亮灭,引脚接入到继电器或三极管,那就可以 通过继电器或三极管控制外部大功率电路的通断。
最基本的输入功能是检测外部输入电平,如把 GPIO 引脚连接到按键,通过电平高低区分按键是否被按下。

2、配置时钟

STM32的时钟是由内部或外部振荡器产生的“频率”,而被人们形象的称为“系统时钟”。最大为72MHz,换成周期T为:1/72MHz≈13.9ns。

STM32功能强大,同时带来的消耗也越严重,如果STM32不引入时钟的话,就像51一样外设全开,相应耗电就很严重了,为了解决这个问题,引入了时钟的概念,即使用哪个外设就给哪个外设时钟(频率),不使用的就关掉(不震荡)。此做法大大降低了功耗,续航持久。
STM32的时钟是有分工的,并且每类时钟的频率不一样,因为没必要所有的时钟都是最高频率,只要够用就行,所以在配置的时候可以配置时钟分频。

时钟控制的名字是RRC,属于AHB总线

通过查找手册找到APB2外设时钟使能寄存器,知道了偏移地址是0x18,从而可计算出APB2的地址是0x4002 1018。

知道了地址,首先对RRC寄存器进行定义,又,要使GPIOx端口时钟使能,可以把RCC_APB2ENR的位X赋值为1,就可以开启该端口的时钟。

#define RCC_APB2ENR (*(unsigned int *)0x40021018)
RCC_APB2ENR |= (1<<3); //GPIOB端口时钟使能
RCC_APB2ENR |= (1<<4); //GPIOC端口时钟使能
RCC_APB2ENR |= (1<<2); //GPIOA端口时钟使能

3、输入输出端口设置

GPIO是通用输入输出端口的简称,是STM32可控制的引脚,STM32芯片的GPIO引脚与外部设备连接起来,从而实现与外部通讯、控制以及数据采集的功能。STM32芯片的GPIO被分为很多组,每组有16个引脚。最基本的输出功能是由STM32控制引脚输出高、低电平,实现开关控制。最基本的输出功能是检测外部输入电平。GPIO的输入输出模式有以下几种:

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;

STM32中,用端口配置低寄存器(GPIOx_CRL)来配置引脚Px0-Px7, 用端口配置高寄存(GPIOx_CRH)来配置引脚Px8-Px15。实验中需要使用A5,B9,C14三个串行口,如下图,定义的寄存器GPIOx_CRH偏移地址是0x04,所以对于GPIOB来说就是0x4001 0c04。如果配置PB0-PB7,那么需要的寄存器是低位的寄存器GPIOB_CRL,它的地址是0x4001 0c00。


这里我们设置通用推挽输出模式,输出模式最大速度是50MHz,即0011,对应的16进制的值为3。

#define GPIOA_CRL    *((unsigned volatile int*)0x40010800)
#define GPIOA_ORD   *((unsigned volatile int*)0x4001080C)#define GPIOB_CRH  *((unsigned volatile int*)0x40010C04)
#define GPIOB_ORD   *((unsigned volatile int*)0x40010C0C)#define GPIOC_CRH  *((unsigned volatile int*)0x40011004)
#define GPIOC_ORD   *((unsigned volatile int*)0x4001100C)

其中GPIO_ORD寄存器的第一位设置为0则代表串行口输出低电平,ODR的第2位设置为1则代表P2口输出高电平。

三、点亮LED流水灯

1、电路连接

USB转串口的GND与STM32板子的GND相连,3v3与3v3相连,RXD与PA9相连,TXD与PA10连接,相应的引脚与LED灯连接。

2、在keil中新建项目

选择芯片STM32F103c8,输入如下代码:

#define GPIOB_BASE 0x40010C00BSRR:
//端口位设置/ 清除寄存器(GPIOx_BSRR),该寄存器其实是间接控制ODR寄存器
#define GPIOC_BASE 0x40011000
#define GPIOA_BASE 0x40010800#define RCC_APB2ENR (*(unsigned int *)0x40021018)#define GPIOA_CRL *((unsigned volatile int*)0x40010800)
#define GPIOA_ORD   *((unsigned volatile int*)0x4001080C)#define GPIOB_CRH  *((unsigned volatile int*)0x40010C04)
#define GPIOB_ORD   *((unsigned volatile int*)0x40010C0C)#define GPIOC_CRH  *((unsigned volatile int*)0x40011004)
#define GPIOC_ORD   *((unsigned volatile int*)0x4001100C)void SystemInit(void);
void Delay_ms(volatile  unsigned  int);
//时延函数
void Delay_ms( volatile  unsigned  int  t)
{unsigned  int  i;while(t--)for (i=0;i<800;i++);
}int main(){//GPIO端口时钟使能RCC_APB2ENR |= (1<<3); RCC_APB2ENR |= (1<<4); RCC_APB2ENR |= (1<<2); GPIOA_CRL&=0xFFFFFFF0;GPIOA_CRL|=0x00000002; //PA0推免输出   GPIOA_ORD|=1<<0;  //设置灯初始为亮   GPIOB_CRH&=0xFFFFFF0F;      GPIOB_CRH|=0x00000020;      //PB9GPIOB_ORD|=1<<9;     //设置初始灯为灭   GPIOC_CRH&=0xF0FFFFFF;  GPIOC_CRH|=0x03000000;      //PC15GPIOC_ORD|=0x1<<14; //设置初始灯为灭       while(1){   GPIOA_ORD=0x0<<0;     //PA0低电平Delay_ms(5000000);GPIOA_ORD=0x1<<0;       //PA0高电平Delay_ms(5000000);GPIOB_ORD=0x0<<9;       //PB9低电平Delay_ms(5000000);GPIOB_ORD=0x1<<9;       //PB9高电平Delay_ms(5000000);GPIOC_ORD=0x0<<14;      //PC15低电平Delay_ms(5000000);GPIOC_ORD=0x1<<14;     //PC15高电平Delay_ms(5000000);}}

勾选生成HEX文件后进行编译。

3、程序烧录

得到运行结果

四、STM32CubeMX生成代码使用HAL库点亮流水灯

1、安装STM32

在官网下载STM32CubeMX的安装包,然后解压进行安装。
双击打开安装包,点击next。


勾选协议,点击next进行下一步。

勾选第一个选项,然后点击next。

选择安装目录,进入下一步。

直接点击next。

点击done完成安装。

2、安装HAL库

打开安装好的软件,点击help,选择manage ebembedded software package:

然后选择自己自己需要安装的HAL库,点击install进行安装。

3、在STM32CubeMX中新建项目

回到主界面,点击start my project from MCU下面的蓝框新建项目。

在part name中选择自己选用的芯片并选中,在信息栏中选择具体芯片,然后点击start project。

点击system core,选择sys,在debug一栏中选择serial wire。

然后进行时钟的配置,点击sys上面的rcc,进入clock configuration,因为我们用的GPIO接口在APB2里面,这里可以看到APB2总线时钟由hse控制,同时勾选上PLLCLK。

将hse设为Crystal/Ceramic Resonator。

然后选择自己需要使用的引脚设置输出寄存器,这里选用了PA5、PB9、PC14三个,选择时设置为GPIO Output。

点击Project Manager,配置项目名和项目路径,然后将IDE一项改为MDK-ARM。

进入Code Generate界面,选择第二栏第一个选项,然后点击GENERATE CODE,选择open project,进入Keil。

4、Keil下替换代码

在project下选择application/user/core,打开main.c文件,找到主函数部分。

用下面的代码替换主函数内的代码

SystemClock_Config();//系统时钟初始化MX_GPIO_Init();//gpio初始化while (1){      HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_RESET);//PA5亮灯HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET);//PB9熄灯HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_SET);//PC14熄灯HAL_Delay(1000);//延时1sHAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET);//PA5熄灯HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);//PB9亮灯HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_SET);//PC14熄灯HAL_Delay(1000);//延时1sHAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET);//PA5熄灯HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET);//PB9熄灯HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_RESET);//PC14亮灯HAL_Delay(1000);//延时1s}

勾选生成HEX文件后进行编译。

5、程序烧录


可以看到流水灯成功实现。

6、keil中调试

在target中修改晶振频率。

然后进入debug,勾选选项,在DCM.DLL和TCM.DLL栏中填写自己所使用的芯片,确认。

进入调试界面,选择逻辑分析仪。

点击setup logic analyzer。

添加需要观察的引脚。

点击zoom下的in或者out设置grid的大小为1s,勾选后面两个选项设置起始线,观察到相关信息。

运行程序,得到波形图。
可以看到当引脚为低电平时,LED灯亮,高低电平转换的周期为1s。

五、总结

使用HAL库实现的确比在keil中自己写代码要简单一些,但是只有在熟练掌握使用keil的情况下,HAL库的便利才能更好的帮助我们完成项目。

参考文章
http://t.csdn.cn/1Shj8

GPIO端口初始化设置,STM32F103点亮LED流水灯过程相关推荐

  1. STM32F103C8T6以寄存器方式借助面包板搭建电路点亮LED流水灯详解

    文章目录 一.寄存器原理 1.什么是寄存器 2.如何访问寄存器 二.GPIO端口的初始化设置 1.时钟配置 (1)找到时钟使能寄存器映射基地址 (2)找到端口偏移地址以及对应端口所在位置 (3)使能对 ...

  2. STM32F03寄存器方式点亮LED流水灯

    STM32F03寄存器方式点亮LED流水灯 文章目录 STM32F03寄存器方式点亮LED流水灯 一.题目内容 二.STM32F03系列芯片的地址映射和寄存器映射映射原理:了解GPIO端口的初始化设置 ...

  3. 【stm32cubeMX】使用HAL库点亮LED流水灯

    stm32cubeMX使用HAL库点亮LED流水灯 1.安装STM32CubeMX 2.安装HAL库 3.新建项目 4.keil仿真调试 五.实现 六.参考资料 1.安装STM32CubeMX 官网下 ...

  4. STM32F103的映射的介绍、GPIO端口初始化设置和点流水灯详细操作

    文章目录 一.STM32F103的映射介绍 1.地址映射介绍 2.寄存器映射的介绍 二.GPIO端口的初始化设置 1.GIPO简介 2.时钟配置 3.输入输出模式设置 4.最大速率设置 三.实例--流 ...

  5. STM32F103寄存器方式点亮LED流水灯

    实验要求:以 STM32最小系统核心板(STM32F103C8T6)+面板板+3只红绿蓝LED 搭建电路,使用GPIOB.GPIOC.GPIOD这3个端口控制LED灯,轮流闪烁,间隔时长1秒.1)写出 ...

  6. 【嵌入式知识07】借助stm32CubeMX,使用STM32F103C8T6点亮LED流水灯

    本文目录 一.简述 二.STM32CubeMX简介 1.利用CubeMX新建工程点亮LED灯 1)前期准备 2)新建工程 2.界面讲解 3.配置引脚 4.时钟源配置 5.工程管理 三.点亮LED 1. ...

  7. 【嵌入式08】STM32F103C8T6寄存器方式借助面包板点亮LED流水灯详解

    文章目录 一.题目简述 二.简述:初始化GPIO,点亮LED灯 三.工程文件模板的建立 四.使用寄存器点亮LED灯--代码部分 1.硬件连接设计 2.打开之前建立的工程模板 3.代码编写 4.硬件连接 ...

  8. stm32cubeMX使用HAL库点亮LED流水灯

    系列文章目录 文章目录 系列文章目录 一.实验工具 二.STM32CubeMX生成代码使用HAL库点亮流水灯 1.安装STM32CubeMX 2.安装HAL库 3.新建项目 4.keil仿真调试 三. ...

  9. 点亮led流水灯c语言程序,用数组的指针控制LED流水灯--C语言编程

    #include/************************************************* 函数功能:延时约150ms (3*200*250=150 000μs=150ms ...

最新文章

  1. MySQL查询结果复制到新表(更新、插入)
  2. 7.测试hadoop安装成功与否,并跑mapreduce实例
  3. 如何在WPF中通过XAML代码创建菜单项
  4. HDU4622(后缀自动机)
  5. 旅游是开车自驾好还是坐火车好?能否从各个方面解答一下?
  6. [原创]windows下unix2dos dos2unix 文本文件批量转换工具
  7. 根据成交量变化寻找黑马
  8. Git初学者:权威的实用指南
  9. html5移动web开发黑马掌上商城_月入35k大佬总结:web前端必须学习的内容(附全套前端教程)...
  10. 浏览器URL中 encodeURIComponent()加密和decodeURIComponent()解码
  11. 如何借助log4j把日志写入数据库中
  12. html选择日期的组件,怎样实现一个datePicker(日期选择)组件
  13. PHP中的ereg()与eregi()
  14. 网站seo优化到底该怎么做?
  15. 你参加了无数 “打卡” 群,为什么收获甚微。。。
  16. 点击网页弹出窗口的js代码
  17. [Erlang危机](3.1)常见过载情景
  18. 少儿编程入门应该从机器人Scratch编程开始
  19. 旭元数艺:科技创新引领文化潮流
  20. 【算法分析】Lucas–Kanade光流算法

热门文章

  1. 壳 查壳 去壳 加壳的基本原理
  2. Java POI合并多个word文件
  3. 物联网系列之WIFI模块ESP8266一介绍
  4. 让宝妈当“团长”卖菜给街坊,社区团购会诞生下一个拼多多吗?
  5. 三级指标 主成分分析_(完整版)主成分分析法的步骤和原理
  6. office PPT插件
  7. 不想将就,所以竭尽所能。
  8. 菜鸟学示波器,示波器视频教程,ZLG示波器学习资料
  9. SpringBoot整合dubbo详解(阿里官方dubbo-spring-boot-starter)
  10. 报错:UnicodeDecodeError:: ‘utf-8‘ codec can‘t decode byte 0xc8 in position 0: invalid contin