简易彩灯控制系统

2003天前 · AVR单片机 · 342次阅读

硬件电路设计

电路图如下:
Annotation.png
(在线电路图绘制安利:https://lceda.cn/editor
当电压U1大于电压U2 1V以上时,二极管导通发光。当导通电流大于5mA时,人的眼睛就可以明显观察到二极管的发光,导通电流越大,亮度越高。一般导通电流不要超过10mA,否则将导致二极管的烧毁或I/O引脚的烧毁。因此在设计硬件电路时,要在LED二极管电路中串接一个限流电阻,阻值在300Ω~1kΩ之间,调节阻值的大小可以控制发光二极管的发光亮度。
导通电流与限流电阻之间的关系由下面的计算公式确定:

I=\frac{U_1-U_2-V_{LED}}{R}

式中VLED为LED的导通电压。
由于AVR的I/O口输出“0”时,可以吸收最大40mA的电流,因此采用控制发光二极管负极的设计比较好。8个LED发光二极管控制系统的硬件电路如下所示。图中ATmega16的PA口工作在输出方式下,8个引脚分别控制8个发光二极管。当I/O口输出“0”时,LED导通发光;输出“1”时,LED截止熄灭。
Annotation.png
(话说没找到怎么在输入文本的时候正确输入单位,直接输入Ω的话会丢失,粗略看了下文档貌似没看到)
(画个图还是有点花时间,细节多)

软件设计

下面的程序代码的功能是8个LED逐一循环发光1s,构成走马灯。

/******
File name            :demo_6_1.c
Chip type            :ATmega16
Program type         :Application
Clock frequency      :4.000000MHz
Memory model         :Small
External SRAM size   :0
Data Stack size      :256
******/
#include<mega16.h>
#include<delay.h>

void main(void)
{
    unsigned char position = 0;        //position为控制位的位置
    PORTA = 0xFF;                      //PA口输出全“1”,LED全灭
    DDRA = 0xFF;                       //PA口工作为输出方式

    while(1)
    {
        PORTA = ~(1 << position);      //1左移0次、1次、...、7次,逐位非传给PORTA
        if(++position >= 8) position = 0;//8个灯(位置)依次点亮
        delay_ms(1000);                //延迟1000ms
    };
}

思考与实践

Q:调整程序中的delay_ms(),延时时间为1ms,彩灯的闪亮有何变化?为什么?
A:彩灯看起来不会闪亮,而是一直保持亮着。因为延时时间过短,闪亮的频率太高,以至于人眼无法分辨彩灯是不是熄灭过。一般来说人眼能分辨的能力是1000ms/24帧,也就是大概需要长达每40ms熄灭一次,人眼才能看得出彩灯(单个)在闪烁。

Q:计算并验证当延时小于多少ms时,“走马灯”的效果会变成“全亮”?给出计算方法。
A:按照实际研究,延时大约小于40ms/8(灯轮流点亮),即小于5ms时就会是“全亮”的效果。验证的方法可以通过更改程序延时,运行程序实际观察可以看出。

Q:设计一个4种闪烁方式交替循环的彩灯,闪烁方式如下:

  1. 8个LED灯逐一点亮0.5s,左移循环2轮(16次),控制初值=0b11111110
  2. 8个LED灯逐一点亮0.5s,右移循环2轮(16次),控制初值=0b01111111
  3. 8个LED灯逐一点亮0.5s,明暗交替16次,控制初值=0b10101010
  4. 8个LED灯随机点亮,每次0.5s,共16次,控制初值=随机数
  5. 再次从头循环

A:主程序代码如下:

#include<mega16.h>
#include<delay.h>

void light_1(unsigned char position)
{
    while(i <= 2)
    {
        PORTA = 0xFF << position;
        if(++position >= 8)
            {
                position = 0;
                i++;
            }
        delay_ms(500);
    };
}

void light_2(unsigned char position)
{
    i = 0;
    while(i <= 2)
    {
        PORTA = 0xFF >> position;
        if(++position >= 8)
            {
                position = 0;
                i++;
            }
        delay_ms(500);
    };
}

void light_3(void)
{
    i = 0;
    while(i <= 16)
    {
        if(++i % 2)
            {
                PORTA = 0x55;
            }
        else
            {
                PORTA = 0xAA;
            }
        delay_ms(500);
    };
}

void light_4(void)
{
    i = 0;
    while(i <= 16)
    {
        PORTA = rand() % (256) + 0;
        i++;
        delay_ms(500);
    };
}

void main(void)
{
    unsigned char position = 0;        //position为控制位的位置
    PORTA = 0xFF;                      //PA口输出全“1”,LED全灭
    DDRA = 0xFF;                       //PA口工作为输出方式
    int i = 0;
    while(1)
    {
        light_1(position);
        light_2(position);
        light_3();
        light_4();
    }
}
👍 0

none

最后修改于2003天前

评论

贴吧 狗头 原神 小黄脸
收起

贴吧

狗头

原神

小黄脸

目录

avatar

未末

迷失

126

文章数

275

评论数

7

分类