查看: 1617|回复: 0

Atmeal 128 学习笔记第四站---流水灯和延时

[复制链接]

该用户从未签到

发表于 2015-4-30 08:46:48 | 显示全部楼层 |阅读模式
分享到:
一日不见如隔三秋,学友们,我想死你们啦。。。。好熟悉的话,让我想起每年春节晚会冯巩那经典的一句开场白,附上冯叔叔照片一张。

     话不多说,我们开始开始我们Atmega128学习笔记的第四站--流水灯和延时
     上一次的学习笔记我们顺利的完成用ATmega128的PA0口点亮和熄灭一个LED灯的功能,在最后让大家思考下,由这个小功能怎么延伸一下去实现流水灯的功能,我们流水灯的个数,可以自己自由确定,在这里我们使用8个LED灯,通过ATmega128的PA口的8个位来实现对这8个LED灯的控制。不要小瞧了流水灯的功能,其实我们的使用中,有时为了构造特殊的效果,或者为了实现特殊的舞台效果,就会使用红、绿、黄、灯多种颜色的灯来实现,其实归根到底就是实现一个流水灯的功能。
     我们还是沿用之前的电路:

   还是跟之前的LED灯闪烁的例子类似,使用嵌套的for循环语句来进行软件的延时,延时之后,使用“<<”这个移位语句将当前ATmega128的PA口输出的高电平的引脚向高位移动一位,在这里要说明一下,“<<”左移移位功能语句是不带进位功能的,也就是说到了最高位后,它无法实现自动循环到最低位,因此就需要我们使用一个判断语句来判断当前点亮的LED灯是否是最高位的LED灯,若是的话就需要将电平移动到最低位的LED灯口,若不是,可继续左移。。。我们可以看到,若是没有编程的基础,就很难完成接下来的操作,所以基础是很关键的。
     构思了流水灯的算法流程,接着我们就来进行编程:
#include<iom128v.h>
main()
{
unsigned char i,j;
unsigned char LED;
DDRA=0xFF;
PORTA=0xFF;
LED=0x01;
PORTA=~LED;
while(1)
{
   for(i=0;i<250;i++)
    {
   for(j=0;j<250;j++);
   for(j=0;j<250;j++);
   for(j=0;j<250;j++);
   for(j=0;j<250;j++);
   }
   if(LED==0X80)
      {
     LED=0X01;
     }
   else
     {
       LED=LED<<1;
       }
   PORTA=~LED;

   }
}
     鉴于大家跟我一样最初对AVR的属性还不熟悉,结合昨天学的,我这里给大家简单的叙述下上面代码的含义:
     1、#include <iom128v.h>初次接触单片机的学友肯定会问,这个是什么意思?在这里是干嘛的?iom128v.h是头文件,在代码中引用头文件,它的意义就是将这个头文件中的全部内容放到引用头文件的位置处,这样就免去了我们每次编写同类程序都要将头文件中的语句重复的编写。它一般定义一些函数,还有包含一些库函数,而库函数是系统自带的,不需要我们自己编,只要#include就可以直接使用这些系统自带的或者自己编的函数了。在代码中加入头文件有两种书写的方法,一种就是我们上面所使用的#include <iom128v.h>,一种就是#include "iom128v.h"
     2、main函数:main()函数称为主函数,一个C程序总是从main()函数开始执行的,我们这里也是一样。一个C程序中可以有很多个子函数,但是只能有一个主函数,子函数可以放在主函数的前面或者后面,但是不能放在主函数中,当子函数放在主函数的后面时候,必须在主函数之前对这个子函数进行声明,这个我们今天后面就会用到,到时咱们再说。
     3、 DDRA=0xFFORTA=0xFF; 这两句代码大家应该知道了吧,在前一站中我们已经详细的解释了含义,在这里我们把PA口全部设置为输出,用来控制LED灯。
     4、for()循环语句在这里起到一个延时的作用
     5、LED=LED<<1; LED灯左移
     6、if(LED==0X80) 判断流水灯是否左移到最高位了,因为左移无法实现到最高位自动转换成最低位,所以在此处进行判断,手动实现换成最低位。

     程序编译好后,下载到我们的板子上面试试吧,效果还是很不错的。。。。。。(请大家原谅我的大意,昨天做这个测试时候,把板子忘记在家了,所以此处就不给大家上图啦。。。。)接下来大家在上面的代码中有没有一个疑问?就是for循环来实现延时,延时多少?是的,这只是粗略的实现了一个延时的功能,若大家在应用中需要准确的实现流水灯中间间隔的时间,就不能这样实现了,那具体应该怎么实现呢?
     这时我们就需要借助于外部晶振来实现了,何为晶振?晶体振荡器的简称,用来给单片机工作提供稳定的时钟信号的东西。用它我们可以准确的控制时间,假如我们在单片机外连接一个8MHz的晶振,这时我们上面的程序代码就可以修改为:
#include<iom128v.h>
#define uchar unsigned char
#define uint unsigned int
void Delayms(uint MS);
main()
{
unsigned char LED;
DDRA=0xFF;
PORTA=0xFF;
LED=0x01;
PORTA=~LED;
while(1)
{
   Delayms(500);
   if(LED==0X80)
      {
     LED=0X01;
     }
   else
     {
       LED=LED<<1;
       }
   PORTA=~LED;

   }
}

void Delayms(uint MS)            
{
   uint i,j;
   for( i=0;i<MS;i++)
   for(j=0;j<1141;j++);     
}
     我们从上面程序代码中可以看到增加了一个void Delayms(uint MS)的子函数,并在主函数中进行了调用,假如我们想对流水灯间隔时间控制在500ms那我们就直接调用函数void Delayms(500),同理,假如想控制在1s则调用函数void Delayms(1000) ,当然了,这个子函数对时间的控制是通过很多次的软件仿真实验得出的数据,我们以后在编程的过程中也可以使用软件仿真看看软件运行的情况或者查找程序代码错误的地方。
好了,对LED灯控制的学习就到这里吧,你学会了吗?
今天的学习笔记就到这,感谢大家的支持,我们下期再见。
回复

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /4 下一条

手机版|小黑屋|与非网

GMT+8, 2024-12-19 08:06 , Processed in 0.118432 second(s), 18 queries , MemCache On.

ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

苏公网安备 32059002001037号

Powered by Discuz! X3.4

Copyright © 2001-2024, Tencent Cloud.