STM32第一集——跑马灯实验(库函数)

文章目录

前言

一、基础知识

二、实验实现

1.通过固件库设置GPIO的相关参数和输出

2.硬件设计

3.软件设计

led.c

led.h

main.c

总结


 


前言

开启小萌新的stm32学习之旅~

正点原子精英板和配套视频


一、基础知识

STM32最小系统:

  • 供电
  • 复位
  • 时钟:外部晶振(2个)
  • Boot启动模式选择
  • 下载电路(串口/JTAG/SWD)
  • 后备电池

一共有7组GPIO:GPIOA——GPIOG;一组GPIO有16个IO口

STM32的IO口可由软件配置成8种模式

  • 输入浮空
  • 输入上拉
  • 输入下拉
  • 模拟输入
  • 开漏输出
  • 推挽输出
  • 推挽式复用功能
  • 开漏复用功能

每个IO端口有7个寄存器来控制

  • CRL(配置模式的32位的端口配置寄存器,低配置)
  • CRH(配置模式的32位的端口配置寄存器,高配置)
  • IDR(32位数据寄存器)只读
  • ODR(32位数据寄存器)可读可写
  • BSRR(32位的置位/复位寄存器)
  • BRR(16位的复位寄存器)
  • LCKR(32位的锁存寄存器)

CRL和CRH控制着每个IO口的模式及输出速率,CRL控制着每组IO端口低八位的模式,CRH控制高八位

STM32第一集——跑马灯实验(库函数)_第1张图片

STM32第一集——跑马灯实验(库函数)_第2张图片

 

二、实验实现

1.通过固件库设置GPIO的相关参数和输出

在固件库开发中,操作寄存器CRH和CRL来配置IO口的模式和速度是通过GPIO初始化函数完成(GPIO相关的函数和定义在固件库文件stm32f10_gpio.c和头文件stm32f10x_gpio.h文件中):

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

  • 第一个参数GPIO_TypeDef* GPIOx,用来指定GPIO,取值范围为GPIOA~GPIOG
  • 第二个参数GPIO_InitTypeDef* GPIO_InitStruct,为初始化参数结构体指针,结构体类型为 GPIO_InitTypeDef,结构体的定义(go to definition)为

typedef struct

{ uint16_t GPIO_Pin; GPIOSpeed_TypeDef GPIO_Speed; GPIOMode_TypeDef GPIO_Mode; }GPIO_InitTypeDef;

GPIO_Pin端口;

GPIO_Speed速度:

typedef enum

{ GPIO_Speed_10MHz = 1, GPIO_Speed_2MHz, GPIO_Speed_50MHz }GPIOSpeed_TypeDef;

GPIO_Mode输入输出模式(8种):

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;

  • GPIO初始化示例

GPIO_InitTypeDef     GPIO_InitStructure;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED0-->PB.5 端口配置

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度 50MHz

GPIO_Init(GPIOB, &GPIO_InitStructure);//根据设定参数配置 GPIO

IDR寄存器的配置

  • IDR是端口输入数据寄存器,只读,只用低16位。要想知道某个IO口的电平状态,只要读这个寄存器,再看某个位的状态就可以了
  • 固件库操作IDR寄存器读取IO端口数据是通过GPIO_ReadInputDataBit 函数实现的:

uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)

返回值是1(Bit_SET)或者 0(Bit_RESET);

  • ODR是端口输出数据寄存器,可读可写,只用低16位。从该寄存器读 出来的数据可以用于判断当前 IO 口的输出状态。而向该寄存器写数据,则可以控制某个 IO 口 的输出电平。
  • 固件库设置ODR寄存器控制IO口的输出状态是通过GPIO_Write函数实现的:

void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);

一次性往一个GPIO的多个端口设值

  • BSRR寄存器是端口设置/清除寄存器。该寄存器和 ODR 寄存器具有类似的作用,都可以用来设置 GPIO 端口的输出位是 1 还是 0。

要设置 GPIOA 的第 1 个端口值为 1,只需往寄存器 BSRR 的低16 位对应位写 1 即可:

GPIOA->BSRR=1<<1;

要设置 GPIOA 的第 1 个端口值为 0,只需往寄存器高 16 位对应为写 1 即可:

GPIOA->BSRR=1<<(16+1)

  • BRR 寄存器是端口位清除寄存器。
  • 通过 BSRR 和 BRR 寄存器设置 GPIO 端口输出是通过函数 GPIO_SetBits()和函数GPIO_ResetBits()来完成的。

void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

如要设置 GPIOB.5 输出1,方法为:

GPIO_SetBits(GPIOB, GPIO_Pin_5);

如果要设置 GPIOB.5 输出位0,方法为:

GPIO_ResetBits (GPIOB, GPIO_Pin_5);

IO步骤:

  1. 使能 IO 口时钟。调用函数为 RCC_APB2PeriphClockCmd(); 不同的IO组,调用的时钟使能函数不一样
  2. 初始化 IO 参数。调用函数 GPIO_Init();
  3. 操作 IO,输出高低电平。GPIO_SetBits()和GPIO_ResetBits()

 

2.硬件设计

DS0 接 PB5,DS1 接 PE5

STM32第一集——跑马灯实验(库函数)_第3张图片

3.软件设计

跑马灯实验要用到的固件库文件是:

stm32f10x_gpio.c /stm32f10x_gpio.h

stm32f10x_rcc.c/stm32f10x_rcc.h       //stm32f10x_rcc.h 头文件在每个实验中都要引入,因为系统时钟配置函数以及相关的外设时 钟使能函数都在这个其源文件 stm32f10x_rcc.c 中。

misc.c/ misc.h

stm32f10x_usart /stm32f10x_usart.h    //stm32f10x_usart.h 和 misc.h 头文件在SYSTEM 文件夹中都需要使用到,所以每个实验都会引用。

led.c

1,时钟    2,GPIO_Init    3,GPIO_SetBits

#include "led.h"

//初始化 PB5 和 PE5 为输出口.并使能这两个口的时钟

//LED IO 初始化

void LED_Init(void)

{

GPIO_InitTypeDef  GPIO_InitStructure;     

 

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB| RCC_APB2Periph_GPIOE, ENABLE);                    

//使能 PB,PE 端口时钟,因为在配置 STM32 外设的时候,任何时候都要先使能该外设的时钟GPIO 是挂载在APB2 总线上的外设,在固件库中对挂载在 APB2 总线上的外设时钟使能是通过函数 RCC_APB2PeriphClockCmd()来实现的。

 

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;                         //端口5

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      //推挽输出

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOB, &GPIO_InitStructure);

GPIO_SetBits(GPIOB,GPIO_Pin_5);                           //PB.5 输出高

 

//因为两个 IO 口的模式和速度都一样,所以只用初始化一次,在 GPIOE.5 的初始化的时候就不需要再重复初始化速度和模式了。

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;            //端口5

GPIO_Init(GPIOE, &GPIO_InitStructure);

GPIO_SetBits(GPIOE,GPIO_Pin_5);                          //PE.5 输出高

}

记得将led.c添加到HARDWARE下

led.h

头文件种,使用   #ifndef   #define   #endif   条件编译,避免头文件内容重复定义

#ifndef __LED_H

#define __LED_H

void LED_Init(void);//初始化

#endif

记得将led.h头文件的路径加入到工程里(魔术棒——c/c++——...)

main.c

#include "led.h"

#include "delay.h"

int main(void)

{

delay_init(); //延时函数初始化

LED_Init(); //初始化与 LED 连接的硬件接口

while(1)

{ GPIO_ResetBits(GPIOB,GPIO_Pin_5); //清零,LED0亮

GPIO_SetBits(GPIOE,GPIO_Pin_5);      //置1,LED1灭

delay_ms(300); //延时300ms

GPIO_SetBits(GPIOB,GPIO_Pin_5);      //置1,LED0灭

GPIO_ResetBits(GPIOB,GPIO_Pin_5);   // 清零,LED1亮

delay_ms(300); //延时 300ms

}

}

 


总结

万事开头难,STM32第一集从昨天写到今天,从头复习了一遍,感觉像新学一样,所以说写博客还是非常有必要的,拒绝眼高手低!

 

你可能感兴趣的:(STM32,笔记,stm32)