TI中文支持网
TI专业的中文技术问题搜集分享网站

28335 的 ADC模块 读取的值和实测的值会有 100MV以内的误差,请教一下怎么优化?

初始化程序

#if (CPU_FRQ_150MHZ)     // Default – 150 MHz SYSCLKOUT
  #define ADC_MODCLK 0x3 // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 150/(2*3)   = 25.0 MHz
#endif
#if (CPU_FRQ_100MHZ)
  #define ADC_MODCLK 0x2 // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 100/(2*2)   = 25.0 MHz
#endif
void Init_ADC(void)
{
 uint16_t tmp = 0;

 EALLOW;
  SysCtrlRegs.HISPCP.all = ADC_MODCLK; // HSPCLK = SYSCLKOUT/ADC_MODCLK
 EDIS;

 AdcRegs.ADCTRL3.all = 0x00E0;   // Power up bandgap/reference/ADC circuits
 tmp = 5000;
 while(tmp–);     // 等待ADC稳定

 //以下开始设置ADC的控制寄存器、转换通道选择寄存器等
 AdcRegs.ADCST.all = 0x30;   //首先清除中断标志位
 AdcRegs.ADCOFFTRIM.all = 0;
 AdcRegs.ADCTRL3.all = 0x0E2;
 //bit7~6:ADCBGRFDN[1:0]:adc 缝隙上电,3上电
 //bit5:ADCPWDN:adc 模块上电,set1 上电
 //bit1~4:ADCCLKPS=1
 // bit0:SMODE_SEL =0  :set 0   顺序采样;   set1 :同步采样
 // 0 = [ADCCLK = HSPCLK/(CPS+1)], 1 = [ADCCLK = HSPCLK/2*(1)(CPS+1)]; HSPCLK 默认情况下 = CPUSYSCLK/2;
 //ADC module clock = HSPCLK/2*ADC_CKPS   = 25.0MHz/(1*2) = 12.5MHz
//设置为顺序采样模式 0 = 连续采样方式 1 = 并发采样方式
 AdcRegs.ADCTRL1.all = 0x0F50;
 /*bit13~12:SUSMOD=0;
 bit11~8:ACQ_PS =F :16 ADC clocks;
 bit7: CPS =0时钟预分频1
 bit6: CONT_RUN=1;//设置为启停模式 0 = 启停模式,1 = 连续转换模式
 bit5:SEQ_OVRD = 0
 bit4:SEQ_CASC =1//级联模式 0 = 双序列发生器方式, 1 = 级联模式
 */
 //AdcRegs.ADCTRL1.bit.CONT_RUN = 1;

 AdcRegs.ADCTRL2.all = 0x0000;
 AdcRegs.ADCMAXCONV.all = 0x0F;   //最大转换16通道

 AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0;  // ADCINA0 & ADCINB0
 AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 1;  // ADCINA1 & ADCINB1
 AdcRegs.ADCCHSELSEQ1.bit.CONV02 = 2;  // ADCINA2 & ADCINB2
 AdcRegs.ADCCHSELSEQ1.bit.CONV03 = 3;  // ADCINA3 & ADCINB3

 AdcRegs.ADCCHSELSEQ2.bit.CONV04 = 4;  // ADCINA4 & ADCINB4
 AdcRegs.ADCCHSELSEQ2.bit.CONV05 = 5;  // ADCINA5 & ADCINB5
 AdcRegs.ADCCHSELSEQ2.bit.CONV06 = 6;  // ADCINA6 & ADCINB6
 AdcRegs.ADCCHSELSEQ2.bit.CONV07 = 7;  // ADCINA7 & ADCINB7

 AdcRegs.ADCCHSELSEQ3.bit.CONV08 = 8;  // ADCINA8 & ADCINB8
 AdcRegs.ADCCHSELSEQ3.bit.CONV09 = 9;  // ADCINA9 & ADCINB9
 AdcRegs.ADCCHSELSEQ3.bit.CONV10 = 10;  // ADCINA10 & ADCINB10
 AdcRegs.ADCCHSELSEQ3.bit.CONV11 = 11;  // ADCINA11 & ADCINB11

 AdcRegs.ADCCHSELSEQ4.bit.CONV12 = 12;  // ADCINA12 & ADCINB12
 AdcRegs.ADCCHSELSEQ4.bit.CONV13 = 13;  // ADCINA13 & ADCINB13
 AdcRegs.ADCCHSELSEQ4.bit.CONV14 = 14;  // ADCINA14 & ADCINB14
 AdcRegs.ADCCHSELSEQ4.bit.CONV15 = 15;  // ADCINA15 & ADCINB15
}

系统时钟用的是150M

读取结果的函数

void Test_Ai_Handle(Ubyte *paramData)
{
     uint16_t i = 0;
  uint16_t value[16];
  uint16_t chan = 0;
  float tmp = 0;
  uint16_t  delay_tmp = 0;

  chan = paramData[0];
  memset((void *)value, 0, sizeof(value));

  /* handle */
  for(i=0; i<10; i++)//3 change 10
  {
   /* start sw conversion */
   AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1;   // Reset SEQ1
   AdcRegs.ADCTRL2.bit.SOC_SEQ1 = 1;   // sofware start ADC

   /* wait conversion done */
   delay_tmp = 1000;
   while(delay_tmp–);
   while(AdcRegs.ADCST.bit.INT_SEQ1 == 0);

   /* value save */
   value[0] += ((AdcRegs.ADCRESULT0) >> 4);
   value[1] += ((AdcRegs.ADCRESULT1) >> 4);
   value[2] += ((AdcRegs.ADCRESULT2) >> 4);
   value[3] += ((AdcRegs.ADCRESULT3) >> 4);
   value[4] += ((AdcRegs.ADCRESULT4) >> 4);
   value[5] += ((AdcRegs.ADCRESULT5) >> 4);
   value[6] += ((AdcRegs.ADCRESULT6) >> 4);
   value[7] += ((AdcRegs.ADCRESULT7) >> 4);
   value[8] += ((AdcRegs.ADCRESULT8) >> 4);
   value[9] += ((AdcRegs.ADCRESULT9) >> 4);
   value[10] += ((AdcRegs.ADCRESULT10) >> 4);
   value[11] += ((AdcRegs.ADCRESULT11) >> 4);
   value[12] += ((AdcRegs.ADCRESULT12) >> 4);
   value[13] += ((AdcRegs.ADCRESULT13) >> 4);
   value[14] += ((AdcRegs.ADCRESULT14) >> 4);
   value[15] += ((AdcRegs.ADCRESULT15) >> 4);
  }

  tmp = (float)(value[chan-1]) / 10;
  tmp = (3000 * tmp / 4095) ;

  if(tmp >= 1499)
   tmp += 1;
  else;
  paramData[3] = Type_Extrh_U8_Of_U16_TE(tmp);
  paramData[4] = Type_Extrl_U8_Of_U16_TE(tmp);

}

把ADC模块的误差缩小到30MV 以内

Annie Liu:

为更加有效地解决您的问题,我们建议您将问题发布在E2E英文技术论坛上https://e2e.ti.com/support/microcontrollers/c2000/f/171,将由资深的工程师为您提供帮助。我们的E2E英文社区有TI专家进行回复,并得到全球各地工程师的支持,分享他们的知识和经验。

初始化程序

#if (CPU_FRQ_150MHZ)     // Default – 150 MHz SYSCLKOUT
  #define ADC_MODCLK 0x3 // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 150/(2*3)   = 25.0 MHz
#endif
#if (CPU_FRQ_100MHZ)
  #define ADC_MODCLK 0x2 // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 100/(2*2)   = 25.0 MHz
#endif
void Init_ADC(void)
{
 uint16_t tmp = 0;

 EALLOW;
  SysCtrlRegs.HISPCP.all = ADC_MODCLK; // HSPCLK = SYSCLKOUT/ADC_MODCLK
 EDIS;

 AdcRegs.ADCTRL3.all = 0x00E0;   // Power up bandgap/reference/ADC circuits
 tmp = 5000;
 while(tmp–);     // 等待ADC稳定

 //以下开始设置ADC的控制寄存器、转换通道选择寄存器等
 AdcRegs.ADCST.all = 0x30;   //首先清除中断标志位
 AdcRegs.ADCOFFTRIM.all = 0;
 AdcRegs.ADCTRL3.all = 0x0E2;
 //bit7~6:ADCBGRFDN[1:0]:adc 缝隙上电,3上电
 //bit5:ADCPWDN:adc 模块上电,set1 上电
 //bit1~4:ADCCLKPS=1
 // bit0:SMODE_SEL =0  :set 0   顺序采样;   set1 :同步采样
 // 0 = [ADCCLK = HSPCLK/(CPS+1)], 1 = [ADCCLK = HSPCLK/2*(1)(CPS+1)]; HSPCLK 默认情况下 = CPUSYSCLK/2;
 //ADC module clock = HSPCLK/2*ADC_CKPS   = 25.0MHz/(1*2) = 12.5MHz
//设置为顺序采样模式 0 = 连续采样方式 1 = 并发采样方式
 AdcRegs.ADCTRL1.all = 0x0F50;
 /*bit13~12:SUSMOD=0;
 bit11~8:ACQ_PS =F :16 ADC clocks;
 bit7: CPS =0时钟预分频1
 bit6: CONT_RUN=1;//设置为启停模式 0 = 启停模式,1 = 连续转换模式
 bit5:SEQ_OVRD = 0
 bit4:SEQ_CASC =1//级联模式 0 = 双序列发生器方式, 1 = 级联模式
 */
 //AdcRegs.ADCTRL1.bit.CONT_RUN = 1;

 AdcRegs.ADCTRL2.all = 0x0000;
 AdcRegs.ADCMAXCONV.all = 0x0F;   //最大转换16通道

 AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0;  // ADCINA0 & ADCINB0
 AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 1;  // ADCINA1 & ADCINB1
 AdcRegs.ADCCHSELSEQ1.bit.CONV02 = 2;  // ADCINA2 & ADCINB2
 AdcRegs.ADCCHSELSEQ1.bit.CONV03 = 3;  // ADCINA3 & ADCINB3

 AdcRegs.ADCCHSELSEQ2.bit.CONV04 = 4;  // ADCINA4 & ADCINB4
 AdcRegs.ADCCHSELSEQ2.bit.CONV05 = 5;  // ADCINA5 & ADCINB5
 AdcRegs.ADCCHSELSEQ2.bit.CONV06 = 6;  // ADCINA6 & ADCINB6
 AdcRegs.ADCCHSELSEQ2.bit.CONV07 = 7;  // ADCINA7 & ADCINB7

 AdcRegs.ADCCHSELSEQ3.bit.CONV08 = 8;  // ADCINA8 & ADCINB8
 AdcRegs.ADCCHSELSEQ3.bit.CONV09 = 9;  // ADCINA9 & ADCINB9
 AdcRegs.ADCCHSELSEQ3.bit.CONV10 = 10;  // ADCINA10 & ADCINB10
 AdcRegs.ADCCHSELSEQ3.bit.CONV11 = 11;  // ADCINA11 & ADCINB11

 AdcRegs.ADCCHSELSEQ4.bit.CONV12 = 12;  // ADCINA12 & ADCINB12
 AdcRegs.ADCCHSELSEQ4.bit.CONV13 = 13;  // ADCINA13 & ADCINB13
 AdcRegs.ADCCHSELSEQ4.bit.CONV14 = 14;  // ADCINA14 & ADCINB14
 AdcRegs.ADCCHSELSEQ4.bit.CONV15 = 15;  // ADCINA15 & ADCINB15
}

系统时钟用的是150M

读取结果的函数

void Test_Ai_Handle(Ubyte *paramData)
{
     uint16_t i = 0;
  uint16_t value[16];
  uint16_t chan = 0;
  float tmp = 0;
  uint16_t  delay_tmp = 0;

  chan = paramData[0];
  memset((void *)value, 0, sizeof(value));

  /* handle */
  for(i=0; i<10; i++)//3 change 10
  {
   /* start sw conversion */
   AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1;   // Reset SEQ1
   AdcRegs.ADCTRL2.bit.SOC_SEQ1 = 1;   // sofware start ADC

   /* wait conversion done */
   delay_tmp = 1000;
   while(delay_tmp–);
   while(AdcRegs.ADCST.bit.INT_SEQ1 == 0);

   /* value save */
   value[0] += ((AdcRegs.ADCRESULT0) >> 4);
   value[1] += ((AdcRegs.ADCRESULT1) >> 4);
   value[2] += ((AdcRegs.ADCRESULT2) >> 4);
   value[3] += ((AdcRegs.ADCRESULT3) >> 4);
   value[4] += ((AdcRegs.ADCRESULT4) >> 4);
   value[5] += ((AdcRegs.ADCRESULT5) >> 4);
   value[6] += ((AdcRegs.ADCRESULT6) >> 4);
   value[7] += ((AdcRegs.ADCRESULT7) >> 4);
   value[8] += ((AdcRegs.ADCRESULT8) >> 4);
   value[9] += ((AdcRegs.ADCRESULT9) >> 4);
   value[10] += ((AdcRegs.ADCRESULT10) >> 4);
   value[11] += ((AdcRegs.ADCRESULT11) >> 4);
   value[12] += ((AdcRegs.ADCRESULT12) >> 4);
   value[13] += ((AdcRegs.ADCRESULT13) >> 4);
   value[14] += ((AdcRegs.ADCRESULT14) >> 4);
   value[15] += ((AdcRegs.ADCRESULT15) >> 4);
  }

  tmp = (float)(value[chan-1]) / 10;
  tmp = (3000 * tmp / 4095) ;

  if(tmp >= 1499)
   tmp += 1;
  else;
  paramData[3] = Type_Extrh_U8_Of_U16_TE(tmp);
  paramData[4] = Type_Extrl_U8_Of_U16_TE(tmp);

}

把ADC模块的误差缩小到30MV 以内

mangui zhang:我觉得你将测试的结果对比一下如果固定偏差一个值就讲采集的值减去一个固定的值
这种做法工程中常用

初始化程序

#if (CPU_FRQ_150MHZ)     // Default – 150 MHz SYSCLKOUT
  #define ADC_MODCLK 0x3 // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 150/(2*3)   = 25.0 MHz
#endif
#if (CPU_FRQ_100MHZ)
  #define ADC_MODCLK 0x2 // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 100/(2*2)   = 25.0 MHz
#endif
void Init_ADC(void)
{
 uint16_t tmp = 0;

 EALLOW;
  SysCtrlRegs.HISPCP.all = ADC_MODCLK; // HSPCLK = SYSCLKOUT/ADC_MODCLK
 EDIS;

 AdcRegs.ADCTRL3.all = 0x00E0;   // Power up bandgap/reference/ADC circuits
 tmp = 5000;
 while(tmp–);     // 等待ADC稳定

 //以下开始设置ADC的控制寄存器、转换通道选择寄存器等
 AdcRegs.ADCST.all = 0x30;   //首先清除中断标志位
 AdcRegs.ADCOFFTRIM.all = 0;
 AdcRegs.ADCTRL3.all = 0x0E2;
 //bit7~6:ADCBGRFDN[1:0]:adc 缝隙上电,3上电
 //bit5:ADCPWDN:adc 模块上电,set1 上电
 //bit1~4:ADCCLKPS=1
 // bit0:SMODE_SEL =0  :set 0   顺序采样;   set1 :同步采样
 // 0 = [ADCCLK = HSPCLK/(CPS+1)], 1 = [ADCCLK = HSPCLK/2*(1)(CPS+1)]; HSPCLK 默认情况下 = CPUSYSCLK/2;
 //ADC module clock = HSPCLK/2*ADC_CKPS   = 25.0MHz/(1*2) = 12.5MHz
//设置为顺序采样模式 0 = 连续采样方式 1 = 并发采样方式
 AdcRegs.ADCTRL1.all = 0x0F50;
 /*bit13~12:SUSMOD=0;
 bit11~8:ACQ_PS =F :16 ADC clocks;
 bit7: CPS =0时钟预分频1
 bit6: CONT_RUN=1;//设置为启停模式 0 = 启停模式,1 = 连续转换模式
 bit5:SEQ_OVRD = 0
 bit4:SEQ_CASC =1//级联模式 0 = 双序列发生器方式, 1 = 级联模式
 */
 //AdcRegs.ADCTRL1.bit.CONT_RUN = 1;

 AdcRegs.ADCTRL2.all = 0x0000;
 AdcRegs.ADCMAXCONV.all = 0x0F;   //最大转换16通道

 AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0;  // ADCINA0 & ADCINB0
 AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 1;  // ADCINA1 & ADCINB1
 AdcRegs.ADCCHSELSEQ1.bit.CONV02 = 2;  // ADCINA2 & ADCINB2
 AdcRegs.ADCCHSELSEQ1.bit.CONV03 = 3;  // ADCINA3 & ADCINB3

 AdcRegs.ADCCHSELSEQ2.bit.CONV04 = 4;  // ADCINA4 & ADCINB4
 AdcRegs.ADCCHSELSEQ2.bit.CONV05 = 5;  // ADCINA5 & ADCINB5
 AdcRegs.ADCCHSELSEQ2.bit.CONV06 = 6;  // ADCINA6 & ADCINB6
 AdcRegs.ADCCHSELSEQ2.bit.CONV07 = 7;  // ADCINA7 & ADCINB7

 AdcRegs.ADCCHSELSEQ3.bit.CONV08 = 8;  // ADCINA8 & ADCINB8
 AdcRegs.ADCCHSELSEQ3.bit.CONV09 = 9;  // ADCINA9 & ADCINB9
 AdcRegs.ADCCHSELSEQ3.bit.CONV10 = 10;  // ADCINA10 & ADCINB10
 AdcRegs.ADCCHSELSEQ3.bit.CONV11 = 11;  // ADCINA11 & ADCINB11

 AdcRegs.ADCCHSELSEQ4.bit.CONV12 = 12;  // ADCINA12 & ADCINB12
 AdcRegs.ADCCHSELSEQ4.bit.CONV13 = 13;  // ADCINA13 & ADCINB13
 AdcRegs.ADCCHSELSEQ4.bit.CONV14 = 14;  // ADCINA14 & ADCINB14
 AdcRegs.ADCCHSELSEQ4.bit.CONV15 = 15;  // ADCINA15 & ADCINB15
}

系统时钟用的是150M

读取结果的函数

void Test_Ai_Handle(Ubyte *paramData)
{
     uint16_t i = 0;
  uint16_t value[16];
  uint16_t chan = 0;
  float tmp = 0;
  uint16_t  delay_tmp = 0;

  chan = paramData[0];
  memset((void *)value, 0, sizeof(value));

  /* handle */
  for(i=0; i<10; i++)//3 change 10
  {
   /* start sw conversion */
   AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1;   // Reset SEQ1
   AdcRegs.ADCTRL2.bit.SOC_SEQ1 = 1;   // sofware start ADC

   /* wait conversion done */
   delay_tmp = 1000;
   while(delay_tmp–);
   while(AdcRegs.ADCST.bit.INT_SEQ1 == 0);

   /* value save */
   value[0] += ((AdcRegs.ADCRESULT0) >> 4);
   value[1] += ((AdcRegs.ADCRESULT1) >> 4);
   value[2] += ((AdcRegs.ADCRESULT2) >> 4);
   value[3] += ((AdcRegs.ADCRESULT3) >> 4);
   value[4] += ((AdcRegs.ADCRESULT4) >> 4);
   value[5] += ((AdcRegs.ADCRESULT5) >> 4);
   value[6] += ((AdcRegs.ADCRESULT6) >> 4);
   value[7] += ((AdcRegs.ADCRESULT7) >> 4);
   value[8] += ((AdcRegs.ADCRESULT8) >> 4);
   value[9] += ((AdcRegs.ADCRESULT9) >> 4);
   value[10] += ((AdcRegs.ADCRESULT10) >> 4);
   value[11] += ((AdcRegs.ADCRESULT11) >> 4);
   value[12] += ((AdcRegs.ADCRESULT12) >> 4);
   value[13] += ((AdcRegs.ADCRESULT13) >> 4);
   value[14] += ((AdcRegs.ADCRESULT14) >> 4);
   value[15] += ((AdcRegs.ADCRESULT15) >> 4);
  }

  tmp = (float)(value[chan-1]) / 10;
  tmp = (3000 * tmp / 4095) ;

  if(tmp >= 1499)
   tmp += 1;
  else;
  paramData[3] = Type_Extrh_U8_Of_U16_TE(tmp);
  paramData[4] = Type_Extrl_U8_Of_U16_TE(tmp);

}

把ADC模块的误差缩小到30MV 以内

user4329368:

回复 mangui zhang:

但是有些AI通道会左右摆动。这个问题解决不了。ADC模块12bit的分辨率,误差不应该有这个大。

赞(0)
未经允许不得转载:TI中文支持网 » 28335 的 ADC模块 读取的值和实测的值会有 100MV以内的误差,请教一下怎么优化?
分享到: 更多 (0)