已阅读5页,还剩20页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
微机原理与接口技术STM32实验 指 导 书V2.0龙岩学院 物理与机电工程学院电子工程系 2016.3实验一 GPIO 模块实验一、实验目的 1、学习 STM32 模块的 GPIO 模块的配置2、学习 STM32 模块的输入输出功能的实验二、实验原理 1 、 STM32 的 IO 口 相 比 51 而 言 要 复 杂 得 多 , 所 以 使 用 起 来 也 困 难 很 多 。 首 先 STM32 的 IO 口可以由软件配置成如下 8 种模式:输入浮空、输入上拉、输入下拉、模拟 输入、开漏输出、推挽输出、推挽式复用功能、开漏复用功能。STM32 的每个 IO 端口都有 7 个寄存器来控制。他们分别是:配置模式的 2 个 32 位的 端口配置寄存器 CRL 和 CRH;2 个 32 位的数据寄存器 IDR 和 ODR;1 个 32 位的置位/复位 寄存器 BSRR;一个 16 位的复位寄存器 BRR; 1 个 32 位的锁存寄存器 LCKR。刚复位后, 复用功能未开启,I/O 端口被配置成浮空输入模式STM32 的 CRL 控 制 着 每组 IO 端口( AG ) 的 低 8 位 的 模式 。 每 个 IO 端 口 的 位占 用 CRL 的 4 个位,高两位为 CNF,低两位为 MODE。这里我们可以记住几个常用的配置, 比如 0X0 表示模拟输入模式(ADC 用)、0X3 表示推挽输出模式(做输出口用,50M 速率)、 0X8 表示上/下拉输入模式(做输入口用)、0XB 表示复用输出(使用 IO 口的第二功能,50M 速率)。CRH 的作用和 CRL 完全一样在固件库开发中, 操作寄存器 CRH 和 CRL 来配置 IO 口的模式和速度是通过 GPIO 初始化 函数完成:void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct); 第一个参数是用来指定 GPIO,取值范围为 GPIOAGPIOG。第二个参数为初始化参数结构体指针,结构体类型为 GPIO_InitTypeDef。查看结构体的定义: typedef structuint16_t GPIO_Pin; GPIOSpeed_TypeDef GPIO_Speed; GPIOMode_TypeDef GPIO_Mode;GPIO_InitTypeDef;通过初始化结构体初始化 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_Mode 是用来设置对应 IO 端口的输出输入模式,这些模式在 MDK 中是通过一个枚举 类型定义的: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;IDR 是一个端口输入数据寄存器,要想知道某个 IO 口的电平状态,只要读这个寄存器,再 看某个位的状态就可以了。使用起来是比较简单的。在固件库中操作 IDR 寄存器读取 IO 端口数据是通过 GPIO_ReadInputDataBit 函数实现的:uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)比如我要读 GPIOA.5 的电平状态,那么方法是:GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_5); 返回值是 1(Bit_SET)或者 0(Bit_RESET); ODR 是一个端口输出数据寄存器。该寄存器为可读写,从该寄存器读出来的数据可以用于 判断当前 IO 口的输出状态。而向该寄存器写数据,则可以控制某个 IO 口的输出电平。在固 件库中设置 ODR 寄存器的值来控制 IO 口的输出状态是通过函数 GPIO_Write 来实现的:void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);BSRR 寄存器是端口位设置/清除寄存器。在 STM32 固件库中,通过 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) 2、IO 操作步骤很简单1)使能 IO 口时钟。调用函数为 RCC_APB2PeriphClockCmd()。2)初始化 IO 参数。调用函数 GPIO_Init();3)操作 IO。STM32 的 GPIO 库函数如下表 1 所示表 1 GPIO 库函数列表三、实验设备与器件 1、计算机2、STM32 开发板3、仿真器四、实验内容 1 通过按键来控制 LED 和蜂鸣器,当按键 KEY0 按下 LED1 亮,KEY2 控制 LED0,KEY3控制 BEEP,电路的硬件连接图 1 所示。图 1 电路连接图1) 设计 LED 的初始化程序新建 led.c 和 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端口时钟 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; /IO口速度为50MHz GPIO_Init(GPIOB, &GPIO_InitStructure); /根据设定参数初始化GPIOB.5 GPIO_SetBits(GPIOB,GPIO_Pin_5); /PB.5 输出高 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;/LED1-PE.5 端口配置, 推挽输出 GPIO_Init(GPIOE, &GPIO_InitStructure); GPIO_SetBits(GPIOE,GPIO_Pin_5); Led.h /推挽输出 ,IO口速度为50MHz /PE.5 输出高 #ifndef LED_H #define LED_H #include sys.h #define LED0 PBout(5)/ PB5 #define LED1 PEout(5)/ PE5 void LED_Init(void);/初始化 #endif 2) 设计 BEEP 驱动程序新建 beep.c 文件并输入下面代码#include beep.h /初始化PB8为输出口.并使能这个口的时钟 /蜂鸣器初始化 void BEEP_Init(void) GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);/使能GPIOB端口时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;/BEEP-PB.8 端口配置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;/推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; /速度为50MHz GPIO_Init(GPIOB, &GPIO_InitStructure); /根据参数初始化GPIOB.8 GPIO_ResetBits(GPIOB,GPIO_Pin_8);/输出0,关闭蜂鸣器输出 新建 beep.h 文件#ifndef BEEP_H #define BEEP_H #include sys.h /蜂鸣器端口定义 #define BEEP PBout(8) / BEEP,蜂鸣器接口 void BEEP_Init(void); /初始化 #endif 3)编写 key.c 文件 #include stm32f10x.h #include key.h #include sys.h #include delay.h /按键初始化函数 void KEY_Init(void) /IO初始化 GPIO_InitTypeDef GPIO_InitStructure; /初始化KEY0-GPIOA.13,KEY1-GPIOA.15 上拉输入 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE,ENABLE);/使能 PORTA,PORTE时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;/PE24 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; /设置成上拉输入 GPIO_Init(GPIOE, &GPIO_InitStructure);/初始化GPIOE2,3,4 /初始化 WK_UP-GPIOA.0 下拉输入 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; /PA0设置成输入,默认下拉 GPIO_Init(GPIOA, &GPIO_InitStructure);/初始化GPIOA.0 /按键处理函数 /返回按键值 /mode:0,不支持连续按;1,支持连续按; /0,没有任何按键按下 /1,KEY0按下 /2,KEY1按下 /3,KEY2按下 /4,KEY3按下 WK_UP /注意此函数有响应优先级,KEY0KEY1KEY2KEY3! u8 KEY_Scan(u8 mode) static u8 key_up=1;/按键按松开标志 if(mode)key_up=1; /支持连按 if(key_up&(KEY0=0|KEY1=0|KEY2=0|KEY3=1) delay_ms(10);/去抖动 key_up=0; if(KEY0=0)return KEY_RIGHT; else if(KEY1=0)return KEY_DOWN; else if(KEY2=0)return KEY_LEFT; else if(KEY3=1)return KEY_UP; else if(KEY0=1&KEY1=1&KEY2=1&KEY3=0)key_up=1; return 0;/ 无按键按下 新建 key.h 文件,并编写如下的代码 #ifndef KEY_H #define KEY_H #include sys.h /#define KEY0 PEin(4) /PE4 /#define KEY1 PEin(3) /PE3 /#define KEY2 PEin(2) /PE2 /#define KEY3 PAin(0) /PA0 WK_UP #define KEY0 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)/读取按键0 #define KEY1 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)/读取按键1 #define KEY2 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2)/读取按键2 #define KEY3 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)/读取按键3(WK_UP) #define KEY_UP4 #define KEY_LEFT 3 #define KEY_DOWN 2 #define KEY_RIGHT 1 void KEY_Init(void);/IO初始化 u8 KEY_Scan(u8);/按键扫描函数 #endif 3) 编写主函数 main.c#include led.h #include delay.h #include key.h #include sys.h #include beep.h int main(void) u8 t; delay_init(); /延时函数初始化 LED_Init();/LED端口初始化 KEY_Init(); /初始化与按键连接的硬件接口 BEEP_Init(); /初始化蜂鸣器端口 LED0=0;/先点亮红灯 while(1) t=KEY_Scan(0);/得到键值 if(t) switch(t) case KEY_UP: /控制蜂鸣器 BEEP=!BEEP; break; case KEY_LEFT:/控制LED0翻转 LED0=!LED0; break; case KEY_DOWN:/控制LED1翻转 LED1=!LED1; break; case KEY_RIGHT: /同时控制LED0,LED1翻转 LED0=!LED0; LED1=!LED1; break; else delay_ms(10); 五、实验总结 1、总结库函数开发方法和寄存器开发方式的区别2、理解 STM32 开发的软件的组织方式六、预习要求 1、预习 GPIO 模块的功能2、预习 GPIO 函数库的配置方法实验二 串口通信实验一、实验目的 1、学习 STM32 串口模块的原理、配置2、学习 STM32 串口的发送和接受的功能实现二、实验原理 STM32 最多可提供 5 路串口,有分数波特率发生器、支持单线光通信和半双工单线通 讯、支持 LIN、智能卡协议和 IrDA SIR ENDEC 规范(仅串口 3 支持)、具有 DMA 等。串口设置的一般步骤可以总结为如下几个步骤: 1) 串口时钟使能,GPIO时钟使能 2) 串口复位 3) GPIO端口模式设置 4) 串口参数初始化 5) 开启中断并且初始化NVIC(如果需要开启中断才需要这个步骤) 6) 使能串口 7) 编写中断处理函数 下面,我们就简单介绍下这几个与串口基本配置直接相关的几个固件库函数。这些函数和定 义主要分布在 stm32f10x_usart.h 和 stm32f10x_usart.c 文件中。 1.串口时钟使能。串口是挂载在APB2下面的外设,所以使能函数为: RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1); 2.串口复位。当外设出现异常的时候可以通过复位设置,实现该外设的复位,然后重新配 置这个外设达到让其重新工作的目的。一般在系统刚开始配置外设的时候,都会先执行复 位该外设的操作。复位的是在函数USART_DeInit()中完成: void USART_DeInit(USART_TypeDef* USARTx);/串口复位 比如我们要复位串口1,方法为:USART_DeInit(USART1); /复位串口1 3.串口参数初始化。串口初始化是通过USART_Init()函数实现的, void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct); 第一个入口参数是指定初始化的串口标号,这里选择USART1。 第二个入口参数是一个USART_InitTypeDef类型的结构体指针,这个结构体指针的成员变 量用来设置串口的一些参数。一般的实现格式为: 先申明一个USART_InitTypeDefUSART_InitStruct变量;后面在对变量进行初始化。初始 化的过程如下程序所示: USART_InitStructure.USART_BaudRate = bound;/一般设置为9600; USART_InitStructure.USART_WordLength = USART_WordLength_8b;/字长为8位数据格式 USART_InitStructure.USART_StopBits = USART_StopBits_1;/一个停止位 USART_InitStructure.USART_Parity = USART_Parity_No;/无奇偶校验位 USART_InitStructure.USART_HardwareFlowControl= USART_HardwareFlowControl_None;/无硬件数据流控制 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;/收发模式 USART_Init(USART1, &USART_InitStructure); /初始化串口 从上面的初始化格式可以看出初始化需要设置的参数为:波特率,字长,停止位,奇偶校 验位,硬件数据流控制,模式(收,发)。我们可以根据需要设置这些参数。 4.数据发送与接收。STM32的发送与接收是通过数据寄存器USART_DR来实现的,这是一个双 寄存器,包含了TDR和RDR。当向该寄存器写数据的时候,串口就会自动发送,当收到收据 的时候,也是存在该寄存器内。 STM32库函数操作USART_DR寄存器发送数据的函数是: void USART_SendData(USART_TypeDef* USARTx, uint16_t Data); 通过该函数向串口寄存器USART_DR写入一个数据。 STM32库函数操作USART_DR寄存器读取串口接收到的数据的函数是: uint16_t USART_ReceiveData(USART_TypeDef* USARTx); 通过该函数可以读取串口接受到的数据。 5.串口状态。串口的状态可以通过状态寄存器USART_SR读取。USART_SR的各位描述如图2.1 所示: 图2.1 状态寄存器位定义 这里我们关注一下两个位,第5、6位RXNE和TC。 RXNE(读数据寄存器非空),当该位被置1的时候,就是提示已经有数据被接收到了,并且 可以读出来了。这时候我们要做的就是尽快去读取USART_DR,通过读USART_DR可以将该位 清零,也可以向该位写0,直接清除。 TC(发送完成),当该位被置位的时候,表示USART_DR内的数据已经被发送完成了。如果 设置了这个位的中断,则会产生中断。该位也有两种清零方式:1)读USART_SR,写 USART_DR。2)直接向该位写0。 状态寄存器的其他位我们这里就不做过多讲解,大家需要可以查看中文参考手册。 在我们固件库函数里面,读取串口状态的函数是: FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG); 这个函数的第二个入口参数非常关键,它是标示我们要查看串口的哪种状态,比如上面讲 解的RXNE(读数据寄存器非空)以及TC(发送完成)。例如我们要判断读寄存器是否非空 (RXNE),操作库函数的方法是: USART_GetFlagStatus(USART1,USART_FLAG_RXNE); 我们要判断发送是否完成(TC),操作库函数的方法是: USART_GetFlagStatus(USART1,USART_FLAG_TC); 这些标识号在MDK里面是通过宏定义定义的: #define USART_IT_PE(uint16_t)0x0028)#define USART_IT_TXE(uint16_t)0x0727)#define USART_IT_TC(uint16_t)0x0626)#define USART_IT_RXNE(uint16_t)0x0525)#define USART_IT_IDLE(uint16_t)0x0424)#define USART_IT_LBD(uint16_t)0x0846)#define USART_IT_CTS(uint16_t)0x096A)#define USART_IT_ERR(uint16_t)0x0060)#define USART_IT_ORE(uint16_t)0x0360)#define USART_IT_NE(uint16_t)0x0260)#define USART_IT_FE(uint16_t)0x0160)6.串口使能。串口使能是通过函数USART_Cmd()来实现的,这个很容易理解,使用方法 是: USART_Cmd(USART1, ENABLE); /使能串口 7.开启串口响应中断。有些时候当我们还需要开启串口中断,那么我们还需要使能串口中 断,使能串口中断的函数是: void USART_ITConfig(USART_TypeDef*USARTx,uint16_t USART_IT, FunctionalState NewState) 这个函数的第二个入口参数是标示使能串口的类型,也就是使能哪种中断,因为串口的中 断类型有很多种。比如在接收到数据的时候(RXNE读数据寄存器非空),我们要产生中 断,那么我们开启中断的方法是: USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);/开启中断,接收到数据中断 我们在发送数据结束的时候(TC,发送完成)要产生中断,那么方法是: USART_ITConfig(USART1,USART_IT_TC,ENABLE); 8.获取相应中断状态。当我们使能了某个中断的时候,当该中断发生了,就会 设置状态寄存器中的某个标志位。经常我们在中断处理函数中,要判断该中断 是哪种中断,使用的函数是: ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT) 比如我们使能了串口发送完成中断,那么当中断发生了,我们便可以在中断处 理函数中调用这个函数来判断到底是否是串口发送完成中断,方法是: USART_GetITStatus(USART1, USART_IT_TC) 返回值是SET,说明是串口发送完成中断发生。 通过以上的讲解,我们就可以达到串口最基本的配置了,关于串口更详细的介 绍,请参考STM32参考手册第516页至548页,通用同步异步收发器一章。 三、实验设备与器件 1、计算机2、STM32 开发板3、仿真器四、实验内容 1、编写程序通过 STM32 串口实现如下功能:PC 向单片机发送“Hello World!”,通过调 试助手在电脑上显示出来,单片机向 PC 发送接收到的内容,同时蜂鸣器响一次。硬件电 路连接图如下图 2.2 所示。图 2.2 串口硬件连接图五、实验总结 1、串口实现发送的原理2、串口实现接受的原理六、预习要求 1、预习串口模块的功能2、预习串口函数库的配置方法实验三 外部中断实验一、实验目的 1、学习 STM32 外部中断模块的原理、配置2、学习 STM32 外部中断程序实现和中断服务程序编程二、实验原理 STM32的每个IO都可以作为外部中断的中断输入口, STM32F103的中断控制器支持 19个外部中断/事件请求。每个中断设有状态位,每个中断/事件都有独立的触发和屏蔽设 置。STM32F103的19个外部中断如表3-1所示: 表3-1 外部中断对应表 中断线号 功能 线015 对应外部IO口的输入中断 线16 连接到PVD输出 线17 连接到RTC闹钟事件 线18 连接到USB唤醒事件 STM32外部IO口的中断功能的代码主要分布在固件库的stm32f10x_exti.h和 stm32f10x_exti.c文件中。 在库函数中,配置GPIO与中断线的映射关系的函数GPIO_EXTILineConfig()来实现 的: void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource)该函数将GPIO端口与中断线映射起来,使用范例是: GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource2); 将中断线2与GPIOE映射起来,那么很显然是GPIOE.2与EXTI2中断线连接了。设置好中断 线映射之后,那么到底来自这个IO口的中断是通过什么方式触发的呢?接下来我们就要设 置该中断线上中断的初始化参数了。 产生一个软件中断的函数是 void EXTI_GenerateSWInterrupt(u32 EXTI_Line) 中断线上中断的初始化是通过函数EXTI_Init()实现的。EXTI_Init()函数的定义是: void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);EXTI_InitTypeDef EXTI_InitStructure; EXTI_InitStructure.EXTI_Line=EXTI_Line4; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE;EXTI_Init(&EXTI_InitStructure);/根据EXTI_InitStruct中指定的 下面我们用一个使用范例来说明这个函数的使用: 上面的例子设置中断线 4 上的中断为下降沿触发。STM32 的外设的初始化都是通过结构 体 来 设 置 初 始 值 的 , 这 里 就 不 罗 嗦 结 构 体 初 始 化 的 过 程 了 。 我 们 来 看 看 结 构 体typedef structuint32_t EXTI_Line;EXTI_InitTypeDef 的成员变量:EXTIMode_TypeDef EXTI_Mode; EXTITrigger_TypeDef EXTI_Trigger; FunctionalState EXTI_LineCmd;EXTI_InitTypeDef;从定义可以看出,有4个参数需要设置。 NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;/使能按键外部中断通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;/抢占优先级2, NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;/子优先级2 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;/使能外部中断通道 NVIC_Init(&NVIC_InitStructure);/中断优先级分组初始化 第一个参数是中断线的标号,取值范围为EXTI_Line0EXTI_Line15。这个在上面已经讲过 中断线的概念。也就是说,这个函数配置的是某个中断线上的中断参数。 第二个参数是中断模式,可选值为中断EXTI_Mode_Interrupt和事件EXTI_Mode_Event。 第三个参数是触发方式,可以是下降沿触发EXTI_Trigger_Falling,上升沿触发 EXTI_Trigger_Rising,或者任意电平(上升沿和下降沿)EXTI_Trigger_Rising_Falling。 最后一个参数就是使能中断线了。 我们设置好中断线和GPIO映射关系,然后又设置好了中断的触发模式等初始化参数。既然 是外部中断,涉及到中断我们当然还要设置NVIC中断优先级。这个在前面已经讲解过,这 里我们就接着上面的范例,设置中断线2的中断优先级。 上面这段代码相信大家都不陌生,我们在前面的串口实验的时候讲解过,这里不再讲解。 EXPORTEXTI0_IRQHandler EXPORTEXTI1_IRQHandler EXPORTEXTI2_IRQHandler EXPORTEXTI3_IRQHandler EXPORTEXTI4_IRQHandler EXPORTEXTI9_5_IRQHandlerEXPORTEXTI15_10_IRQHandler我们配置完中断优先级之后,接着我们要做的就是编写中断服务函数。中断服务函数的名 字是在MDK中事先有定义的。这里需要说明一下,STM32的IO口外部中断函数只有6个, 分别为: 中断线0-4每个中断线对应一个中断函数, 中断线5-9共用中断函数EXTI9_5_IRQHandler, 中断线10-15共用中断函数EXTI15_10_IRQHandler。 在编写中断服务函数的时候会经常使用到两个函数,第一个函数是判断某个中断线上 的中断是否发生(标志位是否置位): ITStatus EXTI_GetITStatus(uint32_t EXTI_Line); 这个函数一般使用在中断服务函数的开头判断中断是否发生。另一个函数是清除某个中断 线上的中断标志位: void EXTI_ClearITPendingBit(uint32_t EXTI_Line); 这个函数一般应用在中断服务函数结束之前,清除中断标志位。 常用的中断服务函数格式为: void EXTI2_IRQHandler(void)if(EXTI_GetITStatus(EXTI_Line3)!=RESET)/判断某个线上的中断是否发生 中断逻辑 EXTI_ClearITPendingBit(EXTI_Line3);/清除LINE上的中断标志位 在这里需要说明一下,固件库还提供了两个函数用来判断外部中断状态以及清除外部状态 标志位的函数EXTI_GetFlagStatus和EXTI_ClearFlag,他们的作用和前面两个函数的作用类 似。只是在EXTI_GetITStatus函数中会先判断这种中断是否使能,使能了才去判断中断标 志位,而EXTI_GetFlagStatus直接用来判断状态标志位。 下面我们再总结一下使用IO口外部中断的一般步骤: 1)初始化IO口为输入。 2)开启IO口复用时钟,设置IO口与中断线的映射关系。 3)初始化线上中断,设置触发条件等。 4)配置中断分组(NVIC),并使能中断。 5)编写中断服务函数。 通过以上几个步骤的设置,我们就可以正常使用外部中断了。三、实验设备与器件 1、计算机2、STM32 开发板3、仿真器四、实验内容 1、利用函数 void EXTI_GenerateSWInterrupt(u32 EXTI_Line),实现软件方式触发中断,要求 每隔 0.5S 触发一次软件中断,触发的中断线是中断线 1,在中断线 1 的中断服务程序中实 现对 LED0 的翻转控制。2、利用 KEY1 按键硬件触发一次中断,触发中断线 3,在对应的中断服务程序中实现对 LED1翻转控制。五、实验总结 1、外部中断的配置流程。2、软件触发中断和硬件触发中断的差别。六、预习要求 1、预习外部中断的配置流程。2、预习外部中断的相关函数。实验四 AD 实验一、实验目的 1、学习 STM32 AD 转换器原理、配置2、学习 STM32 AD 程序实现二、实验原理 STM32 拥有 13 个 ADC(STM32F101/102 系列只有 1 个 ADC),这些 ADC 可以独立 使用,也可以使用双重模式(提高采样率)。STM32 的 ADC 是 12 位逐次逼近型的模拟数字 转换器。它有 18 个通道,可测量 16 个外部和 2 个内部信号源。各通道的 A/D 转换可以单 次、连续、扫描或间断模式执行。ADC 的结果可以左对齐或右对齐方式存储在 16 位数据寄 存器中。模拟看门狗特性允许应用程序检测输入电压是否超出用户定义的高/低阀值。STM32 将 ADC 的转换分为 2 个通道组:规则通道组和注入通道组。规则通道相当于正 常运行的程序,而注入通道呢,就相当于中断。在程序正常执行的时候,中断是可以打断你 的执行的。同这个类似,注入通道的转换可以打断规则通道的转换,在注入通道被转换完成 之后,规则通道才得以继续转换。STM32 其 ADC 的规则通道组最多包含 16 个转换,而注入通道组最多包含 4 个通道。 STM32 的 ADC 最大的转换速率为 1Mhz,也就是转换时间为 1us(在 ADCCLK=14M,采样 周期为 1.5 个 ADC 时钟下得到),不要让 ADC 的时钟超过 14M,否则将导致结果准确度下 降。使用到的库函数分布在stm32f10x_adc.c文件和stm32f10x_adc.h文件中。下面讲解其详 细设置步骤: 1)开启PA口时钟和ADC1时钟,设置PA1为模拟输入。 STM32F103ZET6 的 ADC 通道 1 在 PA1 上,所以,我们先要使能 PORTA 的时钟和 ADC1 时钟,然后设置 PA1 为模拟输入。使能 GPIOA 和 ADC 时钟用 RCC_APB2PeriphClockCmd 函数,设置 PA1 的输入方式,使用 GPIO_Init 函数即可。这里我们列出 STM32 的 ADC 通 道与 GPIO 对应表:2)复位ADC1,同时设置ADC1分频因子。 开启ADC1时钟之后,我们要复位ADC1,将ADC1 的全部寄存器重设为缺省值之后我们就 可以通过RCC_CFGR设置ADC1的分频因子。分频因子要确保ADC1的时钟(ADCCLK)不 要超过14Mhz。这个我们设置分频因子位6,时钟为72/6=12MHz,库函数的实现方法是: RCC_ADCCLKConfig(RCC_PCLK2_Div6); ADC时钟复位的方法是: ADC_DeInit(ADC1); 这个函数非常容易理解,就是复位指定的 ADC。 3)初始化ADC1参数,设置ADC1的工作模式以及规则序列的相关信息。 在设置完分频因子之后,我们就可以开始ADC1的模式配置了,设置单次转换模式、触发 方式选择、数据对齐方式等都在这一步实现。同时,我们还要设置ADC1规则序列的相关 信息,我们这里只有一个通道,并且是单次转换的,所以设置规则序列中通道数为1。这些 在库函数中是通过函数ADC_Init实现的,下面我们看看其定义: void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct); 从函数定义可以看出,第一个参数是指定 ADC 号。这里我们来看看第二个参数,跟其他外typedef structuint32_t ADC_Mode;FunctionalState ADC_ScanConvMode; FunctionalState ADC_ContinuousConvMode; uint32_t ADC_ExternalTrigConv;uint32_t ADC_DataAlign; uint8_t ADC_NbrOfChannel;ADC_InitTypeDef;设初始化一样,同样是通过设置结构体成员变量的值来设定参数。 参数ADC_Mode故名是以是用来设置ADC的模式。前面讲解过,ADC的模式非常多,包括独立模式,注入同步模式等等,这里我们选择独立模式,所以参数 ADC_Mode_Independent。 参数ADC_ScanConvMode用来设置是否开启扫描模式,因为是单次转换,这里我们选择不 开启值DISABLE即可。 参数ADC_ContinuousConvMode用来设置是否开启连续转换模式,因为是单次转换模式, 所以我们选择不开启连续转换模式,DISABLE即可。 参数ADC_ExternalTrigConv是用来设置启动规则转换组转换的外部事件,这里我们选择软 件触发,选择值为ADC_ExternalTrigConv_None即可。 参数DataAlign用来设置ADC数据对齐方式是左对齐还是右对齐,这里我们选择右对齐方式 ADC_DataAlign_Right。 参数ADC_NbrOfChannel用来设置规则序列的长度,这里我们是单次转换,所以值为1即 可。 通过上面对每个参数的讲解,下面来看看我们的初始化范例:ADC_InitTypeDef ADC_InitStructure;ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;/ADC工作模式:独立模式 ADC_InitStructure.ADC_ScanConvMode = DISABLE;/AD单通道模式 ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;/AD单次转换模式 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;/转换由软件而不是外部触发启动 ADC_InitStructure.ADC_
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年养老机构食品安全培训课件
- 2026年基因治疗产品临床试验设计手册
- 2026年半导体评估会员运营协议
- 2026年医教协同促进学生心理健康新模式
- 2026-2030中国砖瓦行业盈利态势及竞争状况分析报告
- 2026年培训师社群运营与持续学习生态构建课程大纲
- 2026年企业管理中个人绩效与组织目标的统一
- 2026年神经外科手术室工作制度及流程
- 温州市2025浙江温州瑞安市事业单位引进人才76人笔试历年参考题库典型考点附带答案详解
- 深圳市2025年4月中共深圳市光明区委统一战线工作部选聘特聘专干1人(广东)笔试历年参考题库典型考点附带答案详解
- 2026广东东莞市松山湖社区卫生服务中心招聘纳入岗位管理编制外人员4人笔试备考试题及答案解析
- 2026西藏阿里地区普兰县审计局招聘审计协助人员的2人备考题库有答案详解
- 2026河南科高产业集团有限责任公司高级管理人员招聘7人笔试备考试题及答案解析
- 2026年中考历史考前冲刺:中国+世界(古代史|近代史|现代史) 小论文范文汇编
- 2025版《CSCO前列腺癌诊疗指南》全文
- DBJ50-T-157-2022房屋建筑和市政基础设施工程施工现场从业人员配备标准
- 天使爱美丽-电影剧本法语版
- 《简单教数学》读书-分享-
- 高标准农田建设监理评估报告
- YS/T 431-2000铝及铝合金彩色涂层板、带材
- 肺隔离症介入治疗课件
评论
0/150
提交评论