事无巨细,流水灯简入
昨天写了GCC AVR的介绍,今天来做第一个同时也是最简单的实验:流水灯(又称跑马灯),是新手们为熟悉IO操作必做的第一个实验。
顾名思义,流水灯,即像水一样流动的灯,这里的“灯”是指我们开发板上的发光二极管(LED),“流动”既是让它按一定规则依次点亮。所以这次的任务是:让数个发光二极管以一定规则依次点亮。
首先我们来看看CEPARK AVR开发板的LED显示部分:
显而易见,流水灯由5V驱动电源,跳线帽,限流排阻,八个LED以及连在LED负极的AVR的PB口构成,很简单的一个电路。
在此先把几个简单小知识点总结一下:
1.在绝大部分的微控制器(MCU)以及数字逻辑器件应用中,5V电源恐怕是最常见的电源供应值了。包括我们熟悉的51单片机,LCD1602,大部分的LED,庞大的74系列IC都是5V供电。
2.LED是灯,但它首先是个二极管,这表示它只在正向压降的情况下才有可能点亮,以上图为例,黑色三角形的尖端表示LED的负极,延伸到任何电路图都一样适用。正向压降即指LED正极的电压大于负极。
3.排阻,一般是单列直插封装,即数个电阻的整合,有一个公共脚并且此脚对其他任意一脚直接的电阻都为某一额定值。
4.1k限流电阻。它的作用是限制流过LED的电流,防止LED烧坏。可为什么是1K呢?大家都知道,功率器件都是有其指定的额定功率,额定电压,额定电流这些参数的,器件在这些参数下有最佳的工作效率。LED也不例外。LED一般有3V和5V供电两种,其工作电压和电流跟其大小,发光颜色等有关。
这里我假设LED为3V工作电压,10mA工作电流(这些参数你可以在LED器件的数据手册上查阅,在此我只是假设),并且LED工作在额定电压和额定电流状态,那么限流电阻和LED是串联关系,所以加载在限流电阻上的电压应该是5-3=2V,电流是10mA,所以可以计算其阻值=2V/10mA=200欧姆。
同样依据此思想,可以计算出CEPAR—K AVR开发板上的LED显示部分的限流电阻取1K时可以得到比较好的显示效果,同时不会严重影响LED的寿命。
了解上述几点之后,点亮LED应该变得非常容易了。当单片机IO输出低电平,则LED承载正向压降,电流的路径为“5V驱动电源端——>限流电阻——>LED——>单片机IO”,LED即被点亮。值得一提的是,AVR单片机的IO口可以吸收大约20mA的电流,驱动能力要比51强了不少。
现在我们开始来编写流水灯的程序如下:
#include
//IO操作头文件
#include //延时函数头文件
#define uint unsigned int
#define uchar unsigned char //宏定义
uchar n; //定义全局变量
void init_portx(void); //函数声明
int main(void)
{
init_portx(); //初始化子函数调用
while(1)
{
for(n=0;n<8;n++) //循环
{
PORTB=1<
_delay_ms(500); //延时500ms
}
}
}
void init_portx(void)
{
DDRB=0xff; //PB口方向寄存器,全部配置为输出模式
}
程序不长,短短26行,但是需要你有一点点C语言的基础才能看懂。
1.avr/io.h,util/delay.h都是GCC AVR本身自带的头文件,分别可以据此进行AVR的IO口操作和延时子函数调用。使用GCC AVR的朋友要逐渐熟悉各个常用的头文件。
2.AVR的IO口是标准的双向IO,即输出或者输入,需要配置方向寄存器来事先规定,DDRA,DDRB,DDRC和DDRD分别是4组IO的方向寄存器,都是八位,对应位置1则表示配置为输出状态,清0则表示输入状态。如DDRB=0xff这句语句则把PB口全部配置为输出状态。
3.标准C语言本身并不支持循环移位操作,只能通过移位符“<<”“>>”来进行左移和右移操作。比如0000 0001左移一位则变为0000 0010。注意,最高位丢弃,最低位补零,它是不带符号位的移位!右移类同。
4.延时程序的调用,_delay_ms(),经查看,头文件中的定义为_delay_ms(double ms),表示该函数的参数是double型的,即双精度浮点数,即保持小数点后两位。所以你可以填写位数为2位的小数比如_delay_ms(1.11)。这点也许很多人不曾意识到。
5.全局变量定义时默认赋初值0,但是局部变量(即在函数中定义的变量)定义时默认初值任意,所以定义局部变量一定要赋初值,这点要谨记。要养成给变量赋初值的习惯。
6.人的视觉停留时间大概是0.1秒,即100ms,所以如果延时太短,人眼是察觉不出来灯的“流动”的。
程序的条理应该是比较清晰的,定义完全局变量,声明了函数之后,进入主函数,初始化端口,进入大循环,重复执行LED流动的for循环。
最后说说GCC AVR的一些特别的语法:
1.主函数要求返回值为int而不是一贯的void;
2.任何函数都要求填写形参,如果没有则要填void;
3.某些版本的GCC AVR,必须在最后添加一行空行,否则会出现警告(奇怪的现象);
希望能给需要的人一点帮助。
[ 本帖最后由 losingamong 于 2010-3-11 13:37 编辑 ]