1 基本原理
1.1 ADC基本原理
根据微芯的ADC手册,ADC可以分为单端ADC和差分ADC。
1.1.1 单端ADC
单端ADC的输出范围是[0,2^n-1]。
根据标黄的这句话,就可以得知,如果电压高于参考电压,ADC的输出结果仍然为全1,如果电压低于0V,ADC的输出结果为全零。
1.1.2 差分ADC
差分ADC的输出范围一般为[-2 ^ (n-1) , 2^(n-1)-1]。编码一般采用补码,最高位表示符号位。
视频教程链接
1.2 PIC16F877A单片机的ADC模式
2 实现原码
/*---------------------------------函数功能:-------------------------------------
将模拟输入变成数字输出AD的转换以及AD转换完成后产生一个AD中断
RA0为模拟电压输入,RD口为AD量化输出
编程思路:参考手册的P131 To do an A/D Conversion, follow these steps
----------------------------------------------------------------------------*/
#include //#include"delay.h"//调用延时子函数的头文件 __CONFIG(0xFF32);//芯片配置字,看门狗关,上电延时开,掉电检测关,低压编程关 //__CONFIG(HS&WDTDIS&LVPDIS); /*-----------宏定义--------------*/ #define uint unsigned int #define uchar unsigned char uint ADbuf=0; // 缓存AD转换结果 /*-----------子函数声明--------------*/ /*-----------主函数--------------*/ void main() { // The corresponding data direction register is TRISA. // Setting a TRISA bit (= 1) will make the corresponding PORTA pi an input. // Clearing a TRISA bit (= 0) will make the corresponding PORTA pin an output. // 解释为什么需要TRISA0=1? After the A/D module has been configured as desired, // the selected channel must be acquired before the conversion is started. // The analog input channels must have their corresponding TRIS bits selected as inputs. TRISA0=1; // RA0口为输入口,电压输入口 TRISE0=0; // AD中断对应的LED灯的数据方向为输出 // 用来显示AD转换结果(10bit,对应10个LED) TRISC7=0; TRISC6=0; TRISD=0x00; // 1 = Port pin is > VIH,即高电平 ; 0 = Port pin is < VIL,即低电平 RA0=0; // 要不要这行语句没有影响,因为该端口是输入端口 RE0=0; // LED灯的初值为灭 // AD转换结果(10bit)对应的led灯初值为灭 RC7=0; RC6=0; RD=0x00; while(1) // 死循环,单片机初始化后,就一直运行这个死循环 { /****************AD初始化****************/ // The ADCON1 register, configures the functions of the port pins. //ADCON1=0x0e; //RA0为AD输入口. ADFM=1,转换后数据右移 //下面几条语句等价于上面一条语句 ADFM=1; // AD Result Format Select bit. 0 = Left justified. 1 = Right justified ADCS2=0; // AD Conversion Clock Select bit. // ADCS1=0; ADCS0=1;(ADCON0配置这两位) FOSC/8 PCFG3=1;PCFG2=1;PCFG1=1;PCFG0=0; //AD Port Configuration Control bits. 1110 D D D D D D D A //ADIE=0; //禁止AD中断 //AD中断使能 ADIE=1; ADIF=0; // Clear ADIF bit PEIE=1; // 允许外设中断 GIE=1; // 总中断允许 /******************启动一次AD转换*******************/ // The ADCON0 register, controls the operation of the A/D module. //ADCON0=0x01;//选择AN0通道准备AD转换,启动AD模块 //下面几条语句等价于上面一条语句 ADCS1=0;ADCS0=0; // AD Conversion Clock Select bits FOSC/8 CHS2=0;CHS1=0;CHS0=0; // Analog Channel Select bits。 000 = Channel 0 (AN0) GO_DONE=0; // AD Conversion Status bit。为什么叫用GO_DONE看一下pic.h头文件,该文件在HT-PICinclude目录下 ADON=1; //模数转换器使能位。 1 = A/D converter module is powered up asm("NOP"); //延时,让模拟电压稳定 asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); // When ADON = 1时,GO_DONE=1: AD conversion in progress set this bit(GO_DONE=1), starts the AD conversion. // it is automatically cleared by hardware when the AD conversion is complete GO_DONE=1; //开始进行AD转换 GO/DONE: A/D Conversion Status bit while(GO_DONE) continue;//等待AD转换结束,AD转换完成后,GO_DONE自动由1变成0 // The conversion of an analog input signal results in a corresponding 10-bit digital number. // The ADRESH(高8位):ADRESL(低8位) registers contain the 10-bit result of the AD conversion. // When the AD conversion is complete, the result is loaded into this AD Result register pair, // the GO/DONE bit is cleared and the A/D interrupt flag bit ADIF is set ADbuf=ADRESH*256+ADRESL;//转换结果一共有10bit。由于2^10为1024,所以这是一个4位数 0-1023 //ADbuf=ADRESL; // 将一个4位数用10位的LED灯显示出来 RC7 RC6 RD7...RD0 RC7= ADbuf/512; RC6=(ADbuf-RC7*512)/256; RD7=(ADbuf-RC7*512-RC6*256)/128; RD6=(ADbuf-RC7*512-RC6*256-RD7*128)/64; RD5=(ADbuf-RC7*512-RC6*256-RD7*128-RD6*64)/32; RD4=(ADbuf-RC7*512-RC6*256-RD7*128-RD6*64-RD5*32)/16; RD3=(ADbuf-RC7*512-RC6*256-RD7*128-RD6*64-RD5*32-RD4*16)/8; RD2=(ADbuf-RC7*512-RC6*256-RD7*128-RD6*64-RD5*32-RD4*16-RD3*8)/4; RD1=(ADbuf-RC7*512-RC6*256-RD7*128-RD6*64-RD5*32-RD4*16-RD3*8-RD2*4)/2; RD0= ADbuf%2; } } /*************中断服务程序***************/ void interrupt ISR(void)//PIC单片机的所有中断都是这样一个入口 { // When the AD conversion is complete, the A/D interrupt flag bit ADIF is set. if(ADIF==1) // 需要进一步判断是否为外部中断的溢出中断标志位 { // The interrupt flag bit(s) must be cleared in software before // re-enabling interrupts to avoid recursive interrupts //溢出中断标志位清零 如果ADIF出现上升沿,则产生中断,所以中断发生之后要清零。 ADIF=0; // 执行中断处理程序,执行中断产生时想要执行的功能 RE0=1; // 外部中断发生时,LED灯亮 } } 3 protues仿真结果 特别要注意ADFM位的选择,左对齐还是右对齐。这会影响ADbuf=ADRESH*256+ADRESL;这条语句对不对。 4 一般的ADC的首位都是符号位,为什么PIC单片机没有符号位,如何解释? 以下结论仅适用于单端ADC。 如上图所示,这是在PIC16F1513的数据手册找到的模拟信号到数字信号的转化图。根据芯片手册可知,该芯片的ADC转换结果一共有10bit。 从这幅图可以看出,最大值为3FFh(0011_1111_1111),最小值为00h。也就是说,如果有符号位,那么符号位肯定在这10bit内。现在看VREF-(负参考电压)这里,它的转换结果为00h。它最小可以接地,即0V,如下图所示。结论:如果电压小于0V,那么相当于会当成0V来被量化,AD量化结果还是为00h。 下面这几幅图是PIC16F877a的AD转换仿真图,这款芯片的转化结果也是10bit,所设置的VREF+(正参考电压)为VDD(+5v),负参考电压为地(0V)。 结论:PIC单片机的ADC转换机理应该是这样的,小于负参考电压的模拟输入电压的量化结果为全0,大于正参考电压的模拟输入电压的量化结果为全1。
上一篇:PIC16F15323单片机 (ADC)--汇编+C语言
下一篇:PIC16F877A单片机 (外部中断与定时器Timer0的综合使用)
推荐阅读最新更新时间:2024-11-13 10:40
推荐帖子
- 讨论一个问题:类似于鸡生蛋还蛋生鸡的问题
- 我们设备发生高压放电现象,主要单元设备进行放电。目前比较困惑的问题,是由于IGBT故障导致过压产生还是过压导致IGBT故障。讨论一个问题:类似于鸡生蛋还蛋生鸡的问题自己顶起来
- eeleader 工控电子
- 恩智浦LPC54100开发板发送状态(2015年03月25日)
- 活动详情:https://www.eeworld.com.cn/huodong/201412_NXP_LPC54100/下面网友的开发板已经发送,大家注意查收。关于LPC54100这块开发板,目前论坛的小伙伴们已经分享了好多资料,在论坛搜索“LPC54100”,就可以发现他们。第九批、2015年03月25日LPC54100开发板发送名单(快递:圆通)序号创意方案名称EEworld用户名货运单号1车载GPS伊亓50010
- nmg NXP MCU
- 轻松玩起24L01例程
- 本帖最后由sacq于2015-11-1723:59编辑 【硬件准备】材料:MSP430G2开发板2块,24L01模块(MINI版)2个,24L01BoosterPack板1块(有2块更好)相关可见:https://bbs.eeworld.com.cn/thread-475407-1-1.html楼主只准备了1块24L01BoosterPack板的无模块空板,需自己动手把24L01模块焊到板上;另一个24L01模块则直接焊在开发板的背面。两块板子的接
- sacq 微控制器 MCU
- 在msp430g2231中如何开启basic timer 的中断
- 我在g2231中的userguide中看到的IE1,即InterruptEnableRegister1,他控制的是Oscillatorfaultinterruptenable,这个是什么东西,还有要想开启g2231basictimer的中断该用什么语句呢?在Fx42x中用IE2=BTIE就可以开中断在msp430g2231中如何开启basictimer的中断设置基础时钟模块的时候,IE1一般都不置位的,因为默认的振荡器错误中断标志就是置一的,不知道楼主为什么想设置
- gh1134537617 微控制器 MCU
- tps65130芯片的几个问题
- 一,TPS65130具有正负(双路)输出的800mA升压电流,用于OLED和CCD传感器,24QFN。tps65130TI德州仪器_提供技术支持模拟产品芯片介绍:TPS6513x是双输出DC-DC转换器,在典型应用中产生高达15V的正输出电压和低至-15V的负输出电压,输出电流在200mA范围内,具体取决于输入电压与输出电压比。该器件的总效率高达85%,是便携式电池供电设备的理想选择。2.7V至5.5V的输入电压范围允许器件由电池或固定的3
- qwqwqw2088 模拟与混合信号
- 有关用2812的GPIO管脚模拟I2C总线时序的问题
- 现在的情况是:启动I2C总线后,发送器件地址(PCF8576CT,器件地址为70H,SA0,A2/A1/A0接地),后能检测到应答信号,但是接下来发送的数据就不能够检测到应答信号了。SDA管脚始终为1。不知到为什么。想各位大侠请教了。^_^有关用2812的GPIO管脚模拟I2C总线时序的问题用万用表测得SDA和SCL两个信号都是有信号的。我发送的数据是:70H(PCF8576CT的器件地址)、E0H(发送子地址)、48H(工作模式)发送70H后测得应答信号是正确的,发
- qy7551693 微控制器 MCU
设计资源 培训 开发板 精华推荐
- SI2415FS08-EVB,带有 UART 接口的 SI2415 ISOmodem 芯片评估板
- NB6L611MNGEVB,时钟/数据输入评估板
- 51单片机红外解码资料+源代码
- 用于 Intel Pentium VRE 处理器的 LT1585CM-3.3 3.3V/4.6A 低压差稳压器的典型应用
- LT6654BHS6-1.25 扩展电源范围电压基准的典型应用
- 使用 Microchip Technology 的 MIC4744YML 的参考设计
- OM13489: 面向Fm+开发板的通用16位通用IO子板
- 便携式吸烟仪(贴片版)
- 使用 Diodes Incorporated 的 AP1512T5 的参考设计
- 手持无线电通讯器