### PIC单片机的内部A/D转换 #### 引言 在现代电子系统设计中,模拟信号和数字信号之间的转换是必不可少的过程。其中,模数转换器(Analog-to-Digital Converter, ADC)扮演着核心角色,它能够将连续变化的模拟信号转换成离散的数字信号,从而便于微处理器或计算机进行处理。本篇文章将详细介绍PIC单片机内部A/D转换的工作原理、配置方法以及其实现过程。 #### PIC单片机简介 PIC(Peripheral Interface Controller)单片机是由Microchip Technology公司开发的一系列微控制器。这些单片机以其高性能、低成本、低功耗等特点,在工业控制、消费电子产品等领域得到了广泛应用。PIC单片机通常集成了多种外围设备,例如定时器、串行通信接口等,其中也包括了模数转换器。 #### 内部A/D转换器概述 在许多应用场景中,需要采集外部环境中的模拟信号并对其进行数字化处理。例如温度传感器输出的模拟电压、光敏电阻的变化等。为了实现这一功能,PIC单片机内置了A/D转换器,可以将模拟信号转换为数字信号。 ##### A/D转换器的基本特性: - **分辨率**:表示A/D转换器能够分辨的最小模拟电压变化。通常由转换后的数字位数决定,如10位、12位等。 - **转换时间**:完成一次A/D转换所需的时间。 - **采样率**:单位时间内能完成的转换次数。 - **参考电压**:用于量化模拟输入信号的标准电压。 #### A/D转换器配置步骤 在开始使用A/D转换器之前,需要通过配置相关的寄存器来设置工作模式。下面通过一个具体的例子来说明如何配置和使用PIC单片机的A/D转换器: ```c #include <pic.h> __CONFIG(0x3831); // 配置位18323831 #define uint unsigned int #define uchar unsigned char // 共阴数码管(板子上用了达林顿管ULN2003,反向器) const unsigned char table[] = {0x3f, 0x6, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x7, 0x7f, 0x6f}; // 加小数点的共阴数码管显示, 非常不错 const uchar table1[] = {0xbf, 0x86, 0xdb, 0xcf, 0xe6, 0xed, 0xfd, 0x87, 0xff, 0xef}; void init(); // 数码管,和AD相关寄存器设置 uint get_ad(); // 获取电压值,其中包括AD读取,及AD值转电压值的处理,返回值为uint型,精度保留小数点后3位 void delay_ms(int z); void disp(uchar num1, uchar num2, uchar num3, uchar num4); // 数码管动态扫描 void main() { uint lednum; // uchar num1, num2, num3, num4; // 高两位接RA1和RA0用不到了 init(); while (1) { lednum = get_ad(); num1 = lednum / 1000; // 求模即取整 num2 = lednum / 100 % 10; num3 = lednum / 10 % 10; num4 = lednum % 10; disp(num1, num2, num3, num4); } } void init() // 数码管,和AD相关寄存器设置 { TRISA = 0x01; // RA0设置为输入,用于AD模拟信号输入 TRISD = 0; // 接数码管段选IO设置为输出 PORTA = 0; PORTD = 0; ADCON0 = 0x41; // 选择8分频(4M/8=0.5MHz)时钟频率即8倍时钟周期,开AD ADCON1 = 0x8E; // 选择结果右对齐,ADRESH高6位读作0,选择A通道以电源VDDVSS作参考电压 delay_ms(10); // 延时等待AD稳定 } // 获取电位器电压,PIC内部AD uint get_ad() // 一般做工程的时候带个通道参数,读取几通道直接带通道数就可以 { // 实际中要进行数字滤波(如20个数取平均值,然后将其返回去,滤波算法有很多,平均值是一种而已) uint adval; // 存放AD的值 float advalf; // 存放AD值转换为的电压值 ADGO = 1; // 开始转换,ADGO与GODONE宏定义一致 while (ADGO); // AD转换完,硬件自动清零ADGO adval = ADRESH; // 先读AD高8位寄存器的低二位 adval = adval << 8 | ADRESL; advalf = adval / 1023.0 * 5.0; // 1023为电位器显示的最大值,假设板子电压为5v时 adval = advalf * 1000; // 精度取小数点后三位,如4.2356,则读为4.235 return (adval); } void disp(uchar num1, uchar num2, uchar num3, uchar num4) // 数码管动态显示 { PORTD = table1[num1]; PORTA = 0x20; // 00100000 delay_ms(2); PORTD = table[num2]; PORTA = 0x10; // 00010000 delay_ms(2); PORTD = table[num3]; PORTA = 0x08; // 00001000 delay_ms(2); PORTD = table[num4]; PORTA = 0x04; // 00000100 delay_ms(2); } void delay_ms(int z) { int x, y; for (x = z; x > 0; x--) for (y = 110; y > 0; y--); } ``` #### 代码解析 1. **初始化函数 `init()`**: - 设置RA0引脚为输入,用于接收模拟信号。 - 设置其他相关引脚为输出,用于连接数码管。 - 配置ADCON0和ADCON1寄存器,设置A/D转换器的工作模式,包括时钟频率、数据对齐方式以及参考电压的选择。 2. **获取电压值函数 `get_ad()`**: - 触发A/D转换,并等待转换完成。 - 读取转换结果,并将其转换为电压值。 - 返回电压值。 3. **数码管显示函数 `disp()`**: - 将获取到的电压值通过数码管动态显示出来。 #### 结论 通过以上内容,我们了解了PIC单片机内部A/D转换器的基本原理及其配置方法。这种技术的应用非常广泛,不仅限于本例中的电压测量,还可以扩展到各种需要模拟信号采集的场合。掌握这些基本配置和编程技巧对于从事电子设计的人来说是非常重要的。
- 粉丝: 4
- 资源: 908
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助