STM32F103 ,LED实验

LED闪烁实验——GPIO输出

1.LED的硬件连接(枭龙)
STM32F103 ,LED实验_第1张图片
黄色LED灯D5(LED2) D6(LED1)分别连接PC5 ,PC4.
红色LED灯D4(LED3)连接PB0,输出高电平LED灯熄灭。(单片机管脚驱动能力有限,供阳设计将驱动能力交给电源)。

2.GPIO的HAL库介绍
GPIO操作HAL库函数分布文件:

头文件:stm32f1xx_gpio.h
源文件:stm32f1xx_gpio.c

重要函数:
1个初始化函数:

void HAL_GPIO_Init(GPIO_TypeDef  *GPIOx/*(对象,哪一个GPIO  (ABCD..)*/, GPIO_InitTypeDef *GPIO_Init/*(属性)*/);


作用:初始化一个或者多个IO口(同一组)的工作模式,输入还是输出,输出类型、速度以及上下拉方式。也就是一组IO口的配置寄存器。
(GPIOx->CRL, GPIOx->CRH)

1个读取输入电平函数:

GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx), uint16_t GPIO_Pin/*(哪一个引脚)*/);

作用:读取某个GPIO的输入电平。实际操作的是GPIOx_IDR寄存器。
示例:HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);

1个设置输出电平函数

void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState);

示例:HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0|GPIO_PIN_2, GPIO_PIN_SET);

1个电平反转函数

void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

示例:HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_0|GPIO_PIN_2);

1个引脚电平锁定函数

HAL_StatusTypeDef HAL_GPIO_LockPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

配置HAL库操作IO口步骤:
1.初始化HAL库:HAL_Init()。
2.初始化系统时钟 :SystemClock_Init( )。
3. 使能IO口时钟
操作寄存器:配置IO口时钟使能寄存器: RCC->APB2ENR

HAL库方法:__HAL_RCC_GPIOB_CLK_ENABLE();
或者__GPIOB_CLK_ENABLE();

4.初始化IO口模式。
操作寄存器:GPIOx_CRL CRH
HAL库方法:HAL_GPIO_Init();

5.操作IO口,输出高低电平。
操作寄存器:配置寄存器GPIOX_ODR或者GPIOx_BSRR 。
HAL库方法:HAL_GPIO_WritePin();

stm32f1xx_hal_conf.h:各个宏定义;(外设)

寄存器代码

main.c

#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "led.h"

int main()
{
	 Stm32_Clock_Init(9);
	 //时钟初始化
	 delay_init(72);
	 //延时初始化
	 LED_Init();
	 //LED灯初始化
	
	while(1)
	{
		
		
		LED1 = 0;
		delay_ms(300);
		LED2 = 0;
		delay_ms(300);
		LED3 = 0;
		delay_ms(300);
		LED1 = 1;
		delay_ms(300);
		LED2 = 1;
		delay_ms(300);
		LED3 = 1;
		delay_ms(300);
		
	}
	 
	
}

led.h

#ifndef __LED_H
#define __LED_H
#include "sys.h"

#define LED1  PCout(4)  //PC4
#define LED2  PCout(5)  //PC5
#define LED3  PBout(0)  //PB0

void LED_Init(void);

#endif

led.c

#include "led.h"


void LED_Init(void)
{
	
	RCC->APB2ENR |= 1<<3; //PORTB时钟使能
	RCC->APB2ENR |= 1<<4; //PORTC时钟使能
	
	GPIOC->CRL &= 0xFFF0FFFF;
	GPIOC->CRL |= 0x00030000;   //推挽高速输出  
	GPIOC->ODR |= 1<<4;// PC4
	
	GPIOC->CRL &= 0xFF0FFFFF;
	GPIOC->CRL |= 0x00300000;
	GPIOC->ODR |= 1<<5;//同理
	
	GPIOB->CRL &= 0xFFFFFFF0;
	GPIOB->CRL |= 0x00000003;
	GPIOB->ODR |= 1;
	
}

HAL库代码

学习加深印象吧,忍不住回头重新学习,根据自己的理解,解释一下代码,如果有错误欢迎在下面指出

main.c

#include "MyIncludes.h"//存放mian.c要使用的.h文件  有 #include "stm32f1xx.h"   #include "stm32_types.h"   #include"stm32_system.h"  #include "delay.h"(延时函数)  #include"led.h"
int main(void)
{
  System_Init();//系统初始化,里面具体
  //不懂,记住就好;
  
  LED_Init();//LED初始化
  
  while (1)
  {
    LED_Flash();//LED闪烁;
  }
}

LED.h

#ifndef __LED_H_
#define __LED_H_

#include "stm32f1xx.h"
#include "stm32_types.h"
#include "stm32f1xx_hal.h"

#define LED1 1 
#define LED2 2 //为什么要在这里将1 2 
//分别宏定义为LED1 LED2,因为在LED.c中要使
//用switch(),定义后描述更方便。

void LED_Init(void);//LED初始化函数
void LED_Flash(void);//LED闪烁,这里STM32F10一共有三个LED灯
void LED_Open(u8 led);//LED 打开函数
void LED_Close(u8 led);//LED 关闭函数

#endif

LED.c

#include "led.h"
#include "delay.h"

void LED_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct;
  /*这里使用的是结构体变量声明为
  GPIO_InitStruct;  结构体内有Pin(管脚)
  Mode(模式),Pull(上拉方式)Speed(速度)*/
  
  __GPIOB_CLK_ENABLE();
  __GPIOC_CLK_ENABLE();
  /*使能GPIOB,GPIOC时钟,因为LED的管脚分别
  在 GPIOB GPIOC上,里面的不怎么太懂,
  先记住就就好*/
  GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5;/*PD
  4,PD5的LED*/
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;/*普通推挽输出模式*/
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;/*高速*/
  GPIO_InitStruct.Pull = GPIO_NOPULL;/*上拉*/ 
  HAL_GPIO_Init(GPIOC,&GPIO_InitStruct);//初始化GPIOC
  
  GPIO_InitStruct.Pin = GPIO_PIN_0;//GPIOB0;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOB,&GPIO_InitStruct);
  
  HAL_GPIO_WritePin(GPIOC,GPIO_PIN_4|GPIO_PIN_5,GPIO_PIN_SET);
  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET);/*这里是关闭LED,GPIO_PIN_SET = 1
   高电平关闭。 HAL_GPIO_WritePin();设置输
   出电平函数,也就是将PC4 PC5 PB0管脚置
   为高电平*/
}
void LED_Flash(void)
{
  HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_4|GPIO_PIN_5);
  HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_0);
  delay_ms(1000);
  /*电平反转函数  也就是高变低 低变高;*/
}

void LED_Open(u8 led)
{
  switch( led )
  {
  case (LED1):

     HAL_GPIO_WritePin(GPIOC,GPIO_PIN_4|GPIO_PIN_5,GPIO_PIN_RESET);break;
    case (LED2):
     HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET);
     break;//拉低亮
  default : break;
  }
}

void LED_Close(u8 led)
{
  switch( led )
  {
    case (LED1):
    HAL_GPIO_WritePin(GPIOC,GPIO_PIN_4|GPIO_PIN_5,GPIO_PIN_SET);
    break;
    case (LED2):
    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET);
    break;
    default : break;//高电平关闭
  }
}


  

深入学习

这个我是看了前20章,感觉到很懵,来深入学习一下把,我感觉HAL库很方便,但是我感觉没有寄存器直抒胸臆吧,是什么就是什么,HAL把内容封装在一起,可能我们知道怎么用,但是不知道为什么这样感觉就很尴尬,所以来了解一下吧。
在这里插入图片描述
System_Init(void)中的HAL_Init()函数

HAL_StatusTypeDef HAL_Init(void)
//结构体函数(可以返回结构体里面的值,也就是HAL库状态)
{
  /*  配置闪存预取*/
#if (PREFETCH_ENABLE != 0)
#if defined(STM32F101x6) || defined(STM32F101xB) || defined(STM32F101xE) || defined(STM32F101xG) || \
    defined(STM32F102x6) || defined(STM32F102xB) || \
    defined(STM32F103x6) || defined(STM32F103xB) || defined(STM32F103xE) || defined(STM32F103xG) || \
    defined(STM32F105xC) || defined(STM32F107xC)

  /* 值行设备上没有预取缓冲区 */
  __HAL_FLASH_PREFETCH_BUFFER_ENABLE();
  //这里看下面的1文字
  //闪存预取缓冲区使能
#endif
#endif /* 闪存预取启用 */

  /* 设置中断优先级 
   4位优先权子优先级为0位*/
  HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);

  /* 使用systick作为时基源并配置1毫秒时钟(重置后的默认时钟为MSI)*/
  HAL_InitTick(TICK_INT_PRIORITY);

  /* 初始化低级硬件*/
  HAL_MspInit();

  /*返回功能状态*/
  return HAL_OK;
}
  1. 先配置闪存预取: 进入__HAL_FLASH_PREFETCH_BUFFER_ENABLE()闪存预取缓冲区使能函数 FLASH->ACR|=FLASH_ACR_PRFTBE(0x1U << 4 也就是 0x10000) 也就是0x4002 2000->ACR |= 0x10000,也就是启用预取缓冲区
    STM32F103 ,LED实验_第2张图片

  2. HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4)设置中断优先级函数

void HAL_NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
{
  /* 检查参数是否为0    ((void)0)函数的运用*/
  assert_param(IS_NVIC_PRIORITY_GROUP(PriorityGroup));
  
  /* 根据PriorityGroup参数值设置PRIGROUP[10:8]位*/
  NVIC_SetPriorityGrouping(PriorityGroup);
}
  1. 1 assert_param(IS_NVIC_PRIORITY_GROUP(PriorityGroup)); 在这里插入图片描述
    而PriorityGroup=NVIC_PRIORITYGROUP_4 也就是((uint32_t)0x00000003),4位优先权子优先级为0位所以没问题

2.2 NVIC_SetPriorityGrouping(PriorityGroup);

__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
//内联函数
{
  uint32_t reg_value;
  uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL);             /* 仅使用值0..7         */

  reg_value  =  SCB->AIRCR;                                                   /* 读取旧寄存器配置->应用中断和复位控制寄存器   */
  reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* 清除要更改的位             */
  reg_value  =  (reg_value                                   |
                ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
                (PriorityGroupTmp << 8U)                      );              /* 插入写入密钥和优先级组 */
  SCB->AIRCR =  reg_value;
}
  1. __weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)函数
  /*配置SysTick,使其在1毫秒内中断  72000000;/10000*/
  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

  /*Configure the SysTick IRQ priority */
  HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority ,0);

   /* Return function status */
  return HAL_OK;
  1. 1 __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)函数
  if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
  {
    return (1UL);                                                   
    /* 无法重新加载值 */
  }

  SysTick->LOAD  = (uint32_t)(ticks - 1UL);                        
   /* 设置重新加载寄存器 */
  NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); 
  /*设置Systick中断的优先级*/
  SysTick->VAL   = 0UL;                                            
   /* 加载SysTick计数器值 */
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
                   SysTick_CTRL_TICKINT_Msk   |
                   SysTick_CTRL_ENABLE_Msk;                         
                   /* 启用SysTick IRQ和SysTick计时器 */
  return (0UL);                                                    
  /* 函数成功 */
}

你可能感兴趣的:(星光STM32)