感谢面包板社区与人民邮电出版社,非常荣幸能够参与这本《32位单片机C语言编--基于PIC32》的评测,先给大家看看这本书的封皮:

图1 封面
这本书的作者名为Luico Di Jasio,是一位研究嵌入式系统开发的资深工程师,值得一提的是虽然书名为“C语言编程”,但是从书中的内容及结构可以看出,作者是一位十分钟爱于汇编语言的程序员。
图2 目录
下面言归正传,回到这本书的内容上来,作者以C语言作为开发语言,对32位PIC单片机的结构、开发流程以及片上外设进行了详细的介绍。C语言大家都比较熟悉,但是对于ARM结构单片机普及流行的今天,有必要简单介绍这本书的主角--PIC单片机的一些背景情况,PIC单片机是美国微芯公司(Microchip)的产品,有8位、16位及32位三种类型的单片机,书中介绍的型号为PIC32MX360FJ512L,属于32位单片机中的一种。PIC单片机属于RISC类型结构,与其他类型的MCU相比,其具有指令集简洁、简单易学、速度高、功能强、功耗低、价格低廉、体积小巧、适用性好及抗干扰能力强等特点,目前大量应用于汽车电气控制、电机控制、工业控制仪表、通信、家电、玩具、低功耗的测控应用等领域,在国内越来越受到广大设计者的欢迎,微芯公司的单片机已经成为目前单片机世界的主流产品。
PIC32位单片机相关特性如下:
1、带5级流水线的MIPS32 M4K 32位内核;
2、80 MHz最大频率;
3、1.56 DMIPS/MHz(Dhrystone 2.1)0等待状态下的闪存访问性能;
4、单周期乘法和高性能除法单元;
5、MIPS16e模式,代码大小可缩小40%;
6、两组32核寄存器文件(32位),以减少中断延迟;
7、预取高速缓存模块以加快闪存的执行速度。
通用的PIC32单片机的结构如图3所示:
图3 PIC32单片机机构
其拥有多达4通道硬件DMA,可自动检测数据大小;可兼容USB 2.0的全速设备和移动(OTG)控制器;USB有一个专用的DMA通道;外部可接3MHz至25MHz晶体振荡器;内部8MHz和32 kHz振荡器;CPU和USB配有独立PLL;两个I2C模块;两个UART模块,支持RS-232、RS-485和LIN,且均带有片上硬件编码器和解码器;最多两个SPI模块;并行主从端口,支持8位和16位数据线及16条地址线;硬件实时时钟和日历(RTCC);五个16位定时器/计数器(两个16位对组合在一起形成两个32位定时器);五个捕获输入;五个PWM调制输出;五个外部中断引脚;高速I/O引脚,可在高达75 MHz的频率下切换;高达16通道10位模拟到数字转换器;两个模拟比较器,PIC32位的不同MCU之间其外设及存储空间略有不同,用户可根据自己需要选择合适的型号。
《32位单片机C语言编程》这本书分为三个部分来介绍PIC单片机开发,分别是“探索”、实践”及“扩展”,以下我也按照这三个方面将本书的主要内容结合自己的学习体会进行介绍:
1、探索
这一部分首先介绍了PIC单片机C语言开发的一些必备基础软件,包括:
1、MPLAB IDE,免费的集成开发环境
2、MPLAB SIM,免费的软件仿真器(包含在MPLAB中)
3、MPLAB C32,C编译器(免费的学生版)
这些均可在官网下载: www.microchip.com/PIC32。
在MPLAB编程中,作者主要介绍了软件中程序编译的方式,并以PIC单片机的GPIO模块为例,建立并编译了一个类似于“Hello world!”工程,带领读者熟悉MPLAB环境。由于MPLAB环境与KEIL环境十分相似,因此其具体使用方法这里就不再展开叙述,有兴趣可参照百度百科https://jingyan.baidu.com/article/4b07be3c9a886948b380f31f.html中介绍的使用方法,以下根据书中内容对MPLAB种编译过程做一介绍。

图4 MPLAB程序编译过程
图4是MPLAB中从源程序到可执行程序的过程,与大多数CPU类似,都需要经过编译、链接两个过程,编译是生成相应的可重定位的目标文件,链接则是为不同的程序内容分配合适的存储空间,并最终输出二进制可执行文件。在GPIO的应用实验中,与我们最初学习的51单片机不同,PIC的IO口需要配置输入输出类型,将输入输出寄存器相应位配置为0时是输出模式,为1时则相反,而后便可以检测引脚输入电平或者输出高低电平。在初步了解了PIC32单片机的GPIO后,作者循序渐进的介绍了C语言的基本语法:While & for循环、数组、算数操作以及C语言中的变量类型,在讲解语法的过程中,辅助以PIC32的GPIO及定时器模块,理论与实践相结合,增加学习乐趣。做为单片机的一个重要外设,这里有必要介绍一下PIC32的定时器模块。

图5 定时器模块结构图
对于PIC32MX360FJ512L来说,如图5所示控制定时器需要三个寄存器即可:TMR1(存放16位计数值),TLCON(用于配置定时器工作模式),PR1(用于产生周期性的定时器复位信号),使用还是十分简洁方便的。在介绍完基本的C语言语法及PIC32后,作者介绍了PIC32的中断,中断是实时控制中的重要技术,它使得应用系统能够处理异步的外部事件,在PIC32中所有的中断都可以看成是异常(Exception),其异常向量表如下:

图6 异常向量表
其中中断包括以下中断源:
1、外部引脚中断
2、与变更通知模块相连的外部引脚
3、输入捕获模块
4、5个输出比较模块
5、2个串行通信接口
6、4个同步串行通信接口(SPI与I2C)
7、1个并行主控端口
8、定时器中断
9、模数转换器
10、模拟比较
11、时钟与日历
12、Flash控制器
13、时钟监视器
14、软中断
15、DMA通道
上述中断均可以设置中断优先级,并且支持中断嵌套,其中断入口函数可以定义如下:
#pragmainterrupt InteruptHandler ipla vector 0 //ipla为优先级
void InterruptHandler(void){
//中断程序
}
对于具体的中断寄存器的配置方法,PIC提供了相应的C语言库“int.h”,因此操作还是十分方便的,这里也就不展开说了。对于一个MCU来讲,除丰富的片上外设拓展性能外,其内部存储也十分重要,对此作者介绍了PIC32的存储空间的分配。

图7 存储分配
PIC32的内存可以分为虚拟内存与实际物理内存,从图7可以看出,RAM的起始地址是0x0,而Flash的存储地址是从0x1D000000开始的,所有的外围设备都位于从0x1F800000开始的单元内,还有一部分12Kb的Flash存储器的地址则起始于0x1FC00000,是boot程序,固化在ROM中的。在此可以发现为防止错误编程危害到应用程序,设计者对不同的存储器做了相应的隔离,而且FMT将所有的物理地址映射为了相应的虚拟地址,以供用户及MIPS的处理器分开使用。
2、实践
作者在第1部分主要是回顾了C语言及PIC32单片机的基础知识,在第2部分中便可以对单片机操作复杂一点的外设了,首先是PIC的时钟,其时钟可由5个振荡器/时钟源提供:
1、内部振荡器:可提供8MHz的时钟,精度在2%之内;
2、内部低频低功耗振荡器:用于低功耗模式,需要外部提供32kHz的时钟;
3、外部主振荡器:可接外部高速高精度晶振;
4、外部低频低功耗振荡器:用于低功耗模式,与外部32768Hz晶体相接;
5、外部时钟源:为单片机输入任意频率的方波输入信号。

图8 时钟结构
总结起来,其低频时钟主要用于低功耗模式,高频是用于正常工作模式,在与内部的PLL配合后,可以产生满足不同适应场景的晶振频率(最高75MHz)。之所以使用如此多的时钟源一个重要的目的在于降低功耗,在时钟方面其控制功耗采取的方法包括,可以实时切换内部和外部振荡源;实时控制时钟分配器;实时控制PLL电路;空闲模式CPU停止,只有个别外设运行;休眠模式下所有外设与CPU停止,等待唤醒,优良的低功耗性能也是PIC单片机的一个主要优势。此外为进一步提高运算性能,书中还介绍可以配置Flash的等待状态,打开指令与数据缓存,打开预取指令功能,应用Cache缓存来提高运算速度,经过以上这些调整一个初始运行需要170.62ms的FFT程序可以降低到16.45ms。
在了解了时钟设置与优化程序性能的设置后,作者介绍了PIC32单片机支持的3种通用的串行通信方式,包括UART、IIC、SPI,与其他单片机的串行外设相比,PIC单片机中这些外设并没有改变多少结构功能,仅需配置相应的控制寄存器即可,相信面包板社区的小伙伴们对于这几种通信方式都十分熟悉,这里也就不展开说了。除这三种通信外设外,作者介绍了使用PIC单片机如何来驱动一块HD44780控制器控制的LCD,与我们常见的LCD1602、12864类似,HD44780系列LCD也需要经过初始化,清除屏幕,写入配置,写入数据等操作,这些操作有PIC专用的函数库,十分方便。
PIC32众多外设中一个十分亮眼的外设莫过于其拥有多达16路输入的模数转化装置,这是一般的MCU所不具备的,其10位ADC输出的数字量可以存储在一个32位宽,16位深的FIFO中,对于需要操作众多模拟传感器的用户来说是一个福音。

图9 ADC结构
以上便是实践部分所介绍的基本内容。
3.扩展
实践部分介绍了PIC32MX的一些关键硬件外围设备模块,在扩展部分则将会介绍一些高级外围设备。
高级外设往往离不开对输入信号的响应,MCU中常见的输入信号当属按键,对于按键的检测我最早也是在郭天祥的《十天学会单片机》教程中才知道并不仅仅检测高低电平,还需要去抖处理,即在按键按下时需要多次检测电平变化,而且最好是在松手时处理响应,这样这样几乎可以完全避免机械按键的抖动。另一种类似按键的设备是编码器,对于参加过飞思卡尔以及玩过平衡小车的小伙伴一定不会陌生,因为要想使小车保持平衡,需要使用编码器实时获取速度与位置反馈数据,对于这一模块,作者从实用的角度出发,提供了旋转编码器的驱动程序。在日常使用中,比上述两种输入设备更高级的莫非是键鼠了,对于键盘接口,无非是USB与PS/2两种,对此这本书中介绍了PS/2协议的相关原理,并利用捕获模块、变更通知模块及IO轮询实现了PS/2协议,以此来接收键盘的数据流并进行解码,这个项目可以让读者充分熟悉PIC32的中断运行机制。

图10 PS/2接口定义
有了输入设备后,我们需要一个显示装置以便于进行交互,这让我们想起在第二部分中所操作的LCD显示屏,这个屏幕最大的特点在于有一个集成的控制器,我们只需使用PIC单片机与控制器进行命令交互即可控制LCD的显示内容,在方便使用的同时也限制了很多拓展功能,例如我们想完全控制屏幕产生动画效果,集成控制器往往爱莫能助,对此作者专门介绍了如何与任意可以接收标准复合视频信号的显示设备相连接的方法。

图11 视频图像扫描方式
如图11所示为视频图像的扫描方式,图像缓存中存放有不同位置的像素点的亮度信息,显示时在按照逐行的方式扫描到屏幕上,由于扫描的速度很快,每秒接近25帧图像,这样我们看到的便是一个动态的视频信息了。

图12 视频信号
所谓复合信号就是指传输信号是由亮度信号及水平与垂直同步信息三种信号组成,其传输信号如图12所示,在每一帧的开始,会传输一个同步信号(Sync),而后才是水平与垂直图像信息。 为产生这一信号,作者利用了PIC自带的输出比较器模块,与此同时利用DMA模块建立显示器与存储器之间的数据交互,接触过DMA的小伙伴一定知道,DMA工作在全系统时钟频率下,并且可以同时执行多个任务,非常适合类似于图像数据这种大容量高速数据的传输,最后利用状态机实现了图像的显示与绘制,在将这些函数封装为库后,作者使用这些函数绘制了一些复杂的图像,如图13,并实现了文字的书写,总体来说这一部分相当于作者用PIC32单片机实现了一个显示屏控制器,这是在以往介绍MCU应用的书中所不多见的。

图13 绘制的二维及三维图像
在实现图像显示的过程中不免会涉及到图像信息的存储与提取,我们会将缓冲的图像信息预先存到RAM中去,以便随时调用读取,对于嵌入式MCU来讲,片上的内存十分有限,因此相当宝贵,图像信息往往容量又相对较大,这会限制处理器其他功能的使用,对此作者介绍了存储卡与PIC32进行数据交互的方法,存储卡往往可以使用SPI协议进行操作,因此这一部分作者实际使介绍了SPI的使用方法。为方便读者管理SD卡,作者还对如何在SD卡中创建操作文件进行了介绍,包括扇区,簇,如何打开关闭文件,如何向文件写入数据等等,十分详尽并配有详细的代码。

图14 PIC单片机与SD卡连接方式
在书的最后,作者则介绍了一款音乐播放器,这款音乐播放器的一个特点在于无需借助外部语音芯片或者DA转换器,而是直接通过解析WAV格式的语音数据,使用了PWM及一个简易的外部滤波器输出到扬声器来产生声音信号,这是我之前所没有见过的。

图15 PWM占空比示意图

图16 PWM频谱图像
PWM信号的频谱特性如图16所示,由其频谱特性可知,其含有一个直流分量,振幅与占空比成正比;一个基频分量,频率与PWM相同;无穷多个谐波分量,其频率时基频的倍数,因此当将PWM信号接入一个低通滤波器,其将只留下一个直流分量,该直流分量的大小又与PWM的占空比相关,因此这实际上是用PWM与滤波器实现了一个DA转换器。作者介绍了详细的实现过程及wav格式音频的解析方法,最终完美实现了一个音乐播放器。
以上便是书中所介绍的全部内容,全书共十六章,可以说涉及了PIC32的所有外设,是一本很好的学习PIC单片机的工具书,书中的前半部分主要叙述理论,涉及到了一些CPU的工作原理,后半部分则主要从应用入手,编写了许多例程,理论与实践相结合,可以让读者不仅能快速了解PIC,同时也能快速上手使用PIC。
最后谈一下自己体会:
PIC最大的特点是不搞单纯的功能堆积,而是从实际出发,重视产品的性能与价格比,靠发展多种型号来满足不同层次的应用要求。就实际而言,不同的应用对单片机功能和资源的需求也是不同的。比如,一个摩托车的点火器需要一个I/O较少、RAM及程序存储空间不大、可靠性较高的小型单片机,若采用40脚且功能强大的单片机,投资大不说,使用起来也不方便,PIC系列从低到高有几十个型号,可以满足各种需要。
我在大二期间做的第一块开发板就是PIC的,当时使用的是PIC16F877,是PIC的一个八位单片机,年代有点久远,实物找不到了,只在电脑里找到一个PCB图,这块板子承载了满满的回忆,虽然所接的外设都比较简单,也没有做出像书中那样复杂的程序,但当我现在看到时还能想起刚拿到板子时的激动,这种感受我想面包板社区的小伙伴一定感同身受。

图17 PIC开发板
PIC单片机也有其不足之处,其专用寄存器(SFR)并不像51单片机一样都集中在一个固定的地址区间内(80-FFH),而是分散在四个地址区间内。只有5个专用寄存器PCL、STATUS、FSR、PCLATH、INTCON在4个存储体内同时出现,但是在编程过程中,少不了要与专用寄存器打交道,得反复地选择对应的存储体,也即对状态寄存器STATUS的第6位(RP1)和第5位(RP0)置位或清零。数据的传送和逻辑运算基本上都得通过工作寄存器W(相当于51系列的累加器A)来进行,而51系列的还可以通过寄存器相互之间直接传送,因而PIC单片机的瓶颈现象比51系列还要严重,这在编程中的朋友应该深有体会。
说到这里特别想提一下本人单位开发的SPARC架构的MCU。SPARC 架构是SUN公司开发的一种开源架构,以高性能高可靠性著称,SPARC 处理器架构具备精简指令集(RISC)、支持32 位/64 位指令精度,其最大的一个特点莫过于寄存器窗口机制,也称重叠窗口技术。

图18 寄存器窗口
这一技术是指将所有寄存器分成若干个组,称为寄存器窗口,建立窗口是为了减少过程调用中保存现场和建立新现场,以及返回时恢复现场等辅助操作。每一组中有若干个寄存器,每当有过程调用时,就分配一个未被使用的寄存器窗口,这样就可减少保存和恢复的开销。在使用时,每一对调用和被调用的寄存器窗口各自的低区和高区相互重叠。一旦发生过程调用或返回,在控制由一个窗口转换到另一窗口时,这些参数就通过两个窗口间的公共寄存器区自动的被传送而不需要再用额外的传送时间,因而Sparc架构的CPU运行效率十分高效,正好可以完美解决PIC的不足。
最后再次感谢面包板社区提供的测评机会,让我得以在家就可以探索美妙的IC世界!