AVR单片机教程——随机点亮LED
本文隶属于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的更多相关文章
- AVR单片机教程——点亮第一个LED
做了这么多准备,我们终于可以开始用开发板做点事了. 单片机编程与计算机编程有一些不同点.程序都要有零个或多个输入.一个或多个输出,这是两者都有的,但是计算机编程的输入输出主要靠控制台,而单片机没有. ...
- AVR单片机教程——闪烁LED
上次我们把LED点亮了.你可能已经试过把 LED_RED 换成其他灯,也可能已经用 led_on() 把所有LED一起点亮了.但是LED点亮以后,程序就退出了,之后LED一直没有暗,直到没有供电.这一 ...
- AVR单片机教程——数码管
先解答之前一个思考题:如果不把引脚配置为输出而写高电平,连接LED会怎样? 实验结果是,LED会亮,但相比于输出高电平的情况,亮度很低.这是为什么呢? 通过上一篇教程我们知道,引脚输入输出模式是由寄存 ...
- AVR单片机教程——数字输出
从上一篇教程中我们了解到,按键与开关的输入本质上就是数字信号的读取.这一篇教程要讲的是,控制LED的原理是数字信号的输出.数字IO是单片机编程之有别于桌面编程的各项内容中最简单.最基础的. 在讲数字信 ...
- AVR单片机教程——按键动作
上一篇教程中我们学习了如何读取按键状态.而按键的动作,比如单击,至少需要两个状态才能判定,长按.双击的判定更加复杂.今天我们来学习如何使用库函数判断按键单击,以及其实现原理. 我们要实现的是:当一个按 ...
- AVR单片机教程——按键状态
好久没更新了,今天开始继续,争取日更. 今天我们来讲按键.开发板的右下角有4个按键,按下会有明显的“咔嗒”声.如何检测按键是否被按下呢?首先要把按键或直接或间接地连接到单片机上.与之前使用的4个LED ...
- AVR单片机教程——烧写hex文件
每一次build项目,编译器都会生成多个文件,其中有一个就是hex文件.之前在IDE中配置的external tools,就是把这个hex文件烧写到单片机中去的. 然而,有些时候你想运行别人的程序,但 ...
- AVR单片机教程——流水灯
上次我们用 delay 函数与 while 循环实现了一个LED的闪烁.这一次我们把所有LED加入进来,让它们依次闪烁,形成流水灯的效果. 开发板上有4个LED,我们可以用不多的语句把循环体直接描述出 ...
- AVR单片机教程——定时器中断
本文隶属于AVR单片机教程系列. 中断,是单片机的精华. 中断基础 当一个事件发生时,CPU会停止当前执行的代码,转而处理这个事件,这就是一个中断.触发中断的事件成为中断源,处理事件的函数称为中断 ...
随机推荐
- 第K个幸运数(京东2017秋招真题)
题目 4和7是两个幸运数字,我们定义,十进制表示中,每一位只有4和7两个数的正整数都是幸运数字.前几个幸运数字为:4,7,44,47,74,77,444,447... 现在输入一个数字K,输出第K个幸 ...
- nodejs搜索包的流程
执行npm install后,如果打包成功,会在当前目录下生成一个node_modules的文件夹,里面存放着我们所需的依赖包. 当需要引用时,例如: var math = require(" ...
- 阿里云 商标 SAAS
商标注册-注册商标查询-商标交易平台-阿里云商标https://tm.aliyun.com/#/ 阿里云商标查询入口-云栖社区-阿里云https://yq.aliyun.com/articles/69 ...
- Visual Studio 2019更新到16.1.4
Visual Studio 2019更新到16.1.4 此次更新仍然是修复bug为主,涉及到Xcode 11无法启动模拟器.Xamarin.Android SDK 9.3.0.23的调试bug.
- flutter 中的搜索条实现
import 'package:flutter/material.dart'; import 'package:flutter_app/SearchBarDemo.dart'; void main() ...
- openresty开发系列18--lua的字符串string操作
openresty开发系列18--lua的字符串string操作 string的相关操作 1)string.upper(s)接收一个字符串 s,返回一个把所有小写字母变成大写字母的字符串.print( ...
- IFC构件位置信息—ObjectPlacement
在IFC标准中,采用相对坐标系对构件定位.如柱(IfcColumn)的定位信息(局部坐标系及参考坐标系)由ObjectPlacement描述.ObjectPlacement由两部分组成: (1)Pla ...
- get请求utf-8解码
package utils;import java.io.UnsupportedEncodingException;import java.net.URLDecoder; /*** <p> ...
- matlab基本函数 randn,rand,orth
一起来学演化计算-matlab基本函数randn, rand, orth 觉得有用的话,欢迎一起讨论相互学习~Follow Me randn X = randn 随机从正态分布中选一个数作为结果 X ...
- php环境选择
第一个 PHPStudy 推荐这个.简单好用. 链接:https://pan.baidu.com/s/1yWRDjfnadkkUE-JX5pqZmg 提取码:4imw 第二个 PHPnow 第三 ...