第2课【CMSIS和标准库开发】标准库 CMSIS 分层

2023-05-16

目录

  • 基本知识框架
  • 课堂笔记
    • CMSIS
      • CMSIS的分层关系和作用
      • CMSIS层文件结构
        • 内核函数层文件
        • 外设函数访问层文件
    • 标准库开发
      • 标准库开发 LED-GPIO
      • 标准库开发 KEY-GPIO
      • 标准库开发 位带操作
        • 位带
          • 位带
          • 位带别名区
          • 位带区和位带别名区的地址转换
        • 通过位带操作点亮LED灯
  • 基本知识框架Xmind文件下载

基本知识框架

在这里插入图片描述

课堂笔记

CMSIS

由于有众多外设厂商为Cortex内核提供外设,不同的外设带来的差异,导致软件在编写或移植时会出现很大困难,所以Arm公司同芯片厂商共同协作推出了CMSIS标准。全称是Cortex MicroController Software Interface Standard【Cortex微控制器软件接口标准】

CMSIS的分层关系和作用

CMSIS标准规定了APPLICATION层CMSIS层MCU层,层与层之间的关系如下图
在这里插入图片描述
CMSIS标准最重要的作用就是在用户层和硬件层之间建立硬件抽象层,从而屏蔽硬件层差异,并向用户层提供处理器软件接口

CMSIS层文件结构

根据CMSIS标准,ST官方提供了内核寄存器相关文件(CMSIS相关)外设寄存器相关文件(CMSIS以外的,外设标准库),它们的关系如下
在这里插入图片描述
从文件结构可以看出,CMSIS层的核心主要分为内核函数层外设函数访问层

  • 内核函数层:其中文件主要由Arm公司提供,文件内容包括内核寄存器的的名称,地址定义
  • 外设函数访问层:其中文件主要由芯片生产商提供,文件内容包括外设寄存器和中断的名称,地址定义

内核函数层文件

内核函数层的文件主要的作用是时钟配置与操作内核寄存器,一般来说很少会使用

  • system_stm32f10x.h / .c:操作RCC时钟,实现系统时钟的配置。系统上电时,会首先执行startup文件,startup文件会调用SystemInit函数,这个函数就是在本文件中定义的,默认状态下调用完成后会将系统时钟初始化为72MHz
  • core_cm3.h / .c:实现内核寄存器的名称地址定义,操作寄存器的函数

外设函数访问层文件

外设函数访问层的文件主要作用是实现外设地址映射,操作外设寄存器,这里的文件会经常用到

  • stm32f10x_xxxx.h / .c:xxxx指的是gpio,adc等等,每个外设都有对应src驱动源文件和inc定义相关头文件。是外设标准库的主要部分
  • stm32f10x.h:实现了片上外设的所有寄存器映射

标准库开发

在之前的第1课中,已经实现了基础的库函数,并通过它点亮了LED灯。在学习了标准库后,可以尝试通过标准库来实现点亮LED的功能,并加上其他进阶的其他功能

标准库开发 LED-GPIO

LED功能 头文件bsp_led.h代码主体部分实现

#ifndef __BSP_LED_H__
#define __BSP_LED_H__

#include "stm32f1xx_hal.h"
// GPIO输出高、低以及反转电平
#define digitalHi(Port, Pin) ((Port)->BSRR = Pin)
#define digitalLi(Port, Pin) ((Port)->BRR  = Pin)
#define digitalRev(Port,Pin) ((Port)->ODR ^= Pin)
// RGB灯的开、关以及反转
#define LED1_ON  digitalLi(LED1_GPIO_Port, LED1_Pin)
#define LED1_OFF digitalHi(LED1_GPIO_Port, LED1_Pin)
#define LED1_REV digitalRev(LED1_GPIO_Port, LED1_Pin)

#define LED2_ON  digitalLi(LED2_GPIO_Port, LED2_Pin)
#define LED2_OFF digitalHi(LED2_GPIO_Port, LED2_Pin)
#define LED2_REV digitalRev(LED2_GPIO_Port, LED2_Pin)

#define LED3_ON  digitalLi(LED3_GPIO_Port, LED3_Pin)
#define LED3_OFF digitalHi(LED3_GPIO_Port, LED3_Pin)
#define LED3_REV digitalRev(LED3_GPIO_Port, LED3_Pin)
// RGB灯以及其它衍生颜色的灯
#define LED_RED \
				LED1_ON;\
				LED2_OFF;\
				LED3_OFF;

#define LED_GREEN \
				LED1_OFF;\
				LED2_ON;\
				LED3_OFF;

#define LED_BLUE \
				LED1_OFF;\
				LED2_OFF;\
				LED3_ON;

#define LED_YELLOW \
				LED1_ON;\
				LED2_ON;\
				LED3_OFF;

#define LED_PURPLE \
				LED1_ON;\
				LED2_OFF;\
				LED3_ON;

#define LED_CYAN \
				LED1_OFF;\
				LED2_ON;\
				LED3_ON;

#define LED_WHITE \
				LED1_ON;\
				LED2_ON;\
				LED3_ON;

#define LED_BLACK \
				LED1_OFF;\
				LED2_OFF;\
				LED3_OFF;

void LED_GPIO_Config(void);

#endif

LED功能 源文件bsp_key.c代码主体部分实现

#ifndef BSP_LED_C_
#define BSP_LED_C_

#include "bsp_led.h"
#include "main.h"
// LED相关GPIO口初始化
void LED_GPIO_Config(void)
{
	// 使能GPIOB的时钟
	__HAL_RCC_GPIOB_CLK_ENABLE();
	
	// 定义并补充结构体信息
	GPIO_InitTypeDef* GPIO_LED_Structure;
	
	GPIO_LED_Structure->Pin   = LED1_Pin;

	GPIO_LED_Structure->Mode  = GPIO_MODE_OUTPUT_PP;

	GPIO_LED_Structure->Speed = GPIO_SPEED_FREQ_HIGH;
	
	// 初始化GPIO口
	HAL_GPIO_Init(LED1_GPIO_Port, GPIO_LED_Structure);

	GPIO_LED_Structure->Pin   = LED2_Pin;

	HAL_GPIO_Init(LED2_GPIO_Port, GPIO_LED_Structure);

	GPIO_LED_Structure->Pin   = LED3_Pin;

	HAL_GPIO_Init(LED3_GPIO_Port, GPIO_LED_Structure);
	
	// 输出高电平
	HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);

	HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_SET);

	HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_SET);
}
#endif

main.c代码主体部分实现

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "bsp_led.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  /* USER CODE BEGIN 2 */
  LED_GPIO_Config();
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
	LED1_ON;
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, LED2_Pin|LED3_Pin|LED1_Pin, GPIO_PIN_SET);

  /*Configure GPIO pin : KEY2_Pin */
  GPIO_InitStruct.Pin = KEY2_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(KEY2_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : KEY1_Pin */
  GPIO_InitStruct.Pin = KEY1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(KEY1_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pins : LED2_Pin LED3_Pin LED1_Pin */
  GPIO_InitStruct.Pin = LED2_Pin|LED3_Pin|LED1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

标准库开发 KEY-GPIO

KEY功能 头文件bsp_key.h代码主体部分实现

#ifndef __BSP_LED_H__
#define __BSP_LED_H__

#include "stm32f1xx_hal.h"

void KEYScan(void);

void LED_GPIO_Config(void);

#endif

KEY功能 源文件bsp_key.c代码主体部分实现

#ifndef BSP_LED_C_
#define BSP_LED_C_

#include "bsp_led.h"
#include "main.h"

void KEYScan(void)
{
	if (GPIO_PIN_SET == HAL_GPIO_WritePin(KEY_GPIO_Port, KEY_Pin))
		while(GPIO_PIN_SET == HAL_GPIO_WritePin(KEY_GPIO_Port, KEY_Pin));
		return GPIO_PIN_SET;
	else
		return GPIO_PIN_RESET;
}

// KEY相关GPIO口初始化
void KEY_GPIO_Config(void)
{
	// 使能GPIOC的时钟
	__HAL_RCC_GPIOC_CLK_ENABLE();
	
	// 定义并补充结构体信息
	GPIO_InitTypeDef* GPIO_LED_Structure;
	
	GPIO_LED_Structure->Pin   = KEY_Pin;

	GPIO_LED_Structure->Mode  = GPIO_Mode_IN_FLOATING;
	
	// 初始化GPIO口
	HAL_GPIO_Init(LED1_GPIO_Port, GPIO_LED_Structure);

}
#endif

main.c代码主体部分实现

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "bsp_led.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  /* USER CODE BEGIN 2 */
  KEY_GPIO_Config();
  LED_GPIO_Config();
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
	if (GPIO_PIN_SET == KEYScan())
		LED1_ON;
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, LED2_Pin|LED3_Pin|LED1_Pin, GPIO_PIN_SET);

  /*Configure GPIO pin : KEY2_Pin */
  GPIO_InitStruct.Pin = KEY2_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(KEY2_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : KEY1_Pin */
  GPIO_InitStruct.Pin = KEY1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(KEY1_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pins : LED2_Pin LED3_Pin LED1_Pin */
  GPIO_InitStruct.Pin = LED2_Pin|LED3_Pin|LED1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

标准库开发 位带操作

位带

位带

位操作指的是可以对单独某个位进行读写操作,当需要对某些位进行频繁读写操作时,通过位操作可以轻松便捷的实现。但Cortex内核的寻址能力仅能达到字节级别,如果要进行位操作,就只能通过位带

位带指的是STM32中可以进行位操作的地址区域。但这里的位操作不是直接对位带中的地址进行位操作,而是要通过访问位带区的“替身”:位带别名区

位带别名区

位带别名区是STM32中服务于位带区的特殊地址范围。对于位带别名区的所有操作,都会体现到位带区上

STM32中可以实现位带的地址区域有两个外设位带区sRam位带区

外设位带区sRam位带区
地址范围:0X4000 0000~0X4010 0000地址范围:0X2000 0000~X2010 0000
大小:1MB大小:1MB
外设位带别名区sRam位带别名区
地址范围:0X4200 0000~0X43FF FFFF地址范围:0X2200 0000~0X23FF FFFF
大小:32MB大小:32MB

访问的原理:将位带区的每1个位【bit】一一映射到位带别名区对应的4个字节【Byte】。而位带别名区地址对应的内容是LSB,也就是最低位有效,这意味着只要读写位带别名区那四个字节的最低位,就等效于读写位带区的对应位

位带区和位带别名区大小的联系
由于将位带区的1个位映射到位带别名区的4个字节,1字节=8位,所以位带别名区的大小是位带区的32倍


为什么要将1个位映射到4个字节
由于STM32内部的数据总线是32位的,CPU进行32位数据的处理是最高效的,所以将1位映射成4字节,是一种用空间换取时间的做法,原理类似于C语言结构体中的成员大小对齐

位带区和位带别名区的地址转换

根据位带区与位带别名区的映射原理,要想得到位带区中地址A对应字节的第n位,对应位带别名区地址。

计算公式:位带别名区地址 = (0xF000 000 * A + 0x0200 0000) + ((A * 0x00FF FFFF * 8 + n) * 4)

  • 前半部分0xF000 000 * A + 0x0200 0000 :计算的是位带别名区的起始地址,并根据地址判断到底是外设位带别名区还是sRam位带别名区
  • 后半部分(A * 0x00FF FFFF * 8 + n) * 4:计算的是位对于位带别名区起始地址的偏移量,(A * 0x00FF FFFF * 8 + n)首先计算出位带区中给,A的第n位相对于起始地址的偏移量,单位为位,最后*4是将这个偏移量转换成对应位带别名区偏移量

通过位带操作点亮LED灯

位带操作LED功能 头文件bsp_bitband.h代码主体部分实现

/*
 * bsp_bitband.h
 *
 *  Created on: Sep 16, 2021
 *      Author: 67566
 */

#ifndef BSP_BITBAND_H_
#define BSP_BITBAND_H_

#include "stm32f1xx_hal.h"
// 计算位带区对应位带别名区地址
#define BITBAND(addr,bit)   ((addr & 0xF0000000)+0x02000000+((addr & 0x000FFFFF)<<5)+(bit<<2))
// 强转地址,其中volatile不能省略,否则编译器会进行参数优化
#define MEM_ADDR(addr)      (*(volatile unsigned long*)(addr))
#define BIT_ADDR(addr,bit)  MEM_ADDR(BITBAND(addr,bit))
// GPIO对应ODR\IDR地址
#define GPIOA_ODR_ADDR      GPIOA_BASE + 0x0c
#define GPIOB_ODR_ADDR      GPIOB_BASE + 0x0c
#define GPIOC_ODR_ADDR      GPIOC_BASE + 0x0c
#define GPIOD_ODR_ADDR      GPIOD_BASE + 0x0c
#define GPIOE_ODR_ADDR      GPIOE_BASE + 0x0c
#define GPIOF_ODR_ADDR      GPIOF_BASE + 0x0c
#define GPIOG_ODR_ADDR      GPIOG_BASE + 0x0c

#define GPIOA_IDR_ADDR      GPIOA_BASE + 0x08
#define GPIOB_IDR_ADDR      GPIOB_BASE + 0x08
#define GPIOC_IDR_ADDR      GPIOC_BASE + 0x08
#define GPIOD_IDR_ADDR      GPIOD_BASE + 0x08
#define GPIOE_IDR_ADDR      GPIOE_BASE + 0x08
#define GPIOF_IDR_ADDR      GPIOF_BASE + 0x08
#define GPIOG_IDR_ADDR      GPIOG_BASE + 0x08
// GPIO引脚输出\输入
#define GPIOA_OUT(bit)      BIT_ADDR(GPIOA_ODR_ADDR,bit)
#define GPIOA_IN(bit)       BIT_ADDR(GPIOA_IDR_ADDR,bit)

#define GPIOB_OUT(bit)      BIT_ADDR(GPIOB_ODR_ADDR,bit)
#define GPIOB_IN(bit)       BIT_ADDR(GPIOB_IDR_ADDR,bit)

#define GPIOC_OUT(bit)      BIT_ADDR(GPIOC_ODR_ADDR,bit)
#define GPIOC_IN(bit)       BIT_ADDR(GPIOC_IDR_ADDR,bit)

#define GPIOD_OUT(bit)      BIT_ADDR(GPIOD_ODR_ADDR,bit)
#define GPIOD_IN(bit)       BIT_ADDR(GPIOD_IDR_ADDR,bit)

#define GPIOE_OUT(bit)      BIT_ADDR(GPIOE_ODR_ADDR,bit)
#define GPIOE_IN(bit)       BIT_ADDR(GPIOE_IDR_ADDR,bit)

#define GPIOF_OUT(bit)      BIT_ADDR(GPIOF_ODR_ADDR,bit)
#define GPIOF_IN(bit)       BIT_ADDR(GPIOF_IDR_ADDR,bit)

#define GPIOG_OUT(bit)      BIT_ADDR(GPIOG_ODR_ADDR,bit)
#define GPIOG_IN(bit)       BIT_ADDR(GPIOG_IDR_ADDR,bit)

#endif /* BSP_BITBAND_H_ */

main.c代码主体部分实现

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "bsp_led.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  /* USER CODE BEGIN 2 */
  LED_GPIO_Config();
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
	GPIOB_OUT(5) = GPIO_PIN_RESET;
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, LED2_Pin|LED3_Pin|LED1_Pin, GPIO_PIN_SET);

  /*Configure GPIO pin : KEY2_Pin */
  GPIO_InitStruct.Pin = KEY2_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(KEY2_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : KEY1_Pin */
  GPIO_InitStruct.Pin = KEY1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(KEY1_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pins : LED2_Pin LED3_Pin LED1_Pin */
  GPIO_InitStruct.Pin = LED2_Pin|LED3_Pin|LED1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

基本知识框架Xmind文件下载

链接:资源下载

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

第2课【CMSIS和标准库开发】标准库 CMSIS 分层 的相关文章

  • 使用airtest实现UI自动化之环境搭建

    1 xff0c 安装python python版本为3 7 1 2 xff0c 安装airtest xff0c pocoui模块 在安装时碰到的问题 xff1a 1 xff09 使用pip命令报错 xff0c 报SSL证书无法识别错误 解决
  • HTTP Digest Authentication在实际应用中的问题

    作者 xff1a 老王 Basic认证实际上是明文传递密码 xff0c 所以 RFC2617里定义了Digest认证以取代它 xff0c 其计算方法如下 xff1a 其中HA1计算方法为 xff1a 如果qop选项的值为auth xff0c
  • 1天精通Apipost--全网最全gRPC调试和智能Mock讲解!

    gRPC 接口调试 grpc 作为一个老程序员 xff0c 最近公司技术架构用到了gPRC xff0c 但国内很少有支持这个的工具 xff0c 大部分都只是支持http 由于我同时也是Apipost骨灰级用户 xff0c 于是就在他们官网的
  • CAN总线波特率的设定——以STM32为例

    波特率的设定 首先是几个名词的含义 xff0c CAN里面1个位的构成如下 注意采样点的位置在PBS1和PBS2的中间 根据这个位时序就可以计算波特率了 最小时间单位 xff08 Tq xff0c Time Quantum xff09 同步
  • 2021电赛备赛心路历程(含代码例程)

    作为一个电子学院学生 xff0c 大二暑假才开始自学单片机知识 xff08 还是因为报名了电赛而不得不去学 xff09 xff0c 深感愧疚 从今年7月至8 4的将近四周时间内哩哩啦啦学了一些基础模块 xff08 其中光是练习点灯和其他基础
  • 20201114-三轴云台storm32 BGC HAKRC调试+

    storm32 BGC HAKRC 2轴云台支持俯仰 xff08 抬头低头 xff09 以及横滚 xff1b 三轴多了一个航向 支持锁头模式 xff0c 拍摄更方便 可以控制俯仰通过接收机或者其他单独PWM通道 可以设置跟随模式或者锁定模式
  • KEIL5中头文件路劲包含问题

    方式1 xff1a 1 Keil中添加头文件相对路劲的方法 在c c 43 43 配置中添加路劲 xff0c 最终是将添加的绝对路径转化为相对路径 xff1b 注意 xff1a 相对路径的当前位置指 uvproj文件所在位置 在C C 43
  • php curl函数应用方法之模拟浏览器

    curl 是使用URL语法的传送文件工具 xff0c 支持FTP FTPS HTTP HTPPS SCP SFTP TFTP TELNET DICT FILE和LDAP curl 支持SSL证书 HTTP POST HTTP PUT FTP
  • WireShark基本抓包数据分析

    WireShark抓包数据分析 xff1a 1 TCP报文格式 源端口 目的端口 xff1a 16位长 标识出远端和本地的端口号 顺序号 xff1a 32位长 表明了发送的数据报的顺序 确认号 xff1a 32位长 希望收到的下一个数据报的
  • VScode下运行调试C++文件

    1 下载vscode 这个可以直接去官网下载 2 下载mingw64 下载mingw64就是下载C 43 43 的编译器g 43 43 和调试器gdb 这个也可以去官网下载 xff0c 下载安装完成后去配置环境变量 我将mingw64安装在
  • c++模板的优点和缺点

    作为C 43 43 语言的新组成部分 xff0c 模板引入了基于通用编程的概念 通用编程是一种无须考虑特定对象的描述和发展算法的方法 xff0c 因此它与具体数据结构无关 但在决定使用C 43 43 模板之前 xff0c 让我们分析一下使用
  • 基于导航网格的A星寻路(Navigation mesh)

    最近花了几个月的时间实现了导航网格寻路和导航网格自动生成 导航网格数据结构定义 由于数据之间有着层级关系 xff0c 所以采用XML进行定义 navmesh基本元素 xff1a 顶点 Verts 43 可走边 Edges 43 凸多边形 P
  • cmake 引入 动态库、静态库

    动态库 xff1a link directories PROJECT SOURCE DIR lib 添加动态连接库的路径 target link libraries project name lMNN 添加libMNN so 静态库 xff
  • 利用JSP内置对象Request和Application实现用户名密码登录注册进入首页显示

    学习目标 xff1a 实验名称 xff1a JSP内置对象目的 xff1a 掌握JSP页面的全部语法 能够编写基本的JSP网页 学习内容 xff1a 1 实验 地点 周三2单元 xff0c 10617综合一实验室 自带电脑 目的 掌握各种内

随机推荐

  • 【如何写CMake】一个解决方案,多个工程

    文章目录 代码参考 一个解决方案 xff0c 多个工程 xff0c 即多个exe dll lib等 代码 多加几个ADD EXECUTABLE即可 1 cmake verson xff0c 指定cmake版本 cmake minimum r
  • 指针、寄存器、位操作

    定义寄存器的绝对地址 xff0c 并转换为指针进行位操作 1 位操作示例一 define PERIPH BASE unsigned int 0x40000000 define APB2PERIPH BASE PERIPH BASE 43 0
  • 详解TCP连接的建立

    TCP首部格式 TCP报文段首部的前20个字节是固定的 xff0c 后面有4N字节是根据需要而增加的选项 xff0c 因此TCP报文段的最小长度为20字节 首部固定部分的各字段的意义如下 xff1a 1 源端口和目的端口 xff1a 加上I
  • printf打印函数的原理浅析

    printf的底层原理浅析 目录 printf的底层原理浅析前言函数变参格式解析一个简单的printf示例结语 补充 前言 最近在学习linux内核的时候用到了自定义实现的printf xff0c 学习了一下 xff0c 在此记录 xff0
  • 基于公开网站挖掘敏感信息的研究与分析- Fofa 搜索

    基于公开公开网站挖掘敏感信息的研究与分析 Fofa 搜索 一 引言 1 1项目概述 基于公开网站的敏感信息挖掘研究与分析 xff1a 针对目前网络安全整体的趋势我们从google等搜索引擎 Github等代码库 FOFA等空间搜索这三个方面
  • HTTP报文

    一 HTTP报文的结构 用于HTTP协议交互的信息 xff0c 称为HTTP报文 客户端的HTTP报文称为请求报文 xff0c 服务端的称为响应报文 HTTP报文结构如下图 xff1a 下面是请求报文的一个实例 xff1a 请求行 xff1
  • 用C++写一个UDP发送和接收程序

    发送程序Sender cpp include lt stdio h gt include lt string gt include lt iostream gt include lt winsock h gt using namespace
  • STM32自学笔记(五)串口通信

    xff08 想要深入理解就把前面的看下 xff0c 否则直接看使用总结即可 xff09 usart文件夹 usart 文件夹内包含了 usart c和usart h两个文件 这两个文件用于串口的初始化和中断接收 代码只针对了串口1 xff0
  • sockaddr_in详解

    struct sockaddr in short sin family Address family一般来说AF INET xff08 地址族 xff09 PF INET xff08 协议族 xff09 unsigned short sin
  • ubuntu下好用的TCP/UDP调试工具

    github官方链接 GitHub s kyo mNetAssist mNetAssist A UDP TCP Assistant 编译好的安装包 ubuntu下好用的TCP UDP调试工具 网络设备文档类资源 CSDN下载 1 解压dpk
  • Linux网络编程之connect函数分析

    在一个 CLIENT SERVER模型的网络应用中 xff0c 客户端的调用序列大致如下 xff1a socket gt connect gt recv send gt close 其中socket没有什么可疑问的 xff0c 主要是创建一
  • linux route 命令

    显示现在所有路由 route n root 64 Ubuntu route Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 10
  • 大量LAST_ACK 分析过程

    记录一下自己的思想过程 现象 在netstat的时候发现大量处于LAST ACK状态的TCP连接 xff0c 达到在ESTABLISHED状态的90 以上 root 64 ccsafe netstat ant fgrep 34 34 cut
  • const 与重载

    const到底是不是一个重载的参考对象 xff0c 请看下面的例子 class A public void f int i std cout lt lt 34 1 34 函数1 void f int i const std cout lt
  • 指向成员函数的指针

    指向成员函数的指针 取一个非静态成员函数的地址 xff0c 如果该函数是nonvirtual xff0c 则得到的结果是它在内存中真正的地址 然而这个值也不是完全的 xff0c 它也需要被绑定于某个class object的地址上 xff0
  • rviz 远程显示及控制移动机器人的导航

    环境 xff1a xff08 1 xff09 虚拟机本地端IP 192 168 10 30 xff08 虚拟机需要通过桥接的形式与PC本地机连接 xff0c PC 机IP 192 168 10 21 xff09 xff08 2 xff09
  • iptables - administration tools for packet filtering and NAT

    2 iptables administration tools for packet filtering and NAT Linux Iptables Manual Incoming Traffic V 43 43 PREROUTING 4
  • C++ 内部类、嵌套类

    1 嵌套类 nested class 一个类可以定义在另一个类的内部 xff0c 前者称为嵌套类 xff0c 嵌套类时一个独立的类 xff0c 和外层类基本没什么关系 它通过提供新的类型类作用域来避免名称混乱 嵌套类必须声明在类的内部 xf
  • SONY VAIO P VPCP118KJ索尼酷袋本 鸡肋上网本初体验

    随着消费者市场需求的不断多样化和个性化 xff0c 个人电脑厂家开始不断突破创新 xff0c 在产品线拼装出各种各样的个人电脑 xff0c 主打性能的游戏本 xff0c 主打便携轻薄本 xff0c 2009年的CES上索大法推出了一款与众不
  • 第2课【CMSIS和标准库开发】标准库 CMSIS 分层

    目录 基本知识框架课堂笔记CMSISCMSIS的分层关系和作用CMSIS层文件结构内核函数层文件外设函数访问层文件 标准库开发标准库开发 LED GPIO标准库开发 KEY GPIO标准库开发 位带操作位带位带位带别名区位带区和位带别名区的