第11章     GPIO输出—使用固件库点亮LED

全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn

野火视频教程优酷观看网址:http://i.youku.com/firege

本章参考资料:《STM32F4xx参考手册》、库帮助文档《stm32f4xx_dsp_stdperiph_lib_um.chm》。

利用库建立好的工程模板,就可以方便地使用STM32标准库编写应用程序了,可以说从这一章我们才开始迈入STM32开发的大门。

LED灯的控制使用到GPIO外设的基本输出功能,本章中不再赘述GPIO外设的概念,如您忘记了,可重读前面"GPIO框图剖析"小节,STM32标准库中GPIO初始化结构体GPIO_TypeDef的定义与"定义引脚模式的枚举类型"小节中讲解的相同。

11.1 硬件设计

本实验板连接了一个RGB彩灯及一个普通LED灯,RGB彩灯实际上由三盏分别为红色、绿色、蓝色的LED灯组成,通过控制RGB颜色强度的组合,可以混合出各种色彩。

图 111 LED硬件原理图

这些LED灯的阴极都是连接到STM32的GPIO引脚,只要我们控制GPIO引脚的电平输出状态,即可控制LED灯的亮灭。图中左上方,其中彩灯的阳极连接到的一个电路图符号"口口",它表示引出排针,即此处本身断开,须通过跳线帽连接排针,把电源跟彩灯的阳极连起来,实验时需注意。

若您使用的实验板LED灯的连接方式或引脚不一样,只需根据我们的工程修改引脚即可,程序的控制原理相同。

11.2 软件设计

这里只讲解核心部分的代码,有些变量的设置,头文件的包含等可能不会涉及到,完整的代码请参考本章配套的工程。

为了使工程更加有条理,我们把LED灯控制相关的代码独立分开存储,方便以后移植。在"工程模板"之上新建"bsp_led.c"及"bsp_led.h"文件,其中的"bsp"即Board Support Packet的缩写(板级支持包),这些文件也可根据您的喜好命名,这些文件不属于STM32标准库的内容,是由我们自己根据应用需要编写的。

11.2.1 编程要点

1.    使能GPIO端口时钟;

2.    初始化GPIO目标引脚为推挽输出模式;

3.    编写简单测试程序,控制GPIO引脚输出高、低电平。

11.2.2 代码分析

1.    LED灯引脚宏定义

在编写应用程序的过程中,要考虑更改硬件环境的情况,例如LED灯的控制引脚与当前的不一样,我们希望程序只需要做最小的修改即可在新的环境正常运行。这个时候一般把硬件相关的部分使用宏来封装,若更改了硬件环境,只修改这些硬件相关的宏即可,这些定义一般存储在头文件,即本例子中的"bsp_led.h"文件中,见代码清单 111。

代码清单 111 LED控制引脚相关的宏

1 //引脚定义

2 /*******************************************************/

3 //R 红色灯

4 #define LED1_PIN GPIO_Pin_10

5 #define LED1_GPIO_PORT GPIOH

6 #define LED1_GPIO_CLK RCC_AHB1Periph_GPIOH

7

8 //G 绿色灯

9 #define LED2_PIN GPIO_Pin_11

10 #define LED2_GPIO_PORT GPIOH

11 #define LED2_GPIO_CLK RCC_AHB1Periph_GPIOH

12

13 //B 蓝色灯

14 #define LED3_PIN GPIO_Pin_12

15 #define LED3_GPIO_PORT GPIOH

16 #define LED3_GPIO_CLK RCC_AHB1Periph_GPIOH

17

18 //小指示灯

19 #define LED4_PIN GPIO_Pin_11

20 #define LED4_GPIO_PORT GPIOD

21 #define LED4_GPIO_CLK RCC_AHB1Periph_GPIOD

22 /************************************************************/

以上代码分别把控制四盏LED灯的GPIO端口、GPIO引脚号以及GPIO端口时钟封装起来了。在实际控制的时候我们就直接用这些宏,以达到应用代码硬件无关的效果。

其中的GPIO时钟宏"RCC_AHB1Periph_GPIOH"和"RCC_AHB1Periph_GPIOD"是STM32标准库定义的GPIO端口时钟相关的宏,它的作用与"GPIO_Pin_x"这类宏类似,是用于指示寄存器位的,方便库函数使用。它们分别指示GPIOH、GPIOD的时钟,下面初始化GPIO时钟的时候可以看到它的用法。

2.    控制LED灯亮灭状态的宏定义

为了方便控制LED灯,我们把LED灯常用的亮、灭及状态反转的控制也直接定义成宏,见代码清单 112。

代码清单 112 控制LED亮灭的宏

1

2 /* 直接操作寄存器的方法控制IO */

3 #define digitalHi(p,i) {p->BSRRL=i;} //设置为高电平

4 #define digitalLo(p,i) {p->BSRRH=i;} //输出低电平

5 #define digitalToggle(p,i) {p->ODR ^=i;} //输出反转状态

6

7

8 /* 定义控制IO的宏 */

9 #define LED1_TOGGLE digitalToggle(LED1_GPIO_PORT,LED1_PIN)

10 #define LED1_OFF digitalHi(LED1_GPIO_PORT,LED1_PIN)

11 #define LED1_ON digitalLo(LED1_GPIO_PORT,LED1_PIN)

12

13 #define LED2_TOGGLE digitalToggle(LED2_GPIO_PORT,LED2_PIN)

14 #define LED2_OFF digitalHi(LED2_GPIO_PORT,LED2_PIN)

15 #define LED2_ON digitalLo(LED2_GPIO_PORT,LED2_PIN)

16

17 #define LED3_TOGGLE digitalToggle(LED3_GPIO_PORT,LED3_PIN)

18 #define LED3_OFF digitalHi(LED3_GPIO_PORT,LED3_PIN)

19 #define LED3_ON digitalLo(LED3_GPIO_PORT,LED3_PIN)

20

21 #define LED4_TOGGLE digitalToggle(LED4_GPIO_PORT,LED4_PIN)

22 #define LED4_OFF digitalHi(LED4_GPIO_PORT,LED4_PIN)

23 #define LED4_ON digitalLo(LED4_GPIO_PORT,LED4_PIN)

24

25

26 /* 基本混色,后面高级用法使用PWM可混出全彩颜色,且效果更好 */

27

28 //红

29 #define LED_RED \

30 LED1_ON;\

31 LED2_OFF;\

32 LED3_OFF

33

34 //绿

35 #define LED_GREEN \

36 LED1_OFF;\

37 LED2_ON;\

38 LED3_OFF

39

40 //蓝

41 #define LED_BLUE \

42 LED1_OFF;\

43 LED2_OFF;\

44 LED3_ON

45

46

47 //黄(红+绿)

48 #define LED_YELLOW \

49 LED1_ON;\

50 LED2_ON;\

51 LED3_OFF

这部分宏控制LED亮灭的操作是直接向BSRR寄存器写入控制指令来实现的,对BSRRL写1输出高电平,对BSRRH写1输出低电平,对ODR寄存器某位进行异或操作可反转位的状态。

RGB彩灯可以实现混色,如最后一段代码我们控制红灯和绿灯亮而蓝灯灭,可混出黄色效果。

代码中的"\"是C语言中的续行符语法,表示续行符的下一行与续行符所在的代码是同一行。代码中因为宏定义关键字"#define"只是对当前行有效,所以我们使用续行符来连接起来,以下的代码是等效的:

#define LED_YELLOW LED1_ON; LED2_ON; LED3_OFF

应用续行符的时候要注意,在"\"后面不能有任何字符(包括注释、空格),只能直接回车。

3.    LED GPIO初始化函数

利用上面的宏,编写LED灯的初始化函数,见代码清单 113。

代码清单 113 LED GPIO初始化函数

1 /**

2 * @brief 初始化控制LED的IO

3 * @param 无

4 * @retval 无

5 */

6 void LED_GPIO_Config(void)

7 {

8 /*定义一个GPIO_InitTypeDef类型的结构体*/

9 GPIO_InitTypeDef GPIO_InitStructure;

10

11 /*开启LED相关的GPIO外设时钟*/

12 RCC_AHB1PeriphClockCmd ( LED1_GPIO_CLK|

13 LED2_GPIO_CLK|

14 LED3_GPIO_CLK|

15 LED4_GPIO_CLK,

16 ENABLE);

17

18 /*选择要控制的GPIO引脚*/

19 GPIO_InitStructure.GPIO_Pin = LED1_PIN;

20

21 /*设置引脚模式为输出模式*/

22 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;

23

24 /*设置引脚的输出类型为推挽输出*/

25 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

26

27 /*设置引脚为上拉模式*/

28 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;

29

30 /*设置引脚速率为2MHz */

31 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;

32

33 /*调用库函数,使用上面配置的GPIO_InitStructure初始化GPIO*/

34 GPIO_Init(LED1_GPIO_PORT, &GPIO_InitStructure);

35

36 /*选择要控制的GPIO引脚*/

37 GPIO_InitStructure.GPIO_Pin = LED2_PIN;

38 GPIO_Init(LED2_GPIO_PORT, &GPIO_InitStructure);

39

40 /*选择要控制的GPIO引脚*/

41 GPIO_InitStructure.GPIO_Pin = LED3_PIN;

42 GPIO_Init(LED3_GPIO_PORT, &GPIO_InitStructure);

43

44 /*选择要控制的GPIO引脚*/

45 GPIO_InitStructure.GPIO_Pin = LED4_PIN;

46 GPIO_Init(LED4_GPIO_PORT, &GPIO_InitStructure);

47

48 /*关闭RGB灯*/

49 LED_RGBOFF;

50

51 /*指示灯默认开启*/

52 LED4(ON);

53 }

整个函数与"构建库函数雏形"章节中的类似,主要区别是硬件相关的部分使用宏来代替,初始化GPIO端口时钟时也采用了STM32库函数,函数执行流程如下:

(1)    使用GPIO_InitTypeDef定义GPIO初始化结构体变量,以便下面用于存储GPIO配置。

(2)    调用库函数RCC_AHB1PeriphClockCmd来使能LED灯的GPIO端口时钟,在前面的章节中我们是直接向RCC寄存器赋值来使能时钟的,不如这样直观。该函数有两个输入参数,第一个参数用于指示要配置的时钟,如本例中的"RCC_AHB1Periph_GPIOH"和"RCC_AHB1Periph_GPIOD",应用时我们使用"|"操作同时配置四个LED灯的时钟;函数的第二个参数用于设置状态,可输入"Disable"关闭或"Enable"使能时钟。

(3)    向GPIO初始化结构体赋值,把引脚初始化成推挽输出模式,其中的GPIO_Pin使用宏"LEDx_PIN"来赋值,使函数的实现方便移植。

(4)    使用以上初始化结构体的配置,调用GPIO_Init函数向寄存器写入参数,完成GPIO的初始化,这里的GPIO端口使用"LEDx_GPIO_PORT"宏来赋值,也是为了程序移植方便。

(5)    使用同样的初始化结构体,只修改控制的引脚和端口,初始化其它LED灯使用的GPIO引脚。

(6)    使用宏控制RGB灯默认关闭,LED4指示灯默认开启。

4.    主函数

编写完LED灯的控制函数后,就可以在main函数中测试了,见代码清单 114。

代码清单 114 控制LED灯,main文件

1 #include "stm32f4xx.h"

2 #include "./led/bsp_led.h"

3

4 void Delay(__IO u32 nCount);

5

6 /**

7 * @brief 主函数

8 * @param 无

9 * @retval 无

10 */

11 int main(void)

12 {

13 /* LED 端口初始化 */

14 LED_GPIO_Config();

15

16 /* 控制LED灯 */

17 while (1) {

18 LED1( ON ); // 亮

19 Delay(0xFFFFFF);

20 LED1( OFF ); // 灭

21

22 LED2( ON ); // 亮

23 Delay(0xFFFFFF);

24 LED2( OFF ); // 灭

25

26 LED3( ON ); // 亮

27 Delay(0xFFFFFF);

28 LED3( OFF ); // 灭

29

30 LED4( ON ); // 亮

31 Delay(0xFFFFFF);

32 LED4( OFF ); // 灭

33

34 /*轮流显示红绿蓝黄紫青白颜色*/

35 LED_RED;

36 Delay(0xFFFFFF);

37

38 LED_GREEN;

39 Delay(0xFFFFFF);

40

41 LED_BLUE;

42 Delay(0xFFFFFF);

43

44 LED_YELLOW;

45 Delay(0xFFFFFF);

46

47 LED_PURPLE;

48 Delay(0xFFFFFF);

49

50 LED_CYAN;

51 Delay(0xFFFFFF);

52

53 LED_WHITE;

54 Delay(0xFFFFFF);

55

56 LED_RGBOFF;

57 Delay(0xFFFFFF);

58 }

59 }

60

61 void Delay(__IO uint32_t nCount) //简单的延时函数

62 {

63 for (; nCount != 0; nCount--);

64 }

在main函数中,调用我们前面定义的LED_GPIO_Config初始化好LED的控制引脚,然后直接调用各种控制LED灯亮灭的宏来实现LED灯的控制。

以上,就是一个使用STM32标准软件库开发应用的流程。

11.2.1 下载验证

把编译好的程序下载到开发板并复位,可看到RGB彩灯轮流显示不同的颜色。

11.3 STM32标准库补充知识

1.    SystemInit函数去哪了?

在前几章我们自己建工程的时候需要定义一个SystemInit空函数,但是在这个用STM32标准库的工程却没有这样做,SystemInit函数去哪了呢?

这个函数在STM32标准库的"system_stm32f4xx.c"文件中定义了,而我们的工程已经包含该文件。标准库中的SystemInit函数把STM32芯片的系统时钟设置成了180MHz,即此时AHB1时钟频率为180MHz,APB2为90MHz,APB1为45MHz。当STM32芯片上电后,执行启动文件中的指令后,会调用该函数,设置系统时钟为以上状态。

2.    断言

细心对比过前几章我们自己定义的GPIO_Init函数与STM32标准库中同名函数的读者,会发现标准库中的函数内容多了一些乱七八糟的东西,见代码清单 115。

代码清单 115 GPIO_Init函数的断言部分

1 void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)

2 {

3 uint32_t pinpos = 0x00, pos = 0x00 , currentpin = 0x00;

4

5 /* Check the parameters */

6 assert_param(IS_GPIO_ALL_PERIPH(GPIOx));

7 assert_param(IS_GPIO_PIN(GPIO_InitStruct->GPIO_Pin));

8 assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode));

9 assert_param(IS_GPIO_PUPD(GPIO_InitStruct->GPIO_PuPd));

10

11 /* ------- 以下内容省略,跟前面我们定义的函数内容相同----- */

基本上每个库函数的开头都会有这样类似的内容,这里的"assert_param"实际是一个宏,在库函数中它用于检查输入参数是否符合要求,若不符合要求则执行某个函数输出警告,"assert_param"的定义见代码清单 116。

代码清单 116 stm32f4xx_conf.h文件中关于断言的定义

1

2 #ifdef USE_FULL_ASSERT

3 /**

4 * @brief assert_param 宏用于函数的输入参数检查

5 * @param expr:若expr值为假,则调用assert_failed函数

6 * 报告文件名及错误行号

7 * 若expr值为真,则不执行操作

8 */

9 #define assert_param(expr) \

10 ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))

11 /* 错误输出函数 ------------------------------------------------------- */

12 void assert_failed(uint8_t* file, uint32_t line);

13 #else

14 #define assert_param(expr) ((void)0)

15 #endif

这段代码的意思是,假如我们不定义"USE_FULL_ASSERT"宏,那么"assert_param"就是一个空的宏(#else与#endif之间的语句生效),没有任何操作。从而所有库函数中的assert_param实际上都无意义,我们就当看不见好了。

假如我们定义了"USE_FULL_ASSERT"宏,那么"assert_param"就是一个有操作的语句(#if与#else之间的语句生效),该宏对参数expr使用C语言中的问号表达式进行判断,若expr值为真,则无操作(void 0),若表达式的值为假,则调用"assert_failed"函数,且该函数的输入参数为"__FILE__"及"__LINE__",这两个参数分别代表"assert_param"宏被调用时所在的"文件名"及"行号"。

但库文件只对"assert_failed"写了函数声明,没有写函数定义,实际用时需要用户来定义,我们一般会用printf函数来输出这些信息,见代码清单 117。

代码清单 117 assert_failed 输出错误信息

1 void assert_failed(uint8_t* file, uint32_t line)

2 {

3 printf("\r\n输入参数错误,错误文件名=%s,行号=%s",file,line);

4 }

注意在我们的这个LED工程中,还不支持printf函数(在USART外设章节会讲解),想测试assert_failed输出的读者,可以在这个函数中做点亮红色LED灯的操作,作为警告输出测试。

那么为什么函数输入参数不对的时候,assert_param宏中的expr参数值会是假呢?这要回到GPIO_Init函数,看它对assert_param宏的调用,它被调用时分别以"IS_GPIO_ALL_PERIPH(GPIOx)"、"IS_GPIO_PIN(GPIO_InitStruct->GPIO_Pin)"等作为输入参数,也就是说被调用时,expr实际上是一条针对输入参数的判断表达式。例如"IS_GPIO_PIN"的宏定义:

1 #define IS_GPIO_PIN(PIN) ((PIN) != (uint32_t)0x00)

若它的输入参数 PIN 值为0,则表达式的值为假,PIN非0时表达式的值为真。我们知道用于选择GPIO引脚号的宏"GPIO_Pin_x"的值至少有一个数据位为1,这样的输入参数才有意义,若GPIO_InitStruct->GPIO_Pin的值为0,输入参数就无效了。配合"IS_GPIO_PIN"这句表达式,"assert_param"就实现了检查输入参数的功能。对assert_param宏的其它调用方式类似,大家可以自己看库源码来研究一下。

3.    Doxygen注释规范

在STM32标准库以及我们自己编写的"bsp_led.c"文件中,可以看到一些比较特别的注释,类似代码清单 118。

代码清单 118 Doxygen注释规范

1 /**

2 * @brief 初始化控制LED的IO

3 * @param 无

4 * @retval 无

5 */

这是一种名为"Doxygen"的注释规范,如果在工程文件中按照这种规范去注释,可以使用Doxygen软件自动根据注释生成帮助文档。我们所说非常重要的库帮助文档《stm32f4xx_dsp_stdperiph_lib_um.chm》,就是由该软件根据库文件的注释生成的。关于Doxygen注释规范本教程不作讲解,感兴趣的读者可自行搜索网络上的资料学习。

4.    防止头文件重复包含

在STM32标准库的所有头文件以及我们自己编写的"bsp_led.h"头文件中,可看到类似代码清单 119的宏定义。它的功能是防止头文件被重复包含,避免引起编译错误。

代码清单 119 防止头文件重复包含的宏

1 #ifndef __LED_H

2 #define __LED_H

3

4 /*此处省略头文件的具体内容*/

5

6 #endif /* end of __LED_H */

在头文件的开头,使用"#ifndef"关键字,判断标号"__LED_H"是否被定义,若没有被定义,则从"#ifndef"至"#endif"关键字之间的内容都有效,也就是说,这个头文件若被其它文件"#include",它就会被包含到其该文件中了,且头文件中紧接着使用"#define"关键字定义上面判断的标号"__LED_H"。当这个头文件被同一个文件第二次"#include"包含的时候,由于有了第一次包含中的"#define __LED_H"定义,这时再判断"#ifndef __LED_H",判断的结果就是假了,从"#ifndef"至"#endif"之间的内容都无效,从而防止了同一个头文件被包含多次,编译时就不会出现"redefine(重复定义)"的错误了。

一般来说,我们不会直接在C的源文件写两个"#include"来包含同一个头文件,但可能因为头文件内部的包含导致重复,这种代码主要是避免这样的问题。如"bsp_led.h"文件中使用了"#include "stm32f4xx.h" "语句,按习惯,可能我们写主程序的时候会在main文件写"#include "bsp_led.h" 及#include "stm32f4xx.h"",这个时候"stm32f4xx.h"文件就被包含两次了,如果没有这种机制,就会出错。

至于为什么要用两个下划线来定义"__LED_H"标号,其实这只是防止它与其它普通宏定义重复了,如我们用"GPIO_PIN_0"来代替这个判断标号,就会因为stm32f4xx.h已经定义了GPIO_PIN_0,结果导致"bsp_led.h"文件无效了,"bsp_led.h"文件一次都没被包含。

11.4 每课一练

1.    参考本章中的工程范例,使用STM32标准库编写控制LED灯的程序。

2.    修改"bsp_led.h"头文件中控制LED灯引脚的宏,改至实验板的其它GPIO引脚,然后使用电压表测量该引脚的电平状态。(注意测量引脚状态的时候,程序要控制GPIO输出恒定的电平,方便电压表检测。部分引脚可能已连接到板子上的其它芯片,可能存在干扰。)

3.    设置"stm32f4xx_conf.h"文件,使能"assert_param"断言功能,并定义"assert_failed"函数,当调用库函数参数错误时,该函数点亮LED红灯警告。

第11章 GPIO输出-使用固件库点亮LED—零死角玩转STM32-F429系列的更多相关文章

  1. 第11章 GPIO输出—使用固件库点亮LED

    第11章     GPIO输出—使用固件库点亮LED 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku. ...

  2. 第12章 GPIO输出—使用固件库点亮LED

    本章参考资料:<STM32F76xxx参考手册>.库帮助文档<STM32F779xx_User_Manual.chm>. 利用库建立好的工程模板,就可以方便地使用STM32 H ...

  3. GPIO 输出—使用固件库点亮 LED

    编程要点 1. 使能 GPIO 端口时钟:  2. 初始化 GPIO 目标引脚为推挽输出模式:  3. 编写简单测试程序,控制 GPIO 引脚输出高.低电平. LED的电路图 过程: 1.拷贝一个库函 ...

  4. GPIO输出—使用固件库点亮LED

    为了使工程更加有条理,我们把 LED 灯控制相关的代码独立分开存储,方便以后移植.在“工程模板”之上新建“ bsp_led.c”及“ bsp_led.h”文件,其中的“ bsp”即 BoardSupp ...

  5. 第8章 自己写库-构建库函数雏形—零死角玩转STM32-F429系列

    第8章     自己写库—构建库函数雏形 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fi ...

  6. 使用固件库点亮led灯

    1. 项目 使用STM32F103VE的固件库实现流水灯设计. 2. 代码 由于这是基于野火的视频进行学习的,项目代码在上节基础上进行编写的. 点亮绿灯: main.c #include " ...

  7. 第40章 CAN—通讯实验—零死角玩转STM32-F429系列

    第40章 CAN—通讯实验—零死角玩转STM32-F429系列   第40章     CAN—通讯实验 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视 ...

  8. 第25章 串行FLASH文件系统FatFs—零死角玩转STM32-F429系列

    第25章     串行FLASH文件系统FatFs 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.c ...

  9. 第1章-如何使用本书—零死角玩转STM32-F429系列

    第1章    如何使用本书 1.1    本书的参考资料 集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com ...

随机推荐

  1. Hello world &博客客户端试用

    第一篇博客,使用 open live writer客户端进行测试,下载地址见http://openlivewriter.org/,软件为英文,但配置比较简单,选择“其他博客类型”就ok. 同时安装了语 ...

  2. CSS选择器之伪类选择器(元素)

    :first-child 选择某个元素的第一个子元素(IE6不支持) :last-child 选择某个元素的最后一个子元素 :first-of-type [CSS3]选择一个上级元素下的第一个同类子元 ...

  3. Android Apk增量更新

    前言 有关APK更新的技术比较多,例如:增量更新.插件式开发.热修复.RN.静默安装. 下面简单介绍一下: 什么是增量更新?   增量更新就是原有app的基础上只更新发生变化的地方,其余保持原样. 与 ...

  4. zTree实现权限列表简单实例

    zTree的简单实例 zTree 是一个依靠jQuery 实现的多功能 "树插件".优异的性能.灵活的配置.多种功能的组合是 zTree 最大优点. zTree官网 zTreeAP ...

  5. ssm单项目整合

    目录 前言 创建maven项目 添加依赖 配置文件 总览 jdbc配置 mybatis配置 dao层配置 service层配置 事务配置 controller配置 web.xml 使用 前言 spri ...

  6. 在asp.net一般应用程序中使用session

    通常我们经常,通过session判定用户是否登录.还有一些临时的.重要的数据也尝尝存放在Session中. 在页面我们很容易的得到Session的值,但在类中就会遇到一些问题.也知道通过下面的方法得到 ...

  7. 教你如何获取ipa包中的开发文件

    教你如何获取ipa包中的开发文件 1. 从iTunes获取到ipa包 2. 修改ipa包然后获取里面的开发文件

  8. NCE2

    1.A private conversation Last week I went to the theatre. I had a very good seat. The play was very ...

  9. fountion 的调用 和 打印返回值 + 占位符

    结果: (2) 结果

  10. Log4net 使用之 日期字段格式化

    Log4net 是.Net下一个非常优秀的开源日志记录组件.log4net记录日志的功能非常强大.它可以将日志分不同的等级,以不同的格式,输出到不同的媒介. 之前Log4net的日期字段Data一直采 ...