本文隶属于AVR单片机教程系列。

之前我们做的闪烁LED和流水灯,灯效都是循环的。这次我们来尝试一些不一样的——每一次随机选择一个LED并点亮。

要实现随机的效果,我们要用C语言标准库中的相关设施:

 #define RAND_MAX /*implementation defined*/
int rand();
void srand(unsigned seed);

以上设施都定义在 <stdlib.h> 中。其中,rand() 可以返回[0, RAND_MAX ]范围内的伪随机整数,srand() 用于给 rand() 提供种子,当种子相同时,多次调用 rand() 得到的序列是相同的,这就是为什么称 rand() 产生的数为“伪随机数”。如果使用 rand() 之前没有调用过 srand() ,则相当于调用过 srand(1) 。

利用这些工具,很容易就能写出一个随机LED的程序:

 #include <ee1/led.h>
#include <ee1/delay.h> #include <stdlib.h> int main()
{
led_init();
// srand(1);
while ()
{
led_set(rand() % , LED_ON);
delay();
led_off();
}
}

rand() 返回[0, RAND_MAX ]范围内的整数,但 led_set 的第一个参数只有在 [, ] 范围内才有效,因此我们把 rand() 的返回值对4取模。

srand() 被打上注释,是因为这行调用没有必要。

把这段代码编译并烧写进单片机,你会发现LED闪烁的时间是不等长的,这是因为可能存在连续两次亮相同灯的情况。为了解决这个问题,我们引入一个变量,保存当前亮的LED,并让下一个亮的LED与当前的不同。代码如下:

 #include <ee1/led.h>
#include <ee1/delay.h> #include <stdint.h>
#include <stdlib.h> int main()
{
led_init();
// srand(0);
uint8_t cur = rand() % ;
while ()
{
led_set(cur, LED_ON);
delay();
uint8_t next = rand() % ;
if (next >= cur)
next++;
led_set(cur, LED_OFF);
cur = next;
}
}

使连续两次不亮相同灯的核心代码是16~18行。程序生成一个[0, 2]范围内的随机值,3种取值概率相等,然后当此值大于或等于当前亮灯值时,让它自增。假设当前亮灯为1,则生成的随机数在值为0、1、2的情况下分别变成(映射为)0、2、3,因此下一次亮灯就是在当前没有亮的3个灯中等概率地选择一个。

按开发板上的RESET键可以让单片机复位。观察LED序列,你会发现对于每一次复位,LED序列都是一样的。这个问题我们暂时无法解决。

今天的作业:一个更复杂的随机效果,每次亮1~2个灯,连续两次不能有相同的灯亮,也不能都亮2个,总体来看亮2个的概率为1/3。

这里有一个hex文件,是作业的一个实现,以及一个.c源文件,把单片机程序的main函数复制到文件最后,用计算机的C编译器编译运行可以检查算法是否正确。一个正确的结果应该跟这个差不多:

AVR单片机教程——随机点亮LED的更多相关文章

  1. AVR单片机教程——点亮第一个LED

    做了这么多准备,我们终于可以开始用开发板做点事了. 单片机编程与计算机编程有一些不同点.程序都要有零个或多个输入.一个或多个输出,这是两者都有的,但是计算机编程的输入输出主要靠控制台,而单片机没有. ...

  2. AVR单片机教程——闪烁LED

    上次我们把LED点亮了.你可能已经试过把 LED_RED 换成其他灯,也可能已经用 led_on() 把所有LED一起点亮了.但是LED点亮以后,程序就退出了,之后LED一直没有暗,直到没有供电.这一 ...

  3. AVR单片机教程——数码管

    先解答之前一个思考题:如果不把引脚配置为输出而写高电平,连接LED会怎样? 实验结果是,LED会亮,但相比于输出高电平的情况,亮度很低.这是为什么呢? 通过上一篇教程我们知道,引脚输入输出模式是由寄存 ...

  4. AVR单片机教程——数字输出

    从上一篇教程中我们了解到,按键与开关的输入本质上就是数字信号的读取.这一篇教程要讲的是,控制LED的原理是数字信号的输出.数字IO是单片机编程之有别于桌面编程的各项内容中最简单.最基础的. 在讲数字信 ...

  5. AVR单片机教程——按键动作

    上一篇教程中我们学习了如何读取按键状态.而按键的动作,比如单击,至少需要两个状态才能判定,长按.双击的判定更加复杂.今天我们来学习如何使用库函数判断按键单击,以及其实现原理. 我们要实现的是:当一个按 ...

  6. AVR单片机教程——按键状态

    好久没更新了,今天开始继续,争取日更. 今天我们来讲按键.开发板的右下角有4个按键,按下会有明显的“咔嗒”声.如何检测按键是否被按下呢?首先要把按键或直接或间接地连接到单片机上.与之前使用的4个LED ...

  7. AVR单片机教程——烧写hex文件

    每一次build项目,编译器都会生成多个文件,其中有一个就是hex文件.之前在IDE中配置的external tools,就是把这个hex文件烧写到单片机中去的. 然而,有些时候你想运行别人的程序,但 ...

  8. AVR单片机教程——流水灯

    上次我们用 delay 函数与 while 循环实现了一个LED的闪烁.这一次我们把所有LED加入进来,让它们依次闪烁,形成流水灯的效果. 开发板上有4个LED,我们可以用不多的语句把循环体直接描述出 ...

  9. AVR单片机教程——定时器中断

    本文隶属于AVR单片机教程系列.   中断,是单片机的精华. 中断基础 当一个事件发生时,CPU会停止当前执行的代码,转而处理这个事件,这就是一个中断.触发中断的事件成为中断源,处理事件的函数称为中断 ...

随机推荐

  1. PostgreSQL远程连接,发生致命错误:没有用于主机“…”,用户“…”,数据库“…”,SSL关闭的pg_hba.conf记录

    PostgreSQL远程连接方法 有时候在远程连接时,会报Error connecting to the server:致命错误:没有用于主机“…”,用户“…”,数据库“…”,SSL关闭的pg_hba ...

  2. cmake 手册详解【转】

    https://www.cnblogs.com/coderfenghc/tag/cmake/   CMake 手册详解(二十三) SirDigit 2012-12-16 22:03 阅读:11058 ...

  3. 对实体 "useSSL" 的引用必须以 ';' 分隔符结尾。 Nested exception: 对实体 "useSSL" 的引用必须以 ';' 分隔符结尾

    今天在定义数据源的时候,在配置context.xml文件时,连接mysql数据库的url一行发生错误,报错:“对实体 "useSSL" 的引用必须以 ';' 分隔符结尾”.以下是我 ...

  4. OpenGL ES: (4) EGL API详解 (转)

    上一节我们初步学习了 OpenGL ES.EGL.GLSL 的相关概念,了解了它们的功能,以及它们之间的关联.我们知道了 EGL 是绘制 API(比如 OpenGL ES)与 底层平台窗口系统之间的接 ...

  5. 1.0 Android基础入门教程

    1.0 Android基础入门教程 分类 Android 基础入门教程 本教程于2015年7月开始撰写,耗时半年,总共148节,涵盖了Android基础入门的大部分知识,由于当时能力局限,虽已竭尽全力 ...

  6. Thread.currentThread与this的区别

    在看多线程的时候,看到这个知识点,感觉需要验证一下. 一:线程自启动 1.程序 package com.jun.it.thread; public class MyThread extends Thr ...

  7. PHP获取远程文件的大小,通过ob_get_contents实现

    function remote_filesize($uri,$user='',$pw='') { ob_start(); $ch = curl_init($uri); curl_setopt($ch, ...

  8. openresty开发系列2--nginx的简单安装,正向、反向代理及常用命令和信号控制介绍

    openresty开发系列2--nginx的简单安装,正向.反向代理及常用命令和信号控制介绍 一.nginx的安装下载及编译安装1.Nginx下载:nginx-1.13.0.tar.gz,下载到:/u ...

  9. 【BIGEMAP一键离线地图服务】

    地址:http://www.bigemap.com/offlinemaps/ 首页 离线地图 代码示例 项目案例 开发文档 关于我们     [BIGEMAP一键离线服务] 1.快速搭建离线地图服务2 ...

  10. Oracle数据库查看表空间sql语句

    转: Oracle数据库查看表空间sql语句 2018-09-03 15:49:51 兰海泽 阅读数 6212   版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出 ...