导语: stm32系列的芯片比起入门级的AT89C51、STC系列芯片,有更强大的性能以及资源。但在编程上也有着或大或小的改变,使得初学者总会面临一些麻烦,下面我来总结下自己初学时的经验。

  1. 首先在keil软件的初始化上,我们需要选择自己对应的型号。
  2. 接下来就是对工程的属性设置,基础的设置网上有很多视频,不知道的童鞋可以去搜索某火的视频,非常的全面。
    但是在这里我要提醒下,在对工程的属性设置时记得将target中的 use Micro LIB 选项勾选住。否则在下载程序后,芯片是不会做出反应的。

我翻阅过资料,但是 始终未能寻找到我想要的答案。( 希望知道的大哥能告知下o( ̄▽ ̄)ブ
只能知道他是一个c的缺省库,用于printf这样的函数转换。

  1. 其次是在新的工程当中要添加一个启动文件,这个汇编文件是startup_stm32f429_439xx.s
    对于这个文件的作用不做详细的解释,具体可以翻阅 某火的资料。简单地说他类似于系统的boot文件,用来启动(初始化)内核的设置。其中值得注意的是他复位后调用了初始化系统时钟的函数,这个函数被存放在文件 system_stm32f4xx.c 中,若创建工程时没有添加该文件,需要自行建立一个子函数来防止编译器报错。

4.再就是将所有的外设函数都添加进工程中

5.最后添加中断函数的存放文件 stm32f4xx_it.c 以及自己创建的main.c 文件。

进行到这里,就可以开始对寄存器操作赋值来控制芯片的led灯。首先看原理图:

这里我们可以看到LED灯属于共阳接法,都挂载再GPIOH(通用输入\输出端口)上,为了能够点亮RLED,需要将PH10置零。值得注意的是,与51等芯片不同的是端口的设置已经被挂载到了AHB1上,所以为了能让数据正常的传输到GPIO上,首先要初始化AHB1总线时钟。

而RCC的起始地址为 0X40023800 ,
所以 具体的实现语句是 *(unsigned int *)0X40023830 |=(1<<7) ; 目的是为了打开GPIOH的总线时钟
接着再设置GPIO的模式、输出类型、输出速度、上拉或下拉以及输入输出的数据
由于GPIO默认为输入模式,推挽输出、低速运行、不进行上拉下拉操作以及输出低电平
所以这里只需要设置模式
具体实现语句是 *(unsigned int * )0X40021C00 |=(1<<20);目的是将模式调整为输出。
至此,我们只需要编译并下载程序,RLED灯就能被点亮。这是对寄存器直接进行操作,下面介绍利用库函数来操作寄存器。
关于RCC时钟方面,后面会有专门的一章,所以先不进行详细的讲解,主要是注释GPIO的库函数。

#define GPIOH_LED 0X00000080
#define RLED    0X0200int mai(void)
{GPIO_InitTypeDef* GPIO_InitStruct
//打开AHB1时钟
RCC_AHB1PeriphClockCmd(GPIOH_LED, ENABLE);   //定义初始化结构体,由于我们只需要初始化模式和引脚且初始化函数中并没有对其他设置进行了防错检查,所以可以不设置。
GPIO_InitStruct->GPIO_Pin = RLED;
GPIO_InitStruct->GPIO_Mode = GPIO_Mode_OUT;//设置GPIOH的模式为输出
GPIO_Init(GPIOH,GPIO_InitStruct);
}

以上仅仅用到了GPIO的初始化函数,在最后我们对GPIO的库函数中挑选常用的函数进行分析:

/*  Function used to set the GPIO configuration to the default reset state ****/
void GPIO_DeInit(GPIO_TypeDef* GPIOx);  //设置GPIOx的AHB1时钟总线为默认状态(不使能) 由于内部程序较为简单不做详细分析/* Initialization and Configuration functions *********************************/
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);//GPIO初始化函数,需要提供初始化结构体和对应GPIO
void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct);//设置所有GPIO为默认状态(输入、20MHz、推挽输出、无上拉下拉  )
void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);//配置锁定函数/* GPIO Read and Write functions **********************************************/
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);//读取指定GPIO中的引脚的当前输入状态
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);//读取指定GPIO的所有引脚输入状态
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);//读取指定GPIO中的引脚的当前输出状态
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);//读取指定GPIO的所有引脚输出状态
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);//对指定的GPIO引脚的输出值进行置位
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);//对指定的GPIO引脚的输出值进行复位
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);//对指定的GPIO进行直接复位或置位
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);//对指定的GPIO的ODR进行写入数据
void GPIO_ToggleBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);//翻转指定GPIO引脚/* GPIO Alternate functions configuration function ****************************/
void GPIO_PinAFConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_PinSource, uint8_t GPIO_AF);//复位功能配置

这里挑出值得学习的代码段进行分析

#define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))#define GPIO_PinSource0            ((uint8_t)0x00)
//这里省略其余的赋值
#define GPIO_PinSource15           ((uint8_t)0x0F)#define IS_GPIO_ALL_PERIPH(PERIPH) (((PERIPH) == GPIOA) || \((PERIPH) == GPIOB) || \((PERIPH) == GPIOC) || \((PERIPH) == GPIOD) || \((PERIPH) == GPIOE) || \((PERIPH) == GPIOF) || \((PERIPH) == GPIOG) || \((PERIPH) == GPIOH) || \((PERIPH) == GPIOI) || \((PERIPH) == GPIOJ) || \((PERIPH) == GPIOK))void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
{uint32_t pinpos = 0x00, pos = 0x00 , currentpin = 0x00;/* Check the parameters */assert_param(IS_GPIO_ALL_PERIPH(GPIOx));  //注释1        assert_param(IS_GPIO_PIN(GPIO_InitStruct->GPIO_Pin));assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode));assert_param(IS_GPIO_PUPD(GPIO_InitStruct->GPIO_PuPd));/* ------------------------- Configure the port pins ---------------- *//*-- GPIO Mode Configuration --*/for (pinpos = 0x00; pinpos < 0x10; pinpos++) //注释2{pos = ((uint32_t)0x01) << pinpos;/* Get the port pins position */currentpin = (GPIO_InitStruct->GPIO_Pin) & pos;if (currentpin == pos){GPIOx->MODER  &= ~(GPIO_MODER_MODER0 << (pinpos * 2));GPIOx->MODER |= (((uint32_t)GPIO_InitStruct->GPIO_Mode) << (pinpos * 2));if ((GPIO_InitStruct->GPIO_Mode == GPIO_Mode_OUT) || (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_AF)){/* Check Speed mode parameters */assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed));/* Speed mode configuration */GPIOx->OSPEEDR &= ~(GPIO_OSPEEDER_OSPEEDR0 << (pinpos * 2));GPIOx->OSPEEDR |= ((uint32_t)(GPIO_InitStruct->GPIO_Speed) << (pinpos * 2));/* Check Output mode parameters */assert_param(IS_GPIO_OTYPE(GPIO_InitStruct->GPIO_OType));/* Output mode configuration*/GPIOx->OTYPER  &= ~((GPIO_OTYPER_OT_0) << ((uint16_t)pinpos)) ;GPIOx->OTYPER |= (uint16_t)(((uint16_t)GPIO_InitStruct->GPIO_OType) << ((uint16_t)pinpos));}/* Pull-up Pull down resistor configuration*/GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPDR0 << ((uint16_t)pinpos * 2));GPIOx->PUPDR |= (((uint32_t)GPIO_InitStruct->GPIO_PuPd) << (pinpos * 2));}}
}

注释1: 库函数中常用IS_XXXX_XXX函数来防止函数调用时参数出现错误,来自宏定义,起到判断参数是否在规定范围内的作用,返回布尔值。返回的参数将被函数assert_param()调用,实际上是想要实现当参数错误时,需要进行报错提示,但是库函数中并没有实现报错的功能,所以需要自行建立。即建立 函数 assert_failed(),若使用该功能,需要在魔术棒的c/c++中定义USE_FULL_ASSERT

注释2: 从函数体的结构来看,该函数支持或运算,即可以一次性对多个引脚进行操作。为了能够统一化操作,将GPIOx_Pinsource 定义为16位的数值,对应的引脚x的数值对应2^x,因此再调用函数时需要配套的算法进行判断。
这里需要和复用功能配置函数区别, 复用功能函数不支持多引脚同时开启功能。接下来对代码进行分析:

void GPIO_PinAFConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_PinSource, uint8_t GPIO_AF)
{uint32_t temp = 0x00;uint32_t temp_2 = 0x00;/* Check the parameters */assert_param(IS_GPIO_ALL_PERIPH(GPIOx));assert_param(IS_GPIO_PIN_SOURCE(GPIO_PinSource));assert_param(IS_GPIO_AF(GPIO_AF));temp = ((uint32_t)(GPIO_AF) << ((uint32_t)((uint32_t)GPIO_PinSource & (uint32_t)0x07) * 4)) ;GPIOx->AFR[GPIO_PinSource >> 0x03] &= ~((uint32_t)0xF << ((uint32_t)((uint32_t)GPIO_PinSource & (uint32_t)0x07) * 4)) ;temp_2 = GPIOx->AFR[GPIO_PinSource >> 0x03] | temp;GPIOx->AFR[GPIO_PinSource >> 0x03] = temp_2;
}

显而易见,在进行相关引脚功能配置时,他没有和初始化函数一样,用for语句进行逐一判断。所以使用只能逐次对单一GPIO使用该函数。

结语:

比较初级的单片机,STM32的GPIO功能强化很多,也将很多功能整合了进去。对于GPIO的使用,有如下步骤:
1、配置相应GPIO所挂载的时钟总线。
2、设置GPIO初始化结构体,并使用函数配置(若使用了复用功能,要注意需要再调用复用功能配置函数)

STM32入门之点亮LED灯相关推荐

  1. 最小系统板 STM32入门,点亮 LED 灯(STM32F103C6T6)

    Hello, I'm Shendi 最近开整单片机,这里记录一下 我目前配置,最小系统板 STM32F103C6T6,ST-LINK V2 最小系统板,通电后PWR灯会亮,ST-LINK插上电脑后也会 ...

  2. 【STM32学习笔记-点亮LED灯】

    STM32学习笔记-点亮LED灯 文章目录 STM32学习笔记-点亮LED灯 一.原理图分析 二.代码分析 1.mian函数 2.led.c函数 3.led.h函数 4.函数文件整理 5.LED_In ...

  3. STM32之初学点亮led灯

    板子使用的是洋桃电子的开发板,核心板上面的两个led灯连接的是PB0和PB1两个引脚,如下图所示 可以看到这个电路图,如果将PB0的引脚的信号设置为高电平,则电流会从LED灯的左边流向右边,即点亮LE ...

  4. 基于STM32F103入门1——点亮LED灯

    今天学习了STM32固件库点灯程序 点灯也可以玩过很多好玩的东西,在这里做一下总结. STM32点灯程序合集 1:新建固件库工程文件 1.1找到一个固件库模板 1.2:打开KEIL5新建工程 1.3: ...

  5. 野火霸道STM32开发板点亮LED灯课后作业

    #include "stm32f10x.h" int main(void) {     //打开GPIOB端口的时钟     *(unsigned int *)0x40021018 ...

  6. STM32汇编语言点亮led灯

    STM32汇编语言点亮led灯 首先,这篇blog的主要内容是在C语言中调用汇编语言写的函数.即在我们常用的标准库函数工程中,对外设(这里指led)使用汇编语言完成相关的寄存器配置和控制. 一.背景 ...

  7. 单片机stm32LED流水灯C语言,STM32单片机入门 篇二:单片机编程:从点亮LED灯开始(二)...

    STM32单片机入门 篇二:单片机编程:从点亮LED灯开始(二) 2019-04-26 13:21:48 19点赞 73收藏 19评论 写在前面的话:本篇是承接上一篇文章,属于小白向. 没看过的朋友点 ...

  8. 【STM32】STM32CubeMX教程二--基本使用(新建工程点亮LED灯)

    前言 在配置好CubeMX之后,就是新建工程的开始了,那么首先我们需要一些准备,本片博客我们会很详细的介绍STM32CubeMx的基本使用和如何创建一个新的工程并且点亮LED灯  面向初学者   如果 ...

  9. 采用STM32外部中断模式控制LED灯亮灭

    文章目录 实验工具 一.STMCube配置项目 1.配置引脚 2.配置EXIT 3.配置SYS 4.配置GPIO 5.创建代码 二.使用KEil配置代码 1.打开生成的项目,找到stm32f1xx_i ...

最新文章

  1. bp神经网络代码_机器学习(周志华)课后习题——第五章——神经网络
  2. owdcloud mysql_MySQL在Ubuntu远程配置
  3. Acwing 271. 杨老师的照相排列
  4. vue 环境的搭建及初始化项目
  5. jquery获得指定元素坐标的方法
  6. Java 多线程:线程池实现原理
  7. sonarqube如何使用自定义规则插件
  8. 凹函数和凸函数,Concave Function和Convex Function
  9. 项目经理OA选型 Teambition、Worktile、iQuicker、Tower
  10. 风格迁移 I2I 论文阅读笔记——U-GAT-IT,动漫风格生成
  11. 酷派t2co1怎么升Android5,而且双清不了怎么办Coolpad725?酷 – 手机爱问
  12. matlab code svm,SVM matlab 代码详解说明
  13. unity 双指触控(以及多指触摸的代码原理分析)
  14. 神经网络中epoch、batch、batchsize
  15. 技术人员的赚钱之道-1:开篇
  16. Potplayer制作视频缩略图的方法
  17. Excel VBA 锁定特定单元格
  18. 如何打印计算机准考证书,一页纸打印多个准考证
  19. 中国的工业自动化已在全球居于前列位置,领先于美国
  20. Qt实现ping命令检测主机是否在线

热门文章

  1. 按键精灵获取系统时间定时点击
  2. 亚信23年笔试(40道)
  3. 几何公差之基准的定义和3-2-1原则
  4. android系统读写速度,Android 通过adb测试机器读写速度(rk)
  5. 第43届金马颁奖礼结束,郭富城连庄金马影帝创历史!
  6. 联想E590 无线网卡不能使用的问题
  7. 使用 Fragment 处理 onActivityResult
  8. STC15系列单片机-PWM模块
  9. 当幻想和现实面对的时候,总是很痛苦,要么你被痛苦击倒,要么你把痛苦踩在脚下。
  10. QQ密码框防键盘记录的研究笔记