所谓的CPU是采用51指令集,它的硬盘就是内置的Flash,它的内存就是内置的RAM和扩展的RAM,不过这些基本配置只是小了点而已。
在网上我们经常会看到一些AT89C51或者AT89C52之类的51单片机的例子,对于一些初学者来说,可能以为只有AT89C51或者AT89C52才是51单片机,你给他们STC89S52他们都不敢用,觉得可能不对(我刚学的时候就遇到过这种情况,哈哈)。其实不是这样的,只要芯片里面用到了51指令集,都可以算是一个51单片机,使用51单片机的开发方法就可以进行代码的开发。它们之间的区别在于芯片厂家不同,CPU支持的频率不同,Flash大小,RAM大小,串口接口,中断个数,烧写程序的接口等都稍有不同。 这样看的话,即使是同一种型号的51单片机,比如STC89C51和STC89S52,基本的区别就是Flash大小,89C51的Flash大小是4kB,而89S52是8kB,STC12C5A08S2和STC89S52的区别是:它们的Flash大小都是8KB,但是12C5A08S2有两个串口处理器,而89S52只有一个串口处理器,12C5A08S2有1kB的扩展RAM,而89S52没有,只有128个子节点的RAM,12C5A08S2也有这128字节的RAM,但是12C5A08S2只有2个定时器中断,而89S52有3个,它们的区别就这样而已。 AT和STC有相似之处,也有不同之处,AT是采用SPI接口烧写程序,而STC是采用串口接口烧写程序。其他的可以参考芯片的PDF文件,里面有各种型号的各种参数说明。根据自己的需求选择不同的芯片型号,就像选择电脑一样,根据配置单选择适合自己的单片机。当然功能越强大的,价格就越贵。比如CC2430就是带无线串口接口的51单片机,但是价格和普通的51单片机就不在一个档次了。当然除了51单片机,还有很多其他标准的单片机,比如AT的AVR单片机,型号有AT Mega 16、Mega 32等,有16位的,也有32位的(我们的51一般都是8位的)。还有DSP、ARM等,它们都有自己的指令集,有自己的标准。 当然速度和各种参数上也有很多区别,而且每一个都很深奥。比如很多掌上电脑、MP4、MP5、手机上用的都是ARM,ARM9还可以直接跑操作系统。至于这个领域,属于嵌入式开发,就不多说了,我们回到51单片机上来说吧。
51单片机的开发涉及到程序的开发。简单来说就是你写程序去控制单片机引脚的供电或不供电,或者读取某个引脚是否供电。我们把这些引脚叫做I/O口(即输入/输出口)。根据不同的应用,设计不同的外围电路,就可以控制或者采集很多外围的东西(当然也可以通讯)。如果和PC机通讯,还可以把采集到的信息反馈给PC机或者根据PC机发来的信息执行指定的任务。
我们先来看看如何开始51单片机程序开发:
开发单片机程序有两种常用的方法:1.用汇编语言开发2.用C语言开发
汇编语言我不太熟,就不多说了,就说说C语言吧,首先下载Keil 8,安装到电脑上,这个是51单片机程序开发工具。
然后启动Keil,注册完成后,开始写第一个工程
首先,在“项目”菜单中选择“新建项目”。将弹出一个窗口,让您选择保存项目的位置。
然后你可以根据自己的需要定义要保存的项目名称,然后点击保存。然后会提示你选择单片机的型号。
我们可以选择Atmel的89C52,然后系统会提示你,选择No就可以了。新建工程之后如下:
这时候我们可以看到项目中还没有任何文件,那么接下来就是添加基本文件,我们点击“文件”菜单中的“新建”项。
然后点击“保存”,将新创建的文件保存为你的主程序
这里我保存的是Main.C,但是此时我在左边的工程文件树中还是找不到Main.c这个文件,所以只好把这个文件插入到工程树中。
双击“源组1”的目录图标,会弹出插入文件的窗口,选择你的文件,点击“添加”按钮
此时你可以看到你的文件已经添加到下面的项目树中。由于你可以连续添加文件,所以必须手动关闭窗口。点击“关闭”按钮
这时候我们可以看到项目中已经存在刚刚新建的Main.c文件了。接下来我们需要稍微设置一下环境,否则无法编译目标文件。
我们右键点击“目标 1”,选择第一项“Options for Target ‘目标 1’”
然后会再次弹出设置窗口
我们将选择选择卡“输出”
我们选择“创建HEX文件”选项
然后点击确定按钮,返回主界面,这样我们的前期步骤就完成了。
现在说一下程序部分,在下位机开发中我们用的是C语言(不是C++,没有类的概念),可用的资源非常少,除了基本的C语言语句之外,能用的东西并不多,所有可用的东西都在Keil安装目录下的/C51/INC中。
我这里多了一个STC12C5A60S2.H文件,这个是STC官网提供的引脚和寄存器地址定义文件,通常我们只需要引用REG52.H就可以了。在C语言开发中,都是用#Include来引用这些头文件。第一步就是引用单片机引脚定义文件REG52.H,然后编写基本的程序入口函数Main。因为单片机只运行这么一个程序,主程序是不能执行到最后,必须进入死循环,否则程序执行完了就不行了。
好了,一个基本的MCU程序现在已经完成了。但是如何控制MCU的IO口呢?我们先看一下芯片说明中的引脚定义图:
这是STC DIP40封装的引脚定义图,我们可以看到一些奇怪的描述,比如P0.0-P0.7,P1.0-P1.7,这些是IO口。
IO口一般有4组,分别为P0、P1、P2、P3,每组IO口有8个引脚,代表8个二进制位。每组IO口除了基本的输入输出外,还可能有特殊的用途,这个要看不同型号的单片机了。比如这款STC单片机,P0口除了基本的输入输出外,还可以做A/D转换,所以它的P0口后面标注了AD0-AD7的字样,不过这些都是后面的应用了。我们先说说如何控制或者读取这些IO口。
在单片机中,这些IO口的引脚都是由厂家指定的系统功能寄存器来控制的,只要知道地址,就可以读取指定寄存器地址的值,从而得到相对的IO口状态。同样,设置相应的寄存器值也会改变IO口状态。因为我们用的是C语言,所以没必要直接用地址,我们可以用一个容易记住的变量来表示0x80这样的地址。所以,我们看REG52.H,会发现
sfr P0=0x80;
sfr P1=0x90;
sfr P2 = 0xA0;
sfr P3 = 0xB0;
P0口的地址是0x80,P1口的地址是0x90,我们在程序中只需要使用P0 = 255或者P0 = 0就可以改变P0口的8个引脚的状态为有电或者无电。
但是如果想单独控制某个引脚的状态怎么办呢?有的朋友可能会想到使用二进制的位运算,比如NOT、AND、OR、XOR等。
是的,这是个方法,但是不太灵活,这里我们还可以定义寻址引脚,比如我们只想控制P0.5的状态,那么用二进制计算方法就有点麻烦了,我们可以这样做
sbitLED1= P0^5; //这里^并不是异或运算符,而是一个特定的寻址符号
这时,如果程序像这样操作
LED1=1;
此时P0.5口将处于无电状态。
当然这个操作会获取P0.5端口的当前状态
位LED状态;
LED状态=LED1;
最后,让我们编写一个基本的 LED 闪烁示例来结束本次讨论。
最后点击编译按钮