奇数的4只灯与偶数的4只灯交替点亮,间隔时间为1秒。

使用库函数编程点亮开发板上的8只LED灯(使用位带和SysTick)。控制规律如下:

(1) 奇数的4只灯与偶数的4只灯交替点亮,间隔时间为1秒。(实验台编号为奇数的同学完成)

在完成第2的基础上,修改8只LED灯的控制规律,要求如下:

1只灯从左到右循环点亮,间隔时间为2秒。

参考GPT和自己的思路:

对于第一个问题,可以使用位带和SysTick定时器来控制8只LED灯的点亮。具体步骤如下:

  1. 初始化SysTick定时器,设置间隔时间为1秒。

  2. 定义一个数组,存储8只LED灯的状态,0表示灭,1表示亮。

  3. 定义两个变量,odd和even,分别表示奇数灯和偶数灯的当前状态,初始值都为0。

  4. 在SysTick中断中,每次触发时,先判断当前状态是奇数灯还是偶数灯,然后将对应的四只灯的状态取反。

  5. 更新奇数灯和偶数灯的状态。

  6. 将数组中的8个元素依次输出到LED灯上,即可实现奇数的4只灯与偶数的4只灯交替点亮,间隔时间为1秒。

对于第二个问题,需要在第一个问题的基础上再做一些修改。具体步骤如下:

  1. 修改SysTick定时器的间隔时间为2秒。

  2. 定义一个变量i,初始值为0,表示当前点亮的是第i只灯。

  3. 在SysTick中断中,每次触发时,将第i只灯的状态取反,并将i加1。如果i已经到达8,则将其重置为0,从第一只灯开始循环点亮。

  4. 将数组中的8个元素依次输出到LED灯上,即可实现1只灯从左到右循环点亮,间隔时间为2秒。

需要注意的是,在修改灯的状态时,可以使用位运算中的位带操作,可以更快速地实现状态的改变。同时,需要设置适当的时钟频率和计数器分频系数,以确保SysTick定时器的间隔时间精准。

参考GPT和自己的思路:

为实现奇数的4只灯与偶数的4只灯交替点亮,间隔时间为1秒,可以使用位带和SysTick进行编程控制。具体的代码实现可以参考以下示例代码:

// 定义8个LED的位带地址
#define LED0  (*((volatile unsigned long *)0x40010800))
#define LED1  (*((volatile unsigned long *)0x40010804))
#define LED2  (*((volatile unsigned long *)0x40010808))
#define LED3  (*((volatile unsigned long *)0x4001080C))
#define LED4  (*((volatile unsigned long *)0x40010810))
#define LED5  (*((volatile unsigned long *)0x40010814))
#define LED6  (*((volatile unsigned long *)0x40010818))
#define LED7  (*((volatile unsigned long *)0x4001081C))

// SysTick定时器初始化函数
void SysTick_Init(void) {
  NVIC_ST_CTRL_R = 0;                 // 关闭SysTick定时器
  NVIC_ST_RELOAD_R = 7999999;         // 设定重装载值,对应1秒
  NVIC_ST_CURRENT_R = 0;              // 清空当前计数值
  NVIC_SYS_PRI3_R |= 0x40000000;      // 设置SysTick优先级为2,即最高优先级
  NVIC_ST_CTRL_R |= 0x07;             // 打开SysTick定时器,选择默认时钟源
}

// 奇偶数灯交替点亮函数
void LED_Control(void) {
  static unsigned long cnt = 0;
  cnt++;

  if (cnt % 2) {
    LED0 = 1;
    LED2 = 1;
    LED4 = 1;
    LED6 = 1;
    LED1 = 0;
    LED3 = 0;
    LED5 = 0;
    LED7 = 0;
  } else {
    LED0 = 0;
    LED2 = 0;
    LED4 = 0;
    LED6 = 0;
    LED1 = 1;
    LED3 = 1;
    LED5 = 1;
    LED7 = 1;
  }
}

int main(void) {
  // 初始化SysTick定时器
  SysTick_Init();

  // 循环执行LED灯控制函数
  while (1) {
    LED_Control();
    while (!(NVIC_ST_CTRL_R & 0x10000)) {}
  }
}

为实现1只灯从左到右循环点亮,间隔时间为2秒,可以在上述代码的基础上,加上一个计数器,实现按照指定的时间间隔点亮LED灯,具体的代码实现可以参考以下示例代码:

// 从左到右循环点亮,间隔时间为2秒
void LED_Control2(void) {
  static unsigned long cnt1 = 0;
  static unsigned long cnt2 = 0;
  cnt1++;
  if (cnt1 >= 2) {
    cnt1 = 0;
    cnt2++;
    switch (cnt2) {
      case 1:
        LED0 = 1;
        break;
      case 2:
        LED1 = 1;
        break;
      case 3:
        LED2 = 1;
        break;
      case 4:
        LED3 = 1;
        break;
      case 5:
        LED4 = 1;
        break;
      case 6:
        LED5 = 1;
        break;
      case 7:
        LED6 = 1;
        break;
      case 8:
        LED7 = 1;
        break;
      default:
        LED0 = 0;
        LED1 = 0;
        LED2 = 0;
        LED3 = 0;
        LED4 = 0;
        LED5 = 0;
        LED6 = 0;
        LED7 = 0;
        cnt2 = 0;
        break;
    }
  }
}

其中,计数器cnt1用于控制每秒点亮的次数,计数器cnt2用于控制点亮的LED灯编号。在每2秒钟内,依次点亮LED0~LED7,点亮完毕后计数器cnt2复位为0,重新开始循环。