单片机c语言编程控制流水灯

单片机c语言编程控制流水灯
单片机c语言编程控制流水灯

说了这么多了,相信你也看了很多资料了,手头应该也有必备的工具了吧!(不要忘了上面讲过几个条件的哦)。那个单片机究竟有什么

功能和作用呢?先不要着急!接下来让我们点亮一个LED(搞电子的应该知道LED是什么吧^_^)

我们在单片机最小系统上接个LED,看我们能否点亮它!对了,上面也有好几次提到过单片机最小系统了,所谓单片机最小系统就是在单片机

上接上最少的外围电路元件让单片机工作。一般只须连接晶体、VCC、GND、RST即可,一般情况下,AT89C51的31脚须接高电平。

#include //头文件定义。或用#include其具体的区别在于:后者定义了更多的地址空间。

//在Keil安装文件夹中,找到相应的文件,比较一下便知!

sbit P1_0 = P1 ^ 0; //定义管脚

void main (void)

{

while(1)

{

P1_0 = 0;//低电平有效,如果把LED反过来接那么就是高电平有效

}

}

就那么简单,我们就把接在单片机P1_0上的LED点亮了,当然LED是低电平,才能点亮。因为我们把LED的正通过电阻接至VCC。

P1_0 = 0; 类似与C语言中的赋值语句,即把0 赋给单片机的P1_0引脚,让它输出相应的电平。那么这样就能达到了我们预先的要求了。

while(1)语句只是让单片机工作在死循环状态,即一直输出低电平。如果我们要试着点亮其他的LED,也类似上述语句。这里就不再讲了。

点亮了几个LED后,是不是让我们联想到了繁华的街区上流动的彩灯。我们是不是也可以让几个LED依次按顺序亮呢?答案是肯定的!其

实显示的原理很简单,就是让一个LED灭后,另一个立即亮,依次轮流下去。假设我们有8个LED分别接在P1口的8个引脚上。硬件连接,在

P1_1--P1_7上再接7个LED即可。例程如下:

#include

sbit P1_0 = P1 ^ 0;

sbit P1_1 = P1 ^ 1;

sbit P1_2 = P1 ^ 2;

sbit P1_3 = P1 ^ 3;

sbit P1_4 = P1 ^ 4;

sbit P1_5 = P1 ^ 5;

sbit P1_6 = P1 ^ 6;

sbit P1_7 = P1 ^ 7;

void Delay(unsigned char a)

{

unsigned char i;

while( --a != 0)

{

for(i = 0; i < 125; i++); //一个; 表示空语句,CPU空转。

} //i 从0加到125,CPU大概就耗时1毫秒

}

void main(void)

{

while(1)

{

P1_0 = 0;

Delay(250);

P1_0 = 1;

P1_1 = 0;

Delay(250);

P1_1 = 1;

P1_2 = 0;

Delay(250);

P1_2 = 1;

P1_3 = 0;

Delay(250);

P1_3 = 1;

P1_4 = 0;

Delay(250);

P1_4 = 1;

P1_5 = 0;

Delay(250);

P1_5 = 1;

P1_6 = 0;

Delay(250);

P1_6 = 1;

P1_7 = 0;

Delay(250);

P1_7 = 1;

}

}

sbit 定义位变量,unsigned char a 定义无符字符型变量a,以节省单片机内部资源,其有效值为0~255。main函数调用Delay()函数。

Delay函数使单片机空转,LED持续点亮后,再灭,下一个LED亮。while(1)产生循环。(三)

上面我们讲了如何使LED产生流动,但是你是否发现一个问题:写的太冗长了!能不能再简单点呢?可以!可以使用C51的内部函数

INTRINS.H实现。函数unsigned char _crol_(unsigned char a, unsigned char n) 可以使变量a循环左移n位,如果我们先给P1口赋

0000 0001那么当n为1时,便会产生和上面一样的效果!

#include

#include

void Delay(unsigned char a)

{

unsigned char i;

while( --a != 0)

{

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

}

}

void main(void)

{

unsigned char b, i;

while(1)

{

b = 0xfe;

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

{

P1 = _crol_(b, 1);

b = P1;

Delay(250);

}

}

}

INTRINS.H函数中的unsigned char _cror_(unsigned char a, unsigned char n)右移也可以实现同样的效果!这里就不再累述。

流水灯的花样很多,我还写过那种拉幕式的流动等,程序很简单,有兴趣的朋友,可以自己试着写写!

对了,讲了那么多,有些朋友一定还不知道编译软件怎么用?这里给大家介绍几个吧?WAVE(伟福)大家一定听说过吧!还有一个

就是KEIL2,我用的就是KEIL2,下面就来讲讲如何使用KEIL2这个编译软件!

1.安装软件,这个应该不用再讲了吧!

2.安装完后,启动KEIL软件左击Project-->New Project-->输入文件名-->选择我们所以使用的芯片(这里我们一般用到Atmel的

AT89C51或AT89C2051,点确定。

3.点File-->New-->输入我们编写的程序,保存为.C文件。(一般情况下,我们保存的文件名和前面的工程名一样。)

4.展开Target 1 -->右击Source Group 1 -->Add Files to Group 'Source Group 1'-->选择刚才保存的.C文件点击ADD后,关闭对

话框。这样.C文件就被加到了Source Group 1 下。

5.右击Target 1-->Options for 'Target 1' -->Target中填写晶体的大小,Output中,在Create HEX Files 前打上钩,点确

定。

6.点Project-->Rebuild All Traget Files ,若提示

creating hex file from "XXX"...

"XXX" - 0 Error(s), 0 Waring(s).

表示编译和生成HEX文件成功!接下来的就是把HEX文件烧到单片机中,或是仿真器上,看是否达到预先的目的!

嘿嘿!现在是否自己好有成就感了,如果让你去做个流水彩灯,开发一个简单的产品,只要加上驱动电路,就可以做出漂亮的流动彩灯

了!到现在为止,你应该知道单片机的功能有多强大了吧,如果单纯的用数字电路或模拟电路的知识去设计一个流动彩灯,可能要花点工夫

和时间才行,有了单片机,那就不一样了,你只要写程序控制他就行!有人说过这样一句话,也并不无道理的,学单片机,程序思想很重要!

(四)

呵呵,朋友!相信你的流水灯也做的不错了吧,现在能玩出几种花样了?你可能会说,只要你想得到,想怎么流就怎么流!呵呵,是的。

但是工程师们设计这么一个单片机,并不是只为了让它做流水灯的,那样也太浪费点了吧 ... ^_^

学过数字电路的朋友,一定动手做过8路或者6路的抢答器。用纯粹的数字电路知识来做,自己设计电路,感到比较困难!抢答器上用的显

示器多为7段数码管,这里我们来讲讲,如何用单片机让数码管显示0-9。抢答器的实现,我们放到后面再来探讨,因为抢答器还涉及了键盘的

内容。8段数码管分为共阴和共阳两种。8段数码管是由8个LED组成(还包括一个小数点)。若为共阳,则8个LED的阳级是连接在一起的,同理

若为共阴,则阴极连接在一起。8个LED对应的标号如下:({0x3f, 0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //0-9数字)

a 0 1 2 3 4

5 6 7 8 9

__ 0011 1111,0000 0110,0100 1111,0101 1011

f | | b

|__|

|g | c

e |__| . dp

d

一般情况下,为了计算或取码的方便,我们把a-dp依次接到单片机某个口上的Px.0--Px.7上。x表示0,1,2,3其中的一个。这样我们只

要给某个口,赋一个值,则相应的LED段就被点亮,但是在硬件连接上要注意了:单片机可能不能直接驱动LED,所以我们可以通过控制三级管

的导通或截止,来控制LED的亮与灭!

如果我们把共阴的数码管的a--dp依次接到单片机的P0.0--P0.7上,注意:P0口需接上拉电阻。何为上拉电阻,简单的说,就是把电平拉

高,以提高驱动能力。那么比如:P0 = 0X3F;则显示为数字0 。因为0X3F 即为2进制的0011 1111 我们低位往高位数,依次为1111 1100,

其I/O的电平分别为高、高、高、高、高、高、低、低,即对应的a--dp 为亮、亮、亮、亮、亮、亮、灭、灭,由上图我们可以看出g和dp段不

亮其他段均亮,即为我们所看到的数字0 字样。其他的数字或字符,也同理可以得到。但

是有些朋友就会问,那我们每取一个字模,岂不是

很麻烦?还有自己考虑高低电平什么的?^-^ 呵呵,其实网上有很多LED取模软件,如果有一定计算机编程语言的朋友,也可以试着自己写个

取模的程序,让计算机为我们计算,诸如上述0X3F的数值。

#include

void Delay(unsigned char a)

{

unsigned char i;

while( --a != 0)

{

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

}

}

void main(void)

{

P0 = 0X3F; //显示0

Delay(250);//延时

P0 = 0X00;//短暂的关闭显示,若不关闭,可能会造成显示模糊不清。

P0 = 0X06; //显示1

Delay(250);

P0 = 0X00;

... //以下显示数字2-F,略。

}

看到这里,想必大家一定可以把0-F显示出来了吧!但是如果要你显示两位数,三位数呢?或许,有的朋友会这么想:在P0口上接一个

数码管,再在P1口上接个数码管!但是,如果要显示4位、5位的数字呢?那岂不是一块AT8951都接不过来!难到就不能接4位或5位以上的吗?

肯定不是的!

说到这里,我们来讲讲数码管的显示方式,可分为两种:动态扫描和静态显示。上面我们所说的即为静态显示。但是如果我们采用动态扫

描显示,那么就可以解决上面的问题,即可以显示多个数码管了。上面我们所说的静态显示把数码管的COM脚接至VCC或GND端,其他的接至PX

口上,这样只要PX口上输出相应的高低电平,就可以显示对应的数字或字符。但是如果我们采用动态扫描的方法,比如显示6个数码管,硬件

连接可以这样解决:a--dp还是接至P0.0--P0.7上,还有6个COM脚再接至另外口的P2.0--P2.5。P0口作段选(控制数字字符)P2口作位选(选

通哪个数码管导通)这样我们控制P0和P2口就可以控制6个数码管了。但是,细心的朋友,会问这样的问题:P2位选,是让数码管一个一个亮

的,那还是不能控制6个一起亮或灭嘛!?^_^ 想想好象是对的哦?怎么办...难道错了?

嘿嘿,问你个问题?黑夜里,拿着一支烟,在你面前快速的晃动,你会发现什么样的现象?是不是原本不连续的点变成了一条看上去连

续的曲线或者直线!再回过头来,仔细想想我们的数码管!原理是一样的,你可别忘了,我

们的单片机可是一个计算机哦,计算机的运算速

度,大家可想而知吧!

这里再说说51单片机的机器周期和时钟周期等概念。所谓机器周期就是访问一次存储器的时间。而1个机器周期包括12个时钟周期。如果

单片机工作在12M晶体下,那么一个时钟周期为:1/12微妙。一个机器周期12*1/12 = 1微妙。如果晶体为6M,时钟周期和机器周期各是多少呢

?在汇编中,我们还要关心,指令执行的机器周期长短不一,有1个周期、2个周期和4个周期等。

说着说着,跑了这么远了...还是回到原来的话题,如果我们把位选的P2也看作上面的“烟”一划而过,那么我们看到的是不是6个一起亮

或一起灭了!^_^ 哈哈,原来如此... 记住,在任何某一时刻,有且只有一个数码管能发光。如果你能把这句话理解了,你是真明白

我的意思了!朋友,现在给你个任务,让6个数码管分别显示1、2、3、4、5、6。看你自己可以搞定不?你自己先试着写写看咯...

#include

void Delay(unsigned char a)

{

unsigned char i;

while( --a != 0)

{

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

}

}

void main(void)

{

while(1)

{

P0 = 0x06;//1的码段

P2 = 0x01;//选通一位,或者P2_0 = 1;

Delay(20);//延时约20毫秒

P0 = 0X00;//关闭显示

P0 = 0x5b;//2的码段

P2 = 0x02; //选通一位,或者P2_1 = 1;

Delay(20);

P0 = 0X00;

P0 = 0x4f;//3的码段

P2 = 0x04; //选通一位,或者P2_2 = 1;

Delay(20);

P0 = 0X00;

P0 = 0x66;//4的码段

P2 = 0x08; //选通一位,或者P2_3 = 1;

Delay(20);

P0 = 0X00;

P0 = 0x6d;//5的码段

P2 = 0x10;//选通一位,或者P2_4 = 1;

Delay(20);

P0 = 0X00;

P0 = 0x7d;//6的码段

P2 = 0x20;//选通一位,或者P2_5 = 1;

Delay(20);

P0 = 0X00;

}

}

(五)

相信大家一定见过数字时钟,教学楼大厅一定有吧。每次路过,基本上只是随便瞟上一眼,根本没去想过他的工作原理什么。但是今天

你也可以把他做出来了,是不是觉得自己很有成就感呢!呵呵!^_^

接上面所讲的,我们先来做个简单的实验:在一个数码管上轮流显示0--9这10个数字。还楞着干什么,快动手写程序呀!好象有点难哦,

要不先不要往下看了,嘿嘿,关机吧,自己先去想想,怎么样?

#include

unsigned char code SEG_TAB[ ] ={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //0-9数字

void Delay(unsigned int a) //unsigned int 定义为无符整形,取值范围为0--32768

{

unsigned char i;

while( --a != 0)

{

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

}

}

void main(void)

{

unsigned char i;

while(1)

{

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

{

P0 = SEG_TAB[ i ]; //取SEG_TAB数组中的值

P2 = 0X01;

Delay(1000);

}

}

}

是不是显示从0--9,跳动显示,你的心是不是也跟着一起跳呀,离我们的目标又迈进了一步!不错,继续努力!

上面只显示了一个数码管的数字0--9,但是怎么样要让他显示6个数字呢?这样我们就可以做个时钟出来玩玩了!还记不记得我们前面

讲过的P2口的位选作用!嘿嘿,没忘记就好!

#include

unsigned char hour = 12, min = 0, sec = 0;

unsigned char code SEG_TAB[ ] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //0-9数字

void Delay(unsigned char a)

{

unsigned char i;

while( --a != 0)

{

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

}

}

void disp(void)

{

P0 = SEG_TAB[ sec % 10 ];//显示秒的个位

P2 = 0X01;

Delay(15);

P2 = 0;

P0 = SEG_TAB[ sec / 10 ];//显示秒的十位

P2 = 0X02;

Delay(15);

P2 = 0;

P0 = SEG_TAB[ min % 10 ];//显示分的个位

P2 = 0X04;

Delay(15);

P2 = 0;

P0 = SEG_TAB[ min / 10 ];//显示分的十位

P2 = 0X08;

Delay(15);

P2 = 0;

P0 = SEG_TAB[ hour % 10 ];//显示时的个位

P2 = 0X10;

Delay(15);

P2 = 0;

P0 = SEG_TAB[ hour / 10 ];//显示时的十位

P2 = 0X20;

Delay(15);

P2 = 0;

}

void main(void)

{

while( 1 )

{

disp( );

}

}

编译烧录芯片后,观察运行现象。矣...怎么一直显示12:00:00,难道是时钟没有启动?还是,另外的原因呢?哦,原来是3个变量

sec,min,hour初始化后,其值一直没有改变!那我们怎么样才能让他改变数值呢?有的朋友一定会这么认为:让秒个位延时1秒,后加1,

而秒十位延时10秒后,再加1,一直加到6,分个位加1,依次类推...这样的想法是不错,但是朋友你有没有想过C语言的一般延时(除非你

把他放到中断里)极不精确!这样累计下来,一天24小时的误差,肯定很大很大,我曾经也用延时的方法写过时钟,1个小时误差8秒,那是

个什么概念!一天24小时就要24*8=192,约为3分钟,一个月就是10分钟...有没有其他的方法可以改进些呢?有!这里就要涉及到单片机中

另一个比较重要的核心部分:单片机的中断和定时器的运用!想写出比较精确(这里说的只的相对前面的做法而言比较精确而已,如果要做

更加精确的时钟,用时钟芯片比较好点,常用的有DS12887和DS1302等)的时钟程序,就一定要调用中断和定时器。还是大家先看看教材和书

吧,毕竟人家出的书,肯定比我要写的系统多了,下面我们再来简单的讲讲!

(六)

什么是中断呢?讲个比较通俗的例子:比如你正在家中看电视,突然电话响了,你的第一反应是什么?是不是先跑过去接电话!接完电话

后,继续看电视。这就是个中断的例子,中断是由电话引起了,你跑过去就是响应中断,接电话就是中断的处理!接完电话后,接续看电视,

即恢复中断,等待下个中断的到来!

但是这个好象和单片机没什么联系呀?有的朋友或许会这样疑问。是的。单片机当然不会看电视了,也不会接电话了!^_^ 但是,类

比一下:比如单片机正在执行某个任务,突然要有更重要的事件,要求单片机响应,单片机就会应答响应,去执行更为重要的任务(中断处理

),原来的任务就继续等待(现场的保护)。执行完更重要的任务后,回到中断的入口处,继续执行原来的任务(现场中断的恢复)。51系列

的单片机共有5个中断源,分别为:外中断0 、定时器T0中断、外中断1、定时器T1中断、串口中断。

或许,有些朋友已经大概领会了其中的意思,有些朋友还迷迷糊糊。不过不要紧,我们继续往下看,下面我们来讲讲单片机的定时器是什

么?如何工作的?定时器,大家从字面上就可以看出其大概的意思吧?简单的说:就是起定时作用!也就是让单片机计数。定时器分为:方式

0方式1、方式2和方式3等4种工作方式。有些朋友一定会问:定时器如何启动?风扇的定时器,相信大家一定都用过吧!但是单片机的定时器,

该如何启动呢?总不该也用手一拧定时器吧! ^_^ 当然不是,我们只要给单片机一些指令,

就可以启动定时器了!下面我们就定时器0,来说

说怎么启动定时器0。

TMOD = 0X01;//设置定时器0 工作方式0

TH0 = (65536 - 5000) / 256;//载入高8位初值

TL0 = (65536 - 5000) % 256;//载入低8位初值

TR0 = 1; //启动定时器

^_^,简单吧,这样我们就可以把定时器启动了。其中TMOD为T/C方式控制寄存器:D7 D6 D5 D4 D3 D2 D1 D0

_ _

GATE C/T M1 M0 GATE C/T M1 M0

|_________ __________| |_________ __________|

| T/C1 | | T/C0 |

C/T就是counter(记数器)和timer(定时器)的选择位,若值为1,则作计数器用。为0,则为定时期用!GATE为门控位。M1和M0工作方

式的选择:若M1=0;M0=0 则为方式0:13位定时/记数器。若M1=0;M0=1则为方式1,16定时/记数器。若M1=1;M0=0则为方式2,自动装载8位

定时/记数器。若M1=1;M0=1则为方式3,只适用于T/C0,2个8位定时/记数器。

说了一大堆,感到有点困惑了吧。那我们还是来说说上面的。TMOD= 0X01;//至于为什么是0X01,大家看:我们选择的是定时器0方式0,

所以T/C1全为0,而T/C0的M1为0。M0为1,所以D0-D7为0X01;0X01表示的是16进制数,这个大家应该都知道吧!还有D0-D7表示的是2进制数。

还需要转换一下!

TH0 = (65536 - 5000) / 256;//载入高8位初值。若在12M晶体下,定时5000微秒,即为5毫秒;但是如果不是在12M下,那又该怎么计算

了呢?如果是11.0592M呢?还记不记得,我们前面讲过的机器周期和时钟周期的概念?^_^忘了,还是看看前面吧!呵呵!没事,学习嘛,忘

了再翻翻书,看看就可以了!其实上诉的5000 = 1 * C 很显然C=5000,但是如果是11.0592M那么就不是1了,应该是1.085了,那么5000 =

1.085 * C,则C就为5000 / 1.085 = ? 具体多少,大家自己去算算吧?同理TL0也是一样的!但是,细心的朋友会发现网上或者是资料上的

TH0,TL0并不是和上面一样的,而是直接TH0 = 0XEC;TL0 = 0X78 是不是和上面的一样的,别忘了单片机也是计算机的一种哦。用C的话,直

接写上计算公式就行,计算就交给单片机完成。

TR0 = 1;这句就是启动定时器0,开始记数!哦,还有一点,有些朋友会问,你是65536是哪里来的呢?呵呵你可别忘了:设置定时器0

工作方式0是16位的(2的16次方是多少,自己算算就知道了)简单吧?但是如何和中断一起使用呢?请继续看下面的讲解!

TMOD = 0X01;//设置定时器0 工作方式0

TH0 = (65536 - 5000) / 256;//载入高8位初值

TL0 = (65536 - 5000) % 256;//载入低8位初值

TR0 = 1; //启动定时器

EA = 1;//开总中断

ET0 = 1;//开定时器中断。若为0则表示关闭!

这样我们,就初始化定时器T0和中断了,也就是定时器满5毫秒后,产生一次中断。产生中断后,我们怎么处理呢?嘿嘿!仔细想想?

^_^

每次中断后,我们可以让一个变量自加1,那么200次中断后,不就是1秒的时间了吗?比起上面我们说的延时来出来是不是更加精确多了呢?

那是肯定的!但是想想1秒种的时间就让单片机产生那么多次的中断,单片机会不会累着呢?恩,那么不好。如果在12M的晶体下,T0每次中

断不是可以产生最多65.336毫秒的时间吗?那么我们让他每50毫秒中断一次好了!这样我们就20次搞定一秒的时间了!·爽·

好了,讲了那么多,现在我们来写个时间的程序吧!^_^

#include

#define HI ((65536 - 50000) / 256)

#define LO ((65536 - 50000) % 256)

#define _TH0_TL0_ (65536 - 50000)

#define M 20 //(1000/25)

/*********************************************************************** ***********************/

unsigned hou = 12, min = 0, sec = 0;

unsigned char SEG_TAB_B[ ] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //0-9数字

unsigned char SEG_TAB_A[ ] = {0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};//0.-9.数字

/*********************************************************************** **********************/

void Delay(unsigned char a)//延时程序a*1MS

{

unsigned char j;

while(a-- != 0)

{

for (j = 0; j < 125; j++);

}

}

/*********************************************************************** **********************/

void Disp(void)//数码管显示

{

P2_0 = 1;

P1 = SEG_TAB_B[ hou / 10 ];

Delay(5);

P2_0 = 0;

P2_1 = 1;

P1 = SEG_TAB_A[ hou % 10 ];

Delay(5);

P2_1 = 0;

P2_2 = 1;

P1 = SEG_TAB_B[ min / 10 ];

Delay(5);

P2_2 = 0;

P2_3 = 1;

P1 =S EG_TAB_A[ min % 10 ];

Delay(5);

P2_3 = 0;

P2_4 = 1;

P1 = SEG_TAB_B[ sec / 10 ];

Delay(5);

P2_4 = 0;

P2_5 = 1;

P1 = SEG_TAB_B[ sec % 10 ];

Delay(5);

P2_5 = 0;

}

/*********************************************************************** *********************/

void IsrTimer0(void) interrupt 1 using 1 //定时50ms

{

static unsigned char count = 0; //定义静态变量count

count++;

if(count == M)

{

count = 0;

sec++;

if(sec == 60)

{

min++;

sec = 0;

if(min == 60)

{

hou++;

min = 0;

if(hou == 24)

{

hou = 0;

}

}//if

}//if

}//if

}

/*********************************************************************** *******************/

void Timer0Init(void) //定时器0

{

TMOD = 0x01;

TH0 = HI;

TL0 = LO;

TR0 = 1;

ET0 = 1;

EA = 1;

}

/*********************************************************************** *******************/

void main(void) //主函数

{

Timer0Init();

while(1)

{

Disp();

}

}

简单吧,还是有点看不懂哦,那你自己慢慢体会吧,如果你自己能写个时钟程序来,那么你的51单片机也就学了80 % 了。中断和

定时/记数器器,是个很重要的东西,几乎用到单片机的地方都会涉及到中断和定时!所以大家要好好掌握哦!^_^

哈哈,赶紧编译HEX文件,搭好硬件,烧入单片机,上电看看效果先!呵呵,现在你应该有成就感了吧,想不到一个时钟居然那么

简单,嘿嘿!但是问题来了!时钟虽然做出来了,但是他的精度怎么样呢?一两个小时,或许看不出什么误差,但是一天或者一年呢?

晕,我的天呀,要是按年来算的话,那这个时钟根本没有实用价值!人家都说用C写不出,精度高的时钟程序来的!!!是不是有点后悔

了,去学汇编吧!但是既然选择了C,那么就不要后悔!嘿嘿,想想C的高级语言,怎么会输给汇编呢^_^ 呵呵!看下面这段代码:

static unsigned char count = 0;

TR0 = 0;

TL0 += (_TH0_TL0_ + 9) % 256;

TH0 += (_TH0_TL0_ + 9) / 256 + (char)CY;

TR0 = 1;

count++;

在中断处理服务程序中,我们加入上面的代码。TR0 = 0; 先关闭定时器T0,然后重新给TH0和TL0 赋值,再开启TR0 = 1;烧入单片

机看看效果,怎么样,你第一次精确多了吧。但是还是有误差!郁闷!为什么呢?那是硬件造成的误差,我们可以用软件来弥补!我们先

把时钟点亮,让他走上几个小时或者是几天,看看到底误差是多少!取个平均值。(这里比如我们10小时快1秒)那么可以通过以下语句

if(hour % 10 = 0)

{

sec--;

}

来弥补!这样可能会出现这样的现象:秒直接跳变!我们可以再通过细分来实现,不要10小时那么大,小些的就行!具体的操作还是留给

朋友们吧!

(七)

这回我们来讲讲键盘,大家肯定见过银行柜员机吧,取钱输入密码就要用到键盘,超市购物取回寄存物品要输入密码,还有你现在在

用的PC机的键盘。但是键盘的是怎么工作的呢?一般有2种方式:(1)扫描法,不断扫描键盘的状态,送CPU判断并处理。如果键盘数目一

大的话,显然不适合(2)线反转法,通过行列状态的改变来判断有无键被按下!

现在我们在P1口接个4*4的键盘,P1.0--P1.3接行,P1.4---P1.7接列,再接4个4K7的上拉电阻至VCC。代码如下:

//----键盘扫描法程序-------

//----用数码管显示相应的键值-----

//P1.0--P1.3接行-------

//P1.4---P1.7接列-------

#include

unsigned char code tab[ ]={0x3F,0x06,0x5B,0x4F,

0x66,0x6D,0x7D,0x07,

0x7F,0x6F,0x77,0x7C,

0x39,0x5E,0x79,0x71};//0到F的16个键植

/*********************************************************************** *******/

void Delayt(unsigned char t)//延时函数

{

unsigned char i;

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

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

}

/*********************************************************************** *******/

bit pkey(void)//判断键的否被按下,通过返回值确定

{

P1=0xf0;

if(P1!=0xf0)

{

Delayt(25);

if(P1!=0xf0)

return 1;

else

return 0;

}

else

return 0;

}

/*********************************************************************** *******/

void main(void)//主函数

{

unsigned char key,j,k,s;

while(1)

{

if(pkey()==1)

{

P1=0xfe;

k=0xfe;

for(j=0;j<4;j++)

{

s=P1&0xf0;

switch(s)

{

case 0xe0: key=4*j+0; break;

case 0xd0: key=4*j+1; break;

case 0xb0: key=4*j+2; break;

case 0x70: key=4*j+3; break;

default: break;

}

k=(k<<1)|0x01;

P1=k;

}//for

}//if

//if((P1&0xf0)==0xf0)

P0=tab[key];

P2=1;

Delayt(50);

}//while

}

还有一种就是线反转法,实现如下:

1.和扫描法相同,把列线置低电平,行置高,读行状态

2.与1相反,把行置低,列置高,读列状态

3.若有键按下,则为2次所读状态的结果即为键所在的位置,这样2次输出和2次读入可以完成键的识别!!!

子函数如下:

unsigned char key_vscan(void)

{

unsigned char row, col;

P1 = 0xF0;

row = P1&0xF0;

row = row&0xF0;

P1 = 0x0F;

col = P1&0x0F;

col = col&0x0F;

return(key_val(row|col));

}

下面我们再来介绍介绍一键多能的程序,即按下一个键,可以执行不同的命令!void main (void)

{

unsigned char b = 0;

while( 1 )

{

if(P1_0 == 0)

{

Delay(10);

if(P1_0 == 0)

{

b++;

if( b == N )//N为键的功能数目

{

b = 0;

}

while(P3_2 == 0);//等待键松开

}

}

switch( b )

{

case 1: P2_0 = 0xFE;

break;

case 2: P2_1 = 0xfd;

//..............add your code here!

}

}

}

(八)//以上的文字写于2005年5月,由于时间关系,一直未能将此完成,最近闲着无聊又接着写了些文字,以下写于2006年6月5日!

在这里我想对上面一点,作个简单的说明,如果你是刚学单片机,那么你写的代码是VERY GOOD的,但是如果把上面的代码应用于产品的话,那么我可以告诉你,上面所写的按键识别代码全部是垃圾代码,^_^,这下傻了吧,呵呵。为什么?我的按键不是可以正常工作吗?

请看这里:

if(P1_0 == 0)

{

Delay(10);//问题就在这里,你让CPU在这里空转?

if(P1_0 == 0)

{

//...add your code here.

}

}

进入第1个if判断语句后,就进入了Delay(10);再看Delay函数,完全让CPU执行(;空语句),所以在做大的产品或者代码时,这个是非常耗费单片机内部资源的。有什么办法吗?呵呵,那是肯定的。

解决方法大致有如下2种:

1.将延时函数放在中断中,在中断里查询延时的标志位。/*不仅仅用于键盘识别,亦可以用于其他的延时代码,见EX1*/

2.直接在中断中查询按键的标志位.//见EX2。

EX1:

unsigned char Delaytime;

void Delay(unsigned char Delaytime)//

{

while(Delaytime !=0 );//等在这里,直到Delaytime为0。

}

void Timer0_interrupt(void) interrupt 1 using 2

{

if(Delaytime != )

Delaytime--;

//...add your other code here

}

Delay函数具体延时多长时间,就要看你设定的T0定时器中断和Delaytime的乘积,比如你的定时器中断为50MS,Delaytime为20的话,那么50MS*20=1S。

EX2:

#define Press_key = P2 ^ 7;//定义按键的I/O

void P_key(void)

{

char new_value,old_value;

new_value = Press_key;

if(new_value && !old_value)//识别按键。

{

Turn_On_LEd( );

//...add your other code here.

}

old_value = new_value;

}

void Timer0_interrupt(void) interrupt 1 using 2

{

P_key();

// ...add your other code

}

当然在实际过程当中,并不是如此简单简洁的,还希望大家能够举一反三哦... ^_^。(九)

写了这么多了,大家也看了这么多了,感觉怎么样?大家也觉得不难吧。其实51也就那么简单,真的很希望大家看完这篇文字以后,很自信的说,51单片机也已经入门。这是对我写怎么多文字最好的回答。时隔13个月之久再来继续写这些东西,没有以前的激情和热情,所以就草草了事结尾,希望大家不要在背地里骂我哦,^_^。当然以上讲的只是最简单的一些东西,单片机的功能非常之强大,只要你能想得到,就一定可以用单片机来实现的。

当然单片机和外部其他的芯片还有很多,比如数字温度传感器DS18B20,实时时钟芯片DS1302,还有比如访问AT24CXX的EEPROM存储器等,更多的电路,还要靠大家在平时的学习过程当中,慢慢掌握。

对于以上文字,欢迎大家来涵交流:

双单片机控制流水灯(精)

案例8 双单片机通信控制流水灯 用串行工作方式进行单片机之间的通信,电路图如下图所示。两个89S51单片机通过串行口进行通信,设置U1使用的晶振频率是11.0592MHz,U2使用的晶振频率是22.1184MHz,U1的RXD接U2的TXD,U1的TXD接U2的RXD,U2接8个发光二极管,要求由U1向U2发送数据,使8个发光二极管按从左到右逐一点亮的流水灯效果。 MCS-51单片机之间的串行异步通信 1.串行口的编程串行口需初始化后,才能完成数据的输入、输出。其初始化过程如下: (1)按选定串行口的工作方式设定SCON的SM0、SM1两位二进制编码。 (2)对于工作方式2或3,应根据需要在TB8中写入待发送的第9位数据(地址为1,数据为0)。 (3)若选定的工作方式不是方式0,还需设定接收/发送的波特率。 (4)设定SMOD的状态,以控制波特率是否加倍。 (5)若选定工作方式1或3,则应对定时器T1进行初始化以设定其溢出率。 2.案例分析由于串行口通信时传输的“0”或者“1”是通过相对于“地”的

电压区分的,因此使用串行口通信时,必须将双方的“地”线相连以使其具有相同的电压参考点。需要注意的是,异步通信时两个单片机的串行口波特率必须是一样的。由于U1使用的晶振频率是11.0592MHz,U2使用的晶振频率是22.1184MHz,因此二者的串行口初始化程序不完全一样。假设使用240bit/s的波特率,使用串行工作方式1,Tl使用自动装载的方式2,则Ul的TH1应初始化为136,U2的TH1应初始化为16。 对应的程序完成如下功能:Ul和U2进行双工串行通信,Ul给U2循环发送流水灯控制字,U2收到控制字后送到P0口,点亮相应发光二极管,双方都用中断方式进行收发。 (1)单片机U1的源程序 #include unsigned char sdata=0xfe; void isr_uart(); void main() { TMOD=0X20; TH1=136; TL1=136; SCON=0x40; PCON=0; TR1=1; EA=1;ES=1; SBUF=sdata; while(1); } void isr_uart() interrupt 4 {

单片机8管跑马闪烁灯控制课程设计

闪 烁 灯 控 制 系 统 院系:电气工程系 班级:电气1002 学号:0401100207 姓名:

第1章概述 (3) 1.1设计的目的及意义 (3) 1.2单片机的概述与应用 (3) 第2章设计原理 (4) 2.1设计要求与基本思路 (4) 2.2设计方案选择 (5) 2.3设计框图 (5) 第3章硬件电路设计 (7) 3.1时钟电路 (7) 3.2扩展电路 (8) 第4章程序设计 (9) 4.1 程序设计思路与流程图 (9) 4.2源程序 (11) 4.3程序调试 (12) 第5章原件明细表 (13) 总结 (14) 参考文献 (15)

第1章概论 1.1设计的目的与意义 当今时代是一个新技术层出不穷的时代,在电子领域尤其是自动化控制领域,传统的分立元件或数字逻辑电路构成的控制系统,正以前所未见的速度被单片机智能控制系统所取代。单片机具有体积小、功能强、成本低、应用面广等优点,可以说,智能控制与自动控制的核心就是单片机。 竞争日益剧烈的今天,当代大学生不仅需要扎实的理论知识,还需要过硬的动手能力。作为自动化专业的学生,更应该熟练掌握各种电路编辑软件,作为专业必需的技能更要及时地对这一类软件的更新版本进行学习,其日趋强大的功能是对我们专业技能的补充。 闪烁灯控制系统是利用8051单片机的P1控制的8个发光二极管。可实现从右到左闪烁一次,再从左到右闪烁一次,每次亮灭0.5秒,如此循环,紧急情况下,控制P3.1进行报警5S停止。 闪烁灯控制系统是简易的单片机控制系统,作为课程设计课题,通过实际程序设计和调试,逐步掌握块化程序设计方法和调试技术,通过课程设计,掌握一单片机核心的电路设计的基本方法和技术,了解有关电路参数的计算方法,通过完成一个包括电路设计和程序设计开发的完整过程,了解开发单片机应用系统的全过程,通过本次设计对单片机应用上有一个初步的了解,增强自我的动手、动脑能力,以及发现问题,解决问题,总计经验教训的能力,为以后走向工作岗位,以及更高更远的发展打下坚实的基础 1.2单片机概述与应用 单片机是将CPU、存储器、定时/计数器以及I/O接口等主要部件集成在一块芯片上的微型计算机。单片机是单片微机(Single Chip Microcomputer)的简称,但准确反映单片机本质的名称应是微控制器。目前国外已经普遍称之为微控制器。鉴于他完全作嵌入式应用,故又称为嵌入式微控制器 单片微机从体系结构到指令系统都是按照嵌入式应用特点专门设计的,它能最好地满足面对控制对象,应用系统的嵌入、现场的可靠运行以及非凡的控制品质等要求。 自从20世纪70年代推出单片机以来,作为微型计算机的一个分支,单片机经过30多年的发展,已经在各行各业得到了广泛的应用,由于单片机具有可靠性高、体积小、干扰能力强、能在恶劣的环境下工作等特点,具有较高的性价比,因此广泛应用于工业控制、仪器仪表智能化,机电一体化、家用电器等(1)工业控制:工业设备如机床、锅炉、供水系统、生产自动化、自动报警系统。 (2)智能设备:用单片机改造普通仪器如:仪表、读卡器、医疗器械。 (3)家用电器:如高档洗衣机、电冰箱、微波炉、电视、音响、手机、空调器。 (4)商用产品:如自动售货机、电子收款机、电子秤。

按键控制单片机改变流水灯速度

按键控制单片机改变流水灯速度 /*程序效果:有三个按键,按下其中任意一个流水灯的速度改变 */#includereg52.h //52 系列单片机的头文件#define uchar unsigned char//宏定义 #define uint unsigned intuchar count=40,flag=0; //定义刚开始的流水灯的速度,后 一个为标志变量void main(){uchar i=0;//定义局部变量EA=1; //打开总 中断ET0=1; //打开定时器TR0=1; //启动定时器TH0=(65536-50000) /256; //装初值TL0=(65536-50000)%256; P2=0xfe; //点亮第一个数码管, 为下次循环做准备while(1){ if(flag) //flag 被置位{ flag=0;//清零,为下次做准备P2=~P2; //取反P2=1; //左移一位P2=~P2; //取反i++; if(i==8) //移到第八个数码管,则从新装初值{ i=0; P2=0xfe; } } P0=0xf0; //赋初值if((P00xf0)!=0xf0) //判断是否有按键按下{ if(P0==0x70) //按下第一个按键count=60; //给count 从新赋值 if(P0==0xb0) count=20; if(P0==0xd0) count=10;} }}void time0() interrupt 1 //定时器0{static uchar cnt; //定义静态变量TH0=(65536-50000)/256;TL0=(65536-50000)%256; cnt++; //计数if(cnt==count){ cnt=0; //清零flag=1; //置标志位}} tips:感谢大家的阅读,本文由我司收集整编。仅供参阅!

流水灯C语言程序

/************************************************************** 51单片机流水灯C语言源程序 文件说明:流水灯C程序 程序说明:MCU采用AT89S51,外接11.0592M晶振,P2口输出 *************************************************************/ #include //51系列单片机定义文件 #define uchar unsigned char //定义无符号字符 #define uint unsigned int //定义无符号整数 void delay(uint); //声明延时函数 void main(void) { uint i; uchar temp; while(1) { temp=0x01; for(i=0;i<8;i++) //8个流水灯逐个闪动 { P2=~temp; delay(100); //调用延时函数 temp<<=1; } temp=0x80; for(i=0;i<8;i++) //8个流水灯反向逐个闪动 { P2=~temp; delay(100); //调用延时函数 temp>>=1; } temp=0xFE; for(i=0;i<8;i++) //8个流水灯依次全部点亮 { P2=temp; delay(100); //调用延时函数 temp<<=1; } temp=0x7F;

for(i=0;i<8;i++) //8个流水灯依次反向全部点亮 { P2=temp; delay(100); //调用延时函数 temp>>=1; } } } void delay(uint t) //定义延时函数 { register uint bt; for(;t;t--) for(bt=0;bt<255;bt++); }

(完整word版)51单片机流水灯

51单片机的流水灯控制 班级:100712 姓名:全建冲 学号:10071047

一、设计要求 用51单片机设计一个流水灯的控制方案,要求采用定时器定时,利用中断法控制流水灯的亮灭,画出电路图和程序流程图,写出程序代码以及代码注释。 二、电路原理图 原理图分析: 本原理图采用STC89S52单片机控制8个LED灯,其中8个LED灯的负极接单片机的P1端口,正极通过1KΩ排阻连接到电源上。原理图中还给出了晶振与复位端,以保证控制器的稳定工作。

三、程序流程图

四、程序代码及注解 1.非中断定时器控制 #include #include//包含了_crol_函数的头文件 #define uchar unsigned char #define uint unsigned int uint i=0; uchar a=0xfe; void main() { TMOD=0x01;//设置工作方式为定时器0,16位手动重装初值 TH0=(65536-46080)/256;//50毫秒定时赋初值 TL0=(65536-46080)%256; TR0=1;//启动定时器0 while(1) { If(TF==1)//读溢出标志位 { TH0=(65536-46080)/256;//重新赋初值 TL0=(65536-46080)%256;

i++; if(i==10)//500毫秒定时 { i=0; P1=a;//P1端口赋值 a=_crol_(a,1);//循环左移 } TF=0;//清除定时器溢出标志 } } } 程序分析:本程序采用非中断定时器法控制流水灯,核心语句在于读取标志位TF位,TF为定时器溢出标志位,溢出时硬件自动置一,所以循环读取标志位以判断定时器是否溢出,而每次溢出需要手动清零,否则定时器无法再次溢出,利用标志i读取10次即可达到500毫秒的定时。另外需要注意的是单片机晶振为11.0592MHz,所以计时一个数的时间为12/11.0592=1.085us,故定时50毫秒的计数为50000/1.085=46080。 2.中断定时器控制 #include

单片机闪烁灯跑马灯控制课程设计

闪烁灯跑马灯控制系统 河南工院

第1 章概述 1.1设计的目的及意义?????????????????????..3 1.2单片机的概述与应用????????????????????..3 第2 章设计原理??????????.. ??????????????4 2.1设计要求与基本思路??????.??????????????4 2.2设计方案选择?????.??????????????????5 2.3设计框图??????????. ?????????????5 第3 章硬件电路设计???????.. ??????????????7 3.1时钟电路???????????????????????.?.7 3.2扩展电路????????????????????????..8 第4 章程序设计???????????????????????9 4.1程序设计思路与流程图??..???????????????? (9) 4.2程序清单与代码???????????????????.?..?11 4.3程序调试??????????????????????.?.?12 第 5 章原件明细表????????????????????13 总结???????????????????????????????14 参考文献15

第1 章概论 1.1设计的目的与意义 当今时代是一个新技术层出不穷的时代,在电子领域尤其是自动化控制领域,传统的分立元件或数字逻辑电路构成的控制系统,正以前所未见的速度被单片机智能控制系统所取代。单片机具有体积小、功能强、成本低、应用面广等优点,可以说,智能控制与自动控制的核心就是单片机。 竞争日益剧烈的今天,当代大学生不仅需要扎实的理论知识,还需要过硬的动手能力。作为自动化专业的学生,更应该熟练掌握各种电路编辑软件,作为专业必需的技能更要及时地对这一类软件的更新版本进行学习,其日趋强大的功能是对我们专业技能的补充。 闪烁灯控制系统是利用8051单片机的P1控制的8 个发光二极管。可实现从右到左闪烁一次,再从左到右闪烁一次,每次亮灭1 秒,如此循环,紧急情况下,控制P3.1 进行报警2S停止。 闪烁灯控制系统是简易的单片机控制系统,作为课程设计课题,通过实际程序设计和调试,逐步掌握块化程序设计方法和调试技术,通过课程设计,掌握一单片机核心的电路设计的基本方法和技术,了解有关电路参数的计算方法,通过完成一个包括电路设计和程序设计开发的完整过程,了解开发单片机应用系统的全过程,通过本次设计对单片机应用上有一个初步的了解,增强自我的动手、动脑能力,以及发现问题,解决问题,总计经验教训的能力,为以后走向工作岗位,以及更高更远的发展打下坚实的基础 1.2单片机概述与应用 单片机是将CPU、存储器、定时/计数器以及I/O 接口等主要部件集成在一块芯片上的微型计算机。单片机是单片微机(Single Chip Microcomputer)的简称,但准确反映单片机本质的名称应是微控制器。目前国外已经普遍称之为微控制器。鉴于他完全作嵌入式应用,故又称为嵌入式微控制器 单片微机从体系结构到指令系统都是按照嵌入式应用特点专门设计的,它能最好地满足面对控制对象,应用系统的嵌入、现场的可靠运行以及非凡的控制品质等要求。 自从20世纪70 年代推出单片机以来,作为微型计算机的一个分支,单片机经过30 多年的发展,已经在各行各业得到了广泛的应用,由于单片机具有可靠性高、体积小、干扰能力强、能在恶劣的环境下工作等特点,具有较高的性价比,因此广泛应用于工业控制、仪器仪表智能化,机电一体化、家用电器等 (1)工业控制:工业设备如机床、锅炉、供水系统、生产自动化、自动报警系统。 (2)智能设备:用单片机改造普通仪器如:仪表、读卡器、医疗器械。 (3)家用电器:如高档洗衣机、电冰箱、微波炉、电视、音响、手机、空调器。

按键控制流水灯设计报告

按键控制流水灯设计报告 一、项目名称: 按键控制流水灯 二、目的: 通过对按键控制发光二极管项目的改变,设计出自己的方案,来加深对硬件技术的理解,同时锻炼关于硬件的编程技术,掌握keil等软件的使用。 三、硬件原理: 数码管与发光二极管硬件电路图: 芯片引脚电路图:

按键与导航按键:

四、软件原理: 变量Key1,Key2,Key3分别代表第一个、第二个、第三个按键,值为零时表示按下了该按键。那么可以写出一个判断条件,当这三个变量的值分别为1 时,就分别调用三个不同的函数,三个函数分别表示LED灯的三种不同的闪亮方式。 五、软件流程:

首先判断哪一个变量的值为1,即哪一个按键被按下,然后就调用相应的函数。 六、关键代码: void main() { Init(); P0=0x00; while(1){ //其他两个key通过中断实现 // if(Key3==0) // { // G_count=0; // while(G_count!=200);//延时10ms // while(!Key3)//等待直到释放按键 // { // P0=0x33; // } // } if(Key1==0)fun2(); if(Key2==0)fun3(); if(Key3==0)fun4();

} } 七、操作说明: 当把软件下载到电路板以后,给它插上电源,然后按下不同的按键,可以观察到LED灯亮。 八、存在的问题: 原先的main()函数中只有KEY3,并没有Key1和Key2,所以暂时不清楚如何感应到按键一和按键二什么时候按下。 九、后续设计计划: 可以设计更炫酷的亮灯方式。

51单片机流水灯C语言源代码

#include #include #define uint unsigned int #define uchar unsigned char uchar z=50,e=0x00,f=0xff; uchar code table1[]={ 0x80,0xc0,0xe0,0xf0, 0xf8,0xfc,0xfe,0xff}; uchar code table2[]={ 0x7f,0x3f,0x1f,0x0f, 0x07,0x03,0x01,0x00}; uchar code table3[]={ 0x01,0x03,0x07,0x0f, 0x1f,0x3f,0x7f,0xff}; uchar code table4[]={ 0xe7,0xdb,0xbd,0x7e, 0xbd,0xdb,0xe7,0xff}; uchar code table5[]={ 0xe7,0xc3,0x81,0x00, 0x81,0xc3,0xe7,0xff}; uchar code table6[]={ 0x7e,0x3c,0x18,0x00, 0x18,0x3c,0x7e,0xff}; void delay(uchar); void lsd1(); void lsd2(); void lsd3(); void lsd4(); void lsd5(); void lsd6(); void lsd7(); void lsd8(); void lsd9(); void lsd10(); void lsd11(); void lsd12(); main() { while(1) { lsd1(); lsd2(); lsd3(); lsd4();

单片机c语言编程控制流水灯

说了这么多了,相信你也看了很多资料了,手头应该也有必备的工具了吧!(不要忘了上面讲过几个条件的哦)。那个单片机究竟有什么 功能和作用呢?先不要着急!接下来让我们点亮一个LED(搞电子的应该知道LED是什么吧^_^) 我们在单片机最小系统上接个LED,看我们能否点亮它!对了,上面也有好几次提到过单片机最小系统了,所谓单片机最小系统就是在单片机 上接上最少的外围电路元件让单片机工作。一般只须连接晶体、VCC、GND、RST即可,一般情况下,AT89C51的31脚须接高电平。 #include //头文件定义。或用#include其具体的区别在于:后者定义了更多的地址空间。 //在Keil安装文件夹中,找到相应的文件,比较一下便知! sbit P1_0 = P1 ^ 0; //定义管脚 void main (void) { while(1) { P1_0 = 0;//低电平有效,如果把LED反过来接那么就是高电平有效 } } 就那么简单,我们就把接在单片机P1_0上的LED点亮了,当然LED是低电平,才能点亮。因为我们把LED的正通过电阻接至VCC。 P1_0 = 0; 类似与C语言中的赋值语句,即把0 赋给单片机的P1_0引脚,让它输出相应的电平。那么这样就能达到了我们预先的要求了。 while(1)语句只是让单片机工作在死循环状态,即一直输出低电平。如果我们要试着点亮其他的LED,也类似上述语句。这里就不再讲了。 点亮了几个LED后,是不是让我们联想到了繁华的街区上流动的彩灯。我们是不是也可以让几个LED依次按顺序亮呢?答案是肯定的!其 实显示的原理很简单,就是让一个LED灭后,另一个立即亮,依次轮流下去。假设我们有8个LED分别接在P1口的8个引脚上。硬件连接,在 P1_1--P1_7上再接7个LED即可。例程如下: #include sbit P1_0 = P1 ^ 0; sbit P1_1 = P1 ^ 1; sbit P1_2 = P1 ^ 2; sbit P1_3 = P1 ^ 3; sbit P1_4 = P1 ^ 4; sbit P1_5 = P1 ^ 5; sbit P1_6 = P1 ^ 6; sbit P1_7 = P1 ^ 7; void Delay(unsigned char a) { unsigned char i; while( --a != 0) {

单片机控制-闪烁灯

单片机控制-闪烁灯 1.实验任务 如图4.1.1所示:在P1.0端口上接一个发光二极管L1,使L1在不停地一亮一灭,一亮一灭的时间间隔为0.2秒。 2.电路原理图 图4.1.1 3.系统板上硬件连线 把“单片机系统”区域中的P1.0端口用导线连接到“八路发光二极管指示模块”区域中的L1端口上。 4.程序设计内容 (1).延时程序的设计方法 作为单片机的指令的执行的时间是很短,数量大微秒级,因此,我们要 求的闪烁时间间隔为0.2秒,相对于微秒来说,相差太大,所以我们在 执行某一指令时,插入延时程序,来达到我们的要求,但这样的延时程 序是如何设计呢?下面具体介绍其原理:

如图4.1.1所示的石英晶体为12MHz,因此,1个机器周期为1微秒机器周期微秒 MOV R6,#20 2个 2 D1: MOV R7,#248 2个 2 2+2×248=498 20× DJNZ R7,$ 2个2×248 (498 DJNZ R6,D1 2个2×20=40 10002 因此,上面的延时程序时间为10.002ms。 由以上可知,当R6=10、R7=248时,延时5ms,R6=20、R7=248时, 延时10ms,以此为基本的计时单位。如本实验要求0.2秒=200ms, 10ms×R5=200ms,则R5=20,延时子程序如下: DELAY: MOV R5,#20 D1: MOV R6,#20 D2: MOV R7,#248 DJNZ R7,$ DJNZ R6,D2 DJNZ R5,D1 RET (2).输出控制 如图1所示,当P1.0端口输出高电平,即P1.0=1时,根据发光二极管 的单向导电性可知,这时发光二极管L1熄灭;当P1.0端口输出低电平,即P1.0=0时,发光二极管L1亮;我们可以使用SETB P1.0指令使P1.0 端口输出高电平,使用CLR P1.0指令使P1.0端口输出低电平。 5.程序框图 如图4.1.2所示

花样流水灯设计

单片机课程设计 2014年 6月 15日 课 程 单片机课程设计 题 目 花样流水灯 院 系 电气工程及其自动化系 专业班级 1112班 学生姓名 温亿锋 学生学号 201111631227 指导教师 张瑛

一丶任务 设计一款以AT89C51单片机作为主控核心,按键控制电路、流水灯显示电路以及单片机最小系统等模块组成的核心主控制电路。 二丶设计要求 通过发光二极管显示不同的花样(至少有六种花样),并且可以通过按键来控制流水灯的速度。 三丶设计方案 本方案主要是通过对基于单片机的多控制、多闪烁方式的LED流水灯循环系统的设计,来达到本设计的要求。其硬件构成框图如下图所示,以单片机为核心控制,由单片机最小系统(时钟电路、复位电路、电源)、按键控制电路、LED 发光二极管和5V直流电源组成。 单片机流水灯循环控制系统硬件框图 此设计方案中单片机的P1口接5路按键控制电路,实现流水灯花型的切换功能;单片机的P3.7引脚接上一个按钮开关以实现对流水灯闪烁频率的控制,即实现了快慢两种节拍实现花型的变换;单片机上的P2口接八路LED发光二极管组成流水灯电路,显示流水灯循环情况。 四丶系统硬件设计 4.1 直流稳压电源电路

对于一个完整的电子设计来讲,首要问题就是为整个系统提供电源供电模块,电源电路的稳定可靠是系统平稳运行的前提和基础。电子设备除用电池供电外,还采用市电(交流电网)供电。通过变压、整流、滤波和稳压后,得到稳定的直流电。直流稳压电源是电子设备的重要组成部分。本项目直流稳压电源为+5V。 直流稳压电源的制作一般有3种制作形式,分别是分立元件构成的稳压电源、线性集成稳压电源和开关稳压电源。下图为稳压电源采用的是三端集成稳压器7805构成的正5V直流电源。 三端固定式集成稳压电源电路图 AT89C51单片机的工作电压范围:4.0V---5.5V,所以通常给单片机外接5V 直流电源。此处用3节1.5V的干电池供电。 4.2 单片机最小系统 要使单片机工作起来,最基本的电路的构成由单片机、时钟电路、复位电路等组成,单片机最小系统如图所示。 时钟电路:本系统采用单片机内部方式产生时钟信号,用于外接一个12MHz 石英晶体振荡器和2个30pF微调电容,构成稳定的的自激振荡器,其发出的脉冲直接送入内部的时钟电路。 复位电路:确定单片机工作的起始状态,完成单片机的启动过程。单片机系统的复位方式有上电自动复位和手动按键复位。本设计采用手动按键复位,该复位方式同样具有上电自动复位功能。

基于51单片机的流水灯

基于51单片机的流水灯 利用51单片机P0口实现8个LED(发光二极管)的流水灯控制。可以使用Proteus软件进行仿真调试。 1 硬件设计 利用单片机的PO口控制8个LED,其电路如下图所示。 在桌面上双击图标,打开ISIS 7 Professional窗口(本人使用的是v7.4 SP3中文版)。单击菜单命令“文件”→“新建设计”,选择DEFAULT模板,保存文件名为“LSD.DSN”。在器件选择按钮中单击“P”按钮,或执行菜单命令“库”→“拾取元件/符号”,添加如下表所示 都可以不画,它们都是默认的。 在ISIS原理图编辑窗口中放置元件,再单击工具箱中元件终端图标,在对象选择器中单击POWER和GROUND放置电源和地。放置好元件后,布好线。左键双击各元件,设置相应元件参数,完成电路图的设计。 2 软件设计 流水灯又称为跑马灯,在函数中可以将P0口的八种不同状态做成一维数组,循环执行即可,如下所示。当然也可以采用其它函授来实现,如左移一位<<1(或右移一位>>1),循环左移函授_crol_(或循环右移函授_cror_)等。 /****************************************************************** 流水灯

*******************************************************************/ #include "reg51.h" const tab[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; void delayms(unsigned int x) //延时 { unsigned int j; unsigned char k; for(j=0;j

单片机课程设计—8个按键控制8个LED自动设定控制流水灯

电子课程设计
东北石油大学
实习总结报告
实习类型
生产实习
实习单位
东北石油大学实习基地
实习起止时间 2018 年 7 月 7 日至 2018 年 7 月 16 日
指导教师
刘东明、孙鉴
所在院(系) 电子科学学院
班 级 电子科学与技术 15-2
学生姓名
学号
1509012402
2018 年 7 月 16 日
I 页脚内容

电子课程设计
目录
第 1 章 按键控制流水灯设计 ....................................... 1 1.1 实习目的 .............................................. 1 1.2 实习要求 .............................................. 1
第 2 章 电路工作原理............................................. 2 2.1 STC89C52 单片机工作原理 ............................... 2 2.2 LED 工作原理 .......................................... 3 2.3 按键工作原理 .......................................... 3 2.4 整体电路图 ............................................ 5 2.5 本章小结 .............................................. 6
第 3 章 C 程序设计 ............................................... 7 3.1 程序设计流程图 ........................................ 7 3.2 实验结果 .............................................. 8 3.3 本章小结 .............................................. 9
总结及体会..................................................... 10 参考文献 ...................................................... 11 附录: ........................................................ 12
I 页脚内容

流水灯控制实验报告及程序

实验三流水灯控制实验 姓名专业通信工程学号成绩 一、实验目的 1.掌握Keil C51 软件与protues软件联合仿真调试的方法; 2.掌握如何使用程序与查表等方法实现流水效果; 3.掌握按键去抖原理及处理方法。 二、实验仪器与设备 1. 微机1台 2. Keil C51集成开发环境 3. Proteus仿真软件 三、实验内容 1.用Proteus设计一流水灯控制电路。利用P1口控制8个发光二级管L1—L8。P3.3口接一按 键K1。参考电路如下图所示。其中74LS240为八反响三态缓冲器/线驱动器。 2.用中断或查询方式编写程序,每按动一次K1键,演示不同的流水效果。若用KEY表示按键的 次数,则其对应的流水效果如下: ① KEY=0: L1-L8全亮; ② KEY=1: L1-L8先全灭,然后自右向左单管点亮,如此循环; ③ KEY=2: L1-L8先全灭,然后自右向左依次点亮,如此循环; ④ KEY=3: L1-L8先全亮,然后自左向右依次熄灭,如此循环; ⑤ KEY=4: L1-L8先全灭,然后整体闪烁,如此循环; ⑥ KEY=5:自行设计效果。 以上移位及闪烁时间间隔均设置为0.3秒,按动5次按键后,再按键时,流水效果从头开始循环。 四、实验原理 1.按键去抖原理:通常按键所用的开关为机械弹性开关,当机械触点断开、闭合时,电压信号 波形如下图所示。由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定的接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动。抖动时间的长短由按键的机械特性决定,一般为5~10ms。按键抖动会引起一次按键被误读多次。为了确保CPU对键的一次闭合仅做一次处理,必须去除按键抖动。在键闭合稳定时,读取键的状态,并且必须判别;在键释放稳定后,再作处理。按键的抖动,可用硬件或软件两种方法消除。常用软件方法去抖动,即检测到按键闭合后执行一个5~10ms延时程序;让前沿抖动消失后,再一次检测键的状态,如果仍保持闭合状态电平,则确认为真正有按键按下。当检测到按键释放后,也要给5~10ms的延时,待后延抖动消失后,才能转入该键的处理程序。 2.74LS240:八反相三态缓冲器/线驱动器 引脚排列图:

最新五种编程方式实现流水灯的单片机c程序讲课教案

五种编程方式实现流水灯的单片机C程序 //功能:采用顺序结构实现的流水灯控制程序 /*此方式中采用的是字操作(也称为总线操作)*/ #include void delay(unsigned char i); //延时函数声明 void main() //主函数 { while(1) { P1 = 0xfe; //点亮第1个发光二极管,0.000389s delay(200); //延时 P1 = 0xfd; //点亮第2个发光二极管,0.155403s,0.1558 delay(200); //延时 P1 = 0xfb; //点亮第3个发光二极管 delay(200); //延时 P1 = 0xf7; //点亮第4个发光二极管 delay(200); //延时 P1 = 0xef; //点亮第5个发光二极管 delay(200); //延时 P1 = 0xdf; //点亮第6个发光二极管 delay(200); //延时 P1 = 0xbf; //点亮第7个发光二极管 delay(200); //延时 P1 = 0x7f; //点亮第8个发光二极管 delay(200); //延时 } } //函数名:delay //函数功能:实现软件延时 //形式参数:unsigned char i; // i控制空循环的外循环次数,共循环i*255次 //返回值:无 void delay(unsigned char i) //延时函数,无符号字符型变量i为形式参数{ unsigned char j, k; //定义无符号字符型变量j和k for(k = 0; k < i; k++) //双重for循环语句实现软件延时 for(j = 0; j < 255; j++); } //功能:采用循环结构实现的流水灯控制程序 //此方式中采用的移位,按位取反等操作是位操作 #include //包含头文件REG51.H void delay(unsigned char i); //延时函数声明 void main() //主函数

单片机课程设计-8个LED灯来回点亮

目录 第一章绪论--------------------------------------------------------3 第二章设计目的及要求-----------------------------------------5 1.1 设计目的--------------------------------------------------------5 1.2 设计要求--------------------------------------------------------5 第三章设计电路原理----------- -------------------------------7 3.1 控制部分的设计与选择-------------------------------------7 3.2 LED显示方案-----------------------------------------------8 第四章硬件系统------------------------------------------------9 4.1 原件清单-------------------------------------------------------9 4.2 单片机AT89C51---------------------------------------------9 4.3 单片机时钟电路--------------------------------------------10

4.4 单片机复位电路---------------------------------------------11 4.5 工作电路------------------------------------------------------12 第五章软件设计------------------------------------------------13 5.1 程序流程图--------------------------------------------------13 5.2 编辑源程序--------------------------------------------------14 第六章系统调试与仿真结果--------------------------------16 6.1系统调试-----------------------------------------------------16 6.2仿真结果----------------------------------------------------16 总结------------------------------------------------------------- 19 参考文献--------------------------------------------------------20 第一章绪论

单片机8个闪烁灯控制

河南工业职业技术学院Henan Polytechnic Institute 单片机应用技术 课程设计说明书 题目:闪烁灯控制系统(6) 班级:电气1001班 姓名:张志海 学号:0401100136 指导教师:赵阳

第1章概述 1.1 设计的目的与意义 1)了解系统的工作原理。 2)掌握8051单片机的工作原理和应用。 3)通过课程设计培养学生自学能力和分析问题、解决问题的能力。 4)闪烁灯控制系统是简易的单片机控制系统,作为课程设计课题,通过实际程序设计和调试,逐步掌握块化程序设计方法和调试技术,通过课程设计,掌握一单片机核心的电路设计的基本方法和技术,了解有关电路参数的计算方法,增强制图能力以及查阅手册的能力和一定的文字表达能力。 5)通过设计使学生具有一定增强自我的动手、动脑能力,以及发现问题,解决问题。 1.2 单片机概述与应用 单片机是将CPU、存储器、定时/计数器以及I/O接口等主要部件集成在一块芯片上的微型计算机。单片机是单片微机(Single Chip Microcomputer)的简称,但准确反映单片机本质的名称应是微控制器。目前国外已经普遍称之为微控制器。鉴于他完全作嵌入式应用,故又称为嵌入式微控制器单片机应用系统是以单片机为核心,配以输入、输出、显示、控制等外围电路和软件,能实现一种或多种功能的实用系统。 单片微机从体系结构到指令系统都是按照嵌入式应用特点专门设计的,它能最好地满足面对控制对象,应用系统的嵌入、现场的可靠运行以及非凡的控制品质等要求。 自从20世纪70年代推出单片机以来,作为微型计算机的一个分支,单片机经过30多年的发展,已经在各行各业得到了广泛的应用,由于单片机具有可靠性高、体积小、干扰能力强、能在恶劣的环境下工作等特点,具有较高的性价比,因此广泛应用于工业控制、仪器仪表智能化,机电一体化、家用电器等(1)工业控制:工业设备如机床、锅炉、供水系统、生产自动化、自动报警系统等。 (2)智能设备:用单片机改造普通仪器如:仪表、读卡器、医疗器械。 (3)家用电器:如高档洗衣机、电冰箱、微波炉、电视、音响、手机、空调器。 (4)商用产品:如自动售货机、电子收款机、电子秤。 (5)通信方面。用于调制解调器、程控交换技术以及各种通信设备。 (6)多机分布式系统。可用单片机构成分布式测控系统,它使单片机进入 了一个新的水平。

cc2530按键控制流水灯

cc2530按键控制流水灯 本次设计用LED1,LED2,LED3 灯及按键S1 为外设。采用P10、P11、P14 口为输出口,驱动LED1/LED2/LED3,P01 口为输入口,接受按键信号输入(高电平为按键信号)。 1.高性能 2.4G 射频模块Q2530RF Q2530RF是丘捷技基于TI公司第二代2.4GHz IEEE 802.15.4 / RF4CE/ZigBee的第二代片上系统解决方案CC2530 F256的全功能模块,集射频收发及MCU控制功能于一体。外围原件包含一颗32MHz晶振和一颗32.768KHz晶振及其他一些阻容器件。射频部分采用巴伦匹配和外置高增益SMA天线,接收灵敏度高,发送距离远,空旷环境最大传输距离可达400米。模块引出CC2530所有IO口,便于功能评估与二次开发。 2.多功能开发板Q2530EB 多功能扩展板Q2530EB 可支持多种射频主控模块(例如Q2530RF等),配置有串口液晶显示接口,USB供电接口,DC 5V电源接口,电池接口,RS232接口,DEBUG接口,五向按键及指示灯,红外遥控信号接收/发射等模块。 所有的外设均通过SPI总线/UART /DEBUG等接口与射频模块Q2530RF 相连,并完全受Q2530RF 控制和访问。 多功能仿真扩展板Q2530EB 采用三种电源供电方式:DC 5V供电、USB接口供电、电池供电,可在插座P5设置跳线选择,PIN1-PIN2 为电池供电,PIN2-PIN3 为外接直流电源或者USB接口供电。电源开关为P4。 Q2530EB 板卡背面的电池盒可放置3节5号干电池,输出电压3.4~4.5V,板载电源电路将其调整到+3.3V 稳定的直流电压输出供后级使用。当电池电压低于3.4V 时,应更换电池以保持模块正常工作。 Q2530EB 带有1个DC 5V的电源适配器接口P2和一个USB接口P1,输入电压经过稳压器降压为+3.3V输出供后极使用。

相关文档
最新文档