您的位置 首页 > 数码极客

8个io口控制12个led的状态如何做到

《中学生C51单片机易学实战入门教程》

  • 实验准备

  • 课程内容

第三课 8 LED玩花样

实验准备:

使用第一课已装配好的实验板

LED 增加7只

电阻 10k ,增加7只

课程内容:

一、 接完整8只LED 电路

参照原理图,类似在P1.0上接LED的方法,把P1.1到P1.7的7只LED和电阻也接好。

这时,为实验板加电,可见到只有P1.0对应的D1这只LED在闪,如果按之前的编程思路,就是使用如下的程序方式:

sbit P10= P1^0;

sbit P11= P1^1;

sbit P12= P1^2;

sbit P13= P1^3;

sbit P14= P1^4;

sbit P15= P1^5;

sbit P16= P1^6;

sbit P17= P1^7;

同时main()程序中使用

P10=!P10;

P11=!P11;

P12=!P12;

P13=!P13;

P14=!P14;

P15=!P15;

P16=!P16;

P17=!P17;

这方式可行吗?当然可行,只要能达到效果,哪一种方式都行,其实这也是编程最先采用的方法,就是先用最容易理解,最简单的实现方法去编程,达到要求结果后,再去做程序优化,否则没达到结果 什么精简高效的程序都是没用的。

好了,现在可以同时控制8 LED了,但看上去很繁,那么就做优化。

单片机虽然只认0与1,但可以一次同时处理多个位,例如C51系列就是8位单片机,同时可以处理8位,更高级的处理器可以同时处理16位、32位、64位或128位等等。

89C52单片机可一次同时处理8位,这单片机把控制数据输入输出的管脚(简称IO口)分成4组,每组8个IO口,分别命名为P1、P2、P3、P4,这在 reg52.h 文件中预先做好定义,方便我们直接操控。

本次实验中8 只LED接在P1的8个IO口处,所以,可以直接一次性控制8只LED。

修改控制,只须改到一行代码。

主程序main()中,把

P10=!P10;

改成

P1=~P1;

下载,观看实验效果,可以见到8只LED同时闪动。

上一课中所用的运算符号!,只对一位数起效,不能同时控制8位,如果把

P1=~P1;

改成

P1=!P1;

那么只有LED1闪,其他不闪,这个可以下载实践下。

而运算符~则是8位同时运算

00000000 做~取反,对每个位取反,结果就是11111111

同理,11111111 做~取反,对每个位取反,结果就是00000000

二、十六进制与二进制

如果8个LED灯想玩下花样,做出特效,有的LED发光,有的不发光,或者做流水灯等广告效果,这时,需要对不同的LED控制它所在位设0或设1,于是 11110000,10101010等这样的结果就出现了,这些数不方便记忆,也不方便编程,于是采用『数制』来实验简化。11110000或10101010这纯机器码表现形式你为二进制数,每位只能是0或1,逢2进1,与平常用的10进制数类似,10进制每位可用0至9个数,逢10进1。还有十六进制的数,成语『半斤八两』中所用的是十六进制,中国古代的重量计量方式是一斤是十六两。

二进制数太长不好写不好记,一般采用十六进制方式表示,

二进制11110000 ---> 十六进制 0xF0

二进制10101010 ---> 十六进制 0xAA

注意,每个十六制数前要加 0x,如果不加,是当成10进制数的。

如果转换,很简单,电脑中有只工具软件『计算器』能帮我们。

在电脑程序附件中可以找到『计算器』这个工具软件。

可以通过 查看 – 科学型 ,切换到 数制转换模式

点二进制,输入11110000,再点十六进制,就自动显示F0

三、8 LED 花样控制

现在,可以实验LED花样特效了,

间闪效果一:(这里仅修改主程序main())

void main()

{

P1=0xAA;//二进制对应是 10101010

mDelay(200);

P1=0x55;//二进制对应是 01010101

mDelay(200);

}

间闪效果二:(这里仅修改主程序main())

void main()

{

P1=0x36;//二进制对应是 01101101

mDelay(200);

P1=0x5B;//二进制对应是 10110110

mDelay(200);

P1=0xDB;//二进制对应是 11011011

mDelay(200);

}

四、 新花样:单点LED轮转

#include "reg52.h"

#define uchar unsigned char

#define uint unsigned int

sbit P10=P1^0;

void mDelay(uint Delay)

{

uint i;

for(;Delay>0;Delay--)

for(i=0;i<124;i++);

}

void main()

{

uchar a = 0x01; // 二进制00000001

for(;;)

{

P1 = ~a; // 首次循环时把a取反的值给P1,11111110

//控制P1.0的LED,注意这时 a 值本身是没有变化的

a = a << 1; // 首次循环时 a左移一位,a值变成 00000010

if (a==0x00) a=0x01; //如果 a 变成了00000000,那么设成00000001

mDelay(200); //延时,之后继续循环 分别控制 各只LED

}

}

程序分析:

第一:uchar 定义的数据,刚好是8位,直接适用于IO的控制。

第二:<< 左移运算符,a中的8个位同时向左移,最后一个用0补上。(同理>>右移运算类似), a=a<<1; 是先计算右边的式子,即左移一位,然后把结果放回a保存。

第三:if (a==0x00) a=0x01;这是判断结构,if 就是『如果』,由于循环结构for(;;)是无限循环,所以其中 a 每左移8次后会变成0,这时让a设成0x01,可以让重新让第一位的LED受控。

注意if (a==0x00)中的 a==0x00 是两个等于号,这是C语言中的,判断运算符中的一个,类似,还有 >=(小于或等于)、<=(大于或等于)、<(小于)、>( 大于)、!=(不等于) 这些运算符。

五、 程序优化

C51单片机开发的前辈已编有一些方便我们使用的功能模块,我们直接按需调用,于是程序可以再简化。在文件in中定义有循环左移位函数_crol_(),使用方法直接看以下修改后的程序。(类似有循环右移位函数_cror_())

#include "reg52.h"

#include "in"

#define uchar unsigned char

#define uint unsigned int

sbit P10=P1^0;

void mDelay(uint Delay)

{

uint i;

for(;Delay>0;Delay--)

for(i=0;i<124;i++);

}

void main()

{

uchar a = 0x01; // 二进制00000001

for(;;)

{

P1 = ~a; // 首次循环时把a取反的值给P1,11111110

//控制P1.0的LED,注意这时 a 值本身是没有变化的

a = _crol_(a,1); // a 循环左移位,左边移出的放回右边的移空位

mDelay(200); //延时,之后继续循环 分别控制 各只LED

}

}

注意:

1.增加了 #include "in" 这一行,

2.循环左移位函数 _crol_(),函数名前面与后面是下划线。

责任编辑: 鲁达

1.内容基于多重复合算法人工智能语言模型创作,旨在以深度学习研究为目的传播信息知识,内容观点与本网站无关,反馈举报请
2.仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证;
3.本站属于非营利性站点无毒无广告,请读者放心使用!

“8个io口控制12个led的状态如何做到”边界阅读