1、嵌入式系统设计(基于STM32F429)第 5 章课后题参考答案1. 列举 GPIO 的工作模式。答:(1) 输入浮空模式。(2) 输入上拉模式。(3) 输入下拉模式。(4) 模拟功能模式。(5) 具有上拉/下拉功能的开漏输出模式。(6) 具有上拉/下拉功能的推挽输出模式。(7) 具有上拉/下拉功能的复用功能推挽模式。(8) 具有上拉/下拉功能的复用功能开漏模式。2. STM32F429 系列微控制器每个 GPIO 端口有 16 个 引脚。3. 当引脚被配置为模拟功能模式时,上拉/下拉功能应被_禁止_。4. 当引脚被配置为输出模式,而输出类型被配置为开漏时,引脚要输出高电平,需要 使能引脚上拉
2、功能 。5. 控制引脚输出电平时,需要操作 ODR 寄存器;获取引脚状态需要操作 IDR 寄存器。6. 在 stm32f429 的库函数中,使能 GPIOA 时钟,使用的库函数是 RCC_AHB1PeriphClockCmd ( RCC_AHB1Periph_GPIOA, ENABLE) 。7. 在 stm32f429 的库函数中,初始化 GPIO 功能,使用的库函数是 void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct) 。8. 当要同时初始化某个 GPIO 的 1 号、2 号引脚,赋给 GPIO_Ini
3、tTypeDef 结构体类型成员 GPIO_Pin的值是 GPIO_Pin_1 | GPIO_Pin_2 。9 在 stm32f429 的库函数中, 读取某个特定 GPIO 引脚状态, 使用的库函数是 uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) 。10. 在 stm32f429 的库函数中,设定某些特定 GPIO 引脚输出状态,使用的库函数是void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) 和 void GPIO_ResetBits(
4、GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) 。11. 结合电路说明推挽输出和开漏输出的区别。答:在推挽输出下,输出电路中有 PMOS 和 NMOS 管组成的推挽结构电路,当 ODR 寄存器中对应位写1 时,NMOS 管截止,PMOS 管导通,引脚输出高电平。当 ODR 寄存器中对应位写0时,NMOS 管导通, PMOS 管截止,引脚输出低电平。在开漏输出下,输出电路中有只有 NMOS 管,当 ODR 寄存器中对应位写1时,NMOS 管截止,这是引脚处于浮空状态,必须通过上拉电阻使引脚输出高电平。当 ODR 寄存器中对应位写0时,NMOS 管导通,PMOS 管
5、截止,引脚输出低电平。12. 当把引脚配置为模拟输入模式时,那么它是否还具备耐 5V 功能? 答:不具备耐 5V 功能。此时,引脚输入通道和数字电路隔离,处于模拟电路状态13. 简述片上外设使用初始化流程。答:(1) 使能 GPIO 的时钟(非常重要),涉及以下文件。(2) 设置对应于片上外设使用的 GPIO 工作模式。(3) 如果使用复用功能,需要单独设置每一个 GPIO 引脚的复用功能。(4) 在应用程序中读取引脚状态、控制引脚输出状态或使用复用功能完成特定功能。14. 编写程序,将GPIOD 的 1 号、3 号、5 号、7 号、9 号引脚配置为推挽输出模式,速度为50MHz, 将 0、2
6、 号、4 号、6 号、8 号引脚配置为上拉输入模式。答:GPIO_InitTypeDef GPIO_InitStructure;RCC_AHB1PeriphClockCmd ( RCC_AHB1Periph_GPIOD, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1| GPIO_Pin_3| GPIO_Pin_5| GPIO_Pin_7| GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;GPIO_InitStructure.GPIO_OType = GPIO_OType_PP
7、; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOD, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0| GPIO_Pin_2| GPIO_Pin_4| GPIO_Pin_6| GPIO_Pin_8; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOD, &GPIO_InitStru
8、cture);15. 编写程序,将 GPIOD 的 1 号、5 号、7 号引脚输出高电平,3 号、9 号引脚输出低电平,并将引脚 2 号、6 号、8 号上的状态读到处理器中。答:unsigned short int a,b,c;GPIO_SetBits(GPIOD , GPIO_Pin_1| GPIO_Pin_5| GPIO_Pin_7) ; GPIO_ResetBits(GPIOD , GPIO_Pin_3| GPIO_Pin_9) ;a = GPIO_ReadInputDataBit(GPIOD , GPIO_Pin_2) ; b = GPIO_ReadInputDataBit(GPIOD
9、 , GPIO_Pin_6) ; c = GPIO_ReadInputDataBit(GPIOD , GPIO_Pin_8) ;16. 有独立按键电路,连接在 STM32F429IGT6 微控制器的 GPIOE 的 5 号引脚,要求在每次按键后将连接 GPIOB 的 2 号引脚上的 LED 灯反转,电路如图 5-16 所示。图 5-16 题 16 电路图请编写程序实现按键动作的检测,编写以下程序。(1) 主程序。(2) 连接按键引脚和 LED 引脚的初始化程序。(3) 按键检测程序。假设已有延时函数 void delay_ms(u16 nms);,此函数可直接调用。答:#define KEY_
10、ON1#define KEY_OFF0(1)int main(void)delay_init(168); /初始化延时函数LED_GPIO_Config(); Key_GPIO_Config();while(1)if( Key_Scan(GPIOE, GPIO_Pin_5) = KEY_ON )GPIO_ToggleBits(GPIOB, GPIO_Pin_2);(2)void Key_GPIO_Config(void)GPIO_InitTypeDef GPIO_InitStructure;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE,ENABLE);
11、 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOE, &GPIO_InitStructure);void LED_GPIO_Config(void) (3)GPIO_InitTypeDef GPIO_InitStructure;RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_GPIOB, ENABLE); GPIO
12、_InitStructure.GPIO_Pin = GPIO_Pin_2 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOB, &GPIO_InitStructure);uint8_t Key_Scan(GPIO_TypeDef* GPIOx,u
13、int16_t GPIO_Pin)if(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) = KEY_ON )delay_ms(100);/去抖动if(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) = KEY_ON)returnKEY_ON;elseelsereturn KEY_OFF;return KEY_OFF;17. 有矩阵按键,其电路如图 5-17 所示。(1) 矩阵按键扫描原理和流程图。(2) 编写程序实现矩阵按键控制,按键 S1S4 分别对应数字 14(引脚初始化程序和按键控制程序)。图 5-17 题 17 电路图答:(1)开
14、始将列线设置为输出模式(图中 PB0 和PB1),并分别在 PB0 和PB1 上输出低电平。行线设置为输入模式(图中 PB2 和 PB3)。都使能上拉。读取 PB2 和 PB3 状态,判断是否有按键按下。(判断原则:PB2 和 PB3 都是高电平时,没有按键按下。PB2 和PB3 有任何一个为低电平是,有按键按下。判断原理:在没有按键按下去的时候,由于上拉电阻的存在,PB2 和 PB3 都是高电平,读取状态时,PB2=1,PB3=1。如果有按键按下去的话,摸一个行线和列线连接在一 起。由于PB0 和 PB1 都为低电平,因此连接在一起的行线会被列线下拉到低电平。这时, 在读取 PB2 和 PB
15、3 状态时,就不会全是高电平。例如:当按下 S1 时,PB1 和 PB2 连在一起,PB2 被PB1 拉低到低电平。读取 PB2和 PB3 状态时,PB2=0,PB3=1。)有按键按下则继续,反之则结束。延时去抖动。典型值是延时 10ms,不同的按键类型,时间长度不一样。在此判断是否有按键按下,原理同步骤都判断有按键按下时,继续。反之则结束。保存读取的 PB2 和 PB3 的状态,作为判别行号的依据。将行线设置为输出模式(图中 PB2 和PB3),并分别在 PB2 和PB3 上输出低电平。列线设置为输入模式(图中 PB0 和 PB1)。都使能上拉。读取 PB0 和 PB1 的状态,并保存。作为
16、判别列线的依据。根据两个步得到的信息,算出是哪一个按键被按下去了。 结束开始设置列为输出低电平,行为输入模式N判断是否有按键按下(第1次判断)Y延时10msN判断是否有按键按下(第2次判断)Y保存行号 设置行为输出低电平 ,列为输入 将键盘值读进来,存起来(列号) 根据两次读到的行号和列号判断是哪一个按键结束矩阵键盘扫描流程图:(2)/*将列设置为输入,行设置为输出*/void GPIO_LieIN_HangOUT(void)GPIO_InitTypeDef GPIO_InitStructure;RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_GPIOB, ENA
17、BLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2| GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_InitStruct
18、ure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOB, &GPIO_InitStructure);/*将列设置为输出,行设置为输入*/ void GPIO_LieOUT_HangIN(void)GPIO_InitTypeDef GPIO_InitStructure;RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_GPIOB, ENAB
19、LE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_InitStructu
20、re.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOB, &GPIO_InitStructure);void KEY_SCAN(void)u8 Lie_Data,Hang_Data; GPIO_LieOUT_HangIN();GPIO_ ResetBits (GPIOB, GPIO_Pin_0|GPIO_Pin_1);/将列设置为低电平,扫描行if(GPIO_Read
21、InputData(GPIOB)&0x0a)!=0x0a)delay_ms(100);/去抖动if(GPIO_ReadInputData(GPIOB)&0x0a)!=0x0a)Hang_Data=GPIO_ReadInputData(GPIOB)&0x0a;/保存行扫描结果GPIO_LieIN_HangOUT ();GPIO_ ResetBits (GPIOB, GPIO_Pin_2|GPIO_Pin_3);/将行设置为低电平,扫描列Lie_Data=GPIO_ReadInputData(GPIOB)&0x0a;/保存列扫描结果switch(Hang_Data|Lie_Data)case 0x09:/return(1); break;case 0xa:/return(2); break;case 0x05:/return(3); break;case 0x06:/return(4); break;default: break;elsereturn(0);