1.通过延时函数实现LED闪烁

  在Keil MDK 4.74上编写一段程序,控制口袋开发板上LPC1114微控制器的GPIO引脚PIO1_9上的LED灯亮(低电平亮)。进一步利用Delay_1s(void)函数实现定时1s,使LED灯状态反转,再延时1s,使LED灯状态反转,如此一直循环,实现LED灯闪烁。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include "LPC11xx.h" 

void LED_Init(void);
void LED_On(void);
void LED_Off(void);
void LED_Toggle(void);
void Delay_1s(void);

int main(void) {

LED_Init(); // 初始化LED

while(1) {
LED_Toggle(); // LED翻转
Delay_1s(); // 延时
}
}


void LED_Init(void) {
LPC_SYSCON->SYSAHBCLKCTRL |= (1UL << 6); // 启用GPIO时钟
LPC_GPIO1->DIR |= (1UL << 9); // 设置GPIO1_9为输出
}
// 点亮LED
void LED_On(void) {
LPC_GPIO1->DATA &= ~(1UL << 9); // 置低电平
}
// 熄灭LED
void LED_Off(void) {
LPC_GPIO1->DATA |= (1UL << 9); // 置高电平
}
// 翻转LED
void LED_Toggle(void) {
//关着就开,开着就关
//LPC_GPIO1->DATA ^= (1UL << 9);
if (LPC_GPIO1->DATA & (1UL << 9)) { // 如果为高电平即熄灭的状态则点亮
LED_On();
}
else{
LED_Off();
}
}
// 延时函数
void Delay_1s(void) {
int i = SystemCoreClock / 5;
while (--i);
}

2.通过SysTick定时器实现LED闪烁

  在Keil MDK 4.74上编写一段程序,利用系统节拍定时器SysTick实现定时1s,控制LPC1114微控制器的GPIO引脚PIO1_9状态反转(BLINKY指示灯闪烁,周期为2s),比较一下与Delay_1s()函数实现1s的定时的异同点,尝试用不同的方法(改变中断次数或者每次中断的时间)改变LED灯闪烁的频率,观察LED灯的闪烁情况。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include "LPC11xx.h"

#define COUNT_MAX 3000 //最大计数值
#define INT_TIME_1MS SystemCoreClock / 1000 //中断时间,1ms

void LED_Init(void);
void SysTick_Init(uint32_t K, uint32_t ticks);
void LED_Toggle(void);
void SysTick_Handler(void);

static uint32_t msTicks = 0;

int main(void) {
LED_Init();
SysTick_Init(1, INT_TIME_1MS); // 1*1ms

while (1) {
if (msTicks >= COUNT_MAX) { // K*COUNT_MAX*INT_TIME_XXX的时间长度翻转一次LED
LED_Toggle();
msTicks = 0; // 计数器清0
}
}
}

void SysTick_Handler(void) {
msTicks++; // 计数器
}

void LED_Init(void) {
LPC_SYSCON->SYSAHBCLKCTRL |= (1UL << 6); // 启用GPIO时钟
LPC_GPIO1->DIR |= (1UL << 9); // 设置GPIO1_9为输出
}

// SysTick定时器初始化函数
void SysTick_Init(uint32_t K, uint32_t ticks) {
SysTick_Config(K * ticks);
}
// 翻转LED
void LED_Toggle(void) {
LPC_GPIO1->DATA ^= (1UL << 9); // 翻转LED
}

Delay()与SysTick定时器的异同

SysTick定时器方式:通过硬件定时器(SysTick)实现精确定时,无需在主程序中阻塞延时。因此主程序可以继续执行其他任务。每次1ms触发一次中断,计数1秒后翻转LED状态。优点是精度高,资源占用低,系统可以在等待定时时做其他事情(多任务环境下尤其有用)。

延时函数方式:通过一个循环进行延时,阻塞CPU,占用 CPU 时间。优点是简单易用,缺点是精度依赖于循环次数,且阻塞程序执行,主程序在延时时间内无法执行其他任务。对于简单的任务可以使用,但对于复杂系统或多任务系统,SysTick 更加合适。

3.通过16位定时器实现LED闪烁

  利用16位定时器1实现定时1s,控制LPC1114微控制器的GPIO引脚PIO1_9状态反转(可以用中断方式也可以用匹配输出功能)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <LPC11xx.h>

void LED_Init(void);
void TMR16B1_Init(void);
void LED_Toggle(void);
void TIMER16_1_IRQHandler(void);

int main() {

LED_Init(); // 初始化LED
TMR16B1_Init(); // 初始化16位定时器

while(1){};
}

void LED_Init(void) {
LPC_SYSCON->SYSAHBCLKCTRL |= (1UL << 6); // 启用GPIO时钟
LPC_GPIO1->DIR |= (1UL << 9); // 设置GPIO1_9为输出
}
//定时1s
void TMR16B1_Init(void) {
LPC_SYSCON->SYSAHBCLKCTRL |= (1UL << 8); // 16位定时器1时钟使能
LPC_TMR16B1->IR = 0x1F;
LPC_TMR16B1->PR = 799; // 分频系数;
LPC_TMR16B1->MCR = 3; //设置MR0匹配后复位TC并产生中断;
LPC_TMR16B1->MR0 = SystemCoreClock/800; //中断时间
LPC_TMR16B1->TCR = 0x01; // 启动定时器
NVIC_EnableIRQ(TIMER_16_1_IRQn);
}

void LED_Toggle(void) {
LPC_GPIO1->DATA ^= (1UL << 9); // 翻转LED
}

void TIMER16_1_IRQHandler(void) {
if((LPC_TMR16B1->IR|=0x01) == 1){ //判断是否MR0中断,并清MR0中断
LED_Toggle(); //执行LED翻转
}
}