[牛人杂谈] N76E003的ADC

[复制链接]
827|20
 楼主 | 2018-7-8 10:38 | 显示全部楼层 |阅读模式

好多人说不知道参考电压,看这个图,就知道了,VDD嘛。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
| 2018-7-8 11:10 | 显示全部楼层
本帖最后由 tianxj01 于 2018-7-8 11:12 编辑

本来用Vdd作为Vref也没什么,对比那些内置Vref绝对精度比较差的带隙基准而言,大家通过控制单一电源电压值,就可以获得不错的精确性。
可坏就坏在,这一类采用VDD作为ADC基准的芯片,他们都是单片机,单片机本质内部有复杂的高频信号在运行,导致VCC上面非常容易产生随机的,各种不可预知的波动,这对ADC来说,采样速度要求低的,可以通过多次读取平均来抵消这个影响,对于需要高采样速率的数据,就让我们不知所措了。你好歹弄另外一个AVDD,并入ADC基准,或者至少弄一个ADC基准的旁路电容引脚这样的类似硬件配置,这样我们只需要通过一个简单退偶就可以既精确控制ADC基准,又单电源解决问题。
可貌似目前该类单片机,都只是简单的和数字系统直接连接,新唐如此,ST公司的  STM8如此,48引脚的STM32也是如此。这个非常坑。
 楼主 | 2018-7-8 12:26 | 显示全部楼层
      N76E003内嵌12位逐次逼近寄存器型(SAR)的模拟数字转换器(ADC)。模数转换模块负责将管脚上的模拟信号转换为12位二进制数据。N76E003支持8信道单端输入模式。内部带隙电压(band-gap voltage)为1.22V,同时也可用作内部ADC输入端。所有模拟电路复用同一组采样电路和同一组采样保持电容。该组采样保持电容为转换电路的输入端。然后转换器通过逐次逼近的方式得到有效结果并存放在ADC结果寄存器中。
 楼主 | 2018-7-8 12:31 | 显示全部楼层
在开始ADC转换前,通过设置ADCEN (ADCCON1.0)位使能ADC电路,从而激活ADC电路,由于ADC模块需要
额外功耗,一旦ADC转换模块不再使用,建议清零ADCEN位关闭ADC模块电路以节省功耗。
ADC转换输入管脚需要特别配置,通过ADCHS[2:0] 来选择采样所需要的ADC通道连接到采样电路上。同时,用
户需要通过PxMn寄存器把采样所用的管脚配置为“输入高阻模式” (input-only high impedance) 。配置后用于
ADC管脚与数字输出电路将断开,但数字输入电路仍然可以工作,因此数字输入将可能产生漏电流。所以还需要
通过配置AINDIDS寄存器相应位来关闭数字输入缓冲区。如上配置后,ADC输入脚将变成纯模拟输入电路。同
样ADC采样时钟也需要认真考虑。ADC最高时钟频率参考表
表 31‑9. 当采样时钟设置超过最大值时,采样结果数据为不可预测。
通过置ADCS位(ADCCON0.6)开启AD转换。当转换完成后,硬件会自动清除该位,同时置ADCF (ADCCON0.7)
位,如果之前ADC中断已使能,则会产生ADC中断。转换结果存放在ADCRH (高8位) 及 ADCRL (低4位)中。12
位转换结果值为

  1. void main (void)
  2. {
  3.                 InitialUART0_Timer1(115200);

  4.                 Enable_ADC_AIN3;                                                // Enable AIN0 P1.7 as ADC input, Find in "Function_define.h" - "ADC INIT"
  5.                 while(1)
  6.     {
  7.                         clr_ADCF;
  8.                         set_ADCS;                                                                        // ADC start trig signal
  9.       while(ADCF == 0);
  10.                         printf ("\n Value = 0x%bx",ADCRH);
  11.                         printf ("\n Value = 0x%bx",ADCRL);
  12.                         Timer0_Delay1ms(100);
  13.     }
  14. }
复制代码


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
 楼主 | 2018-7-8 12:34 | 显示全部楼层
上面的例子就是说明这个操作过程:
1,使能相应的通道,一共9个通道,0~7,带隙
2,清理中断标志位
3,启动ADC转换开关
4,等待标志位置位
5,读取转换结果的寄存器值
这样就完成了一轮一共通道的转换。
 楼主 | 2018-7-8 13:05 | 显示全部楼层
tianxj01 发表于 2018-7-8 11:10
本来用Vdd作为Vref也没什么,对比那些内置Vref绝对精度比较差的带隙基准而言,大家通过控制单一电源电压值 ...

其实用VDD有个好处啊,比如你通过ADC和一个已知的电阻,测量另外一个电阻,不管VDD怎么波动,都是准确的。就看使用在什么场合了,如果是测电压那就要用更加可靠的电源才行,而且最好VDD单独一路。
 楼主 | 2018-7-8 13:10 | 显示全部楼层
好多人说怕电源不稳干扰,其实官方说明了,PCB做的时候要考虑这些因素
内部及外部数字电路,可能影响采样结果的准确度。所以如果需要高精准的转换结果,请参考如下应用,以降低噪声电平干扰。
1. 模拟输入脚尽量离芯片越近越好,避免管脚附近有高速数字电路经过,并离高速数字电路越远越好。
2. 在转换过程中,将芯片进入空闲模式。
3. 如果模拟输入脚AIN在系统中同时需要切换做数字管脚,请确保在转换过程中不要做数字/模拟切换动作
 楼主 | 2018-7-8 13:22 | 显示全部楼层
外部触发的操作可以参考上面的图。
 楼主 | 2018-7-8 13:24 | 显示全部楼层
外部触发的,这种就是中断操作,你也可以查询操作
  1. /******************************************************************************
  2. * FUNCTION_PURPOSE: ADC interrupt Service Routine
  3. ******************************************************************************/
  4. void ADC_ISR (void) interrupt 11
  5. {
  6.     clr_ADCF;                               //clear ADC interrupt flag
  7.                 printf ("\n Value = 0x%bx",ADCRH);
  8. }

  9. /******************************************************************************
  10. The main C function.  Program execution starts
  11. here after stack initialization.
  12. ******************************************************************************/
  13. void main (void)
  14. {
  15.     Set_All_GPIO_Quasi_Mode;
  16.                 InitialUART0_Timer1(115200);
  17. /*---------------------------------------------------------------
  18.         ADC port trig initial setting toggle P0.4 to start ADC
  19. ----------------------------------------------------------------*/
  20.                 Enable_ADC_AIN0;                                                                                                                        // Enable AIN0 P1.7 as ADC pin
  21.                 P04_FALLINGEDGE_TRIG_ADC;                                                                                        // P0.4 falling edge as adc start trig signal
  22. // find ADC result in ADC interrupt
  23.     set_EADC;                                                                                                                                                        // Enable ADC interrupt (if use interrupt)
  24.                 EA = 1;                                                                                                                                                                // Enable global interrupt
  25. //        set_ADCS;                                                                                                                                                        // Trig P04 falling edge to start adc, no need set ADCS bit
  26.                 while(1);                                                                                                                                                        // Wait ADC interrupt


  27. }


复制代码

 楼主 | 2018-7-8 13:27 | 显示全部楼层
采集16次的平均滤波法
  1.                 int ADCdataH[16], ADCdataL[16], ADCsumH=0, ADCsumL=0;
  2.                 unsigned char ADCavgH, ADCavgL;
  3.                                
  4. /******************************************************************************
  5. The main C function.  Program execution starts
  6. here after stack initialization.
  7. ******************************************************************************/
  8. void main (void)
  9. {
  10.                 int i;                       
  11.                 P05_PushPull_Mode;
  12.                 P05 = 1;
  13.                 Timer0_Delay1ms(300);
  14.        
  15.                 P05 = 0;       
  16.                 Enable_ADC_AIN0;                                                // Enable AIN0 P1.7 as ADC input, Find in "Function_define.h" - "ADC INIT"
  17.                 ADCsumH = 0x0000;
  18.                 ADCsumL = 0x0000;
  19.                        
  20.                 for(i=0;i<16;i++)
  21.     {
  22.                         clr_ADCF;
  23.                         set_ADCS;                                                                        // ADC start trig signal
  24.       while(ADCF == 0);
  25.                         ADCdataH[i] = ADCRH;
  26.                         ADCdataL[i] = ADCRL;
  27.                 }               
  28.                
  29.                 for(i=0;i<16;i++)
  30.     {
  31.                         ADCsumH = ADCsumH + ADCdataH[i];
  32.                         ADCsumL = ADCsumL + ADCdataL[i];
  33.                 }                               

  34.                 ADCavgH = ADCsumH/16;
  35.                 ADCavgL = ADCsumL/16;
  36.                 P05 = 1;
  37.                 while(1);
  38. }
复制代码
 楼主 | 2018-7-8 13:30 | 显示全部楼层
本帖最后由 捉虫天师 于 2018-7-8 13:31 编辑

PWM触发的


  1. void ADC_ISR (void) interrupt 11
  2. {
  3.     clr_ADCF;                               // Clear ADC interrupt flag
  4.                 printf ("\n Value = 0x%bx",ADCRH);                // printf display will cause delay in ADC interrupt
  5.                 P30 ^= 1;                                                                                                                                // Check the P3.0 toggle at falling edge of PWM
  6. }



  7. void main (void)
  8. {
  9.     Set_All_GPIO_Quasi_Mode;
  10.                 InitialUART0_Timer1(9600);
  11.         
  12. /*-------------------------------------------------
  13.         ADC trig initial setting
  14.         Please modify #if value to open diffent type
  15. --------------------------------------------------*/

  16. // By PWM falling edge
  17.                 PWM0_P12_OUTPUT_ENABLE;                                
  18.                 Enable_ADC_AIN0;                                                                                                                // Enable AIN0 P1.7 as ADC input
  19.                 PWM0_FALLINGEDGE_TRIG_ADC;

  20. // Setting PWM value
  21.     PWMPH = 0x07;                                                                                                                                //Setting PWM value         
  22.     PWMPL = 0xFF;
  23.     PWM0H = 0x02;
  24.     PWM0L = 0xFF;
  25.           set_LOAD;                                                                                                                                                // PWM run
  26.     set_PWMRUN;
  27. // Setting ADC
  28.           set_EADC;                                                                                                                                                // Enable ADC interrupt (if use interrupt)
  29.                 EA = 1;        
  30.                 while(1);

  31. }
  32.       
复制代码


| 2018-7-8 18:23 | 显示全部楼层
仔细把官方资料看看,就不难了。
| 2018-7-8 22:34 | 显示全部楼层
除了PWM那个是怎么关联的, 其他的都看懂了。
| 2018-7-10 20:32 | 显示全部楼层
等我回去找个板子演练一下。
| 2018-7-10 22:56 | 显示全部楼层
这个系列的非常好用。
| 2018-7-12 16:11 | 显示全部楼层
我不知道用串口采集的电压波动很大

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
| 2018-7-12 16:17 | 显示全部楼层
不知道是不是连线造成的,等打了样品回来在测试。
| 2018-7-12 19:26 | 显示全部楼层
其实这样挺好用的。
| 2018-7-14 09:55 | 显示全部楼层
实际用一下,就知道好用了
| 2018-7-15 22:25 | 显示全部楼层
用过的都说好
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式
我要创建版块 申请成为版主

论坛热帖

快速回复 返回顶部 返回列表