在上一教程中,我们学习了有关使用PIC微控制器闪烁LED的知识,并在Perf板上构建了相同的电路。然后,我们使用PICkit 3,ICSP和MPLAB IPE将程序转储到我们的Perf板上。现在,在本教程中,我们将继续使用PIC微控制器上的更多引脚。我们将使用7个输出(LED)和一个输入。在本教程中,我们将使用旧的Perf板(如下所示),并添加冰棍将所需的引脚拉出到第二个LED板上。在本教程的最后,我们将使用PIC微控制器PIC16F877A生成一系列闪烁的LED,并将学习如何使用多个输入和输出,以及有关“ for”循环和函数调用的一些基础知识。
LED板只不过是另一块穿孔板,我们将在其上用限流电阻器(如下所示)焊接LED。我们还将添加一个按钮来启动序列LED闪烁。
电路原理图:
PIC单片机PIC16F877A LED闪烁序列代码和工作说明:
完整的代码已在下面给出(请在最后检查),在这里我们将逐行获取它。当按下按钮时,此代码将开始以顺序的方式使LED发光。为了理解序列,请观看本教程结尾的视频。我建议您将视频中显示的输出与以下代码进行比较,并尝试理解该程序。
让我们逐行查看代码。前几行用于设置配置位,这在上一教程中已进行了说明,因此我暂时跳过它们。理解任何程序的最佳方法是从main( void main() )函数开始,所以让我们开始吧
TRISB0 = 1; //指示MCU PORTB引脚0用作按钮的输入。TRISD = 0x00; //指示MCU所有引脚都输出PORTD = 0x00; //将所有引脚初始化为0
单词TRIS用于定义引脚是否被用作输入/输出,而单词PORT用于使引脚变为高/低。线 TRISB0 = 1 将使PORT B的第0引脚作为输入。这将是我们的按钮。线 TRISD = 0x00; PORTD = 0x00; 将端口D的所有引脚设为输出,并将初始值LOW分配给这些引脚。
因为我们说过B0用作输入,所以我们将按钮的一端连接到引脚B0,另一端接地。届时,每当我们按下按钮时,插针将保持接地,如上图所示。但是要实现这一点,我们必须使用上拉电阻,以便在不按下按钮时将引脚保持在高电平。上拉电阻就是这样。
但是我们的PIC MCU具有内部弱上拉电阻,可以通过软件激活该电阻,从而省去了很多麻烦(当要连接更多按钮时)。
什么是弱上拉电阻?
上拉电阻有两种,一种是弱上拉,另一种是强上拉。弱上拉电阻为高阻值,因此允许弱电流流过,而强上拉电阻为低阻值,因此允许强电流流过。所有MCU大多使用弱上拉电阻。为了在PIC MCU中激活此功能,我们必须查看OPTION_REG(选项寄存器)的数据表,如下面的快照所示。
如图所示,位7处理弱上拉电阻。应该将其激活为零。这是通过 OPTION_REG <7> = 0完成的 。专门处理位7,其他位保留默认值。这样,我们进入while循环,在其中使用if (RB0 == 0) 检查按钮是否被按下 。 如果满足条件,则使用参数1、3、7和15调用函数。
sblink(1); //带有参数1的功能调用1 sblink(3); //带有参数3的功能调用3 sblink(7); //带有参数7 sblink(15)的功能调用7 //带有参数15的功能调用4
我们为什么要使用功能?
函数用于减少代码中的行数。这就是我们大多数人所知道的。但是为什么我们需要减少行数,尤其是在MCU编程时。的原因是我们的程序存储空间有限。如果我们没有正确优化代码,则可能会耗尽内存空间。当我们编写较长的代码页时,这将很方便。
任何函数都将具有函数定义( 在本例中为 sblink(int get) )和函数Call( 在本例中为 sblink(1) )。有一个函数声明是可选的,为避免它,我在将函数调用到主函数中之前已放置函数定义。
函数参数是将从函数调用传递到函数定义的值。在我们的示例中,整数值(1、3、7、15)是从函数调用传递的参数,变量 “ get” 将参数的值获取到函数定义中以对其进行处理。一个函数可以具有多个参数。
调用函数后,将执行函数定义中的以下几行。
对于(int i = 0; i <= 7 && RB0 == 0; i ++){PORTD = get << i; // LED向左移动__delay_ms(50); } for(int i = 7; i> = 0 && RB0 == 0; i--){PORTD = get << i; // LED向左移动__delay_ms(50); }
现在这行似乎很奇怪: PORTD = get << i 。我将解释这里实际发生的情况。
“ <<”是左移位运算符,它将所有位移位到其左位置。现在,当我们使用参数'1'调用 sblink(int get) 函数作为 sblink(1)时, 它将使 'get'的 值成为1,其二进制值为0b00000001。因此,此行类似于 PORTD = 0b00000001 << i 。
“ i”的值将在0到7之间变化,因为我们已经使用了“ for循环” (int i = 0; i <= 7 && RB0 == 0; i ++)。 'i'的值从0到7将更改结果,如下所示:
如您所见,通过保持其余LED熄灭,我们一次(从左到右)打开了一个LED。 (int i = 7; i> = 0 && RB0 == 0; i--) 的下一个“ for循环” 也将执行相同的操作,但是这次LED将按从右到左的顺序打开,从7开始,一直下降到0。我们使用了200ms的延迟,以便可以直观地看到LED的开和关状态。
现在,当我们在 sblink(int get) 函数中传递值3时,将执行函数 sblink(3) ,使'get'的值为0b00000011,因此PORTD上的结果为:
因此,现在这一次将通过使用 sblink(3) 在任何给定时间打开两个LED 。 同样,对于 sblink(7) 和 sblink(15), 三个和四个LED将依次点亮。完成此操作后,我们将使用 PORTD = 0xFF 线使所有LED点亮。查看下面的视频以获取完整的演示。
希望您了解代码,从而学会了如何使用函数“ for”和“ while”循环来获得所需的输出。现在,您可以调整代码以获取不同的LED闪烁顺序。继续编译您的代码并将其转储到您的MCU上并享受输出。如果您卡在某个地方,可以使用注释部分。我还在此处附加了仿真文件和程序文件。
就是这样,在下一个教程中,我们将学习如何使用PIC16F877A定时器而不是使用延迟功能。您可以在此处浏览所有PIC微控制器教程。