STM32的IO口基本操作

## STM32的IO口基本操作 ##

 void LED_GPIO_Config(void)
{       
    /*定义一个GPIO_InitTypeDef类型的结构体*/
    GPIO_InitTypeDef GPIO_InitStructure;

    /*开启GPIOC的外设时钟*/
    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE); 

    /*选择要控制的GPIOC引脚*/                                                              
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5; 

    /*设置引脚模式为通用推挽输出*/
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   

    /*设置引脚速率为50MHz */   
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 

    /*调用库函数,初始化GPIOC*/
    GPIO_Init(GPIOC, &GPIO_InitStructure);        

    /* 关闭所有led灯 */
    GPIO_SetBits(GPIOC, GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5);   
}

1.初始化结构体
先来看下GPIO_InitTypeDef这个结构体,源代码如下

typedef struct
{
  uint16_t GPIO_Pin; //制定将要配置的GPIO引脚                                      
  GPIOSpeed_TypeDef GPIO_Speed;  //制定IO引脚可输出的最高频率
  GPIOMode_TypeDef GPIO_Mode;    //制定IO引脚将要配置的状态
}GPIO_InitTypeDef;

结构体中包含了GPIO_Pin,GPIO_Speed和GPIO_Mode信息,
GPIO_Pin在stm32f10x_gpio.h中有宏定义

/** @defgroup GPIO_pins_define 
  * @{
  */
#define GPIO_Pin_0    ((uint16_t)0x0001)  /*!< Pin 0 selected */
#define GPIO_Pin_1    ((uint16_t)0x0002)  /*!< Pin 1 selected */
#define GPIO_Pin_2    ((uint16_t)0x0004)  /*!< Pin 2 selected */
#define GPIO_Pin_3    ((uint16_t)0x0008)  /*!< Pin 3 selected */
#define GPIO_Pin_4    ((uint16_t)0x0010)  /*!< Pin 4 selected */
#define GPIO_Pin_5    ((uint16_t)0x0020)  /*!< Pin 5 selected */
#define GPIO_Pin_6    ((uint16_t)0x0040)  /*!< Pin 6 selected */
#define GPIO_Pin_7    ((uint16_t)0x0080)  /*!< Pin 7 selected */
#define GPIO_Pin_8    ((uint16_t)0x0100)  /*!< Pin 8 selected */
#define GPIO_Pin_9    ((uint16_t)0x0200)  /*!< Pin 9 selected */
#define GPIO_Pin_10   ((uint16_t)0x0400)  /*!< Pin 10 selected */
#define GPIO_Pin_11   ((uint16_t)0x0800)  /*!< Pin 11 selected */
#define GPIO_Pin_12   ((uint16_t)0x1000)  /*!< Pin 12 selected */
#define GPIO_Pin_13   ((uint16_t)0x2000)  /*!< Pin 13 selected */
#define GPIO_Pin_14   ((uint16_t)0x4000)  /*!< Pin 14 selected */
#define GPIO_Pin_15   ((uint16_t)0x8000)  /*!< Pin 15 selected */
#define GPIO_Pin_All((uint16_t)0xFFFF)  /*!< All pins selected */

刚好对应16个端口。
GPIO_Speed是一个枚举类型的结构体,在stm32f10x_gpio.h中有宏定义:

typedef enum
{ 
  GPIO_Speed_10MHz = 1,//枚举常量,值为1,代表输出最高速率为10M
  GPIO_Speed_2MHz, //对不赋值的常量,自动加1
  GPIO_Speed_50MHz
}GPIOSpeed_TypeDef;

当STM32的GPIO端口设置为输出模式时,有三种速度可以选择:2MHz、10MHz和50MHz,这个速度是指I/O口驱动电路的速度,是用来选择不同的输出驱动模块,达到最佳的噪声控制和降低功耗的目的。
高频的驱动电路,噪声也高,当你不需要高的输出频率时,请选用低频驱动电路,这样非常有利于提高系统的EMI性能。
当然如果你要输出较高频率的信号,但却选用了较低频率的驱动模块,你很可能会得到失真的输出信号。
关键是,GPIO的引脚速度跟应用匹配。
比如对于串口,假如最大波特率只需115.2k,那么用2M的GPIO的引脚速度就够了,既省电也噪声小。
对于I2C接口,假如使用400k波特率,若想把余量留大些,那么用2M的GPIO的引脚速度或许不够,这时可以选用10M的GPIO引脚速度。
对于SPI接口,假如使用18M或9M波特率,用10M的GPIO的引脚速度显然不够了,需要选用50M的GPIO的引脚速度。
GPIO_Mode也是一个枚举类型的结构体:

/** 
  * @brief  Configuration Mode enumeration  
  */
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;

2.设置系统时钟
在使用端口前必须要开启外设时钟,在开启外设时钟前我们首先要配置好系统时钟,系统时钟的设置主要在库函数SystemInit()中完成,在启动文件startup_stm32f10x_md.s中有如下一段代码:

Reset_Handler    PROC
                 EXPORT  Reset_Handler             [WEAK]
     IMPORT  __main
     IMPORT  SystemInit
                 LDR     R0, =SystemInit 
                 BLX     R0
                 LDR     R0, =__main
                 BX      R0
                 ENDP

在调用main函数之前首先要调用SystemInit()函数,这个函数定义在system_stm32f10x.c中,函数原型为

/**
  * @}
  */

/** @addtogroup STM32F10x_System_Private_Functions
  * @{
  */

/**
  * @brief  Setup the microcontroller system
  *         Initialize the Embedded Flash Interface, the PLL and update the 
  *         SystemCoreClock variable.
  * @note   This function should be used only after reset.
  * @param  None
  * @retval None
  */
void SystemInit (void)
{
  /* Reset the RCC clock configuration to the default reset state(for debug purpose) */
  /* Set HSION bit */
  RCC->CR |= (uint32_t)0x00000001;

  /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
#ifndef STM32F10X_CL
  RCC->CFGR &= (uint32_t)0xF8FF0000;
#else
  RCC->CFGR &= (uint32_t)0xF0FF0000;
#endif /* STM32F10X_CL */   

  /* Reset HSEON, CSSON and PLLON bits */
  RCC->CR &= (uint32_t)0xFEF6FFFF;

  /* Reset HSEBYP bit */
  RCC->CR &= (uint32_t)0xFFFBFFFF;

  /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
  RCC->CFGR &= (uint32_t)0xFF80FFFF;

#ifdef STM32F10X_CL
  /* Reset PLL2ON and PLL3ON bits */
  RCC->CR &= (uint32_t)0xEBFFFFFF;

  /* Disable all interrupts and clear pending bits  */
  RCC->CIR = 0x00FF0000;

  /* Reset CFGR2 register */
  RCC->CFGR2 = 0x00000000;
#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
  /* Disable all interrupts and clear pending bits  */
  RCC->CIR = 0x009F0000;

  /* Reset CFGR2 register */
  RCC->CFGR2 = 0x00000000;      
#else
  /* Disable all interrupts and clear pending bits  */
  RCC->CIR = 0x009F0000;
#endif /* STM32F10X_CL */

#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)
  #ifdef DATA_IN_ExtSRAM
    SystemInit_ExtMemCtl(); 
  #endif /* DATA_IN_ExtSRAM */
#endif 

  /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */
  /* Configure the Flash Latency cycles and enable prefetch buffer */
  SetSysClock();

#ifdef VECT_TAB_SRAM
  SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
#else
  SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
#endif 

该函数的主要功能是将配置时钟相关的寄存器都复位为默认值,并调用
SetSysClock(void)函数,

/**
  * @brief  Configures the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers.
  * @param  None
  * @retval None
  */
static void SetSysClock(void)
{
#ifdef SYSCLK_FREQ_HSE
  SetSysClockToHSE();
#elif defined SYSCLK_FREQ_24MHz
  SetSysClockTo24();
#elif defined SYSCLK_FREQ_36MHz
  SetSysClockTo36();
#elif defined SYSCLK_FREQ_48MHz
  SetSysClockTo48();
#elif defined SYSCLK_FREQ_56MHz
  SetSysClockTo56();  
#elif defined SYSCLK_FREQ_72MHz
  SetSysClockTo72();
#endif

 /* If none of the define above is enabled, the HSI is used as System clock
    source (default after reset) */ 
}

对于SYSCLK_FREQ的宏定义在system_stm32f10x.c文件开头已经给出,默认的系统时钟为72M,当然前提条件是外接8M晶振。

#if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
/* #define SYSCLK_FREQ_HSE    HSE_VALUE */
 #define SYSCLK_FREQ_24MHz  24000000
#else
/* #define SYSCLK_FREQ_HSE    HSE_VALUE */
/* #define SYSCLK_FREQ_24MHz  24000000 */ 
/* #define SYSCLK_FREQ_36MHz  36000000 */
/* #define SYSCLK_FREQ_48MHz  48000000 */
/* #define SYSCLK_FREQ_56MHz  56000000 */
#define SYSCLK_FREQ_72MHz  72000000
#endif

3.开启外设时钟
开启或者关闭外设时钟主要由以下函数设置

void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState);
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);

不同的外设调用不同的函数,如果使用了io的引脚复用功能除了开启io功能时钟还需要开启复用功能时钟,例如GPIOC的Pin4还可以作为ADC1的输入引脚,当它作为ADC1来使用时,除了开启GPIOC的时钟外,还要开启ADC1的时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);

其他操作函数参看库函数使用手册。

  • 7
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
STM32是一款流行的嵌入式微控制器,其IO口可以用来连接各种外设,如LED、按键、LCD等。下面介绍一下如何设计一个简单的IO口驱动程序。 首先,需要了解IO口的基本操作。每个IO口都有一个GPIOx寄存器,其中包含了该IO口的配置信息和数据状态。配置信息包括输入/输出模式、上/下拉电阻、输出速度等;数据状态包括输入/输出值、状态标志等。通过对这些寄存器的读写操作,可以实现对IO口的控制。 例如,要控制一个LED灯,可以将其连接到一个IO口上,并将该IO口配置为输出模式。然后,将该IO口的输出值设置为高电平或低电平,就可以控制LED灯的亮灭。 以下是一个简单的IO口驱动程序的实现代码: ```c #include "stm32f10x.h" #define LED_PIN GPIO_Pin_8 #define LED_GPIO GPIOA void LED_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA时钟 GPIO_InitStructure.GPIO_Pin = LED_PIN; //LED接在PA8上 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz GPIO_Init(LED_GPIO, &GPIO_InitStructure); //根据设定参数初始化GPIO } void LED_On(void) { GPIO_SetBits(LED_GPIO, LED_PIN); //将LED对应的GPIO输出高电平 } void LED_Off(void) { GPIO_ResetBits(LED_GPIO, LED_PIN); //将LED对应的GPIO输出低电平 } ``` 在主函数中调用LED_Init函数初始化LED灯的IO口,然后就可以通过调用LED_On和LED_Off函数来控制LED的亮灭了。 ```c int main(void) { LED_Init(); while(1) { LED_On(); delay(500); LED_Off(); delay(500); } } ``` 以上是一个简单的IO口驱动程序的实现,可以通过类似的方法来控制其他外设的IO口。需要注意的是,不同型号的STM32微控制器可能有不同的IO口配置方式和寄存器地址,需要根据具体型号的数据手册来编写相应的驱动程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值