前 言
Embedded C Programming: Techniques and Applications of C and PIC MCUS
微控制器是将微型计算机的主要部分集成到一个芯片上的单芯片微型计算机。上电后,它会运行内部程序存储器上的程序。内部程序存储器可以使用只读存储器(ROM)或者Flash。我们在各种地方都会发现微型计算机的踪影,如家用电器、玩具、汽车和计算机外设(如键盘或鼠标)。从电池充电器到雷达系统,几乎所有的电子设备中都有微型计算机的身影。
PIC微控制器的速度很快,在写作本书时已经达到每秒7000万次指令,且价格低廉,某些型号的单价在1美元以内。由于这些优点,它逐渐成为新的设计方案中最流行的选型,并大量地应用于接口中,如USB、以太网和模拟信号接口。
C语言最初是由AT&T实验室的Brian Kernighan和Dennis Ritchie开发的,称为K&R C,随后在1989年被ANSI标准化,也就是C89。从C语言中衍生出的新特性催生了C++语言。1998年,C++的ISO标准被批准通过。C++有些复杂的语言元素,使其无法应用于微控制器而只能用于PC这样相对宏观的设备。C是微控制器编程中最常用的语言。
C语言在计算机语言中属于高级语言。高级语言使用一种名为编译器的工具将C文本文件转换成机器语言文件。
本书的前半部分着重讲述C语言。如果读者在这之前已经有些编程经验,这会对阅读本书有些帮助,但这些经验并不是必需的。我们会使用C语言元素的正式定义,详细列出微控制器所需要的全部语言特性。本书从第15章开始介绍PIC微控制器及其外围组件,以及如何在C语言中使用这些组件。硬件接口部分相关的基础电子知识有助于读者理解本书,但这些知识对于阅读本书也不是必需的。
在不同的编译器厂商之间或不同的微控制器系列之间会有些不同的C语言扩展。本书中出现的不同的处理器或编译器之间可能会产生兼容性问题,这些部分都做了标记。每一章也会分享一些好的编程实践经验以及相应的文档。为了巩固所学的概念,每章都会提供练习和测验。本书中的例子全部可以在CCS C编译器中编译通过,这也是Microchip PIC系列处理器最常用的编译器。
商标说明:PIC? MCU、dsPIC? DSC和MPLAB?属于Microchip Technology公司在美国及其他国家的注册商标。
Mark Siegesmund
目 录
Embedded C Programming: Techniques and Applications of C and PIC MCUS
出版者的话
译者序
前言
第1章 C语言概述和程序结构
1.1 C源代码
1.2 注释
1.3 程序结构
1.4 C预编译指令
1.5 函数
1.6 声明
1.7 语句和表达式
1.8 时间
1.9 输入准确度
1.10 文本格式
1.11 兼容性
1.12 小结
1.13 练习
1.14 测验
第2章 常量
2.1 位、字节等
2.1.1 位
2.1.2 半字节
2.1.3 字节
2.1.4 内存大小
2.2 C常量语法
2.2.1 二进制
2.2.2 十进制
2.2.3 有符号整数
2.2.4 十六进制
2.2.5 八进制
2.2.6 浮点数
2.2.7 定点数
2.2.8 字符
2.2.9 字符串
2.2.10 真和假
2.2.11 常量
2.3 三字母词
2.4 兼容性
2.5 设计文档
2.6 小结
2.7 练习
2.8 测验
第3章 预编译指令
3.1 标准预编译指令
3.1.1 #def?ine id text
3.1.2 #include 或#include “f?ilename”
3.1.3 #ifdef、#ifndef、#else、#endif和#undef
3.1.4 #if、#else、#elif和#endif
3.1.5 #error
3.1.6 #nolist和#list
3.2 兼容性
3.3 非标准编译指示
3.3.1 #warning
3.3.2 #use delay
3.3.3 关于频率
3.3.4 #use rs232(options)
3.3.5 #fuses options
3.3.6 #locate id = address
3.3.7 #byte id=x和#word id=x
3.3.8 #bit id=x.y
3.3.9 #reserve address
3.3.10 引导加载程序
3.3.11 #rom address={data}
3.3.12 #id data
3.3.13 其他编译指示
3.4 小结
3.5 练习
3.6 测验
第4章 变量和数据类型
4.1 数据类型
4.1.1 字符
4.1.2 整数
4.1.3 兼容性
4.1.4 整数格式
4.1.5 枚举类型
4.1.6 定点数
4.1.7 浮点数
4.1.8 帮助
4.1.9 浮点格式
4.1.10 空类型
4.1.11 类型定义
4.2 变量声明
4.2.1 标识符
4.2.2 变量作用域
4.2.3 变量生命周期
4.2.4 附加限定词
4.3 设计资料
4.4 RAM
4.5 小结
4.6 练习
4.7 测验
第5章 表达式和运算符
5.1 数学运算符
5.2 兼容性
5.3 运算符优先级
5.4 表达式类型和类型转换
5.5 关系运算符
5.6 位运算符
5.7 兼容性
5.8 赋值运算符
5.9 自增/自减运算符
5.10 其他运算符
5.11 序列点
5.12 表达式示例
5.13 小结
5.14 练习
5.15 测验
第6章 语句
6.1 语句定义
6.1.1 if语句
6.1.2 while循环
6.1.3 for循环
6.1.4 跳转语句
6.1.5 switch/case语句
6.2 副作用
6.3 嵌套、缩进和括号的使用
6.4 设计文档
6.5 程序复杂度
6.6 小结
6.7 练习
6.8 测验
第7章 函数
7.1 main()函数
7.2 函数定义
7.3 函数参数
7.4 高级特性
7.4.1 兼容性
7.4.2 引用参数
7.4.3 默认参数
7.4.4 重载函数
7.5 返回值
7.6 内联函数
7.7 嵌套函数
7.8 递归函数
7.9 序列点进阶
7.10 结构良好的程序
7.11 设计文档
7.12 实现细节
7.13 小结
7.14 练习
7.15 测验
第8章 数组
8.1 数组初始化
8.2 常量数组
8.3 字符串变量
8.4 无下标数组
8.5 多维数组
8.6 索引范围
8.7 数组使用示例
8.8 查找表
8.9 数组搜索
8.10 数组排序
8.11 小结
8.12 练习
8.13 测验
第9章 结构体
9.1 结构体嵌套和结构体数组
9.2 结构体在内存中的存储
9.3 位字段
9.4 联合体
9.5 程序中的结构体示例
9.6 小结
9.7 练习
9.8 测验
第10章 内存和指针
10.1 内存
10.2 取地址运算符
10.3 间接运算符
10.4 强制指定变量地址
10.5 指针类型
10.6 指针运算
10.7 下标
10.8 函数参数
10.9 结构体
10.10 函数指针
10.11 指针的其他用途
10.12 错误行为
10.13 常见错误
10.14 ROM指针
10.15 用户定义内存
10.16 兼容性
10.17 通关之后
10.18 小结
10.19 练习
10.20 测验
第11章 内置函数
11.1 数学
11.2 内存
11.3 动态内存
11.4 一些更有趣的函数
11.5 可变参数列表
11.6 文本输入/输出
11.7 实现常量
11.8 兼容性
11.9 位和字节操作
11.10 非易失性内存
11.11 看门狗
11.12 延时
11.13 多个时钟频率
11.14 更多标准函数
11.15 小结
11.16 练习
11.17 测验
第12章 字符串
12.1 字符串复制和字符串长度
12.2 字符串查找
12.3 字符串比较
12.4 字符串操作
12.5 字符串输入/输出
12.6 字符串和数字相互转换
12.7 字符操作
12.8 统一字符编码
12.9 常量字符串管理
12.10 小结
12.11 练习
12.12 测验
第13章 函数式宏定义
13.1 参数
13.2 宏名字
13.3 串联运算符
13.4 字符串化运算符
13.5 可变参数宏
13.6 函数式宏定义与内联函数
13.7 可读性
13.8 高级示例
13.9 宏调试
13.10 小结
13.11 练习
13.12 测验
第14章 条件编译
14.1 基本指令
14.2 关系表达式
14.3 特殊宏
14.4 特殊定义
14.5 全局定义
14.6 奇怪的错误
14.7 条件编译示例
14.8 小结
14.9 练习
14.10 测验
第15章 PIC微控制器
15.1 PIC架构
15.1.1 CPU
15.1.2 栈
15.1.3 工作寄存器
15.1.4 特殊功能寄存器
15.1.5 程序存储器
15.1.6 指令
15.1.7 时钟
15.1.8 复位
15.1.9 睡眠
15.1.10 中断
15.1.11 配置位
15.1.12 外围组件
15.2 最小系统
15.3 设备编程
15.4 hex文件
15.5 上电过程
15.6 时钟配置
15.7 调试
15.8 引导加载
15.9 小结
15.10 练习
15.11 测验
第16章 离散输入和输出
16.1 输入电压
16.2 驱动电流
16.3 驱动更大的电流
16.4 集电极开路输出
16.5 方向
16.6 按钮输入
16.7 上拉电阻
16.8 消抖
16.9 滤波
16.10 内存映射端口
16.11 小结
16.12 练习
16.13 测验
第17章 中断
17.1 简单中断示例
17.2 时间都去哪儿了
17.3 再议消抖
17.4 中断发生的时刻
17.5 为什么需要中断
17.6 中断详解
17.6.1 中断标志位(IF)
17.6.2 中断使能标志位(IE)
17.6.3 全局中断使能标志位(GIE)
17.6.4 中断处理
17.7 正确处理中断
17.8 多个中断同时发生
17.8.1 12位字长
17.8.2 14位字长
17.8.3 16位字长
17.8.4 24位字长
17.9 延迟
17.10 重入
17.11 兼容性
17.12 小结
17.13 练习
17.14 测验
第18章 定时器/计数器
18.1 定时器组件
18.1.1 计数器核心
18.1.2 计数器周期
18.1.3 后分频器
18.1.4 预分频器
18.1.5 门
18.1.6 多路转换器
18.2 PIC特性
18.3 C代码
18.4 用定时器实现延迟
18.5 精度循环
18.6 中断
18.6.1 以特定频率产生中断
18.6.2 在特定时间产生中断
18.7 虚拟定时器
18.8 小结
18.9 练习
18.10 测验
第19章 高级定时器
19.1 PWM
19.2 使用PWM库
19.3 捕捉
19.4 对比
19.5 兼容性
19.6 小结
19.7 练习
19.8 测验
第20章 模拟技术
20.1 数/模转换
20.2 模/数转换
20.2.1 电压高于5V
20.2.2 过滤
20.2.3 波形分析
20.2.4 混叠现象
20.2.5 在睡眠时工作
20.2.6 参考电压
20.3 比较器
20.4 电压检测
20.5 兼容性
20.6 小结
20.7 练习
20.8 测验
第21章 内部串行总线
21.1 串行外围接口
21.1.1 SPI模式
21.1.2 硬件SPI
21.1.3 多点SPI
21.1.4 减少连线
21.1.5 噪声
21.1.6 帧信号
21.1.7 PIC从设备
21.2 I2C
21.2.1 多个主设备
21.2.2 特殊地址
21.2.3 10位地址
21.2.4 I2C从设备
21.2.5 SMBus
21.3 小结
21.4 练习
21.5 测验
第22章 外部串行总线
22.1 RS-232
22.2 源代码
22.3 UART
22.4 输入数据中断
22.5 输出数据中断
22.6 调制解调器控制信号
22.7 硬件流控制
22.8 软件流控制
22.9 协议
22.10 RS-232的未来
22.11 RS-422
22.12 RS-485
22.13 文档
22.14 小结
20.15 练习
22.16 测验
第23章 多任务
23.1 抢占式调度
23.2 调度器调度
23.3 确定性调度
23.4 信号量
23.5 消息传递
23.6 await( )
23.7 任务管理
23.8 小结
23.9 练习
23.10 测验
第24章 内联汇编
24.1 C代码中的汇编代码
24.2 内联汇编代码
24.3 PIC16/PIC18数据传送指令
24.4 在汇编代码中访问C变量
24.5 PIC16/PIC18数学指令
24.6 PIC16/PIC18位操作类指令
24.7 PIC16/PIC18控制操作类指令
24.8 PIC16/PIC18立即数操作指令
24.9 编译器对汇编代码的修改
24.10 访问SFR
24.11 关于FSR
24.12 哪些不能做
24.13 优化汇编代码
24.14 PIC24指令
24.15 dsPIC指令
24.16 小结
24.17 练习
24.18 测验
第25章 调试
25.1 概述
25.2 ICSP
25.3 ICSP插座
25.4 断点
25.5 查看内存
25.6 单步
25.7 增强调试
25.8 监控
25.9 数据流
25.10 实时性问题
25.11 使用示波器
25.12 诊断接口
25.13 记录/回放
25.14 性能分析工具
25.15 代码性能分析
25.16 设计验证
25.17 小结
25.18 练习
25.19 测验
附录A
附录B
附录C
参考资料