之前我们做的闪烁LED和流水灯,灯效都是循环的。这次我们来尝试一些不一样的——每一次随机选择一个LED并点亮。
要实现随机的效果,我们要用C语言标准库中的相关设施:
1 #define RAND_MAX /*implementation defined*/
2 int rand();
3 void srand(unsigned seed);
以上设施都定义在
利用这些工具,很容易就能写出一个随机LED的程序:
1 #include
2 #include
3
4 #include
5
6 int main()
7 {
8 led_init();
9 // srand(1);
10 while (1)
11 {
12 led_set(rand() % 4, LED_ON);
13 delay(200);
14 led_off();
15 }
16 }
rand() 返回[0, RAND_MAX ]范围内的整数,但 led_set 的第一个参数只有在 [0, 3] 范围内才有效,因此我们把 rand() 的返回值对4取模。
srand(1) 被打上注释,是因为这行调用没有必要。
把这段代码编译并烧写进单片机,你会发现LED闪烁的时间是不等长的,这是因为可能存在连续两次亮相同灯的情况。为了解决这个问题,我们引入一个变量,保存当前亮的LED,并让下一个亮的LED与当前的不同。代码如下:
1 #include
2 #include
3
4 #include
5 #include
6
7 int main()
8 {
9 led_init();
10 // srand(0);
11 uint8_t cur = rand() % 4;
12 while (1)
13 {
14 led_set(cur, LED_ON);
15 delay(200);
16 uint8_t next = rand() % 3;
17 if (next >= cur)
18 next++;
19 led_set(cur, LED_OFF);
20 cur = next;
21 }
22 }
使连续两次不亮相同灯的核心代码是16~18行。程序生成一个[0, 2]范围内的随机值,3种取值概率相等,然后当此值大于或等于当前亮灯值时,让它自增。假设当前亮灯为1,则生成的随机数在值为0、1、2的情况下分别变成(映射为)0、2、3,因此下一次亮灯就是在当前没有亮的3个灯中等概率地选择一个。
按开发板上的RESET键可以让单片机复位。观察LED序列,你会发现对于每一次复位,LED序列都是一样的。这个问题我们暂时无法解决。
关键字:AVR 单片机教程 随机点亮LED『本文转载自网络,版权归原作者所有,如有侵权请联系删除』