精选文章 【STM32F429开发板用户手册】第38章 STM32F429的FMC总线应用之是32路高速IO扩展

【STM32F429开发板用户手册】第38章 STM32F429的FMC总线应用之是32路高速IO扩展

作者:Simon223 时间: 2021-02-05 09:43:17
Simon223 2021-02-05 09:43:17
【摘要】最新教程下载:http://www.armbbs.cn/forum.php?mod=viewthread&tid=93255 
第38章       STM32F429的FMC总线应用之是32路高速IO扩展 
本章教程为大家讲解利用STM32429的FMC总线扩展出32路高速IO,且使用简单,实际项目中也比较有实用价值。 
目录 
第38章       STM32F429的FMC总线应用之是...

最新教程下载:http://www.armbbs.cn/forum.php?mod=viewthread&tid=93255

第38章 STM32F429的FMC总线应用之是32路高速IO扩展

本章教程为大家讲解利用STM32429的FMC总线扩展出32路高速IO,且使用简单,实际项目中也比较有实用价值。

目录

第38章 STM32F429的FMC总线应用之是32路高速IO扩展

38.1 初学者重要提示

38.2 FMC扩展IO硬件设计

38.2.1 第1步,先来看FMC的块区分配

38.2.2 第2步,增加译码器及其地址计算

38.2.3 第3步,FMC的IO扩展部分

38.2.4 第4步,举例扩展IO驱动LED应用

38.3 FMC扩展IO驱动设计

38.3.1 FMC扩展IO所涉及到的GPIO配置

38.3.2 FMC扩展IO时钟源选择

38.3.3 时序配置(重要)

38.3.4 操作数据位宽注意事项

38.4 FMC扩展IO板级支持包(bsp_fmc_io.c)

38.4.1 函数bsp_InitExtIO

38.4.2 函数HC574_SetPin

38.4.3 函数HC574_TogglePin

38.4.4 函数HC574_GetPin

38.5 FMC扩展IO驱动移植和使用

38.6 实验例程设计框架

38.7 实验例程说明(MDK)

38.8 实验例程说明(IAR)

38.9 总结


 

38.1 初学者重要提示

  1.   学习本章节前,务必优先学习第37章,需要对FMC的基础知识和HAL库的几个常用API有个认识。
  2.   为什么要做IO扩展,不是已经用了208脚的F429BIT6吗?因为开发板使用了32位SDRAM和RGB888硬件接口,消耗IO巨大,所以必须得扩展了。
  3.   扩展的32路高速IO非常实用,且使用简单,只需初始下FMC,32路IO就可以随意使用了。当前的扩展方式只支持高速输出。
  4.   FMC总线扩展32路高速IO理解成GPIO的ODR寄存器就很简单了,其实就是一个东西。FMC扩展IO是对地址0x60001000的32bit数据空间的0和1的操作。GPIOA的ODR寄存器是对地址 0x40000000 + 0x18020000 + 0x14 空间的操作。但只能操作16个引脚。

使用总线的优势就在这里了,相当于在GPIOA到GPIOK的基础上,又扩展出GPIOL和GPIOM。

#define PERIPH_BASE ((uint32_t)0x40000000)
#define D3_AHB1PERIPH_BASE (PERIPH_BASE + 0x18020000)
#define GPIOA_BASE (D3_AHB1PERIPH_BASE + 0x0000)
#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)

typedef struct
{
  __IO uint32_t MODER; /*!< GPIO port mode register, Address offset: 0x00 */
  __IO uint32_t OTYPER;   /*!< GPIO port output type register, Address offset: 0x04 */
  __IO uint32_t OSPEEDR;  /*!< GPIO port output speed register, Address offset: 0x08 */
  __IO uint32_t PUPDR; /*!< GPIO port pull-up/pull-down register,  Address offset: 0x0C */
  __IO uint32_t IDR; /*!< GPIO port input data register, Address offset: 0x10 */
  __IO uint32_t ODR; /*!< GPIO port output data register, Address offset: 0x14 */
  __IO uint16_t BSRRL; /*!< GPIO port bit set/reset low register,  Address offset: 0x18 */
  __IO uint16_t BSRRH; /*!< GPIO port bit set/reset high register, Address offset: 0x1A */
  __IO uint32_t LCKR; /*!< GPIO port configuration lock register, Address offset: 0x1C */
  __IO uint32_t AFR[2];   /*!< GPIO alternate function registers, Address offset: 0x20-0x24 */
} GPIO_TypeDef;

38.2 FMC扩展IO硬件设计

扩展IO涉及到的知识点稍多,下面逐一为大家做个说明。

38.2.1 第1步,先来看FMC的块区分配

注,这个知识点在前面第37章的2.3小节有详细说明。

FMC总线可操作的地址范围0x60000000到0xDFFFFFFF,具体的框图如下:

【STM32F429开发板用户手册】第38章 STM32F429的FMC总线应用之是32路高速IO扩展1

从上面的框图可以看出,NOR/PSRAM/SRAM块区有4个片选NE1,NE2,NE3和NE4,但由于引脚复用,部分片选对应的引脚要用于其他功能,而且要控制的总线外设较多,导致片选不够用。因此需要增加译码器。

38.2.2 第2步,增加译码器及其地址计算

有了前面的认识之后再来看下面的译码器电路:

 【STM32F429开发板用户手册】第38章 STM32F429的FMC总线应用之是32路高速IO扩展2

SN74LVC1G139APWR是双2-4线地址译码器,也就是带了两个译码器。原理图上仅用了一个。下面是139的真值表和引脚功能:

【STM32F429开发板用户手册】第38章 STM32F429的FMC总线应用之是32路高速IO扩展3

【STM32F429开发板用户手册】第38章 STM32F429的FMC总线应用之是32路高速IO扩展4

通过上面的原理图和真值表就比较好理解了,真值表的输出是由片选FMC_NE2和地址线FMC_A10、FMC_A11控制。

FMC_NE1 输出低电平:

  •   FMC_A11(B),FMC_A10(A) = 00时,1Y0输出的低电平,选择的是OLED。
  •   FMC_A11(B),FMC_A10(A) = 01时,1Y1输出的低电平,选择的是74HC574。
  •   FMC_A11(B),FMC_A10(A) = 10时,1Y2输出的低电平,选择的是DM9000。
  •   FMC_A11(B),FMC_A10(A) = 11时,1Y3输出的低电平,选择的是AD7606。

然后我们再计算译码器的地址,注意,这里地址的计算都是按照FMC的32bit访问模式计算的,因为我们的V6程序中是将NE1对应的FMC配置为32bit模式了。

具体FMC的32bit访问模式,16bit访问模式和8bit访问模式的区别在第37章的2.4小节有详细讲解。

 【STM32F429开发板用户手册】第38章 STM32F429的FMC总线应用之是32路高速IO扩展5

32bit模式下,我们计算A10和A11的时候,实际上需要按HADDR12和HADDR13计算的。

如果来算NE1 + HADDR12 + HADDR13的四种组合地址就是如下:

NE2 + HADDR13 + HADDR12 = 0x64000000 +  0<<13 + 0<<12 = 0x64000000

NE2 + HADDR13 + HADDR12 = 0x64000000 +  0<<13 + 1<<12 = 0x64001000

NE2 + HADDR13 + HADDR12 = 0x64000000 +  1<<13 + 0<<12 = 0x64002000

NE2 + HADDR13 + HADDR12 = 0x64000000 +  1<<13 + 1<<12 = 0x64003000

这样一来,原理图里面给的地址就对应上了。同理如果配置为16位模式和8位模式,大家应该也都会计算了。

38.2.3 第3步,FMC的IO扩展部分

先来看下IO扩展的原理图实现,如果不太了解FMC的通信时序和数字逻辑芯片的使用,可能会比较懵,下面逐一为大家说明。

 【STM32F429开发板用户手册】第38章 STM32F429的FMC总线应用之是32路高速IO扩展6

有了这个原理图,首先要做的就是了解74HC574和SN74HC32的功能。

74HC574是一款8位三态D触发器,起到锁存的功能,上升沿触发,对应的真值表如下(L表示低电平,H表示高电平,Z表示高阻):

 【STM32F429开发板用户手册】第38章 STM32F429的FMC总线应用之是32路高速IO扩展7

SN74HC02是一款2输入或非门,一个芯片带了四组或非门,对应的真值表如下(L表示低电平,H表示高电平):

 【STM32F429开发板用户手册】第38章 STM32F429的FMC总线应用之是32路高速IO扩展8

有了这个认识后,我们再来看FMC的配置,V6开发板的BSP驱动包里面专门做了一个IO扩展的FMC配置,即文件bsp_fmc_io.c,配置方式是FMC_AccessMode_A,这种模式对应的写时序是:

 【STM32F429开发板用户手册】第38章 STM32F429的FMC总线应用之是32路高速IO扩展9

那么问题来了,我们要实现的功能是通过FMC输出的数据要锁存在扩展IO的输出端,否则FMC时序信号消失了,扩展IO的输出数据也消失了,就起不到控制作用了。所以就用到74HC574的锁存功能,而锁存的实现需要一个上升沿触发,这个上升沿就是通过74HC32输出的。

再结合上面FMC写时序图,在NE片选为低电平,NWE写使能信号为高电平期间,即地址建立时间段ADDSET内,74HC32是输出的高电平。

进入到DATAST数据建立阶段,在NE片选为低电平,NWE写使能信号也为低电平时,74HC32输出低电平。等NEW上升沿的时候,正好是实现1个上升沿的变化。

38.2.4 第4步,举例扩展IO驱动LED应用

进行到这里,再回过头来看LED驱动就比较好理解了。操作LED的亮灭就是操作FMC的数据引脚D8,D9,D10和D11。

 【STM32F429开发板用户手册】第38章 STM32F429的FMC总线应用之是32路高速IO扩展10

【STM32F429开发板用户手册】第38章 STM32F429的FMC总线应用之是32路高速IO扩展11

对地址0x64001000发送数据就可以了,但是如何对这个地址发送数据呢? 反映到C语言的实现上就是通过固定地址的指针变量(跟我们操作寄存器是一样的),即

#define  HC574_PORT *(uint32_t *)0x64001000

如果要点亮LED1(低电平点亮),就是 HC574_PORT = 0x0000 0000。

如果要熄灭LED1就是HC574_PORT = 0x0000 0100,即操作FMC_D8的高低电平即可。

38.3 FMC扩展IO驱动设计

下面将程序设计中的相关问题逐一为大家做个说明。

38.3.1 FMC扩展IO所涉及到的GPIO配置

这里仅需把用到的GPIO时钟、FMC时钟、GPIO引脚和复用配置好即可:

/*
*********************************************************************************************************
* 函 数 名: HC574_ConfigGPIO
* 功能说明: 配置GPIO,FMC管脚设置为复用功能
* 形 参:  无
* 返 回 值: 无
*********************************************************************************************************
*/
static void HC574_ConfigGPIO(void)
{
/* 安富莱STM32-V6开发板接线方法:4片74HC574挂在FMC 32位总线上。1个地址端口可以扩展出32个IO PD0/FMC_D2 PD1/FMC_D3 PD4/FMC_NOE ---- 读控制信号,OE = Output Enable , N 表示低有效 PD5/FMC_NWE -XX- 写控制信号,AD7606 只有读,无写信号 PD8/FMC_D13 PD9/FMC_D14 PD10/FMC_D15 PD14/FMC_D0 PD15/FMC_D1 PE7/FMC_D4 PE8/FMC_D5 PE9/FMC_D6 PE10/FMC_D7 PE11/FMC_D8 PE12/FMC_D9 PE13/FMC_D10 PE14/FMC_D11 PE15/FMC_D12 PG0/FMC_A10 --- 和主片选FMC_NE2一起译码 PG1/FMC_A11 --- 和主片选FMC_NE2一起译码 PG9/FMC_NE2 --- 主片选(OLED, 74HC574, DM9000, AD7606) +-------------------+------------------+ +   32-bits Mode: D31-D16 + +-------------------+------------------+ | PH8 <-> FMC_D16   | PI0 <-> FMC_D24  | | PH9 <-> FMC_D17   | PI1 <-> FMC_D25  | | PH10 <-> FMC_D18  | PI2 <-> FMC_D26  | | PH11 <-> FMC_D19  | PI3 <-> FMC_D27  | | PH12 <-> FMC_D20  | PI6 <-> FMC_D28  | | PH13 <-> FMC_D21  | PI7 <-> FMC_D29  | | PH14 <-> FMC_D22  | PI9 <-> FMC_D30  | | PH15 <-> FMC_D23  | PI10 <-> FMC_D31 | +------------------+-------------------+ */ GPIO_InitTypeDef gpio_init_structure; /* 使能 GPIO时钟 */ __HAL_RCC_GPIOD_CLK_ENABLE(); __HAL_RCC_GPIOE_CLK_ENABLE(); __HAL_RCC_GPIOG_CLK_ENABLE(); __HAL_RCC_GPIOH_CLK_ENABLE(); __HAL_RCC_GPIOI_CLK_ENABLE(); /* 使能FMC时钟 */ __HAL_RCC_FMC_CLK_ENABLE(); /* 设置 GPIOD 相关的IO为复用推挽输出 */ gpio_init_structure.Mode = GPIO_MODE_AF_PP; gpio_init_structure.Pull = GPIO_PULLUP; gpio_init_structure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; gpio_init_structure.Alternate = GPIO_AF12_FMC; /* 配置GPIOD */ gpio_init_structure.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_14 | GPIO_PIN_15; HAL_GPIO_Init(GPIOD, &gpio_init_structure); /* 配置GPIOE */ gpio_init_structure.Pin = GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15; HAL_GPIO_Init(GPIOE, &gpio_init_structure); /* 配置GPIOG */ gpio_init_structure.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_9; HAL_GPIO_Init(GPIOG, &gpio_init_structure); /* 配置GPIOH */ gpio_init_structure.Pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15; HAL_GPIO_Init(GPIOH, &gpio_init_structure); /* 配置GPIOI */ gpio_init_structure.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_9 | GPIO_PIN_10; HAL_GPIO_Init(GPIOI, &gpio_init_structure);
}

38.3.2 FMC扩展IO时钟源选择

STM32F429的FMC是采用的HCLK时钟,位于AHB总线上。比如主频设置的是168MHz,那么FMC时钟也是168MHz。

【STM32F429开发板用户手册】第38章 STM32F429的FMC总线应用之是32路高速IO扩展12

38.3.3 时序配置(重要)

这里要补充两个重要的知识点,74HC574的CP端接收到上升沿触发到Qn输出的时间参数:

【STM32F429开发板用户手册】第38章 STM32F429的FMC总线应用之是32路高速IO扩展13

 【STM32F429开发板用户手册】第38章 STM32F429的FMC总线应用之是32路高速IO扩展14

通过时序图和对应的参数要了解到以下几点:

  •   tpd传输延迟在这里等效于tPHL和tPLH。
  •   V6开发板的74HC574有三片是3.3V供电,另外一片是5V供电。参数表格里面没有给3.3V供电时的参数,也没有最小值。

 

了解了74HC574,再来看SN74HC32:

【STM32F429开发板用户手册】第38章 STM32F429的FMC总线应用之是32路高速IO扩展15

 【STM32F429开发板用户手册】第38章 STM32F429的FMC总线应用之是32路高速IO扩展16

通过时序图和对应的参数要了解到以下几点:

  •   tpd传输延迟在这里等效于tPHL和tPLH。
  •   tt过渡时间等效于tr上升沿时间和tf下降沿时间。

对应74HC574和74HC02的时序参数有个了解后,继续往下看:

 【STM32F429开发板用户手册】第38章 STM32F429的FMC总线应用之是32路高速IO扩展17

当写使能信号NWE出现上升降沿后,74HC32非门就会输出一个上升沿,然后触发74HC574做锁存。此时我们要考虑到一个重要的知识点,就是使用的数字逻辑芯片有个传输延迟问题,也就是要我们要保证74HC02的tpd传输延迟时间 + 74HC02的tr传输延迟时间 + 74HC574的tpd传输延迟时间的这段时间内,数据总线上要有数据,而这种模式下,NEW上升沿后,仅有1个HCLK时钟周期了,所以只能加大两个连续读数据的时间间隔和地址建立时间(其实是下一次的地址建立时间,可以和两个连续读的时间段放在一起)。实际测试FMC频率在168MHz的情况下,3-6个FMC时钟周期就已经可正常使用。

有了这些认识后,再来看FMC的时序配置就比较好理解了:

1. /*
2. ******************************************************************************************************
3. * 函 数 名: HC574_ConfigFMC
4. * 功能说明: 配置FMC并口访问时序
5. * 形 参:  无
6. * 返 回 值: 无
7. ******************************************************************************************************
8. */
9. static void HC574_ConfigFMC(void)
10. {
11. SRAM_HandleTypeDef hsram = {0};
12. FMC_NORSRAM_TimingTypeDef SRAM_Timing = {0};
13. 14. hsram.Instance  = FMC_NORSRAM_DEVICE;
15. hsram.Extended  = FMC_NORSRAM_EXTENDED_DEVICE;
16. 17. /* FMC使用的HCLK,主频168MHz,1个FMC时钟周期就是5.95ns */
18. SRAM_Timing.AddressSetupTime = 3;  /* 3*5.95ns=17.85ns,地址建立时间,范围0 -15个FMC时钟周
19. 期个数 */
20. SRAM_Timing.AddressHoldTime = 0;  /* 地址保持时间,配置为模式A时,用不到此参数 范围1 -15
21. 个时钟周期个数 */
22. SRAM_Timing.DataSetupTime = 6;  /* 6*5.95ns=35.7ns,数据保持时间,范围1 -255个时钟周期个
23. 数 */
24. SRAM_Timing.BusTurnAroundDuration  = 3;  /* 6*5.95ns,两个连续读数据的时间间隔 */
25. SRAM_Timing.CLKDivision = 0;  /* 此配置用不到这个参数 */
26. SRAM_Timing.DataLatency = 0;  /* 此配置用不到这个参数 */
27. SRAM_Timing.AccessMode = FMC_ACCESS_MODE_A; /* 配置为模式A */
28. 29. hsram.Init.NSBank = FMC_NORSRAM_BANK2; /* 使用的BANK2,即使用的片选
30. FMC_NE2 */
31. hsram.Init.DataAddressMux = FMC_DATA_ADDRESS_MUX_DISABLE;   /* 禁止地址数据复用 */
32. hsram.Init.MemoryType = FMC_MEMORY_TYPE_SRAM; /* 存储器类型SRAM */
33. hsram.Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_32;   /* 32位总线宽度 */
34. hsram.Init.BurstAccessMode = FMC_BURST_ACCESS_MODE_DISABLE;  /* 关闭突发模式 */
35. hsram.Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_LOW;   /* 用于设置等待信号的极性,关闭突
36. 发模式,此参数无效 */
37. hsram.Init.WaitSignalActive   = FMC_WAIT_TIMING_BEFORE_WS; /* 关闭突发模式,此参数无效 */
38. hsram.Init.WriteOperation = FMC_WRITE_OPERATION_ENABLE; /* 用于使能或者禁止写保护 */
39. hsram.Init.WaitSignal = FMC_WAIT_SIGNAL_DISABLE; /* 关闭突发模式,此参数无效 */
40. hsram.Init.ExtendedMode = FMC_EXTENDED_MODE_DISABLE; /* 禁止扩展模式 */
41. hsram.Init.AsynchronousWait   = FMC_ASYNCHRONOUS_WAIT_DISABLE;  /* 用于异步传输期间,使能或者禁止
42. 等待信号,这里选择关闭 */
43. hsram.Init.WriteBurst = FMC_WRITE_BURST_DISABLE; /* 禁止写突发 */
44. hsram.Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ONLY; /* 仅同步模式才做时钟输出 */
45. hsram.Init.WriteFifo = FMC_WRITE_FIFO_ENABLE; /* 使能写FIFO */
46. 47. /* 初始化SRAM控制器 */
48. if (HAL_SRAM_Init(&hsram, &SRAM_Timing, &SRAM_Timing) != HAL_OK)
49. {
50. /* 初始化错误 */
51. Error_Handler(__FILE__, __LINE__);
52. }
53. }

这里把几个关键的地方阐释下:

  •   第11 - 12行,对作为局部变量的HAL库结构体做初始化,防止不确定值配置时出问题。
  •   第18行,地址建立时间,配合参数BusTurnAroundDuration两个连续读数据的时间间隔,组成或门74HC32的低高电平时间,实际测试3-6个时钟周期即可。
  •   第20行,地址保持时间,对于FMC模式A来说,此参数用不到。
  •   第22行,数据建立时间,这里设置为6个时钟周期,大家可以根据情况减小此数值。
  •   第23行,两个连续读数据的时间间隔,
  •   第24 – 25行,当前配置用不到这两个参数,配合参数AddressSetupTime两个连续读数据的时间间隔,组成或门74HC32的低高电平时间,实际测试3-6个时钟周期即可
  •   第29行,使用的BANK2,即使用的片选FMC_NE2。
  •   第31行,由于是扩展的32路IO,所以这里要配置为32位带宽。

38.3.4 操作数据位宽注意事项

在bsp_fmc_io.c文件开头有个宏定义#define  HC574_PORT  *(uint32_t *)0x64001000。特别注意,这里是要操作地址0x64001000上的32位数据空间,即做了一个强制转换uint32_t *,要跟FMC配置时设置的位宽一致。这样做的原因,在第37章的2.6小节有说明。

38.4 FMC扩展IO板级支持包(bsp_fmc_io.c)

驱动文件bsp_fmc_io.c提供了如下几个函数供用户调用:

  •   bsp_InitExtIO
  •   HC574_SetPin
  •   HC574_TogglePin
  •   HC574_GetPin

38.4.1 函数bsp_InitExtIO

函数原型:

/*
*********************************************************************************************************
* 函 数 名: bsp_InitExtIO
* 功能说明: 配置扩展IO相关的GPIO. 上电只能执行一次。
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void bsp_InitExtIO(void)
{ HC574_ConfigGPIO(); HC574_ConfigFMC(); /* 将开发板一些片选,LED口设置为高 */ g_HC574 = (NRF24L01_CE | VS1053_XDCS | LED1 | LED2 | LED3 | LED4); HC574_PORT = g_HC574; /* 写硬件端口,更改IO状态 */
}

函数描述:

此函数用于初始化FMC扩展IO所用到的GPIO和FMC的参数配置。

使用举例:

作为初始化函数,直接在在bsp.c文件的bsp_Init函数里面调用即可。

38.4.2 函数HC574_SetPin

函数原型:

/*
*********************************************************************************************************
* 函 数 名: HC574_SetPin
* 功能说明: 设置74HC574端口值
* 形 参: _pin : 管脚号, 0-31; 只能选1个,不能多选
* _value : 设定的值,0或1
* 返 回 值: 无
*********************************************************************************************************
*/
void HC574_SetPin(uint32_t _pin, uint8_t _value)
{ if (_value == 0) { g_HC574 &= (~_pin); } else { g_HC574 |= _pin; } HC574_PORT = g_HC574;
}

函数描述:

此函数用于设置扩展IO的输出状态。调用此函数前,要保证调用了函数bsp_InitExtIO进行了初始化。

函数参数:

  •   第1个参数是扩展IO的引脚,支持的形参如下,每次仅支持调用下面1个,不支持多个IO一起操作。
#define GPIO_PIN_0 ((uint16_t)0x0001)  /* Pin 0 selected */
#define GPIO_PIN_1 ((uint16_t)0x0002)  /* Pin 1 selected */
#define GPIO_PIN_2 ((uint16_t)0x0004)  /* Pin 2 selected */
#define GPIO_PIN_3 ((uint16_t)0x0008)  /* Pin 3 selected */
#define GPIO_PIN_4 ((uint16_t)0x0010)  /* Pin 4 selected */
#define GPIO_PIN_5 ((uint16_t)0x0020)  /* Pin 5 selected */
#define GPIO_PIN_6 ((uint16_t)0x0040)  /* Pin 6 selected */
#define GPIO_PIN_7 ((uint16_t)0x0080)  /* Pin 7 selected */
#define GPIO_PIN_8 ((uint16_t)0x0100)  /* Pin 8 selected */
#define GPIO_PIN_9 ((uint16_t)0x0200)  /* Pin 9 selected */
#define GPIO_PIN_10 ((uint16_t)0x0400)  /* Pin 10 selected */
#define GPIO_PIN_11 ((uint16_t)0x0800)  /* Pin 11 selected */
#define GPIO_PIN_12 ((uint16_t)0x1000)  /* Pin 12 selected */
#define GPIO_PIN_13 ((uint16_t)0x2000)  /* Pin 13 selected */
#define GPIO_PIN_14 ((uint16_t)0x4000)  /* Pin 14 selected */
#define GPIO_PIN_15 ((uint16_t)0x8000)  /* Pin 15 selected */
#define GPIO_PIN_16 ((uint32_t)0x00010000)  /* Pin 16 selected */
#define GPIO_PIN_17 ((uint32_t)0x00020000)  /* Pin 17 selected */
#define GPIO_PIN_18 ((uint32_t)0x00040000)  /* Pin 18 selected */
#define GPIO_PIN_19 ((uint32_t)0x00080000)  /* Pin 19 selected */
#define GPIO_PIN_20 ((uint32_t)0x00100000)  /* Pin 20 selected */
#define GPIO_PIN_21 ((uint32_t)0x00200000)  /* Pin 21 selected */
#define GPIO_PIN_22 ((uint32_t)0x00400000)  /* Pin 22 selected */
#define GPIO_PIN_23 ((uint32_t)0x00800000)  /* Pin 23 selected */
#define GPIO_PIN_24 ((uint32_t)0x01000000)  /* Pin 24 selected */
#define GPIO_PIN_25 ((uint32_t)0x02000000)  /* Pin 25 selected */
#define GPIO_PIN_26 ((uint32_t)0x04000000)  /* Pin 26 selected */
#define GPIO_PIN_27 ((uint32_t)0x08000000)  /* Pin 27 selected */
#define GPIO_PIN_28 ((uint32_t)0x10000000)  /* Pin 28 selected */
#define GPIO_PIN_29 ((uint32_t)0x20000000)  /* Pin 29 selected */
#define GPIO_PIN_30 ((uint32_t)0x40000000)  /* Pin 30 selected */
#define GPIO_PIN_31 ((uint32_t)0x80000000)  /* Pin 31 selected */
  •   第2个参数用于设置指定扩展IO的高低电平,0表示输出低电平,1表示输出高电平。

使用举例:

比如设置扩展IO引脚GPIO_PIN_23为高电平:HC574_SetPin(GPIO_PIN_23, 1)。

38.4.3 函数HC574_TogglePin

函数原型:

/*
*********************************************************************************************************
* 函 数 名: HC574_TogglePin
* 功能说明: 饭庄74HC574端口值
* 形 参: _pin : 管脚号, 0-31; 只能选1个,不能多选
* 返 回 值: 无
*********************************************************************************************************
*/
void HC574_TogglePin(uint32_t _pin)
{ if (g_HC574 & _pin) { g_HC574 &= (~_pin); } else { g_HC574 |= _pin; } HC574_PORT = g_HC574;
}

函数描述:

此函数用于FMC扩展IO的翻转。调用此函数前,要保证调用了函数bsp_InitExtIO进行了初始化。

函数参数:

  •   第1个参数是扩展IO的引脚,支持的形参如下,每次仅支持调用下面1个,不支持多个IO一起操作。
#define GPIO_PIN_0 ((uint16_t)0x0001)  /* Pin 0 selected */
#define GPIO_PIN_1 ((uint16_t)0x0002)  /* Pin 1 selected */
#define GPIO_PIN_2 ((uint16_t)0x0004)  /* Pin 2 selected */
#define GPIO_PIN_3 ((uint16_t)0x0008)  /* Pin 3 selected */
#define GPIO_PIN_4 ((uint16_t)0x0010)  /* Pin 4 selected */
#define GPIO_PIN_5 ((uint16_t)0x0020)  /* Pin 5 selected */
#define GPIO_PIN_6 ((uint16_t)0x0040)  /* Pin 6 selected */
#define GPIO_PIN_7 ((uint16_t)0x0080)  /* Pin 7 selected */
#define GPIO_PIN_8 ((uint16_t)0x0100)  /* Pin 8 selected */
#define GPIO_PIN_9 ((uint16_t)0x0200)  /* Pin 9 selected */
#define GPIO_PIN_10 ((uint16_t)0x0400)  /* Pin 10 selected */
#define GPIO_PIN_11 ((uint16_t)0x0800)  /* Pin 11 selected */
#define GPIO_PIN_12 ((uint16_t)0x1000)  /* Pin 12 selected */
#define GPIO_PIN_13 ((uint16_t)0x2000)  /* Pin 13 selected */
#define GPIO_PIN_14 ((uint16_t)0x4000)  /* Pin 14 selected */
#define GPIO_PIN_15 ((uint16_t)0x8000)  /* Pin 15 selected */
#define GPIO_PIN_16 ((uint32_t)0x00010000)  /* Pin 16 selected */
#define GPIO_PIN_17 ((uint32_t)0x00020000)  /* Pin 17 selected */
#define GPIO_PIN_18 ((uint32_t)0x00040000)  /* Pin 18 selected */
#define GPIO_PIN_19 ((uint32_t)0x00080000)  /* Pin 19 selected */
#define GPIO_PIN_20 ((uint32_t)0x00100000)  /* Pin 20 selected */
#define GPIO_PIN_21 ((uint32_t)0x00200000)  /* Pin 21 selected */
#define GPIO_PIN_22 ((uint32_t)0x00400000)  /* Pin 22 selected */
#define GPIO_PIN_23 ((uint32_t)0x00800000)  /* Pin 23 selected */
#define GPIO_PIN_24 ((uint32_t)0x01000000)  /* Pin 24 selected */
#define GPIO_PIN_25 ((uint32_t)0x02000000)  /* Pin 25 selected */
#define GPIO_PIN_26 ((uint32_t)0x04000000)  /* Pin 26 selected */
#define GPIO_PIN_27 ((uint32_t)0x08000000)  /* Pin 27 selected */
#define GPIO_PIN_28 ((uint32_t)0x10000000)  /* Pin 28 selected */
#define GPIO_PIN_29 ((uint32_t)0x20000000)  /* Pin 29 selected */
#define GPIO_PIN_30 ((uint32_t)0x40000000)  /* Pin 30 selected */

使用举例:

比如翻转扩展IO引脚GPIO_PIN_23为高电平:HC574_TogglePin(GPIO_PIN_23)。

38.4.4 函数HC574_GetPin

函数原型:

/*
*********************************************************************************************************
* 函 数 名: HC574_GetPin
* 功能说明: 判断指定的管脚输出是1还是0
* 形 参: _pin : 管脚号, 0-31; 只能选1个,不能多选
* 返 回 值: 0或1
*********************************************************************************************************
*/
uint8_t HC574_GetPin(uint32_t _pin)
{ if (g_HC574 & _pin) { return 1; } else { return 0; }
}

函数描述:

此函数用于读取FMC扩展IO的状态。调用此函数前,要保证调用了函数bsp_InitExtIO进行了初始化。

函数参数:

  •   第1个参数是扩展IO的引脚,支持的形参如下,每次仅支持调用下面1个,不支持多个IO一起操作。
#define GPIO_PIN_0 ((uint16_t)0x0001)  /* Pin 0 selected */
#define GPIO_PIN_1 ((uint16_t)0x0002)  /* Pin 1 selected */
#define GPIO_PIN_2 ((uint16_t)0x0004)  /* Pin 2 selected */
#define GPIO_PIN_3 ((uint16_t)0x0008)  /* Pin 3 selected */
#define GPIO_PIN_4 ((uint16_t)0x0010)  /* Pin 4 selected */
#define GPIO_PIN_5 ((uint16_t)0x0020)  /* Pin 5 selected */
#define GPIO_PIN_6 ((uint16_t)0x0040)  /* Pin 6 selected */
#define GPIO_PIN_7 ((uint16_t)0x0080)  /* Pin 7 selected */
#define GPIO_PIN_8 ((uint16_t)0x0100)  /* Pin 8 selected */
#define GPIO_PIN_9 ((uint16_t)0x0200)  /* Pin 9 selected */
#define GPIO_PIN_10 ((uint16_t)0x0400)  /* Pin 10 selected */
#define GPIO_PIN_11 ((uint16_t)0x0800)  /* Pin 11 selected */
#define GPIO_PIN_12 ((uint16_t)0x1000)  /* Pin 12 selected */
#define GPIO_PIN_13 ((uint16_t)0x2000)  /* Pin 13 selected */
#define GPIO_PIN_14 ((uint16_t)0x4000)  /* Pin 14 selected */
#define GPIO_PIN_15 ((uint16_t)0x8000)  /* Pin 15 selected */
#define GPIO_PIN_16 ((uint32_t)0x00010000)  /* Pin 16 selected */
#define GPIO_PIN_17 ((uint32_t)0x00020000)  /* Pin 17 selected */
#define GPIO_PIN_18 ((uint32_t)0x00040000)  /* Pin 18 selected */
#define GPIO_PIN_19 ((uint32_t)0x00080000)  /* Pin 19 selected */
#define GPIO_PIN_20 ((uint32_t)0x00100000)  /* Pin 20 selected */
#define GPIO_PIN_21 ((uint32_t)0x00200000)  /* Pin 21 selected */
#define GPIO_PIN_22 ((uint32_t)0x00400000)  /* Pin 22 selected */
#define GPIO_PIN_23 ((uint32_t)0x00800000)  /* Pin 23 selected */
#define GPIO_PIN_24 ((uint32_t)0x01000000)  /* Pin 24 selected */
#define GPIO_PIN_25 ((uint32_t)0x02000000)  /* Pin 25 selected */
#define GPIO_PIN_26 ((uint32_t)0x04000000)  /* Pin 26 selected */
#define GPIO_PIN_27 ((uint32_t)0x08000000)  /* Pin 27 selected */
#define GPIO_PIN_28 ((uint32_t)0x10000000)  /* Pin 28 selected */
#define GPIO_PIN_29 ((uint32_t)0x20000000)  /* Pin 29 selected */
#define GPIO_PIN_30 ((uint32_t)0x40000000)  /* Pin 30 selected */
#define GPIO_PIN_31 ((uint32_t)0x80000000)  /* Pin 31 selected */
  •   返回值,返回0表示低电平,返回1表示高电平。

使用举例:

比如获取扩展IO的GPIO_PIN_23高低电平状态,调用函数HC574_GetPin(GPIO_PIN_23)获取即可。

38.5 FMC扩展IO驱动移植和使用

扩展IO的移植比较方便:

  •   第1步:复制bsp_fmc_io.c和bsp_fmc_io.h到自己的工程目录,并添加到工程里面。
  •   第2步:这几个驱动文件主要用到HAL库的GPIO和FMC驱动文件,简单省事些可以添加所有HAL库.C源文件进来。
  •   第3步,应用方法看本章节配套例子即可,另外就是根据自己的需要做配置修改。

38.6 实验例程设计框架

通过程序设计框架,让大家先对配套例程有一个全面的认识,然后再理解细节,本次实验例程的设计框架如下:

【STM32F429开发板用户手册】第38章 STM32F429的FMC总线应用之是32路高速IO扩展18

  第1阶段,上电启动阶段:

  •   这部分在第14章进行了详细说明。

  第2阶段,进入main函数:

  •   第1步,硬件初始化,主要是HAL库,系统时钟,滴答定时器,LED和串口。
  •   第2步,按键应用程序设计部分。定时器中断服务程序里面实现翻转FMC扩展引脚20和23。

38.7 实验例程说明(MDK)

配套例子:

V6-018-FMC总线扩展32路高速IO

实验目的:

  1. 学习FMC总线扩展32路高速IO。

实验内容:

  1. 系统上电后驱动了1个软件定时器,每100ms翻转一次LED2。
  2. 启动1个TIM6周期性中断,频率10KHz,在中断服务程序里面翻转FMC扩展引脚20和23。

实验操作:

  1. K1按键按下,开启TIM6的周期性中断。
  2. K2按键按下,关闭TIM6的周期性中断。

FMC扩展引脚20和23的位置:

【STM32F429开发板用户手册】第38章 STM32F429的FMC总线应用之是32路高速IO扩展19

上电后串口打印的信息:

波特率 115200,数据位 8,奇偶校验位无,停止位 1

【STM32F429开发板用户手册】第38章 STM32F429的FMC总线应用之是32路高速IO扩展20

程序设计:

  系统栈大小分配:

【STM32F429开发板用户手册】第38章 STM32F429的FMC总线应用之是32路高速IO扩展21

  硬件外设初始化

硬件外设的初始化是在 bsp.c 文件实现:

/*
*********************************************************************************************************
* 函 数 名: bsp_Init
* 功能说明: 初始化所有的硬件设备。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。只需要调用一次
* 形 参:无
* 返 回 值: 无
*********************************************************************************************************
*/
void bsp_Init(void)
{ /* STM32F429 HAL 库初始化,此时系统用的还是F429自带的16MHz,HSI时钟: - 调用函数HAL_InitTick,初始化滴答时钟中断1ms。 - 设置NVIV优先级分组为4。 */ HAL_Init(); /* 配置系统时钟到168MHz - 切换使用HSE。 - 此函数会更新全局变量SystemCoreClock,并重新配置HAL_InitTick。 */ SystemClock_Config(); /* Event Recorder: - 可用于代码执行时间测量,MDK5.25及其以上版本才支持,IAR不支持。 - 默认不开启,如果要使能此选项,务必看V5开发板用户手册第8章 */ #if Enable_EventRecorder == 1 /* 初始化EventRecorder并开启 */ EventRecorderInitialize(EventRecordAll, 1U); EventRecorderStart();
#endif bsp_InitKey(); /* 按键初始化,要放在滴答定时器之前,因为按钮检测是通过滴答定时器扫描 */ bsp_InitTimer(); /* 初始化滴答定时器 */ bsp_InitUart(); /* 初始化串口 */ bsp_InitExtIO();   /* 初始化扩展IO */ bsp_InitLed(); /* 初始化LED */ BEEP_InitHard();   /* 初始化蜂鸣器 */

}

  主功能:

主程序实现如下操作:

  •   K1按键按下,开启TIM6的周期性中断。
  •   K2按键按下,关闭TIM6的周期性中断。
/*
*********************************************************************************************************
* 函 数 名: main
* 功能说明: c程序入口
* 形 参: 无
* 返 回 值: 错误代码(无需处理)
*********************************************************************************************************
*/
int main(void)
{ uint8_t ucKeyCode; /* 按键代码 */ bsp_Init(); /* 硬件初始化 */ PrintfLogo(); /* 打印例程名称和版本等信息 */ PrintfHelp(); /* 打印操作提示 */ bsp_StartAutoTimer(0, 100); /* 启动1个100ms的自动重装的定时器 */ bsp_SetTIMforInt(TIM6, 10000, 2, 0); /* 设置为10KHz频率定时器中断*/ /* 进入主程序循环体 */ while (1) { bsp_Idle(); /* 这个函数在bsp.c文件。用户可以修改这个函数实现CPU休眠和喂狗 */ /* 判断定时器超时时间 */ if (bsp_CheckTimer(0)) { /* 每隔100ms 进来一次 */ bsp_LedToggle(2); } /* 按键滤波和检测由后台systick中断服务程序实现,我们只需要调用bsp_GetKey读取键值即可。 */ ucKeyCode = bsp_GetKey(); /* 读取键值, 无键按下时返回 KEY_NONE = 0 */ if (ucKeyCode != KEY_NONE) { switch (ucKeyCode) { case KEY_DOWN_K1: /* K1键按下,开启TIM6的周期性中断*/ TIM6->DIER |= TIM_IT_UPDATE; break; case KEY_DOWN_K2: /* K2键按下,关闭TIM6的周期性中断*/ TIM6->DIER &= ~TIM_IT_UPDATE; break; default: /* 其它的键值不处理 */ break; } } }
}

定时器6中断服务程序:

/*
*********************************************************************************************************
* 函 数 名: TIM6_DAC_IRQHandler
* 功能说明: TIM6定时中断服务程序
* 返 回 值: 无
*********************************************************************************************************
*/
void TIM6_DAC_IRQHandler(void)
{ if((TIM6->SR & TIM_FLAG_UPDATE) != RESET) { /* 清除更新标志 */ TIM6->SR = ~ TIM_FLAG_UPDATE; /* 翻转FMC扩展引脚20和23脚 */ HC574_TogglePin(GPIO_PIN_23); HC574_TogglePin(GPIO_PIN_20); }
}

38.8 实验例程说明(IAR)

配套例子:

V6-018-FMC总线扩展32路高速IO

实验目的:

  1. 学习FMC总线扩展32路高速IO。

实验内容:

  1. 系统上电后驱动了1个软件定时器,每100ms翻转一次LED2。
  2. 启动1个TIM6周期性中断,频率10KHz,在中断服务程序里面翻转FMC扩展引脚20和23。

实验操作:

  1. K1按键按下,开启TIM6的周期性中断。
  2. K2按键按下,关闭TIM6的周期性中断。

FMC扩展引脚20和23的位置:

【STM32F429开发板用户手册】第38章 STM32F429的FMC总线应用之是32路高速IO扩展22

上电后串口打印的信息:

波特率 115200,数据位 8,奇偶校验位无,停止位 1

【STM32F429开发板用户手册】第38章 STM32F429的FMC总线应用之是32路高速IO扩展23

程序设计:

  系统栈大小分配:

【STM32F429开发板用户手册】第38章 STM32F429的FMC总线应用之是32路高速IO扩展24

  硬件外设初始化

硬件外设的初始化是在 bsp.c 文件实现:

/*
*********************************************************************************************************
* 函 数 名: bsp_Init
* 功能说明: 初始化所有的硬件设备。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。只需要调用一次
* 形 参:无
* 返 回 值: 无
*********************************************************************************************************
*/
void bsp_Init(void)
{ /* STM32F429 HAL 库初始化,此时系统用的还是F429自带的16MHz,HSI时钟: - 调用函数HAL_InitTick,初始化滴答时钟中断1ms。 - 设置NVIV优先级分组为4。 */ HAL_Init(); /* 配置系统时钟到168MHz - 切换使用HSE。 - 此函数会更新全局变量SystemCoreClock,并重新配置HAL_InitTick。 */ SystemClock_Config(); /* Event Recorder: - 可用于代码执行时间测量,MDK5.25及其以上版本才支持,IAR不支持。 - 默认不开启,如果要使能此选项,务必看V5开发板用户手册第8章 */ #if Enable_EventRecorder == 1 /* 初始化EventRecorder并开启 */ EventRecorderInitialize(EventRecordAll, 1U); EventRecorderStart();
#endif bsp_InitKey(); /* 按键初始化,要放在滴答定时器之前,因为按钮检测是通过滴答定时器扫描 */ bsp_InitTimer(); /* 初始化滴答定时器 */ bsp_InitUart(); /* 初始化串口 */ bsp_InitExtIO();   /* 初始化扩展IO */ bsp_InitLed(); /* 初始化LED */ BEEP_InitHard();   /* 初始化蜂鸣器 */

}

  主功能:

主程序实现如下操作:

  •   K1按键按下,开启TIM6的周期性中断。
  •   K2按键按下,关闭TIM6的周期性中断。
/*
*********************************************************************************************************
* 函 数 名: main
* 功能说明: c程序入口
* 形 参: 无
* 返 回 值: 错误代码(无需处理)
*********************************************************************************************************
*/
int main(void)
{ uint8_t ucKeyCode; /* 按键代码 */ bsp_Init(); /* 硬件初始化 */ PrintfLogo(); /* 打印例程名称和版本等信息 */ PrintfHelp(); /* 打印操作提示 */ bsp_StartAutoTimer(0, 100); /* 启动1个100ms的自动重装的定时器 */ bsp_SetTIMforInt(TIM6, 10000, 2, 0); /* 设置为10KHz频率定时器中断*/ /* 进入主程序循环体 */ while (1) { bsp_Idle(); /* 这个函数在bsp.c文件。用户可以修改这个函数实现CPU休眠和喂狗 */ /* 判断定时器超时时间 */ if (bsp_CheckTimer(0)) { /* 每隔100ms 进来一次 */ bsp_LedToggle(2); } /* 按键滤波和检测由后台systick中断服务程序实现,我们只需要调用bsp_GetKey读取键值即可。 */ ucKeyCode = bsp_GetKey(); /* 读取键值, 无键按下时返回 KEY_NONE = 0 */ if (ucKeyCode != KEY_NONE) { switch (ucKeyCode) { case KEY_DOWN_K1: /* K1键按下,开启TIM6的周期性中断*/ TIM6->DIER |= TIM_IT_UPDATE; break; case KEY_DOWN_K2: /* K2键按下,关闭TIM6的周期性中断*/ TIM6->DIER &= ~TIM_IT_UPDATE; break; default: /* 其它的键值不处理 */ break; } } }
}

定时器6中断服务程序:

/*
*********************************************************************************************************
* 函 数 名: TIM6_DAC_IRQHandler
* 功能说明: TIM6定时中断服务程序
* 返 回 值: 无
*********************************************************************************************************
*/
void TIM6_DAC_IRQHandler(void)
{ if((TIM6->SR & TIM_FLAG_UPDATE) != RESET) { /* 清除更新标志 */ TIM6->SR = ~ TIM_FLAG_UPDATE; /* 翻转FMC扩展引脚20和23脚 */ HC574_TogglePin(GPIO_PIN_23); HC574_TogglePin(GPIO_PIN_20); }
}

38.9 总结

本章节就为大家讲解这么多,由于FMC总线可以扩展出32路高速IO且使用简单,所以实际项目中也比较有实用价值,望初学者熟练掌握。

 

勿删,copyright占位
分享文章到微博
分享文章到朋友圈

上一篇:React解密:React Hooks函数之useContext

下一篇:LeetCode-015三数之和

您可能感兴趣

  • 用VC5 制 作 应 用 程 序 启 动 封 面

    用VC5 制 作 应 用 程 序 启 动 封 面    用VC5 制 作 应 用 程 序 启 动 封 面 很 多 大 型 应 用 程 序 都 有 启 动 封 面, 如Word 等 办 公 系 列 软件 和VC + + 等编 程 软 件。 通 过 启 动 封 面, 除 了 显 示 应 用程 序 名 称 和 版 权 等 提 示 画 面,还 可 避 免 由 于 应 用 程 序启 动 前 进 行 大...

  • JDBC2.0扩展API(1)

    JDBC 2.0 API被划分为两部分:JDBC 2.0核心API和JDBC 2.0标准扩展API。核心API在java.sql里面。这是原来的版本就实现了的基本的功能。标准扩展API在javax.sql里面。由JDBC2.0规范新规定的一些接口在这里面。当然,JDBC2.0也对原来版本的java.sql核心做了一些改动。不过不是很大。原来JDBC1.0的程序可以不加修改的在JDBC2.0上...

  • JDBC2.0扩展API(2)

    下面我们来介绍JDBC2.0的标准扩展API。标准扩展API分为如下几个方面:  1、 DataSource接口:和Java名字目录服务(JNDI)一起工作的数据源接口。它提供了对数 吹囊恢指玫牧臃椒ā?br>  2、 Connection pooling(连接池):可以重复使用连接,而不是对每个请求都使用一个新的连接。  3、 Distrubute transaction(分布式的事务...

  • 用VC 开 发 基 于ORACLE 数 据 库 应 用 程 序 的 两 种 方 法

    用VC 开 发 基 于ORACLE 数 据 库 应 用 程 序 的 两 种 方 法 北 京 航 空 航 天 大 学 计 算 机 科 学 与 工 程 系黎 杰 麦 中 凡 ---- 1. 引 言 ---- ORACLE 公 司 自1979 年 推 出 基 于SQL 标 准 的 关 系 数 据 库 产 品 到1997 年 版 本8 的 推 出,ORACLE 数 据 库 以 其 支 持 大 ...

  • 虚拟函数是否应该被声明仅为private/protected?

    虚拟函数是否应该被声明仅为private/protected?   问题导入 我想对于大家来说,虚拟函数并不能算是个陌生的概念吧。至于怎么样使用它,大部分人都会告诉我:通过在子类中重写(override)基类中的虚拟函数,就可以达到OO中的一个重要特性——多态(polymorphism)。不错,虚拟函数的作用也正是如此。但如果我要你说一说虚拟函数被声明为public和被声明为private/...

  • mapinfo用户手册 第22章(一)

    第22章 使用MapBasic 打开mapbasic窗口 要打开mapbasic窗口,选择选项》显示mapbasic窗口,mapbasic窗口就显示在屏幕上。 象其他窗口一样,你可以改变它的大小或移动到一个新位置。你可以在该窗口输入mapbasic代码或在集成mapinfo时阅读mapbasic代码。要知道mapinfo是怎样执行一个选定的语句,打开mapbasic窗口,然后打开世界地图表。...

  • API在VB中应用之技巧集锦

    API在VB中应用之技巧集锦          API函数在VB中得到了充分的运用,同时也让无数VB爱好者沉溺于其中。以下是笔者几年来收集整理的几十个API函数在VB中应用的实例,现在写出来与大伙分享,希望能对大伙有所帮助。          1、如何让窗体总在最前面?          *API函数声明     Declare Function SetWindowPos Lib "user...

  • PHP4用户手册:数据类型->arrays

    Arrays 在PHP中一个数组实际上是一个有次序的映射。一个映射是映射值到关键字上。这个类型在单独的方法上被优化的,你可以作为一个真实的数组或一个列表(向量),hashtable (一个映射的执行),字典,聚集,堆栈,队列和更多的来使用它。因为你可能还有另外的PHP-数组作为一个值,你也可以十分容易的模仿树结构。 这个结构的解释超过了这本手册的范围,但是你将发现为这结构的最小的范例。关于...

CSDN

CSDN

中国开发者社区CSDN (Chinese Software Developer Network) 创立于1999年,致力为中国开发者提供知识传播、在线学习、职业发展等全生命周期服务。

华为云40多款云服务产品0元试用活动

免费套餐,马上领取!
【STM32F429开发板用户手册】第38章 STM32F429的FMC总线应用之是32路高速IO扩展介绍:华为云为您免费提供【STM32F429开发板用户手册】第38章 STM32F429的FMC总线应用之是32路高速IO扩展在博客、论坛、帮助中心等栏目的相关文章,同时还可以通过 站内搜索 查询更多【STM32F429开发板用户手册】第38章 STM32F429的FMC总线应用之是32路高速IO扩展的相关内容。| 移动地址: 【STM32F429开发板用户手册】第38章 STM32F429的FMC总线应用之是32路高速IO扩展 | 写博客