【嵌入式之外部中断实验】

外部中断实验:

本次实验是在基础工程建立的基础上进行的

点击跳转: 基础项目建立

题目:

PB8、 PB0作为中断请求输入端,PA0-PA7作为推挽输出,输出速度50MHz, 接8个LED灯。主程序实现的功能:8个LED灯流水显示。中断服务程序实现的功能-EXTI8:高4位、低4位LED灯交替闪6次。EXTI0:8位LED灯全闪4次。 EXTI0可以嵌套EXTI8。

题目详解:

  1. PB8、PB0作为中断请求输入端:GPIOB的引脚8和0设置为输入端
  2. PA0-PA7作为推挽输出,输出速度50MHz, 接8个LED灯:对GPIOA设置
  3. 8个LED灯流水显示:对PA0-PA7操作
  4. 中断服务程序实现的功能-EXTI8:高4位、低4位LED灯交替闪6次:PA0~ PA3 与 PA4~ PA7交替闪烁六次
  5. EXTI0:8位LED灯全闪4次:PA0-PA7闪四次
  6. EXTI0可以嵌套EXTI8:引脚0的抢占优先级比引脚8的高(当8执行后立即执行0,0的操作会抢断8,会先执行0然后再会到8)

工程文件简介:

  1. CMSIS
    (1)core_cm3.c:提供ARM Cortex-M3内核的接口,管理内核的控制和协调。
    (2)system_stm32f10x.c:设置系统时钟和总线时钟,配置STM32的启动和外设寄存器。

  2. Library
    (1)stm32f10x_flash.c:管理STM32的闪存操作,如擦除、编程和读取数据。
    (2)stm32f10x_gpio.c:控制STM32的通用输入/输出(GPIO)引脚,读取或设置其状态。
    (3)stm32f10x_rcc.c:配置和管理STM32的复位和时钟控制(RCC),包括系统时钟、时钟源和分频。
    (4)misc.c:包含一些杂项功能,如初始化函数和延迟函数。
    (5)stm32f10x_exti.c:管理STM32的外部中断(EXTI),配置、触发或处理外部中断。

  3. STARTUP
    (1)startup_stm32f10x_hd.s:初始化处理器和设置堆栈的启动文件。

  4. USER
    (1)stm32f10x_it.c:处理STM32的中断,包括配置、触发或处理中断。
    (2)stm32f10x_conf.h:包含STM32的一些配置选项,如系统时钟频率和外设时钟频率。

实验过程

1.在基础项目建立的项目上再添加两个文件:
在这里插入图片描述
2.配置User中的main.c文件

/*Include---------------------------*/
#include"stm32f10x.h" // 包含所需的STM32F10x系列的头文件
#include<stdio.h>

//----------------函数声明--------------------
void Delay_MS(u16 dly); // 声明延迟函数,以毫秒为单位
void RCC_Configuration(void); // 声明系统时钟配置函数
void GPIO_Configuration(void); // 声明GPIO配置函数
void EXTI_Configuration(); // 声明外部中断配置函数
void NVIC_Configuration(); // 声明中断向量表配置函数

/*******************************************************************************
* Function Name  : main
* Description    : 主程序。
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/ 
int main(void)
{ 
    /* ------------- 从这里开始 -------------- */
    u8 i; // 定义一个8位无符号整数变量 i
    
    RCC_Configuration(); // 调用系统时钟配置函数
    GPIO_Configuration(); // 调用GPIO配置函数
    EXTI_Configuration(); // 调用外部中断配置函数
    NVIC_Configuration(); // 调用中断向量表配置函数
    
    while(1) // 无限循环
    {
        for(i=0;i<8;i++){ // 循环8次,控制GPIO输出
            GPIO_Write(GPIOA,0x01<<i); // 在GPIOA端口写入一个值,控制LED等输出
            Delay_MS(500); // 延迟500毫秒
        }	 
    }
    /* ------------- 从这里结束 -------------- */
}

/*******************************************************************************
* Function Name  : Delay_Ms
* Description    : 延迟1毫秒。
* Input          : dly (毫秒)
* Output         : None
* Return         : None
*******************************************************************************/
void Delay_MS(u16 dly)
{
    u16 i, j;
    for(i=0; i<dly; i++) // 外层循环,用于控制延迟的次数
        for(j=1000; j>0; j--); // 内层循环,用于实现延迟
}

/*******************************************************************************
* Function Name  : RCC_Configuration
* Description    : 配置不同的系统时钟。
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
// 系统时钟配置函数
void RCC_Configuration(void)
{
    //----------启用外部RC振荡-----------
    RCC_DeInit(); // 将时钟配置为复位值
    RCC_HSEConfig(RCC_HSE_ON); // 启用外部高速振荡器
    while(RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET); // 等待外部高速振荡器就绪
    
    // 配置FLASH存储器
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); // 启用预取缓冲区
    FLASH_SetLatency(FLASH_Latency_2); // Flash存储器延迟为2个等待周期
    
    // 配置时钟分频系数
    RCC_HCLKConfig(RCC_SYSCLK_Div1); // HCLK = SYSCLK
    RCC_PCLK2Config(RCC_HCLK_Div1); // PCLK2 = HCLK
    RCC_PCLK1Config(RCC_HCLK_Div2); // PCLK1 = HCLK/2
    
    // 配置PLL时钟
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9); // PLLCLK = 8MHz * 9 = 72MHz
    RCC_PLLCmd(ENABLE); // 启用PLLCLK
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); // 等待PLLCLK就绪
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); // 选择PLL作为系统时钟
    while(RCC_GetSYSCLKSource()!=0x08); // 等待PLL作为系统时钟源生效
    
    // 启用GPIOA和GPIOB的时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); // 启用APB2外设GPIOA的时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); // 启用APB2外设GPIOB的时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); // 启用AFIO的时钟
}

/* ------------- 从这里开始 -------------- */
// GPIO配置函数	
void GPIO_Configuration(void)
{
    GPIO_InitTypeDef GPIO;
 
    // 配置PA0~PA7引脚为推挽输出模式,最大输出速率为50MHz
    GPIO.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
    GPIO.GPIO_Speed = GPIO_Speed_50MHz;	//输出速率为50MHz
    GPIO.GPIO_Mode = GPIO_Mode_Out_PP;	// 将PA0~PA7引脚设置为推挽输出模式
    GPIO_Init(GPIOA , &GPIO);	// 初始化GPIOA
 
    // 配置PB8和PB0引脚为带上拉输入模式	// 配置PB8和PB0
    GPIO.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_8;
    GPIO.GPIO_Mode = GPIO_Mode_IPU;  // 将PB8和PB0引脚为带上拉输入模式
    GPIO_Init(GPIOB , &GPIO);	// 初始化GPIOB
}

// 外部中断配置函数
void EXTI_Configuration(void)
{
    EXTI_InitTypeDef EXTI_InitStructure; 	// 定义结构体变量
    // 配置外部中断线8(对应PB8引脚)
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource8);	// 将GPIOB引脚8配置为外部中断线
    EXIT_Delnit();	// 对外部终端初始化,清除引脚的引用
    EXTI_InitStructure.EXTI_Line = EXTI_Line8; 	// 将GPIOB的引脚8设置为外部中断线
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; 	// 中断模式 (还有事件模式)
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;	//下降沿触发模式(有高电平转换为低电平) (还有上升言模式、上升下降沿模式)
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;  // 指定启用外部中断线,允许相应的中断请求触发
    EXTI_Init(&EXTI_InitStructure);	// 初始化外部中断控制器的配置
    
    // 配置外部中断线0(对应PB0引脚)
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);	// 将GPIOB引脚0配置为外部中断线
    EXTI_InitStructure.EXTI_Line = EXTI_Line0; 	// 将GPIOB的引脚0设置为外部中断线
    EXTI_Init(&EXTI_InitStructure);	// 初始化外部中断控制器的配置
}

// 中断向量表配置函数
void NVIC_Configuration(void)
{   
    NVIC_InitTypeDef NVIC_InitStructure;	// 定义结构体变量
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); // 设置优先级分组为第一组
	
    // 配置外部中断9到5的中断通道
    NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;	// 配置的是外部中断线9到5的中断通道
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;	// 设置抢占优先级为1
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 设置响应优先级为0
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;	// 启用该中断通道
    NVIC_Init(&NVIC_InitStructure);	// 初始化嵌套向量中断控制器
	
    // 配置外部中断0的中断通道
    NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;	// 配置的是外部中断线0的中断通道
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;	// 设置抢占优先级为0
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; 	// 设置响应优先级为0
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;	// 启用该中断通道
    NVIC_Init(&NVIC_InitStructure);	// 初始化嵌套向量中断控制器
}
/* ------------- 从这里结束 -------------- */

3.配置User中的stm32f10x_it.c

/**
  ******************************************************************************
  * @file    Project/STM32F10x_StdPeriph_Template/stm32f10x_it.c 
  * @author  MCD Application Team
  * @version V3.5.0
  * @date    08-April-2011
  * @brief   Main Interrupt Service Routines.
  *          This file provides template for all exceptions handler and 
  *          peripherals interrupt service routine.
  ******************************************************************************
  * @attention
  *
  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  *
  * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_it.h"

/** @addtogroup STM32F10x_StdPeriph_Template
  * @{
  */

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/******************************************************************************/
/* Cortex-M3 Processor Exceptions Handlers                                     */
/******************************************************************************/

// Cortex-M3 处理器的异常处理函数

/**
  * @brief  This function handles NMI exception.
  * @param  None
  * @retval None
  */
void NMI_Handler(void)
{
    // 处理 NMI 异常
}

// ...(其他异常处理函数,如 HardFault_Handler、MemManage_Handler等)

/******************************************************************************/
/* STM32F10x Peripherals Interrupt Handlers                                   */
/******************************************************************************/

// STM32F10x 外设的中断处理函数

/**
  * @brief  EXTI9_5_IRQHandler 处理外部中断线5到9的中断。
  * @param  None
  * @retval None
  */
  
// 当EXTI9-5的中断发生时,会调用这个中断处理函数
void EXTI9_5_IRQHandler(void)
{
    if(EXTI_GetFlagStatus(EXTI_Line8) != RESET)  // 检查Line8(即Pin8上的外部中断)是否被触发。如果已经触发,会返回一个非零值
    {
        u8 i;	// 定义一个8位无符号整数变量i,用于循环控制
        for(i=0; i<6; i++){	// 对i进行一个从0到5的循环
            GPIO_Write(GPIOA, 0x0F); // 高四位灯亮
            Delay_MS(500);	// 延迟500毫秒,让LED灯亮起来。
            GPIO_Write(GPIOA, 0xF0); // 低四位灯灭
            Delay_MS(500); 	 
        }
    }            
    EXTI_ClearFlag(EXTI_Line8);	// 清除Line8的中断标志,意味着我们处理了这次中断,不会再被这个中断再次打断
}

/**
  * @brief  EXTI0_IRQHandler 处理外部中断线0的中断。
  * @param  None
  * @retval None
  */
void EXTI0_IRQHandler(void)
{
    if (EXTI_GetFlagStatus(EXTI_Line0) != RESET) {	// 检查Line8(即Pin8上的外部中断)是否被触发。如果已经触发,会返回一个非零值
        u8 i;	// 定义一个8位无符号整数变量i,用于循环控制
        for (i = 0; i < 4; i++) {
            GPIO_Write(GPIOA, 0xFF); // 所有灯全亮
            Delay_MS(2000);
            GPIO_Write(GPIOA, 0x00); // 所有灯全灭
            Delay_MS(2000);
        }
    }
    EXTI_ClearFlag(EXTI_Line0);	// 清除Line8的中断标志,意味着我们处理了这次中断,不会再被这个中断再次打断
}

4.编译,选择main.c,点击编译(第一次出错可能,再编译一次):
在这里插入图片描述
5.编译成功:
在这里插入图片描述
6.仿真:
在这里插入图片描述

7.打开GPIOA(输出),GPIOB(输入)
在这里插入图片描述
8.运行:
在这里插入图片描述
9.调试:
9.1 P0功能测试:
在这里插入图片描述
9.2 P8功能测试
在这里插入图片描述

  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值