目录
- 准备工作:你需要什么?
- 第一个程序:点亮LED (Blinking LED)
- 步骤1:创建项目
- 步骤2:编写C代码
- 步骤3:配置熔断位
- 步骤4:编译与烧录
- 核心概念解析
- 硬件抽象层
- 特殊功能寄存器
- I/O端口控制
- 延时函数
- 进阶主题
- 中断
- 定时器
- 模数转换
- 学习资源与建议
准备工作:你需要什么?
在开始之前,请确保你拥有以下“四件套”:

1 硬件
- 一块开发板: 对于初学者,强烈推荐购买一块集成了调试器的入门开发板,可以省去很多麻烦。
- 经典选择: Microchip官方的 Curiosity PIC16F1704/08或PIC16F18446开发板,它们价格便宜,功能齐全,并且自带了调试器。
- 其他选择: 很多第三方厂商(如EasyPIC, UNO R4 for PIC等)也提供优秀的开发板。
- USB数据线: 用于连接开发板和电脑。
- LED和电阻 (可选): 大部分开发板已 onboard LED,但自己动手焊接可以加深理解,一个LED通常需要220Ω-1kΩ的限流电阻。
2 软件
- 集成开发环境:
- MPLAB X IDE: Microchip官方的免费IDE,用于编写、编译和调试代码,支持Windows, macOS和Linux。
- 下载地址: Microchip官网
- 编译器:
- XC8编译器: Microchip官方的C语言编译器,有免费版、标准版和专业版。入门学习,免费版完全足够。
- 注意: 安装MPLAB X时,通常会提示你安装或配置编译器,请确保XC8被正确安装。
- 硬件调试器/编程器驱动:
如果你使用的是带调试器的开发板(如Curiosity),MPLAB X通常能自动识别并安装驱动,无需手动操作。
第一个程序:点亮LED
这是嵌入式世界的 "Hello, World!",我们将让开发板上的一个LED灯以1秒的间隔闪烁。
步骤1:创建项目
- 打开 MPLAB X IDE。
- 点击菜单栏的
File->New Project...。 - 在弹出的窗口中,选择
Microchip Embedded->Standalone Project Project,然后点击Next。 - 选择器件: 在 "Select Device" 界面,搜索并选择你的开发板上使用的单片机型号,如果你的开发板是 PIC16F1704,就选择它,然后点击
Next。 - 选择工具: 在 "Select Hardware Tool" 界面,选择你的开发板自带的调试器(如
PICkit On Board或Curiosity Nano),如果连接正常,状态会显示 "Connected",点击Next。 - 选择项目名称: 在 "Select Project Name" 界面,给你的项目起一个名字(
Blink_LED),并选择一个存放位置,点击Next。 - 添加文件: 在 "Add Firmware" 界面,选择
C Main file,然后点击Finish。
一个基础的项目结构已经创建好了,并且会自动打开一个 main.c 文件。
步骤2:编写C代码
删除 main.c 中的所有默认代码,然后粘贴以下代码:

// 包含Microchip官方提供的头文件,它定义了所有特殊功能寄存器的名称
#include <xc.h>
// 配置位设置,非常重要!我们稍后在MPLAB X图形化界面配置。
// _CONFIG1 是一个宏,用于设置配置字1
#pragma config FOSC = INTOSC // 内部振荡器
#pragma config WDTE = OFF // 关闭看门狗定时器
#pragma config PWRTE = OFF // 上电延时定时器关闭
#pragma config MCLRE = ON // MCLR引脚使能
#pragma config CP = OFF // 代码保护关闭
#pragma config CPD = OFF // 数据代码保护关闭
#pragma config BOREN = OFF // 欠压复位关闭
#pragma config CLKOUTEN = OFF // CLKOUT引脚功能关闭
#pragma config IESO = OFF // 内外部振荡器切换关闭
#pragma config FCMEN = OFF // 故障时钟监测关闭
// 配置位2
#pragma config WRT = OFF // 写保护关闭
#pragma config PPS1WAY = ON // PPS锁定一次
#pragma config ZCDDIS = ON // 雯电容放电关闭
#pragma config PLLEN = OFF // PLL关闭
#pragma config STVREN = ON // 欠压复位使能
#pragma config BORV = LO // 欠压复位电平为低
#pragma config LPBOR = OFF // 低功耗欠压复位关闭
#pragma config LVP = OFF // 低电压编程模式关闭
// 定义CPU时钟频率,用于延时函数
#define _XTAL_FREQ 8000000 // 8MHz
void main(void) {
// --- 1. 初始化 ---
// 设置RA5引脚为数字输出模式
// TRISx寄存器控制端口方向: 1=输入, 0=输出
TRISA5 = 0;
// --- 2. 主循环 ---
// while(1) 是一个无限循环,程序会一直在这里运行
while(1) {
// 将RA5引脚的电平拉高(点亮LED,具体取决于硬件电路)
LATA5 = 1;
// 延时500毫秒
__delay_ms(500);
// 将RA5引脚的电平拉低(熄灭LED)
LATA5 = 0;
// 再延时500毫秒
__delay_ms(500);
}
}
代码解释:
#include <xc.h>: 必须包含,这是PIC C编程的灵魂,它包含了所有寄存器定义(如TRISA,LATA)和编译器内置函数(如__delay_ms)。#pragma config ...: 配置熔断位,这些是单片机的“永久性”设置,决定了单片机的基本工作方式,如使用哪个时钟源、是否启用看门狗等,我们先写在这里,之后会用图形化工具修改。#define _XTAL_FREQ 8000000: 定义晶振频率。__delay_ms()函数需要这个宏来计算正确的延时时间,如果你的板子是8MHz内部振荡器,就写8000000。void main(void): C程序的入口函数。TRISA5 = 0;: 设置I/O方向。TRISA是A端口的数据方向寄存器。TRISA5控制A端口的第5个引脚。0代表输出模式,这样我们才能通过程序控制RA5引脚输出高电平或低电平。while(1): 主循环,单片机程序没有操作系统,所以必须有一个无限循环来持续执行任务。LATA5 = 1;: 输出高电平。LATA是A端口的锁存寄存器,向LATA5写入1,会使RA5引脚输出高电平(通常是3.3V或5V),点亮LED。LATA5 = 0;: 输出低电平,向LATA5写入0,会使RA5引脚输出低电平(0V),熄灭LED。__delay_ms(500);: 延时函数,这是XC8编译器提供的内置函数,可以产生精确的毫秒级延时。注意:它依赖于前面定义的_XTAL_FREQ。
步骤3:配置熔断位
虽然我们在代码中写了 #pragma config,但更推荐使用MPLAB X的图形化配置工具,因为它更直观,不容易出错。
- 在左侧的 "Projects" 窗口中,右键点击你的项目名(如
Blink_LED)。 - 选择
Properties。 - 在左侧导航栏中,展开
Conf: [Default],然后选择XC8 linker。 - 在右侧,选择
Categories下的Memory Model和Code Generation等选项卡,根据你的需求进行配置,对于初学者,保持默认即可。 - 最关键的一步: 在左侧导航栏中,选择
Conf: [Default]->Bit Gen。 - 在右侧,你会看到所有熔断位的配置,将它们与我们代码中的
#pragma config一一对应进行设置,找到FOSC,将其设置为INTOSC,找到WDTE,将其设置为OFF。 - 点击
OK保存配置。
步骤4:编译与烧录
- 连接硬件:用USB线将开发板连接到电脑。
- 选择工具:确保在MPLAB X右上角的工具栏中,选对了你的硬件调试器。
- 编译:点击工具栏上的 "Make" 按钮(一个锤子图标),如果一切顺利,底部的 "Output" 窗口会显示
BUILD SUCCESSFUL。 - 烧录与调试:
- 点击工具栏上的 "Program" 按钮(一个闪电图标),这会将编译好的代码烧录到单片机中。
- 烧录成功后,点击 "Debug Project" 按钮(一个绿色的“开始”按钮),这会启动调试模式,程序会开始运行。
- 你应该能看到开发板上的LED灯开始闪烁了!
- 调试结束后,点击工具栏上的 "Finish Debugger Session" 按钮(红色的方块)。
核心概念解析
1 硬件抽象层
<xc.h> 文件就是PIC的硬件抽象层,它将复杂的寄存器地址、位定义等,用易于理解的C语言宏(如 TRISA, PORTA, LATA)包装起来,你不需要关心 TRISA 的具体地址是 0x85,只需要知道 TRISA = 0xFF 就能将A端口全部设置为输入。
2 特殊功能寄存器
单片机内部有一块特殊的RAM区域,称为特殊功能寄存器,它们是CPU与外设(如I/O端口、定时器、ADC等)沟通的桥梁。

- 数据方向寄存器:
TRISA,TRISB,TRISC... (1=输入, 0=输出) - 端口寄存器:
PORTA,PORTB,PORTC... (读取引脚的外部电平) - 锁存寄存器:
LATA,LATB,LATC... (写入/读取引脚的内部输出电平)- 最佳实践:对于输出,尽量使用
LATx寄存器,而不是PORTx,因为PORTx在读取时可能会受到引脚外部电路的影响,导致读取值不准确。
- 最佳实践:对于输出,尽量使用
3 I/O端口控制
总结一下控制一个引脚为输出的步骤:
- 设置方向:
TRISxy = 0;(TRISA5 = 0;) - 输出电平:
LATxy = 1;(输出高) 或LATxy = 0;(输出低)
4 延时函数
__delay_ms() 和 __delay_us() 非常方便,但有两大注意事项:
- 依赖
_XTAL_FREQ:必须在代码中正确定义时钟频率。 - 有最大延时限制:延时时间不能超过某个最大值(由
_XTAL_FREQ决定),如果需要更长的延时,可以用循环嵌套的方式实现。
进阶主题
掌握了LED闪烁,你已经入门了,接下来可以探索这些更强大的功能:
1 中断
中断是单片机的核心机制之一,它允许CPU在执行主程序的同时,响应外部或内部事件(如按键按下、定时器溢出)。
- 工作原理:当事件发生时,CPU会暂停当前任务,跳转到预先编写好的中断服务程序执行,执行完毕后再返回原来的任务继续。
- 应用:按键检测(不占用CPU轮询)、精确的时序控制、通信(UART, SPI)等。
- XC8中的实现:需要设置中断使能寄存器(如
INTCON),编写void interrupt myISR(void)函数,并在主函数中enable_interrupts()。
2 定时器
定时器是单片机的“心脏”,用于产生精确的时间间隔、测量信号频率或脉宽。
- 工作原理:定时器本质上是一个计数器,它会以固定的频率(通常来自CPU时钟)递增或递减,当计数器从最大值归零(或达到某个设定值)时,就会产生一个中断。
- 应用:精确延时(比
__delay_ms更灵活)、生成PWM波(控制电机亮度、舵机角度)、测量输入信号的频率。 - XC8中的实现:需要配置定时器的工作模式(如8位、16位)、预分频器,并编写中断服务程序来处理定时器溢出事件。
3 模数转换
ADC可以将外部的模拟电压信号(如光敏电阻、温度传感器的输出)转换成单片机可以处理的数字值。
- 工作原理:通过一个采样保持电路,将模拟电压在某一瞬间的“快照”转换成一个数字编码(如0-1023,对应0-5V)。
- 应用:读取环境光强度、温度、电位器位置等模拟传感器数据。
- XC8中的实现:需要配置ADC模块(选择参考电压、时钟源、通道),然后启动转换并等待结果,最后读取结果寄存器。
学习资源与建议
-
官方文档是圣经:
- 器件数据手册:你的单片机的“圣经”,包含了所有寄存器的详细说明、电气特性、引脚图等,遇到任何问题,第一反应就是查数据手册。
- 器件参考手册:比数据手册更详细,深入解释了每个外设模块的工作原理和配置方法。
-
在线社区与论坛:
- Microchip官方论坛:官方工程师和资深用户在这里解答问题。
- EEVblog论坛、Reddit的 r/embedded 和 r/Microchip:非常活跃的嵌入式社区。
-
视频教程:
在YouTube上搜索 "PIC Microcontroller XC8 Tutorial",有大量优秀的英文和中文视频教程,可以跟着一步步操作。
-
学习建议:
- 动手为主:不要只看代码,一定要亲手敲、亲手编译、亲手调试。
- 由简到繁:从LED -> 按键 -> 定时器 -> ADC -> UART,一步步搭建知识体系。
- 学会调试:熟练使用MPLAB X的调试器,设置断点、单步执行、查看变量值,是快速定位问题的关键。
- 多读数据手册:刚开始会觉得枯燥,但这是成为高手的必经之路。
祝你学习愉快,早日成为PIC开发高手!
