书名:STM32单片机原理与项目实战
ISBN:978-7-115-57851-8
本书由人民邮电出版社发行数字版。版权所有,侵权必究。
您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。
我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。
如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。
著 刘 龙 高照玲 田 华
责任编辑 胡俊英
人民邮电出版社出版发行 北京市丰台区成寿寺路11号
邮编 100164 电子邮件 315@ptpress.com.cn
网址 http://www.ptpress.com.cn
读者服务热线:(010)81055410
反盗版热线:(010)81055315
近年来,嵌入式系统开发技术和嵌入式产品的发展势头迅猛,其应用领域涉及通信、消费电子、汽车工业等各个方面。嵌入式系统的设计与开发是一项实践性很强的专业技术,要求从业者深刻理解理论知识,并将原理与实践紧密结合。
本书旨在以实践驱动学习,通过“做中学”的方式让读者掌握相关知识点。全书内容分为10章,主要介绍了STM32系列处理器的基础知识、开发工具、基本系统、通用输入输出端口应用、系统节拍定时器、中断系统、定时器、串行通信、模数转换器,并展示了一个综合项目—温度控制系统。书中提供了19个范例,这些范例可以帮助读者循序渐进地掌握嵌入式系统开发的核心技术。
本书适合电子信息、通信、控制、计算机等相关专业的师生阅读,也适合作为嵌入式系统开发的入门教程,是一本既适合自学入门,又适合教学参考的图书。
刘龙 熟悉项目管理,精通嵌入式系统软硬件设计,以及C、Python等编程语言,拥有10余年的嵌入式产品研发经验。现就职于某高校健康医疗科技学院,从事医工结合方面的研究工作。
高照玲 就职于某高校智能与电子工程学院电子信息工程系,主要研究方向为嵌入式软硬件开发与导航、制导和控制。
田华 就职于某高校智能与电子工程学院电子信息工程系,主要研究方向为微控制系统、FPGA嵌入式应用。
近年来,嵌入式系统开发技术和嵌入式产品的发展势头迅猛,其应用领域涉及通信、消费电子、汽车工业、工业控制、信息家电、国防工业等各个方面。嵌入式产品在信息技术产业以及电子工业的经济总额中所占的比重越来越大,对国民经济增长的贡献日益显著。随着手机、媒体播放器、数码相机和机顶盒等嵌入式产品的普及,嵌入式系统的相关知识在广大民众中的传播越来越广泛。出于对嵌入式知识的追求,广大学生纷纷选修嵌入式系统课程,以学习嵌入式系统的理论知识和开发技能。目前,嵌入式系统课程已经成为高等院校计算机及相关专业的一门重要课程,嵌入式系统开发技术是相关领域研究、应用和开发等专业技术人员必须掌握的重要技术之一。
为了适应嵌入式系统开发技术的发展,目前国内众多院校都开设了这门课程,教学目标和内容各有特色和侧重。由于嵌入式系统的设计与开发是一项实践性很强的专业技术,光有理论知识是无法真正深刻理解和掌握的,因此嵌入式系统教学的问题是:讲授理论原理比较容易,难在如何让读者能够有效地进行实践。作者根据近年自身进行嵌入式系统设计的教学和工程实践的经验体会到,只通过书本难以让读者提高嵌入式系统的实际设计能力。传统的以课堂讲授为主、以教师为中心的教学方式会使学生感到枯燥和抽象,难以锻炼学生的嵌入式系统设计所必需的对器件手册、源代码和相关领域的自学能力,难以提高嵌入式系统的实际设计能力。
本书的内容组织遵循工程教育理念,从培养读者能力入手,以实用、切合实际为原则,为读者提供简明、直观、易懂的内容。书中采用实际项目实现为向导,深入浅出地介绍单片机技术的具体应用,并通过具体项目讲解单片机开发的基本流程和方法,以及单片机开发工具的使用方法。这样,读者可以清楚地看到运行的现象或结果,从而留下直观和深刻的印象,并且能迅速理解和掌握单片机的基本工作原理、一般开发流程,以及相关开发工具的使用方法。
本书适用于电子信息、通信、控制、计算机等相关专业单片机原理及应用课程的教学,也可作为有志于从事嵌入式系统开发的读者的入门教程。
学习本书内容需要读者具备基本的C语言编程能力,且学习过数字电路、模拟电路等课程,熟悉基本的电路原理。
本书将为读者深入学习嵌入式系统开发打下良好的基础,并着重从以下两方面培养读者的能力。
(1)理论知识:了解单片机的基本概念;了解单片机的应用和发展;理解单片机C语言基础;理解ARM开发的Cortex微控制器软件接口标准(CMSIS);熟悉ARM开发工具和开发环境;理解单片机基本系统;熟悉单片机内部资源。
(2)专业技能:掌握JLink驱动安装及其接口调试的方法;掌握MDK开发环境的搭建和使用方法;掌握STM32系列处理器系统时钟的配置和使用方法;掌握STM32系列处理器输入输出端口的配置和使用方法;掌握STM32系列处理器中断的配置和使用方法;掌握STM32系列处理器的系统节拍定时器和通用定时计数器的配置和使用方法;掌握STM32系列处理器通用异步串行通信的配置和使用方法;掌握STM32系列处理器模数转换器的配置和使用方法;掌握单片机常用外部设备的扩展和使用方法;掌握单片机软件工程开发方法。
本书以工程教育理念为指导,合理安排结构。书中采用典型情境任务开发的方式介绍相应的知识点,充分体现“做中学”的教学思路。本书以STM32系列处理器为核心自行设计开发板,设计一个来自工业控制领域的实际项目——温度控制系统,并围绕此项目展开具体内容的讲解。
温度表征的是物体的冷热程度,是生活及生产中最基本的物理量。自然界中所发生的物理、化学变化过程很多都与温度紧密相关。在生产过程中,温度的测量和控制直接和安全生产、生产效率、节约能源等相关。工业过程中离不开温度控制,不同的控制精度与控制方法对结果起着重要的作用。基于此目的,本书将带领读者完成一个基本的工业温度控制系统的软硬件设计。
工业温度控制系统是工业控制领域的典型系统,通常由采集模块、显示模块、通信模块与控制模块4部分组成。
本书首先通过第 1~3 章使读者掌握单片机的基本概念与典型的软硬件开发工具的使用方法;然后在第4~9章中,通过理论讲解与实践,完成温度控制系统4个组成模块的软硬件设计;最后在第10章中,通过对单片机软件工程基础内容的讲解,使读者完成对上述内容的整合与调试。项目与内容的关系如图0-1所示。
图0-1 项目与内容的关系
全书共10章。
第1章介绍ARM的基本概念、体系结构、应用与发展;ARM Cortex-M系列微处理器的功能、特点和结构;STM32系列处理器的性能、结构、存储系统;C语言开发的编程规范和设计思想;CMSIS的基本概念、设计及规范。
第2章介绍STM32系列处理器开发时常用的软件平台及硬件工具;JLink驱动的安装与调试;MDK的使用方法。
第3章介绍STM32系列处理器的基本系统的组成;电源电路的设计与注意事项;复位电路的设计与注意事项;时钟电路的设计与注意事项;调试电路的设计与注意事项等。
第4章介绍STM32系列处理器通用输入输出端口的内部结构、配置及其使用方法。
第5章介绍STM32系列处理器系统节拍定时器的概念、相关寄存器和使用方法。
第6章介绍STM32系列处理器的中断源、中断处理过程、中断寄存器和嵌套向量中断控制器等。
第7章介绍STM32系列处理器定时器的基本原理及相关寄存器等。
第8章介绍串行通信的基本概念;RS-232C总线标准;STM32串行通信接口的特性、引脚、结构;STM32的UART中断使用等。
第9章介绍STM32单片机模数转换器的概念、分类、主要技术指标、引脚配置、相关寄存器等。
第 10 章以温度控制系统为中心,介绍STM32单片机系统开发过程中涉及的程序结构、状态机等内容。
本书由刘龙、高照玲、田华编写,其中,刘龙负责编写第 1~4 章(约合 15 万字),高照玲负责编写第 5~7 章(约合 11 万字),田华负责编写第 8~10 章(约合 18 万字)。此外,鞠尔男、韩雪、杨永、王治强、孙丽飞、王伟、宋文斌、李德胜等人也为本书的写作提供了帮助。在编写本书的过程中,大连理工大学的王哲龙博士为本书的创作提供了全面的支持和具有建设性的指导,在此对上述人员表示特别感谢。
由于水平有限,书中难免有遗漏和不足之处,恳请广大读者提出宝贵意见,本书作者的电子邮箱是edaworld@163.com,QQ为915897209,欢迎来信交流。
本书由异步社区出品,社区(https://www.epubit.com/)为您提供相关资源和后续服务。
本书提供配套资源,请在异步社区本书页面中单击“配套资源”,跳转到下载界面,按提示进行操作即可。注意:为保证购书读者的权益,该操作会给出相关提示,要求输入提取码进行验证。
如果您是教师,希望获得教学配套资源,请在社区本书页面中直接联系本书的责任编辑。
作者和编辑尽最大努力来确保书中内容的准确性,但难免会存在疏漏。欢迎您将发现的问题反馈给我们,帮助我们提升图书的质量。
当您发现错误时,请登录异步社区,按书名搜索,进入本书页面,单击“提交勘误”,输入勘误信息,单击“提交”按钮即可。本书的作者和编辑会对您提交的勘误进行审核,确认并接受后,您将获赠异步社区的100积分。积分可用于在异步社区兑换优惠券、样书或奖品。
扫描下方二维码,您将会在异步社区微信服务号中看到本书信息及相关的服务提示。
我们的联系邮箱是contact@epubit.com.cn。
如果您对本书有任何疑问或建议,请您发邮件给我们,并请在邮件标题中注明本书书名,以便我们更高效地做出反馈。
如果您有兴趣出版图书、录制教学视频,或者参与图书翻译、技术审校等工作,可以发邮件给我们;有意出版图书的作者也可以到异步社区在线投稿(直接访问www.epubit.com/ contribute即可)。
如果您所在的学校、培训机构或企业,想批量购买本书或异步社区出版的其他图书,也可以发邮件给我们。
如果您在网上发现有针对异步社区出品图书的各种形式的盗版行为,包括对图书全部或部分内容的非授权传播,请您将怀疑有侵权行为的链接发邮件给我们。您的这一举动是对作者权益的保护,也是我们持续为您提供有价值的内容的动力之源。
“异步社区”是人民邮电出版社旗下IT专业图书社区,致力于出版精品IT图书和相关学习产品,为作译者提供优质出版服务。异步社区创办于2015年8月,提供大量精品IT图书和电子书,以及高品质技术文章和视频课程。更多详情请访问异步社区官网https://www.epubit.com。
“异步图书”是由异步社区编辑团队策划出版的精品IT专业图书的品牌,依托于人民邮电出版社近40年的计算机图书出版积累和专业编辑团队,相关图书在封面上印有异步图书的LOGO。异步图书的出版领域包括软件开发、大数据、人工智能、测试、前端、网络技术等。
异步社区
微信服务号
本章导读
单片机是一种集成电路芯片,也是采用超大规模集成电路技术,把CPU、RAM、ROM、I/O口和中断系统、定时器/计时器等功能集成到一块硅片上,构成的一个小而完善的微型计算机系统。目前单片机已经渗透到我们生活的很多领域,几乎很难找到哪个领域没有应用单片机。
由于ARM具有强大的处理能力和极低的功耗,现在越来越多的公司在产品选择的时候都考虑使用ARM处理器。特别是在工控领域,随着ARM功能的增强和完善,其在某些方面可以取代原先x86架构的单片机。基于以上两个原因,学习和使用ARM处理器已经变得非常流行。
本章主要介绍ARM的基本概念、体系结构、应用与发展;ARM Cortex-M系列微处理器的功能、特点和结构;STM32系列处理器的性能、结构、存储系统;C语言开发的编程规范和设计思想;CMSIS的基本概念、设计及规范。
(1)掌握ARM的基本概念;
(2)了解ARM的体系结构、应用与发展;
(3)了解ARM Cortex-M系列微处理器的功能、特点和结构;
(4)理解STM32系列处理器的性能、结构、存储系统;
(5)掌握C语言开发的编程规范和设计思想;
(6)掌握CMSIS的基本概念、设计及规范。
重点:掌握ARM的基本概念;了解ARM Cortex-M系列微处理器的功能、特点和结构;理解STM32系列处理器的性能、结构、存储系统;掌握C语言开发的编程规范和设计思想。
难点:掌握CMSIS的基本概念、设计及规范。
对于CMSIS的基本概念、设计及规范,可通过对具体实例中代码的逐条讲解,强化概念理解记忆。
在各种不同类型的嵌入式系统中,以微控制器(Microcontroller)作为系统的主要控制核心所构成的单片嵌入式系统(国内通常称为单片机系统)占据着非常重要的地位。本书将介绍以Cortex-M系列微控制器为核心的单片嵌入式系统的原理,以及硬软件设计、调试等方法。
单片嵌入式系统的硬件基本构成可分成两大部分:微控制器芯片和外围的接口与控制电路。其中微控制器是构成单片嵌入式系统的核心。
微控制器又称为单片微型计算机(Single-Chip Microcomputer或One-Chip Microcomputer),或者嵌入式微控制器(Embedded Microcontroller)。国内普遍使用的名字为“单片机”。尽管单片机的“机”的含义并不十分恰当,甚至比较模糊,但考虑到多年来国内习惯了“单片机”这一叫法,为了符合我国的使用习惯,本书仍采用“单片机”的名称。
所谓的微控制器即单片机,它通常只是一片大规模集成电路芯片,但在芯片的内部却集成了中央处理器(Central Processing Unit,CPU)、各种存储器(RAM、ROM、EPROM、EEPROM和FlashROM等)、各种输入输出接口(定时器/计数器、并行I/O接口、串行I/O接口以及模数转换接口等)等众多的部件。因此,一片芯片就构成了一个基本的微型计算机系统。
单片机的微小体积,极低的成本和面向控制的设计,使得它作为智能控制的核心器件被广泛地应用于嵌入式工业控制、智能仪器仪表、家用电器、电子通信产品等各个领域中的电子设备和电子产品。可以说,由以单片机为核心构成的单片嵌入式系统已成为现代电子系统中最重要的组成部分。
以往我们按照计算机的体系结构、运算速度、结构规模、适用领域,将其分为巨型计算机、大型计算机、小型计算机和微型计算机,并以此来组织学科和产业分工,这种分类沿袭了约40年。近20年来,随着计算机技术的迅速发展,以及计算机技术和产品对其他行业的广泛渗透,以应用为中心的分类方法变得更切合实际。具体来说,就是按计算机的非嵌入式应用和嵌入式应用将其分为通用系统和嵌入式系统。
通用系统具有计算机的标准形态,通过装配不同的应用软件,以类同面目出现,并应用在社会的各个方面。现在我们在办公室里、家里,最广泛使用的PC就是通用系统最典型的代表。
而嵌入式计算机以嵌入式系统的形式出现在各种装置、产品和系统中。在许多的应用领域中,如工业控制、智能仪器仪表、家用电器、电子通信设备等的电子系统和电子产品中,我们对计算机的应用有着不同的要求。这些要求的主要特征为:
● 面对控制对象。面对传感器转换的信号输入;面对人机交互的操作控制;面对对象的伺服驱动和控制。
● 嵌入应用系统。体积小、功耗小、价格低廉,可方便地嵌入应用系统和电子产品。
● 能在工业现场环境中可靠地运行。
● 优良的控制功能。面对外部的各种模拟和数字信号能及时地捕捉,面对多种不同的控制对象能灵活地进行实时控制。
可以看出,满足上述要求的计算机系统与通用系统是不同的。换句话讲,能够满足和适合以上这些应用的计算机系统与通用系统在应用目标上有巨大的差异。
我们将具备高速计算能力和海量存储,用于高速数值计算和海量数据处理的计算机系统称为通用系统。而将面对工控领域对象,嵌入各种控制应用系统、各类电子系统和电子产品,实现嵌入式应用的计算机系统称为嵌入式系统(Embedded System)。
对于特定的环境、特定的功能,计算机系统需要与所嵌入的应用环境成为一个统一的整体,并且往往要满足紧凑、高可靠性、实时性好、低功耗等技术要求。这样一种面向具体、专用应用目标的计算机系统的设计方法和开发技术,构成了今天嵌入式系统的重要内涵,也是嵌入式系统发展成一个相对独立的计算机研究和学习领域的原因。
嵌入式系统是以应用为核心、以计算机技术为基础、软件硬件可裁剪,以及对功能、可靠性、安全性、成本、体积、重量、功耗、环境等方面有严格要求的专用计算机系统。嵌入式系统将应用程序、操作系统与计算机硬件集成在一起,简单地讲就是系统的应用软件与系统的硬件一体化。这种系统具有软件代码少、高度自动化、响应速度快等特点,特别适用于面向对象的实时性要求高的应用和多任务的应用。
嵌入式系统在应用数量上远远超过了各种通用系统,一台通用系统计算机,如PC的外部设备中包含了 5~10 个嵌入式系统:键盘、鼠标、软驱、硬盘、显卡、显示器、调制解调器(Modem)、网卡、声卡、打印机、扫描仪、数字相机、USB集线器等均是由嵌入式处理器控制的。制造、过程控制、通信、仪器、仪表、汽车、船舶、航空、航天、军事装备、消费等均是嵌入式计算机的应用领域。
通用系统和嵌入式系统形成了计算机技术的两大分支。与通用系统相比,嵌入式系统最显著的特性是它面对工控领域的测控对象。工控领域的测量对象几乎都是物理量,如压力、温度、速度、位移等;控制对象则包括马达、电磁开关等。嵌入式系统对这些量的采集、处理等是有限的,而对控制方式和能力的要求是多种多样的。显然,这一特性形成并决定了嵌入式系统和通用系统在系统结构、技术、学习、开发和应用等诸多方面的差别,也使得嵌入式系统成为计算机技术发展中的一个重要分支。
嵌入式系统以其独特的结构和性能,越来越多地应用于国民经济的各个领域。
嵌入式系统根据其核心控制部件的不同可分为几种不同的类型:
● 各种类型的工控机;
● 可编程逻辑控制器(Programmable Logic Controller,PLC);
● 以通用微处理器或数字信号处理器构成的嵌入式系统;
● 单片嵌入式系统。
采用上述不同类型的核心控制部件所构成的系统都实现了嵌入式系统的应用,组成了嵌入式系统应用的“庞大家族”。
以单片机作为控制核心的单片嵌入式系统大部分应用于专业性极强的工业控制系统,其主要特点是:结构和功能相对单一、存储容量较小、计算能力和效率比较低、具有简单的用户接口。由于这种嵌入式系统功能专一可靠、价格便宜,因此在工业控制、电子智能仪器仪表等领域有着广泛的应用。
作为单片嵌入式系统的核心控制部件,单片机从体系结构到指令系统都是按照嵌入式系统的应用特点专门设计的,它能较好地满足面对控制对象、应用系统的嵌入、现场的可靠运行和优良的控制功能等要求。因此,单片系统应用是发展最快、品种最多、数量最大的嵌入式系统,有着广泛的应用前景。由于单片机具有嵌入式系统的专用体系结构和指令系统,因此在其基本体系结构上,可衍生出能满足各种不同应用系统要求的系统或产品。用户可根据应用系统的各种不同要求和功能,选择最佳型号的单片机。
一个典型的嵌入式系统——单片嵌入式系统,在我国大规模应用已有几十年的历史。它不但是中小型工控领域、智能仪器仪表、家用电器、电子通信设备和电子系统中的重要工具和普遍的应用手段,同时,单片嵌入式系统的广泛应用和不断发展,也大大推动了嵌入式系统技术的快速发展。因此对于电子、通信、工业控制、智能仪器仪表等相关专业的学生来讲,深入学习和掌握单片嵌入式系统的原理与应用,不仅能对自己所学的基础知识进行检验,而且能够培养和锻炼自己的分析问题、综合应用和动手实践的能力,掌握真正的专业技能和应用技术。同时,深入学习和掌握单片嵌入式系统的原理与应用,可为更好地掌握其他嵌入式系统打下基础。
美国英特尔(Intel)公司在1971年推出了4004型4位微处理器芯片;1972年推出了8位单片机雏形8008;1976年推出MCS-48单片机。此后的30年中,单片机的发展和其相关的技术经历了数次的更新换代,大约每三四年更新一代、集成度增加、功能加强。
尽管单片机的历史并不长,但以8位单片机的推出为起点,单片机的发展大致可分为4个阶段。
第一阶段(1976—1978年):初级单片机阶段。以Intel公司的MCS-48为代表,这个系列的单片机内集成8位CPU、I/O口、8位定时器/计数器,寻址范围不大于4KB,有简单的中断功能,无串行接口。
第二阶段(1978—1982年):单片机完善阶段。在这一阶段推出的单片机的功能有较大的加强,能够应用于更多的场合。这个阶段的单片机普遍带有串行I/O口、有多级中断处理系统、16位定时器/计数器,片内集成的RAM、ROM容量加大,寻址范围可达64KB。一些单片机内还集成了模数转换器。这类单片机的典型代表有Intel公司的MCS-51、摩托罗拉(Motorola)公司的6801和Zilog公司的Z80等。
第三阶段(1982—1992年):8位单片机巩固阶段及16位高级单片机发展阶段。在此阶段,尽管8位单片机的应用已普及,但为了更好地满足测控系统的嵌入式应用的要求,单片机集成的外围接口电路有了更大的扩充。这个阶段单片机的代表为8051系列。许多半导体公司和生产厂商以MCS-51的8051为内核,推出了满足各种嵌入式应用的多种类型和型号的单片机。单片机主要技术发展如下。
(1)外围功能集成。满足模拟量直接输入的模数转换接口;满足伺服驱动输出的PWM;保证程序可靠运行的程序监控定时器WDT(俗称看门狗定时器)。
(2)出现了为满足串行外围扩展要求的串行扩展总线和接口,如串行外部接口(Serial Peripheral Interface,SPI)、内部集成总线(Inter Integrated Circuit,I2C)、单总线(1-Wire)等。
(3)出现了为满足分布式系统,突出控制功能的现场总线接口,如CAN总线等。
(4)在程序存储器方面广泛使用了片内程序存储器技术,出现了片内集成EPROM、EEPROM、FlashROM以及MaskROM、OTPROM等各种类型的单片机,以满足不同产品的开发和生产的需求,也为最终取消外部程序存储器扩展奠定了良好的基础。
与此同时,一些公司面向更高层次的应用,推出了16位单片机,典型代表有Intel公司的MCS-96系列单片机。
第四阶段(1993年至今):百花齐放阶段。现阶段单片机发展的显著特点是百花齐放、技术创新,以满足日益增长的广泛需求。单片机主要技术发展如下。
(1)单片嵌入式系统应用是面对最底层的电子技术应用,从简单的玩具、小家电到复杂的工业控制系统、智能仪器仪表、电器控制,以及机器人、个人通信信息终端、机顶盒等。因此,面对不同的应用对象,不断推出满足不同领域要求的,从简易功能到功能齐全的单片机。
(2)大力发展专用型单片机。早期的单片机是以通用型为主的。由于单片机设计生产技术提高、周期缩短、成本下降,以及许多特定类型电子产品(如家电类产品的巨大的市场需求)推动了专用型单片机的发展。在这类产品中采用专用型单片机,具有低成本、资源有效利用、系统外围电路少、可靠性高等优点。因此,专用型单片机也是单片机发展的一个主要方向。
(3)致力于提高单片机的综合品质。采用更先进的技术来提高单片机的综合品质,如提高I/O口的驱动能力;增加抗静电和抗干扰功能;宽(低)电压低功耗等。
纵观30多年的发展过程,单片嵌入式系统的核心——单片机,正朝着多功能、多选择、高速度、低功耗、低价格、扩大存储容量和加强I/O功能等方向发展。其进一步的发展趋势是多方面的。
(1)全盘互补金属氧化物半导体(Complementary Metal Oxide Semiconductor,CMOS)化。CMOS电路具有许多优点,如极宽的工作电压范围、极佳的低功耗及功耗管理特性等。CMOS化已成为目前单片机及其外围器件流行的趋势。
(2)采用精简指令集计算机(Reduced Instruction Set Computer,RISC)体系结构。早期的单片机大多采用CISC体系结构,指令复杂,指令代码、周期数不统一,指令运行很难实现流水线操作,大大阻碍了运行速度的提高。如MCS-51系列单片机,当外部时钟频率为12MHz时,其单周期指令运行速度仅为1MIPS。采用RISC体系结构和精简指令后,单片机的指令绝大部分成为单周期指令,而通过增加程序存储器的指令宽度(如从8位增加到16位),实现了一个地址单元存放一条指令。在这种体系结构中,很容易实现并行流水线操作,可大大提高指令运行速度。目前,一些RISC体系结构的单片机,如美国爱特梅尔半导体(Atmel)公司的AVR系列单片机已实现了在一个时钟周期执行一条指令。与MCS-51相比,在相同的12MHz外部时钟频率下,单周期指令运行速度可达12MIPS,一方面可获得很高的指令运行速度;另一方面,在相同的运行速度下,可大大降低时钟频率,有利于获得良好的电磁兼容效果。
(3)多功能集成化。单片机在内部已集成了越来越多的部件,如定时器/计数器、模拟比较器、模数转换器、模数转换器、串行通信接口、WDT、LCD控制器等。还有的单片机为了构成控制网络或形成局部网,内部含有局部网络控制模块CAN总线。为了能在变频控制中方便地使用单片机,需形成最具经济效益的嵌入式控制系统。有的单片机内部设置了专门用于变频控制的脉宽调制(Pulse Width Modulation,PWM)控制电路。
(4)片内存储器的改进与发展。目前新型的单片机一般在片内集成两种类型的存储器:静态随机存储器(Static Random Access Memory,SRAM),作为临时数据存储器存放工作数据;只读存储器ROM,作为程序存储器存放系统控制程序和固定不变的数据。片内存储器的改进与发展的方向是扩大容量、加强ROM数据的易写和保密等特性。一般新型的单片机在片内集成的SRAM的容量在128B~1KB,ROM的容量一般为4KB~8KB。为了适应网络、音视频等高端产品的需要,单片机在片内集成了更大容量的RAM和ROM,如Atmel公司的ATmega16,片内的SRAM为1KB,FlashROM为16KB。而该系列的高端产品ATmega256片内集成了8KB的SRAM,256KB的FlashROM和4KB的EEPROM。
● 片内程序存储器由EPROM型向FlashROM型发展。早期的单片机在片内往往没有程序存储器或片内集成EPROM型的程序存储器。将程序存储器集成在单片机内可以大大提高单片机的抗干扰性能、提高程序的保密性、减少硬件设计的复杂性等,因此片内程序存储器已成为新型单片机的标准方式。但由于EPROM需要使用12V电压编程写入,具有紫外线擦除、重写入次数有限等特点,给使用带来了不便。新型的单片机则采用FlashROM、MaskROM、OTPROM作为片内的程序存储器。FlashROM在常用电压(如5V/3V)下就可以实现编程写入和擦除操作,重写次数在10 000次以上,并可实现在线系统可编程(In System Programmable,ISP)技术的优点,为使用带来极大的方便。采用MaskROM的微控制器称为掩模芯片,它是在芯片制造过程中就将程序“写入”了,并且永远不能改写。采用OTPROM的微控制器,其芯片出厂时片内的程序存储器是“空的”,它允许用户将自己编写好的程序一次性地编程写入,之后便再也无法修改了。后两种类型的单片机适合大批量产品生产,而前两种类型的微控制器适合产品的设计开发、批量生产以及学习培训的应用。
● 程序保密化。一个单片嵌入式系统的系统程序是系统的最重要的部分,是知识产权保护的核心。为了防止片内的程序被非法读出并复制,新型的单片机往往对片内的程序存储器采用加锁保密措施。系统程序编程写入片内的程序存储器后,可以再对加密保护单元编程,给芯片加锁。加锁加密后,从芯片的外部无法读取片内的系统程序代码,若将加密单元擦除,则片内的程序同时被擦除,这样便达到了程序保密的目的。
(5)ISP、IAP及基于ISP、IAP技术的开发和应用。微控制器在片内集成EEPROM、FlashROM的发展,导致了ISP技术在单片机中的应用。首先实现了系统程序的串行编程写入(下载),使得我们不必将焊接在印制电路板(Printed Circuit Board,PCB)上的芯片取下,就可直接将程序下载到单片机的程序存储器,淘汰了专用的程序下载写入设备。其次,基于ISP技术的实现,模拟仿真开发技术重新兴起。在单时钟、单指令运行的RISC结构的单片机中,可实现PC通过串行电缆对目标系统进行在线仿真调试。在ISP技术应用的基础上,又发展了在线程序可编程(In Application Programmable,IAP)技术,也称在线应用可编程技术。利用IAP技术,可实现用户随时根据需要在线对原有的系统方便地更新软件、修改软件,还能实现对系统软件的远程诊断、远程调试和远程更新。
(6)实现全面功耗管理。采用CMOS工艺后,单片机具有极佳的低功耗和功耗管理功能。它包括以下几个方面。
● 传统的CMOS单片机的低功耗运行方式,即闲置方式(Idle Mode)、掉电方式(Power Down Mode)。
● 双时钟技术。配置有高速(主)和低速(子)两个时钟系统。在不需要高速运行时,则转入低速时钟系统的控制下,以节省功耗。
● 片内外围电路的电源管理。对集成在片内的外围接口电路实行供电管理,当该外围电路不运行时,关闭其供电。
● 低电压节能技术。CMOS电路的功耗与电源电压有关,降低系统的供电电压,能大幅度降低器件的功耗。新型的单片机往往具有宽电压(3V~5V)或低电压(3V)运行的特点。低电压、低功耗是手持便携式系统重要的追求目标,也是绿色电子的发展方向。
(7)以串行总线方式为主的外围扩展。目前,单片机与外围器件接口技术发展的一个重要方向是由并行外围总线接口向串行外围总线接口的发展。采用串行总线方式为主的外围扩展技术具有方便、灵活、电路系统简单、占用I/O资源少等特点。虽然采用串行接口比采用并行接口数据传输速度慢,但随着半导体集成电路技术的发展,大批采用标准串行总线通信协议(如SPI、I2C、1-Wire等)的外围芯片器件的出现,串行传输速度不断提高(可达到1Mbit/s~10Mbit/s的速率),可片内集成程序存储器而不必外部并行扩展程序存储器,加上单片嵌入式系统有限速的要求,使得以串行总线方式为主的外围扩展方式能够满足大多数系统的需求,从而成为流行的扩展方式,而采用并行接口的扩展技术成为辅助方式。
(8)单片机向单片系统的发展。单片系统(System on a Chip,SoC)是一种高度集成化、固件化的芯片级集成技术,其核心思想是把除了无法集成的某些外部电路和机械部分之外的所有电子系统等电路全部集成在一片芯片。现在,一些新型的单片机(如AVR系列单片机)已经具有SoC的雏形,在一片芯片集成了各种类型和更大容量的存储器、更多性能更加完善和强大的功能电路接口,这使得原来需要几片甚至十几片芯片组成的系统,现在只用一片芯片就可以实现。其优点是不仅减小了系统的体积和降低了成本,而且大大提高了系统硬件的可靠性和稳定性。
仅由一片单片机芯片是不能构成一个应用系统的。系统的核心控制芯片往往还需要与一些外围芯片、器件和控制电路机构有机地连接在一起,才能构成一个实际的单片机系统;进而嵌入应用对象的环境体系中,作为其中的核心智能化控制单元而构成典型的单片系统,如洗衣机、电视机、空调、智能仪器仪表等。
单片嵌入式系统的结构如图 1-1 所示,通常包括三大部分,即能实现嵌入式对象各种应用要求的单片机、系统硬件电路和系统软件。
图1-1 单片嵌入式系统的结构
(1)单片机:单片机是单片嵌入式系统的核心控制芯片,由它实现对控制对象的测控、系统运行管理控制和数据运算处理等功能。
(2)系统硬件电路:根据系统采用单片机的特性以及嵌入对象要实现的功能要求而配备的外围芯片、器件所构成的全部硬件电路。通常包括以下几部分。
● 基本系统电路。提供和满足单片机系统运行所需要的时钟电路、复位电路、供电电路、驱动电路、扩展的存储器等。
● 前向通道接口电路。这是应用系统面向对象的输入接口电路,通常有传感器、变换器输入通道。根据现实世界物理量转换成输出信号的类型的不同,如模拟电压、开关信号、数字脉冲信号等,接口电路也不同。常见的有传感器、信号调理器、模数转换器(Analog-to-Digital Conversion,ADC)、开关量输入、频率测量接口等。
● 后向通道接口电路。这是应用系统面向对象的输出接口电路。根据应用对象伺服和控制要求,通常有数模转换器(Digital-to-Analog Conversion,DAC)、开关量输出电路、功率驱动接口、PWM输出控制器等。
● 人机交互通道接口电路。人机交互通道接口电路是满足应用系统人机交互需求的电路,包括与键盘、拨动开关、发光二极管、数码管、液晶显示器、打印机等相连多种输入输出接口电路。
● 数据通信接口电路。数据通信接口电路是满足远程数据通信或构成多机网络应用系统的电路,通常包括RS-232、PSI、I2C、CAN总线、USB总线等通信接口电路。
(3)系统软件:系统软件的核心就是下载到单片机中的系统运行程序。整个嵌入式系统全部硬件的相互协调工作、智能管理和控制都由系统运行程序决定。它可被认为是单片嵌入式系统核心的核心。一个系统软件设计的好坏,往往决定了整个系统性能的好坏。
系统软件是根据系统功能要求设计的,一个嵌入式系统的运行程序实际上是该系统的监控与管理程序。对于小型系统的应用程序,一般采用汇编语言编写。而对于中型和大型系统的应用程序,往往采用高级程序设计语言(如C语言)来编写。
编写嵌入式系统应用程序与编写其他类型的软件程序(如基于PC的应用软件设计开发)有很大的不同,嵌入式系统应用程序多面向硬件底层和控制,而且要面对有限的资源(如有限的RAM)。因为嵌入式系统的应用软件不仅要直接面对单片机及与它连接的各种不同种类和设计的外围硬件电路编程,还要面对系统的具体应用和功能编程。整个运行程序常常是输入输出接口设计、存储器、外围芯片、中断处理等交织在一起。因此,除了硬件系统的设计,系统应用软件的设计也是嵌入式系统开发研制过程中重要和困难的任务。
需要强调的是,单片嵌入式系统的硬件设计和软件设计之间的关系是十分紧密、互相依赖和制约的。因此,通常要求嵌入式系统的开发人员既要具备扎实的硬件设计能力,也要具备相当优秀的软件设计能力。
以单片机为核心构成的单片嵌入式系统已成为现代电子系统中最重要的组成部分。在现代的数字化世界中,单片嵌入式系统已经大量地渗透到我们生活的各个领域,几乎很难找到哪个领域没有单片机的踪迹。飞机上各种仪表的控制、计算机的网络通信与数据传输、工业自动化过程的实时控制和数据处理、生产流水线上的机器人、医院里先进的医疗器械和仪器、广泛使用的各种智能IC卡、小朋友的程控玩具和电子宠物等都是典型的单片嵌入式系统应用。
单片机芯片的微小体积、极低的成本和面向控制的设计,使得它作为智能控制的核心器件被广泛地用于嵌入式工业控制、智能仪器仪表、家用电器、电子通信产品等各个领域的电子设备和电子产品中,主要的应用领域有以下几个方面。
(1)智能家用电器。俗称带“电脑”的家用电器,如电冰箱、空调、微波炉、电饭锅、电视机、洗衣机等。在传统的家用电器中嵌入单片机系统后,产品的性能、特点都可得到很大的改善,实现运行智能化、温度的自动控制和调节、节约电能等。
(2)智能机电一体化产品。单片机嵌入式系统与传统的机械产品相结合,使传统的机械产品结构简化、控制智能化,从而构成新一代的机电一体化产品。这些产品已在纺织、机械、化工、食品等工业生产中发挥出巨大的作用。
(3)智能仪器仪表。用嵌入式系统改造原有的测量、控制仪器仪表,能促使仪器仪表向数字化、智能化、多功能化、综合化、柔性化等方向发展。由嵌入式系统构成的智能仪器仪表可以集测量、处理、控制功能于一体,赋予传统的仪器仪表崭新的面貌。
(4)测控系统。用嵌入式系统可以构成各种工业控制系统、适应控制系统、数据采集系统等,例如温室人工气候控制、汽车数据采集与自动控制系统。
在单片机发展的历程中,51单片机做出了非常重要的贡献。
今天的所谓的51单片机实际上是一个总概念,泛指所有采用了Intel公司的MCS-51内核架构,或与MCS-51兼容的那些单片机。典型的代表为Intel公司生产的8051系列单片机。目前国际上仍有许多半导体公司和生产厂商以MCS-51为内核,推出了经过改进和扩展的、满足各种嵌入式应用的多种类型和型号的51兼容单片机。所以51单片机在单片嵌入式系统的应用中占据着非常重要的地位。
在国内高校的单片机系统课程与教学中,20多年来基本上都是以51单片机作为构成单片机系统的典型控制芯片介绍的,培养出了大批了解、熟悉以及掌握51单片机的技术人员和工程师,出版了大批与51单片机相关的教材和应用参考书。直到现在,国内的51单片机还是有着相当庞大的用户群体。
从应用和市场的角度看,51单片机仍能满足许多应用系统的需求,并且有着价格低廉、参考资料和例程多等许多优点。除此之外,现在许多半导体公司和生产厂商也不断地在推出多种类型和型号的、以MCS-51为内核、经过比较大的改进和扩展的51兼容SoC单片机,它们的性能比标准的8051单片机高得多,也能够满足许多更高要求的应用。
但由于MCS-51本身的内核结构的局限性,51单片机,尤其是标准51架构的单片机,在性能、技术和硬件与软件设计理念等方面已经落后了。从技术角度看,标准51架构的单片机已经跟不上单片机流行和发展的趋势了。
随着单片机系统技术的发展,目前市场上出现了许多新型的32位芯片。其中以ARM公司为基础的微控制器、微处理器的发展尤为引人注目。ARM采用了RISC结构,在速度、内存容量、外围接口的集成化程度,以及向串行扩展、更适合使用高级语言编程等众多的特性,其所使用的开发技术和仿真调试技术等方面,都充分体现和代表了当前单片嵌入式系统发展的趋势。也正是这些显著特点和具有极高的性价比,使得ARM处理器得到广泛的应用,成为市场上的主流芯片之一。
因此,从教育的长远和发展眼光出发,我们的教学与学习的目标应该更高些。要相应地改变教学内容、教学方式和学习方式,充分体现和融入新的技术、新的硬件和软件系统设计理念和方法,为培养适应当今技术发展的嵌入式系统工程师和打好坚实的基础,以满足社会对高水平人才的需求。
ARM是Advanced RISC Machines的缩写,ARM公司是微处理器行业的一家知名企业,最初是由苹果(Apple)、Acorn计算机集团和VLSI Technology组成的合资企业。ARM公司的总部位于英国剑桥,在全球设立了多个办事处和设计中心,也设计了大量高性能、廉价、低功耗的RISC处理器及软件,发展了相关技术。ARM公司设计的处理器具有性能高、成本低、功耗小和代码密度大等特点,广泛应用于手机、数字机顶盒、汽车制动系统、网络路由器等。
ARM公司将其一些知识产权授权给世界上许多著名的半导体、软件和OEM企业,每个厂商得到IP内核后结合自己的特点,设计生产各自特点的ARM芯片。利用这种方式,ARM公司已经和全世界200多家公司合作,出售了600多个处理器许可证。以这种合作关系,ARM公司很快成为全球RISC标准的缔造者。目前为止,市面上已有超过150亿枚基于ARM的芯片。ARM取得了巨大的市场份额,可以说ARM公司的收益增速通常要比整个半导体行业快。
随着ARM的不断普及,ARM已不再是遥不可及的高端处理器。ARM公司设计出了一系列面向低端市场的微处理器内核——Cortex-M系列内核,大有以之取代8位和16位微处理器的趋势。
ARM的体系结构并不复杂,可以进行极小规模的实现,从而实现其高性能、低功耗等特点。ARM是32位精简指令集计算机(RISC),它集成了非常典型的RISC结构并具有以下特性:
● 大型统一寄存器文件;
● 加载/存储体系结构。其中的数据处理操作只针对寄存器内容,并不直接针对内存内容;
● 简单寻址模式。所有加载/存储地址只通过寄存器内容和指令字段确定。
此外,ARM体系结构还包括某些可改进代码密度和性能的其他主要特性:
● 可组合使用转换与算术或逻辑运算的指令;
● 用于优化程序循环的自动递增和自动递减寻址模式;
● 加载和存储多个指令以使数据吞吐量最大化;
● 几乎所有指令都采取条件执行的方式执行,以使执行吞吐量最大化。
这些对基本RISC体系结构的增强使ARM处理器可以在高性能、较少代码、较低功耗和较小硅片几个方面实现良好平衡。
ARM公司开发了很多系列的ARM处理器内核,以前都是以ARMx(x为具体数字)进行命名的,如比较经典的ARM7、ARM9、ARM11等。目前,ARM公司不再按照这样的方式命名,而是按照应用等级划分成3个类别,并以Cortex为前缀进行命名,而且每一个大的系列又分若干小的系列。
ARM Cortex系列处理器采用全新的ARM v7架构,根据适用的领域不同,ARM微处理器分为三大类:
● Cortex-A系列——面向开放式操作系统的高性能处理器;
● Cortex-R系列——面向实时应用且具备卓越性能的处理器;
● Cortex-M系列——面向具有确定性的微控制器应用的成本敏感型解决方案的处理器。
图 1-2 所示为目前市场上比较流行的根据性能、功能和处理能力来划分的几大系列的微处理器。
图1-2 ARM处理器性能比较
ARM体系结构的发展经历了几个关键时期,图1-3所示为ARM体系结构的发展过程,包含其各阶段支持的指令集和对应的内核版本。
图1-3 ARM体系结构的发展过程
ARM Cortex-M系列微处理器是考虑不同的成本、功耗和性能的处理器,同时是各类可兼容、易于使用的嵌入式设备的理想解决方案。针对十分广泛的嵌入式应用,不同的处理器在性能、成本、功耗等方面进行了权衡和取舍。ARM Corter-M系列微处理器应用定位如表1-1所示。
表1-1 ARM Cortex-M系列微处理器应用定位
微处理器系列 |
ARM Cortex-M0 |
ARM Cortex-M3 |
ARM Cortex-M4 |
---|---|---|---|
应用领域 |
“8/16位”应用 |
“16/32位”应用 |
“32位/DSC”应用 |
特点 |
低成本和简单性 |
性能效率 |
有效的数字信号控制 |
图1-4所示为ARM Cortex-M系列微处理器性能比较。Cortex-M系列微处理器都是二进制向上兼容的,这使得软件重用以及从一个Cortex-M处理器无缝发展成另一个处理器成为可能。
图1-4 ARM Cortex-M系列微处理器性能比较
ARM Cortex-M3是一种基于ARMv7架构的ARM嵌入式内核,它采用哈佛结构,使用分离的指令和数据总线。ARM公司对Cortex-M3的定位是:向专业嵌入式市场提供低成本、低功耗的芯片。在成本和功耗方面,Cortex-M3具有相当好的性能。和所有的ARM内核一样,ARM公司将其设计授权给各个制造商开发具体的芯片。Cortex-M3内核通过接口总线的形式挂载了储存器、外设、中断等组成一个多点控制器(Multipoint Control Unit,MCU)。迄今为止,已经有多家芯片制造商开始生产基于Cortex-M3内核的MCU。目前Cortex-M3处理器内核的授权客户包括东芝(Toshiba)、意法半导体(ST)、Ember、Accent、Actel、ENERGY、ADL、思智浦半导体(NXP)、德州仪器(TI)、Atmel、博通(Broadcom)、三星(Samsung)、ZiLOG和Renesas等,其中东芝、ST、NXP、TI、Atmel等已经推出基于Cortex-M3的MCU产品。
Cortex-M3处理器是一个32位的处理器,内部的数据路径是32位的,寄存器是32位的,寄存器接口也是32位的。基于ARMv7架构的 Cortex-M3处理器带有一个分级结构,它集成了名为CM3Core的中心处理器内核和先进的系统外设,实现了内置的中断控制、存储器保护以及系统的调试和跟踪功能。对这些外设可进行高度配置,允许 Cortex-M3处理器处理大范围的应用并贴近系统的需求。
Cortex-M3中央内核基于哈佛架构,指令和数据各使用一条总线,所以Cortex-M3处理器对多个操作可以并行执行,加快应用程序的执行速度。内核流水线分3个阶段:取指、译码和执行。当遇到分支指令时,译码阶段也包含预测的指令取指,这提高了执行的速度。
处理器在译码阶段自行对分支指令进行取指。在稍后的执行过程中,处理完分支指令后便知道下一条要执行的指令。如果分支指令不跳转,那么紧跟着的下一条指令随时可供使用。如果分支指令跳转,那么在跳转的同时分支指令可供使用,空闲时间限制为一个周期。
Cortex-M3内核包含一个适用于传统Thumb和新型Thumb2指令的译码器、一个支持硬件乘法和硬件除法的先进算术逻辑单元、控制逻辑和用于连接处理器其他部件的接口。
Cortex-M3处理器是一个32位处理器,带有32位的数据路径、寄存器库和存储器接口,其中有13个通用寄存器、2个堆栈指针、1个链接寄存器、1个程序计数器和一系列包含编程状态寄存器的特殊寄存器。Cortex-M3处理器支持两种工作模式[线程(Thread)模式和处理器(Handler)模式]和两个等级的访问形式(有特权或无特权),在不牺牲应用程序安全的前提下实现了对复杂的开放式系统的执行。执行无特权代码限制或拒绝对某些资源的访问,如某个指令或指定的存储器位置。线程是常用的工作模式,它同时支持享有特权的代码以及没有特权的代码。当异常发生时进入处理器模式,在该模式中所有代码都享有特权。
Cortex-M3的内核架构如图1-5所示,下面主要关注图中标了序号的模块:寄存器组、嵌套向量中断控制器、外部中断信号组、存储器接口、总线互联网络、调试接口。
图1-5 Cortex-M3的内核架构
● 通用寄存器(R0~R12):R0~R12都是32位通用寄存器,可用于数据操作。绝大多数16位Thumb指令只能访问R0~R7,32位Thumb2指令可以访问所有寄存器。
● 两个堆栈指针(R13):Cortex-M3拥有两个堆栈指针,都是堆积的,因此任一时刻只能使用其中一个。
● 连接寄存器(R14):当调用一个子程序时,由R14存储并返回地址。与其他大多数处理器不同,ARM为了减少访问内存的次数,把返回地址直接存储在寄存器中。这样使很多只有一级子程序调用的代码无须访问内存(堆栈内存),从而提高子程序调用的效率。如果多于一级,则需要把前一级的R14的值压到堆栈里。
● 程序计数寄存器(R15):指向当前的程序地址,如果修改它的值,就能改变程序的执行流程。
● 特殊功能寄存器:如程序状态字寄存器组、中断屏蔽寄存器组、控制寄存器等。
嵌套向量中断控制器(Nested Vectored Interrupt Controller,NVIC)的功能为可嵌套中断支持、向量中断支持、动态优先级调整、中断延时大大缩短、中断可屏蔽。
Cortex-M3的所有中断机制都由NVIC实现。除了支持240条中断之外,NVIC还支持16−4−1=11个内部异常源(5个为保留中断源),可以实现容错管理机制。Cortex-M3有256个预定义的异常类型。
Cortex-M3支持4GB存储空间。与其他ARM架构不同,Cortex-M3的存储器映射由半导体厂商决定。Cortex-M3预先定义了“粗线条的”存储器映射。通过把片上外设的寄存器映射到外设区,就可以简单地以访问内存的方式来访问这些外设的寄存器,从而控制外设工作。
总线互联网络是指Cortex-M3内部的若干个总线接口,使Cortex-M3能同时取指和访问内存。用于访问指令存储器的总线:有两条代码存储区总线负责对代码存储区的访问,分别是ICode总线和DCode总线。ICode总线用于取指,DCode总线用于查表等操作。用于访问存储器和外设的系统总线:覆盖的区域包含SRAM、片上外设、片外RAM、片外扩展设备以及系统级存储区的部分空间。用于访问私有外设的总线负责一部分私有外设的访问,主要是访问调试组件。它们也在系统级存储区。
Cortex-M3在内核水平上搭载了若干种与调试相关的特性,最主要的就是程序执行控制,包括停机、单步执行、指令断点、数据观察点、寄存器和存储器访问、性能速写以及各种跟踪机制。目前可用的访问接口包括SWJ-DP,既支持传统的联合测试工作组(Joint Test Action Group,JTAG)调试,也支持新的串行线调试(Serial Wire Debug,SWD)协议。
ARM公司是专门从事基于RISC技术芯片设计开发的公司,作为知识产权供应商,ARM公司本身不直接从事芯片生产,通过转让设计许可由合作公司生产各具特色的芯片。2004年,ARM公司推出了Cortex-M3的MCU内核。紧随其后,ST公司推出了基于Cortex-M3内核的MCU,就是STM32。STM32凭借其产品的多样化、极高的性价比、简单易用的开发方式,迅速在众多Cortex-M3内核的MCU中脱颖而出,从而被广大嵌入式产品开发者所使用。STM32系列芯片专门用于满足功耗低、处理性能强、芯片的实时性效果好、价格低廉的嵌入式场合要求,给微处理器使用者带来了广阔的开发空间,提供全新的32位产品供用户选择、使用,结合了产品性能高、能耗低、实时性强、电压要求低等特点,还具备芯片的集中程度高、方便开发的优点。
STM32系列处理器目前主要有三大类别:“基本型”系列STM32F101;“增强型”系列STM32F103;“互联型”系列STM32F105、STM32F107。
STM32F101是基本型产品系列,其处理运算频率可以达到36MHz。STM32F103是增强型产品系列,其处理运算频率可以达到72MHz,是同类产品中性能较高的产品。两个系列都内置32~128KB的FlashROM,不同的是SRAM的最大容量和外设接口的组合。当时钟频率为72MHz时,从FlashROM执行代码,STM32功耗36mA,相当于0.5mA/MHz。该系列芯片本身集成很多内部的RAM和外围设备。
STM32系列的F105和F107是该公司应用于网络通信的芯片产品,沿用增强型系列的72MHz处理频率,增加了以太网接口和USB接口。内存包括64~256KB FlashROM和2064KB嵌入式SRAM。该系列采用LQFP64、LQFP100和LFBGA100这3种封装,不同的封装保持引脚排列一致,结合STM32的设计理念,开发人员通过选择产品可重新优化功能、存储器、性能和引脚数量,以最小的硬件变化来满足个性化的应用需求。
STM32的系统架构如图1-6所示。其中,主系统主要由4个驱动单元和4个被动单元构成。4个驱动单元是DCode总线;系统(System)总线;通用DMA1;通用DMA2。4个被动单元是AHB到APB的桥(连接所有的APB设备);内部FlashROM;内部SRAM;可变静态存储控制器(FSMC)。
图1-6 STM32的系统架构
各单元之间通过如下总线结构相连。
(1)ICode总线:将Cortex-M3内核ICoed总线和闪存指令接口相连,指令的预取在该总线上完成。
(2)DCode总线:将Cortex-M3内核的DCode总线与闪存存储器的数据接口相连,常量加载和调试访问在该总线上面完成。
(3)系统总线:连接Cortex-M3内核的系统总线到总线矩阵,总线矩阵协调内核和DMA之间的访问。
(4)DMA总线:将DMA的AHB主控接口与总线矩阵相连,总线矩阵协调CPU的DCode和DMA到SRAM、闪存和外设的访问。
(5)总线矩阵:协调内核系统总线和DMA主控总线之间的访问仲裁,仲裁使用轮换算法。
(6)AHB/APB桥:这两个桥在AHB和2个APB总线间提供同步连接,APB1操作限速36MHz,APB2的最大频率是72MHz。
STM32F103系列单片机的特点如下。
(1)ARM Cortex-M3处理器核。
其主要特点如下:
● ARM32位的Cortex-M3 CPU;
● 最大频率为72MHz;
● 单周期硬件乘法和除法——加快计算。
(2)存储器。
其主要特点如下:
● 片上集成32~128KB Flash ROM;
● 6~20KB SRAM;
● 多重自举功能。
(3)时钟、复位和供电管理。
● 2.0~3.6V供电和I/O引脚的驱动电压;
● 上电/断电复位(POR/PDR)、可编程电压检测器(Programmable Votage Detector,PVD);
● 内嵌频率为4~16MHz高速晶体振荡器;
● 内嵌经出厂调校的频率为8MHz的RC振荡器;
● 内嵌频率为40kHz的RC振荡器;
● 内嵌锁相环PLL供应CPU时钟;
● 内嵌外部有32kHz晶体的RTC振荡器。
(4)低功耗。
● 3种省电模式,包括睡眠、停机和待机模式;
● VBAT为RTC和后备寄存器供电。
(5)STM32F10x的一些外围构成。
● 3个12位模数转换器,1μs转换时间(16通道),转换范围是0~3.6V,双采样和保持功能,温度传感器;
● 7通道DMA控制器;
● 多达80个快速I/O口,26、36、51、80个多功能双向5V兼容的I/O口,所有I/O口可以映射到16个外部中断。
(6)多达11个定时器。
● 4个16位定时器,每个定时器有4个IC、OC、PWM或脉冲计数器;
● 2个16位的6通道高级控制定时器,最多6个通道可用于PWM输出;
● 2个看门狗定时器(独立看门狗和窗口看门狗);
● SysTick定时器,24位倒数计数器;
● 2个16位基本定时器,用于驱动DAC。
(7)多达13个通信接口。
● 多达2个I2C接口(SMBus/PMBus);
● 多达3个USART接口,支持ISO7816、LIN、IrDA接口和调制解调控制;
● 多达2个SPI(18Mbit/s);
● CAN接口(2.0B);
● USB 2.0全速接口;
● 串行线调试(SWD)和JTAG接口。
STM32类似一个人的生命系统,而时钟系统就像人的心脏,也像CPU的“脉搏”,是STM32不可或缺的一部分。STM32既有高速外设又有低速外设,各外设工作频率不尽相同,所以需要分频,把高速设备和低速设备分开管理;另外,同一电路,时钟频率越高功耗越大,抗电磁干扰能力越弱,会给电路设计带来困难,考虑到电磁兼容需要倍频。因此,较复杂的MCU一般采用多时钟源的方法解决这些问题,并为每个外设配备外设时钟开关,在不使用外设时将其时钟关闭,以降低功耗。
在STM32中,有4个最重要的时钟源,分别为LSI、LSE、HSI、HSE。
(1)低速内部时钟(LSI):由内部RC振荡器产生,提供给实时时钟模块(RTC)和独立看门狗。
(2)低速外部时钟(LSE):以外部晶振作为时钟源,主要将其时钟信号提供给实时时钟,一般采用32.768kHz的频率。
(3)高速内部时钟(HSI):由内部RC振荡器产生,频率为8MHz,但不稳定,可以直接作为系统时钟或者PLL输入。
(4)高速外部时钟(HSE):以外部晶振作为时钟源,晶振频率可取4MHz~16MHz,一般采用8MHz的晶振频率;也可直接以系统时钟或者以PLL输入的外部高速时钟为例来分析,并假设外部晶振频率为8MHz。如图1-7所示,从左端的OSC_OUT和OSC_IN开始,这两个引脚分别接外部晶振的两端。频率为8MHz的时钟信号遇到第一个分频器PLLXTPRE,通过寄存器配置,对输入时钟信号进行二分频或不分频。假定选择不分频,经过PLLXTPRE后,频率仍为8MHz。然后遇到开关PLLSRC,可以选择其输出为外部高速时钟HSE或是内部高速时钟HSI。这里选择输出为HSE,接着遇到锁相环PLL(具有倍频作用),在这里可以输入倍频因子PLLMUL。如果倍频因子设定为9倍频,那么经过PLL之后,时钟从原来频率为8MHz的
图1-7 STM32单片机时钟树
HSE变为频率为72MHz的PLLCLK。紧接着为一个开关SW,经过此开关输出的是STM32的系统时钟SYSCLK,此开关用来选择SYSCLK的时钟源,可选择HSI、PLLCLK、HSE。这里选择PLLCLK,SYSCLK的频率就为72MHz。SYSCLK的信号经过AHB预分频器,分频后输入其他外设,如AHB总线、核心存储器、DMA、SDIO、存储器控制器FSMC,可作为APB1和APB2预分频器的输入端及作为Cortex自由运行时钟的FCLK。本例中设置AHB预分频器不分频,即输出信号的频率为72MHz。另外PLLCLK的信号在输入开关SW前,流向了USB预分频器,该分频器输出为USB外设的时钟(USBCLK)信号。
从上面时钟树可看到,经过一系列的倍频、分频后得到了几个与开发密切相关的时钟信号。
(1)SYSCLK:系统时钟,STM32大部分器件的时钟源,主要由AHB预分频器分配到各个部件。
(2)HCLK:由AHB预分频器直接输出得到,提供AHB总线、核心存储器、DMA及Cortex内核的时钟信号。HCLK是Cortex内核运行的时钟,即CPU主频,该数值的大小与STM32的运算速度、数据存取速度密切相关。
(3)FCLK:同样由AHB预分频器输出得到,是Cortex的“自由运行时钟”。“自由”表现在它不来自时钟HCLK,因此不受HCLK影响,它的存在可保证处理器休眠时也能够采样和跟踪到休眠事件,与HCLK同步。
(4)PCLK1:外设时钟,由APB1预分频器输出得到,最大频率为36MHz,提供给挂载在APB1总线上的外设。
(5)PCLK2:外设时钟,由APB2预分频器输出得到,最大频率为72MHz,提供给挂载在APB2总线上的外设。
外部时钟源在精度和稳定性上有很大优势,上电后需通过软件配置,才能采用外部时钟信号。内部时钟起振较快,在芯片刚上电时,默认使用内部高速时钟。
编写单片机应用程序使用的C语言与标准C语言有区别。用C语言编写单片机应用程序时,需根据单片机存储结构及内部资源定义相应的数据类型和变量,而用标准C语言编写程序不需要考虑这些问题。
STM32单片机C语言编程时,包含的库函数、数据类型、变量的存储模式、输入/输出处理等方面与标准C语言有一定的区别。其他的语法规则、程序结构及程序设计方法等与标准C语言的相同。
具体区别如下。
(1)STM32定义的库函数和标准C语言定义的库函数不同。标准C语言定义的库函数是按通用微型计算机来定义的,而STM32编程中的库函数是按STM32单片机相应情况来定义的。
(2)STM32编程中的数据类型与标准C语言的数据类型也有一定的区别,增加了几种STM32单片机特有的数据类型。
(3)STM32编程中的变量存储模式与标准C语言中变量的存储模式不一样,其存储模式与STM32单片机的存储器紧密相关。
(4)STM32编程中的输入/输出处理与标准C语言的不一样,前者的输入/输出是根据不同的操作来设定的。
编程过程中,不同的MCU或编译器的数据类型的意义各不相同,所以一定要注意相应变量数据类型的定义和转换,否则在程序编译时会出错。
STM32的开发环境MDK的基本数据类型如表1-2所示。
表1-2 MDK的基本数据类型
数据类型 |
关键字 |
长度/B |
---|---|---|
字符型 |
char |
1 |
短整型 |
short int |
2 |
整型 |
int |
4 |
长整型 |
long int |
4 |
单精度浮点型 |
float |
4 |
双精度浮点型 |
double |
8 |
另外,为了使用方便,MDK还进行了数据类型的定义,如表1-3所示。
表1-3 MDK定义的新数据类型
原类型 |
新类型 |
含义 |
---|---|---|
unsigned char |
uint8 |
无符号8位字符型 |
signed char |
int8 |
有符号8位字符型 |
unsigned short |
uint16 |
无符号16位短整型 |
signed short |
int16 |
有符号16位短整型 |
unsigned int |
uint32 |
无符号32位整型 |
signed int |
int32 |
有符号32位整型 |
float |
fp32 |
单精度浮点型(32位长度) |
double |
fp64 |
双精度浮点型(64位长度) |
STM32采用了大量的固件库,保存在V3.5库的stm32f10x.h文件中,同时有自己的数据类型定义。STM32库中的数据类型定义如表1-4所示。
表1-4 STM32库中的数据类型定义
类型 |
符号 |
长度/B |
数据范围 |
有符号整型 |
s8 |
1 |
−27~(27−1) |
s16 |
2 |
−215~(215−1) |
|
s32 |
4 |
−231~(231−1) |
|
int64_t |
8 |
−263~(263−1) |
|
无符号整型 |
u8 |
1 |
0~28 |
u16 |
2 |
0~216 |
|
u32 |
4 |
0~232 |
|
uint64_t |
8 |
0~264 |
STM32也使用float和double表示负数和小数。其中,float至少能精确表示到小数点后6位,double至少能精确表示到小数点后10位。在编程过程中,不同CPU的数据类型的意义各不相同,所以一定要注意相应变量数据类型的定义和转换,否则在计算中可能会出现不确定的错误。在C语言中,不同类型的数据是可以混合运算的。在进行运算时,不同类型的数据要先转换成同一类型的数据,然后进行运算。数据类型转换规则如图1-8所示。其中,箭头的方向只表示数据类型级别的高低,按照箭头所指的方向由低向高转换,这个转换过程是“一步到位”的,分为两种方式:隐式转换(编译软件自动完成)和显式转换(程序强制转换)。
图1-8 数据类型转换规则
(1)字符型数据必须先转换为整型数据(C语言规定字符型数据和整型数据之间可以通用)。
(2)short型数据转换为int型数据(同属于整型)。
(3)赋值时,一律是赋值符号右部值转换为赋值符号左部类型。其中,当整型数据和双精度浮点型数据进行运算时,先将整型数据转换成双精度浮点型数据,再进行运算,结果为双精度浮点型数据;当字符型数据和实型数据进行运算时,先将字符型数据转换成实型数据,然后进行计算,结果为实型数据。
例如:
(int)(x+y);//将(x+y)转换为int
其中,进行强制类型转换时,我们会得到一个所需要的中间变量,原来变量的类型未发生变化。
这里主要介绍STM32编程中常用的几个C语言基础知识点。
位操作是对基本类型变量在位级别进行的操作。C语言支持6种位操作,如表1-5所示。
表1-5 C语言支持的位操作
运算符 |
含义 |
|
运算符 |
含义 |
---|---|---|---|---|
& |
按位与 |
|
~ |
取反 |
| |
按位或 |
|
<< |
左移 |
^ |
按位异或 |
|
>> |
右移 |
在STM32开发中的位操作有一些实用技巧,如下所述。
● 对指定位进行设置。
在不改变其他位的值的情况下,对一位或某几位进行设置。这种方法是先对需要设置的位用“&”操作符进行清0操作,然后用“|”操作符设置值。
对GPIOA的状态修改,先对寄存器CRL的值进行清0操作。
GPIOA->CRL&=0XFFEFFFE0;//将第0~3位清0
然后,与需要设置的值进行或运算。
GPIOA->CRL|=0X00000004;//设置第2位的值,不改变其他位的值
● 移位操作提高代码的可读性。
例如,一个固件库的GPIO初始化的函数里面的代码为GPIOx→BSRR=(((uint32 t)0x01)<<5),下面是直接设置一个固定的值:
GPIOx-> BSRR =0x0020
两者相比,可以直观地看出,将寄存器BSRR的第5位设置为1,能提高代码的可读性。
● 使用“~”取反操作提高可读性。
寄存器SR的每一位代表一个状态,有时需要设置某一位的值为0,同时其他位都保留为1。例如,设置第3位为0,可以直接参考以下代码:
TIMx->SR = OxFFF7
也可以使用库函数代码:
TIMx->SR = (uint32_t)~TIM_FLAG_Update;
TIM FLAG通过宏定义来定义:
#define TIM_FLAG_Update ((uint32_t)0x0008)
从宏定义中可以看出,利用TIMFLAG Update设置第3位为0,可读性非常强。
● define宏定义。
define是C语言中的预处理命令,用于宏定义可以提高源代码的可读性,为编程提供方便。常见的格式如下:
# define标识符字符串
“标识符”为所定义的宏名,“字符串”可以是常数、表达式、格式串等。例如:
#define SYSCLK FREQ 8MHz 8000000
定义标识符SYSCLK_FREQ_8MHz的值为8000000。
● ifdef条件编译。
在STM32程序开发过程中,经常会遇到一种情况,当满足某条件时对一组语句进行编译,而当条件不满足时编译另一组语句。这时需要使用条件编译命令,常见形式为:
# ifdef标识符
程序段1
#else
程序段2
#endif
条件编译的作用是,当标识符已经被定义过(一般是用# define定义),则对程序段1进行编译,否则编译程序段2。其中,#else部分也可以没有,即:
#ifdef程序段1
#endif
这个条件编译在STM32开发环境MDK里面用得很多,例如,在stm32f10x.h这个头文件中经常会看到这样的语句:
#ifdef STM32F10X_MD
<中容量芯片需要的一些变量定义>
#end
在需要引入<中容量芯片需要的一些变量定义>时,在代码中加入“# define STM32F10X_MD”编译预处理命令即可,否则忽略对其的编译。条件编译编程技巧在STM32中使用得较多,有必要熟练掌握。
C语言中extern可以置于变量或者函数前,以表示变量或者函数的定义在其他文件中。编译器遇到此变量和函数时,在其他模块中寻找其定义。可以多次用extern声明变量,但定义只有一次。例如,在main.c定义全局变量u8 USART_RX_STA:
u8 USART_RX_STA;//变量定义
如果同一个工程中包含test.c文件,可以写一个声明语句将该变量引入并使用:
extern u8 USART_RX_STA;//声明变量,可以多次声明
void test(void)
{
printf("%d", USART_RX_STA)
}
typedef用于为现有类型创建一个新的名字,或称为类型别名。定义类型别名后,就可以用类型别名代替数据类型说明符对变量进行定义。类型别名可以用大写字母,也可以用小写字母,为了区别一般用大写字母表示。在MDK中用得最多的就是定义结构体的类型别名和枚举类型。例如如下结构体类型定义:
struct _GPIO
{
__IO uint32_t CRL;
__IO uint32_t CRH;
};
定义该类型变量的方式为:
struct _GPIO GPIOA;//定义结构体变量GPIO
MDK中有很多这样的结构体变量需要定义,可以为结构体定义一个类型别名GPIO_TypeDef,在使用时可以通过GPIO_TypeDef来定义结构体变量:
typedef struct
{
__IO uint32_t CRL;
__IO uint32_t CRH;
}GPIO_TypeDef; //结构体类型别名定义
GPIO_TypeDef GPIOA, GPIOB;//结构体变量
这里,GPIO_TypeDef与struct _GPIO的作用是等同的。
MDK中很多地方使用结构体以及结构体指针。结构体就是将多个变量组合为一个有机的整体。结构体的使用方法是:先声明结构体类型,再定义结构体变量,最后,通过结构体变量引用其成员。
结构体类型声明形式如下:
struct结构体名
{
成员列表;
};
结构体变量定义形式如下:
struct结构体变量名列表;
例如:
struct U_TYPE
{
int BaudRate;
int WordLength;
};
struct U_TYPE usart1, usart2, *usart3;
也可以在结构体声明的时候直接定义变量和指针。
结构体成员变量的引用方法如下:
结构体变量名.成员名
结构体指针名->成员名
例如要引用usart1的成员BaudRate,方法如下:
usart1.BaudRate;
usart1->BaudRate;
在STM32程序开发过程中,经常会遇到要初始化一个外设(如串口),它的初始化状态是由几个属性来决定的,如串口号、波特率、极性以及模式。不使用结构体的初始化函数形参列表的形式如下:
void USART_Init(u8 usartx, u32 BaudRate, u8 parity, u8 mode);
如果需要增加一个入口参数,需要进行如下修改:
void USART_Init(u8 usartx, u32 BaudRate, u8 parity, u8 node, u8 WordLength)
函数的入口参数随着开发不断地增多,就要不断地修改函数的定义。使用结构体就能解决这个问题:只需要改变结构体的成员变量,就可以达到改变入口参数的目的。
参数BaudRate、WordLength、StopBits、Parity BardwareFlowControl对于串口而言,是一个有机整体,可以将其定义成一个结构体。MDK中是这样定义的:
typedef struct {
uint32_t USART BaudRate;
uint16_t USART WordLength;
uint16_t USART StopBits;
uint16_t USART_ Parity;
uint16_t USART_ BardwareFlowControl;
}USART_InitTypeDef;
这样,初始化串口的时候,入口参数可以使用 USART_InitTypeDef类型的变量或者指针变量,MDK中是这样做的:
void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART Initstruct);
其中,USART_TypeDef和USART_InitTypeDef是两种结构体类型。在结构体中加入新的成员变量,就可以达到修改入口参数同样的目的,不用修改任何函数定义,同时可以提高代码的可读性。
受到简洁的C语言入门程序范例的影响,初学者往往将所有的代码都写在一个C文件中。这是一个非常坏的习惯。当程序逐渐变长,编辑、查找和调试就将变得非常困难。而且这种代码很难用在别的项目中,除非仔细地理顺函数关系,然后寻找并复制每一段函数。
一种合理的方法是将一个大程序划分为若干个小的C文件。在单片机程序中,最常用的划分方法是按照功能模块划分,将每个功能模块做成独立的C文件。例如某个项目中用到模数转换器、串行端口、数码管、按键,可以据此划分为4个文件:ADC.c、Uart.c、Seg.c、Key.c。属于每个功能模块的函数写在相应的文件中,然后在相应的头文件中声明对外引用的函数与全局变量。
做好文件划分与管理后,每个文件都不会很长。如果需要修改或调试某个函数,打开相应模块的C文件,很容易找到;打开相应的头文件还可以查看函数列表。
下面用一个简单的例子说明模块对应的C文件与其头文件的关系。
假设编写一个数据处理功能模块DataProcess.c文件,其中包含两个功能函数:求和函数与求平均值函数。
新建DataProcess.c文件并将其添加进工程,编写两个功能函数的代码:
int Sum(int a,int b,int c) //对3个数据求和的函数
{
int y;
y = a + b + c;
return y;
}
float Average(int a,int b,int c) //对3个数据求平均值的函数
{
float y;
y = a + b + c;
return (y/3);
}
假设在main.c文件内的某函数需要调用DataProcess.c文件内的两个函数,需要在main.c文件开头用extern关键字声明外部函数,告诉编译器这两个函数属于其他文件。
extern int Sum(int a,int b,int c); //声明Sum()是外部函数
extern float Average(int a,int b,int c); //声明Average()是外部函数
为了避免重复劳动,可以创建DataProcess.h头文件,将上述两句代码写入头文件,在main.c文件开头处包含“DataProcess.h”,就相当于做了函数声明。
按照上面的方法,在编写程序时,为每个功能模块都写一个C文件和一个同名的头文件。在C文件内写代码,将函数声明集中写在相应的头文件内。若在FileA文件中需要调用FileB文件内的函数,只需在FileA文件的开头添加#include “FileB.h”即可。
图1-9给出一个按照此规则创建的一个项目工程文件示意。
图1-9 项目工程文件示意
对于可能被多个功能模块访问到的全局变量,也可以通过头文件中的extern声明对外引用。例如,各个C文件中都会用到的系统级的全局变量,可以单独放到global.c文件中:
int AlarmValue; //报警阈存放变量
unsigned int SystemStatus; //系统状态存放变量
再写一个global.h文件,将这些全局变量对外引用:
extern int AlarmValue; //报警阈值存放变量
extern unsigned int SystemStatus; //系统状态存放变量
之后在任何C文件中,如果需要调用这些全局变量,只需要在文件开头处包含global.h头文件即可。这种方法的好处是只要文件包含global.h头文件,就可以访问所有的全局变量,但有可能会破坏程序的结构性和模块的独立性。例如多个文件中会用到上例中的AlarmValue变量,这几个文件都必须通过global.c文件访问该变量,所以这多个文件之间有了额外的关联,在以后其他工程中重复使用时不能独立出来,必须重写global.c文件。
访问全局变量的第二种方法就是:全局变量隶属于哪个模块,就写在哪个C文件中,然后在相应的头文件中用extern声明对外引用。例如OverflowFlag全局变量是前例中求和函数模块中的全局变量,用于指示加法运算溢出。这个全局变量应该隶属于DataProcess.c文件。在DataProcess.c文件中写函数体,并声明OverflowFlag全局变量:
unsigned char OverflowFlag;
int Sum(int a,int b,int c) //3个数据求和函数
{
int y;
y = a + b + c;
if (y > 65535) OverflowFlag = 1;
return y;
}
然后在DataProcess.h文件中声明求和函数与全局标志变量:
extern unsigned char OverflowFlag; //加法溢出标志全局变量
extern int Sum(int a,int b,int c); //声明Sum()是外部函数
这种方法的好处是结构清晰,以后重复使用这个模块时,包含该模块的头文件,则不仅包含功能函数的声明,还包含相关的全局变量。但是对于一些隶属关系模糊的变量,特别是各个文件都会用到的系统级变量,例如系统状态、警告标志等,不好将其归类。即使强行将其归类到某个模块,很可能因为难以记忆该变量属于哪个头文件而给下次重复使用带来困难,所以工程中一般将这两种方法结合起来。隶属关系明确的全局变量一般写在相应模块的C文件中,系统级或各个模块都需要访问的全局变量,一般写到公共文件global.c中。
第三种方法是使用函数来访问全局变量。可以通过GetOverflowFlag()函数来读取溢出标志全局变量;通过ClrOverflowFlag()函数来清除溢出标志。
unsigned char OverflowFlag; //加法溢出标志全局变量
int Sum(int a,int b,int c) //对3个数据求和的函数
{
int y;
y = a + b + c;
if (y > 65535) OverflowFlag = 1;
return y;
}
char GetOverflowFlag() //访问OverflowFlag标志
{
return OverflowFlag;
}
void ClrOverflowFlag() //清除OverflowFlag标志
{
OverflowFlag = 0;
}
然后在DataProcess.h中声明这些函数:
extern int Sum(int a,int b,int c); //声明Sum()是外部函数
extern char GetOverflowFlag() //访问OverflowFlag标志
extern void ClrOverflowFlag() //清除OverflowFlag标志
这种方法可以让全局变量仅存在于每个功能模块的内部,不对外暴露。该方法的结构性和安全性最好,但代码的执行效率较低,对于访问频繁的操作来说,步骤烦琐。
文件的划分和管理方便了阅读和调试,建议初学者养成文件管理的习惯,即使对于简单的程序,最好也要按模块划分和管理文件,这对以后提高工作效率有很大的帮助。
在嵌入式开发领域,软件的投入在不断提高,相反硬件的投入却逐年降低,如图1-10所示。因此嵌入式领域的公司,越来越多地把精力放到了软件上,但软件在芯片更换或是开发工具的更新换代中,其代码的重用性不高,随着Cortex-M处理器大量进入市场,ARM公司意识到建立一套软件开发标准的重要性,Cortex微控制器软件接口标准(Cortex Microcontroller Software Interface Standard,CMSIS)应运而生。
图1-10 软件与硬件开发成本对比
CMSIS是ARM和一些编译器厂商以及半导体厂商共同遵循的一套标准,是由ARM公司提出的,专门针对Cortex-M系列的标准。在该标准的约定下,ARM公司和芯片厂商会提供一些通用的应用程序接口(Application Program Interface,API)来访问Cortex内核以及一些专用外设,以减少更换芯片以及开发工具等移植工作所带来的金钱以及时间上的浪费。只要都是基于同样内核的芯片,代码均是可以复用的。
如图1-11所示,CMSIS可以分为以下3个基本功能层:
● 核内外设访问层(Core Peripheral Access Layer,CPAL);
● 中间件访问层(Middleware Access Layer,MWAL);
● 设备外设访问层(Device Peripheral Access Layer,DPAL)。
图1-11 基于CMSIS软件架构
下面将对CMSIS层次结构进行剖析。
CPAL用来定义一些Cortex-M处理器内部的一些寄存器地址以及功能函数,如对内核寄存器、NVIC、调试子系统的访问。一些对特殊用途寄存器的访问被定义成内联函数或是内嵌汇编的形式。该层由ARM实现。
MWAL定义中间件的一些通用API,该层也由ARM负责实现,但芯片厂商需要根据自己的设备特性进行更新。
DPAL和CPAL类似,用来定义一些硬件寄存器的地址以及对外设的访问函数。另外芯片厂商还需要对异常向量表进行扩展,以实现对自己设备的中断处理。该层可引用CPAL定义的地址和函数,该层由具体的芯片厂商提供。
通过以上3个层次的划分,芯片厂商能根据自己特性外设的差异化,提供专业的服务,以简化程序的开发,达到高速、低成本的开发目的。
不同芯片的CMSIS的头文件是有区别的,但是结构基本是一致的,图1-12所示为STM32系列微处理器的CMSIS头文件结构。
图1-12 CMSIS头文件结构
其中,stdint.h文件包含对8位、16位、32位等数据类型指示符的定义,主要用来屏蔽不同编译器之间的差异。core_cm3.h文件中包含了Cortex-M3的全局变量的声明和定义,并定义了一些静态功能函数。system_stm32f10x.h是不同芯片厂商定义的包含系统初始化函数以及一些系统时钟的定义配置和时钟变量等的文件。虽然CMSIS提供的文件比较多,但用户在编写应用程序过程中可以只写入stm32f10x.h文件即可。
(1)单片嵌入式系统通常包括 、 、 三大部分。
(2)Cortex-M3处理器是一个 位的处理器。
(3)STM32系列处理器目前主要有 、 、 三大类别。
(1)什么是嵌入式系统?什么是单片机?什么是ARM?
(2)ARM微处理器分为三大系列吗?这三大系列各有什么特点?
(3)列举出三种以上的单片机厂商和单片机型号。
(4)在STM32中,4个重要的时钟源是什么?
(5)什么是CMSIS?为什么要使用CMSIS?