2024-09-08
单片机
00

目录

使用PIC16F1719进行ADC配置与读取详解
什么是ADC?
项目目标
硬件配置
ADC模块配置
代码解析
1. 时钟配置
2. 引脚配置
3. ADC参数设置
4. 启动ADC转换
5. 读取结果
6. 延迟处理
总结

使用PIC16F1719进行ADC配置与读取详解

在嵌入式系统开发中,ADC(模数转换器) 是一个非常常见且重要的功能。它可以将模拟信号转换为数字信号,从而使得微控制器能够处理来自外部传感器等设备的模拟数据。在本文中,我们将使用PIC16F1719微控制器,并详细介绍如何配置和使用其内置的ADC模块来读取模拟信号。

什么是ADC?

ADC(Analog-to-Digital Converter,模数转换器) 是一种将模拟信号转换为数字信号的设备。模拟信号是连续的电压信号,而数字信号则是离散的,通常为0和1组成的二进制数据。在许多应用中,传感器产生的信号往往是模拟信号,因此使用ADC可以将这些信号转换为微控制器可以处理的数字形式。

项目目标

在这个示例中,我们将使用PIC16F1719的ADC模块,通过读取A0引脚上的模拟电压信号,将其转换为数字值并存储在变量中。通过循环采样,每秒更新一次转换结果。

硬件配置

在使用ADC之前,首先需要了解PIC16F1719的ADC模块支持的输入电压范围。在这个示例中,ADC的参考电压Vref+Vdd,即微控制器的供电电压,Vref-为接地电压Vss。这意味着ADC可以将0V到Vdd之间的模拟信号转换为数字值。

ADC模块配置

PIC16F1719的ADC模块有多个可配置的选项,比如参考电压、输入通道、转换时钟和结果的对齐方式等。下面我们逐步讲解如何进行配置。

代码解析

以下是配置ADC并进行模数转换的示例代码:

c
#include <xc.h> #define _XTAL_FREQ 32000000 // 设置系统时钟为32MHz void main(void) { // 系统初始化 OSCCON = 0xF0; // 设置内部振荡器为8MHz,并启用4倍PLL,系统时钟达到32MHz ANSELA = 0x00; // 将A端口全部设置为数字模式 ANSELAbits.ANSA0 = 1; // 将A0设置为模拟输入 TRISAbits.TRISA0 = 1; // 将A0引脚设置为输入 // ADC配置 ADCON1bits.ADCS = 0b010; // 设置ADC时钟为Fosc/32 ADCON1bits.ADFM = 1; // 设置结果右对齐 ADCON1bits.ADNREF = 0; // Vref-为Vss ADCON1bits.ADPREF = 0b00; // Vref+为Vdd ADCON0bits.CHS = 0b00000; // 选择通道AN0(对应A0引脚) // 清空ADRESH和ADRESL寄存器 ADRESL = 0; ADRESH = 0; // 开始ADC操作 while (1) { ADCON0bits.ADON = 1; // 开启ADC模块 __delay_us(10); // 等待采样时间 ADCON0bits.GO = 1; // 启动ADC转换 while (ADCON0bits.GO_nDONE); // 等待转换完成 int result = ((ADRESH << 8) + ADRESL); // 获取10位ADC结果 __delay_ms(1000); // 每秒采样一次 } }

1. 时钟配置

首先,我们需要配置系统的时钟源。通过配置OSCCON寄存器,我们设置了内部振荡器为8MHz,并启用了4倍锁相环(PLL),将系统时钟频率提升至32MHz。高频率时钟能保证ADC转换的快速响应。

c
OSCCON = 0xF0; // 设置内部振荡器为8MHz,使用4x PLL

2. 引脚配置

在PIC16F1719中,A0引脚(AN0通道) 将作为模拟输入。为了启用ADC功能,必须将相应的引脚配置为模拟模式。

c
ANSELA = 0x00; // 将A端口全部设置为数字模式 ANSELAbits.ANSA0 = 1; // 设置A0为模拟输入 TRISAbits.TRISA0 = 1; // 设置A0为输入

3. ADC参数设置

通过ADCON1ADCON0寄存器,我们可以配置ADC的各项参数:

  • ADCS: 设置ADC时钟为Fosc/32,使得每次模数转换的时间为1微秒。
  • ADFM: 选择结果右对齐,这样高8位存储在ADRESH,低8位存储在ADRESL。
  • ADPREF/ADNREF: 设置参考电压为Vdd(正参考电压)和Vss(负参考电压)。
  • CHS: 选择通道AN0(即A0引脚)。
c
ADCON1bits.ADCS = 0b010; // 设置ADC时钟为Fosc/32 ADCON1bits.ADFM = 1; // 结果右对齐 ADCON1bits.ADNREF = 0; // Vref- 为 Vss ADCON1bits.ADPREF = 0b00; // Vref+ 为 Vdd ADCON0bits.CHS = 0b00000; // 选择通道AN0

4. 启动ADC转换

每次ADC操作前,我们需要先开启ADC模块,之后通过设置GO位启动转换,并等待转换完成。转换结果存储在两个寄存器ADRESHADRESL中,将其组合即可得到完整的10位ADC结果。

c
ADCON0bits.ADON = 1; // 开启ADC模块 __delay_us(10); // 等待采样时间 ADCON0bits.GO = 1; // 启动ADC转换 while (ADCON0bits.GO_nDONE); // 等待转换完成 int result = ((ADRESH << 8) + ADRESL); // 获取10位结果

5. 读取结果

ADC完成转换后,结果存储在ADRESHADRESL寄存器中。由于我们选择了右对齐,最终结果是一个10位的数字。我们通过将高8位左移8位,然后与低8位相加,得到最终的转换结果。

c
int result = ((ADRESH << 8) + ADRESL); // 获取10位结果

6. 延迟处理

为了避免频繁采样,我们在每次ADC读取后延迟1秒钟。这个延迟可以根据实际应用进行调整。

c
__delay_ms(1000); // 每秒采样一次

总结

通过上述步骤,我们成功使用了PIC16F1719的ADC模块,从模拟输入引脚读取电压值,并将其转换为数字信号。ADC的使用非常广泛,例如读取温度传感器、电位计等模拟设备的信号。掌握了ADC的配置与使用,能够帮助开发者在嵌入式系统中实现丰富的功能。

c
/* PIC16F1719 配置位设置 */ #pragma config FOSC = INTOSC /* 振荡器选择位 (INTOSC 振荡器: CLKIN 引脚上的 I/O 功能) */ #pragma config WDTE = OFF /* 看门狗定时器使能 (WDT 禁用) */ #pragma config PWRTE = OFF /* 上电定时器使能 (PWRT 禁用) */ #pragma config MCLRE = ON /* MCLR 引脚功能选择 (MCLR/VPP 引脚功能为 MCLR) */ #pragma config CP = OFF /* 闪存程序存储器代码保护 (程序存储器代码保护禁用) */ #pragma config BOREN = OFF /* 低电压复位使能 (低电压复位禁用) */ #pragma config CLKOUTEN = OFF /* 时钟输出使能 (CLKOUT 功能禁用。CLKOUT 引脚上的 I/O 或振荡器功能) */ #pragma config IESO = ON /* 内外部切换模式 (内外部切换模式使能) */ #pragma config FCMEN = ON /* 故障安全时钟监控器使能 (故障安全时钟监控器使能) */ #pragma config WRT = OFF /* 闪存自写保护 (写保护关闭) */ #pragma config PPS1WAY = OFF /* 外设引脚选择单向控制 (PPSLOCK 位可以通过软件反复设置和清除) */ #pragma config ZCDDIS = ON /* 零交叉检测禁用 (ZCD 禁用。ZCD 可以通过设置 ZCDCON 的 ZCDSEN 位来启用) */ #pragma config PLLEN = ON /* 锁相环使能 (4x PLL 使能) */ #pragma config STVREN = ON /* 栈溢出/下溢复位使能 (栈溢出或下溢将导致复位) */ #pragma config BORV = LO /* 低电压复位电压选择 (低电压复位电压 (Vbor),选择低触发点。) */ #pragma config LPBOR = OFF /* 低功率低电压复位 (低功率低电压复位禁用) */ #pragma config LVP = ON /* 低电压编程使能 (低电压编程使能) */ /* 定义系统振荡器频率 */ #define _XTAL_FREQ (32000000ul) #include <xc.h> #include <stdio.h> #include <stdlib.h> #include <string.h> //counter variable int count = 0; void main(void) { unsigned char index = 0; /* 程序初始化设置 */ OSCCON = 0xF0; /* 设置 INTOSC 为 8MHz,并使用 4xPLL,使系统振荡器达到 32MHz */ INTCON = 0; /* 禁用所有中断源 */ PIE1 = 0; PIE2 = 0; PIE3 = 0; // Allow PLL startup time ~2 ms __delay_ms(10); ANSELA = 0x00; // 将所有A端口引脚设置为数字模式 ANSELB = 0x00; // 将所有B端口引脚设置为数字模式 ANSELC = 0x00; // 将所有C端口引脚设置为数字模式 // Set PIN D1 as output TRISDbits.TRISD1 = 0; // Turn off LED LATDbits.LATD1 = 0; // Setup PORTD TRISD = 0; ANSELD = 0; TRISBbits.TRISB2 = 0; ANSELBbits.ANSB2 = 0; ///////////////////// // Setup EUSART //////////////////// PPSLOCK = 0x55; PPSLOCK = 0xAA; PPSLOCKbits.PPSLOCKED = 0x00; // unlock PPS RB2PPSbits.RB2PPS = 0x14; //RB2->EUSART:TX; RXPPSbits.RXPPS = 0x0B; //RB3->EUSART:RX; PPSLOCK = 0x55; PPSLOCK = 0xAA; PPSLOCKbits.PPSLOCKED = 0x01; // lock PPS //////////////////// // Configure ADC /////////////////// // Set A0 as input TRISAbits.TRISA0 = 1; // Set A0 as analog ANSELAbits.ANSA0 = 1; // Fosc/32 ADC conversion time is 1.0 us ADCON1bits.ADCS = 0b010; // Right justified ADCON1bits.ADFM = 1; // Vref- is Vss ADCON1bits.ADNREF = 0; // Vref+ is Vdd ADCON1bits.ADPREF = 0b00; // Set input channel to AN0 ADCON0bits.CHS = 0b00000; // Zero ADRESL and ADRESH ADRESL = 0; ADRESH = 0; // enable peripheral interrupt INTCONbits.PEIE = 1; INTCONbits.GIE = 1; // 使能全局中断 // variable to store conversion result int result; while (1) { // Turn ADC on ADCON0bits.ADON = 1; // Sample CH0 __delay_us(10); ADCON0bits.GO = 1; while (ADCON0bits.GO_nDONE); // Store ADC result result = ((ADRESH << 8) + ADRESL); __delay_ms(1000); } }

希望这篇文章能够帮助你理解如何在PIC微控制器上使用ADC模块!

如果对你有用的话,可以打赏哦
打赏
ali pay
wechat pay

本文作者:Dong

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC。本作品采用《知识共享署名-非商业性使用 4.0 国际许可协议》进行许可。您可以在非商业用途下自由转载和修改,但必须注明出处并提供原作者链接。 许可协议。转载请注明出处!