This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] AM3352:PRU ADC 驱动器返回意外值

Guru**** 2931860 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/664570/am3352-pru-adc-driver-returning-unexpected-values

器件型号:AM3352

我们正在尝试了解如何从 BeagleBone Black 的 PRU 配置和访问 AIN 值。 我们已按照如下所示配置系统以读取 AIN0-2、但当我们从 FIFO 读取 AIN 值时、根据我们在输入端测量的电压、这些值与我们预期的值不匹配。

ADC_GET()根据计时器(当前为100ms)进行定期调用。 例如、我们看到的 AIN1值如下:

伏     FIFO
0.571V = 1057
0.900V = 1895
1.297V = 2705

数字值正在发生变化、但不像我们从公式中所期望的那样:

D = Vin *(2^n - 1)/Vref

Vin = 0.571 *(2^12-1)/ 1.8
VIN = 1299.025

我们实际上得到的是1057

我们正在尝试了解原因?

另一个观察结果:中心0.9V 与上面和下面的值之间的差值为0.002V 或28个计数。

0.9 - 0.571 = 0.329V = 838 ADC 计数
1.227 - 0.9 = 0.327V = 810 ADC 计数
----------------------------------
0.002V 的差值= 28次计数

 

在 out 设备树.dtsi 文件中、我们有:

tscadc{(&T)
  ADC{
     TI、ADC 通道=<0 1 2>;
  };
};

 

void ADC_Init_Steps (void)

   ADC_TSC (0x40)|=(1 << 2);// CTRL:步进配置寄存器是可写的

   ADC_TSC (0x64)&=(0x1F);// STEPCONFIG1:清除模式和采样平均值
   ADC_TSC (0x64)|=  // STEPCONFIG1:
           (
           (3 << 2)  // 8个样本平均调试 du
         |(0 < 19) //通道 ID 0 SEL_INP
         |(0 < 15) //通道 ID 0 SEL_INM
         |(0 < 0)  //启用软件、单次触发
           );
   ADC_TSC (0x68)= 0x98;     // STEPDELAY1:开路延迟= 0x98

   ADC_TSC (0x6C)&=(0x1F);// STEPCONFIG2:清除模式和采样平均值
   ADC_TSC (0x6C)|=  // STEPCONFIG2:
           (
           (3 << 2)  // 8个样本平均调试 du
         |(1 << 19) //通道 ID 1 SEL_INP
         |(1 << 15) //通道 ID 1 SEL_INM
         |(0 < 0)  //启用软件、单次触发
           );
   ADC_TSC (0x70)= 0x98;     // STEPDELAY2:开路延迟= 0x98

   ADC_TSC (0x74)&=(0x1F);// STEPCONFIG3:清除模式和采样平均值
   ADC_TSC (0x74)|=  // STEPCONFIG3:
           (
           (3 << 2)  // 8个样本平均调试 du
         |(2 << 19) //通道 ID 2 SEL_INP
         |(2 << 15) //通道 ID 2 SEL_INM
         |(0 < 0)  //启用软件、单次触发
           );
   ADC_TSC (0x78)= 0x98;     // STEPDELAY3:开路延迟= 0x98

   ADC_TSC (0x54)= 0;// STEPENABLE:禁用所有步骤

   ADC_TSC (0x40)&=~(1 << 2);// CTRL:步进配置寄存器受到保护



void ADC_DRAT_Fifos (void)

   //清除 FIFO
   uint16_t fifo_count;

   FIFO_COUNT = ADC_TSC (0xE4); // FIFO0COUNT
   while (fifo_count->0)
   {
       (空) ADC_TSC (0x100);// FIFO0DATA
   }

   FIFO_COUNT = ADC_TSC (0xF0); // FIFO1COUNT
   while (fifo_count->0)
   {
       (空) ADC_TSC (0x200);// FIFO1DATA
   }


空 ADC_Enable (bool 启用)

   uint32_t ctrl_mask =
           (
           (1 << 1)  // FIFO 中包含捕捉数据的步进 ID 号
         |(1 << 0)  //已启用
           );

   uint32_t STEP_ENABLE_MASK =
           (
           (1 << 1) //启用步骤1
         |(1 << 2) //启用步骤2
         |(1 << 3) //启用步骤3
           );
   if (启用)
   {
       ADC_TSC (0x54)= 0;// STEPENABLE:
       ADC_RELET_Fifos ();

       ADC_TSC (0x54)= STEP_ENABLE; // STEPENABLE:
       ADC_TSC (0x40)|= CTRL_MASK;// CTRL:
   }
   其他
   {
       ADC_TSC (0x54)= 0;       // STEPENABLE:
       ADC_TSC (0x40)&=~(CTRL_MASK);// CTRL:
   }


int32_t ADC_Get (uint32_t ADC_DATA[]、size_t NUMBER_OW_SAples)

   int timeout = 1000;

   //对数据进行旋转等待
   while (1)
   {
       if (超时--<= 0)
       {
           返回-1;
       }

       uint32_t fifo_count = ADC_TSC (0xE4); // FIFO0COUNT
       if (fifo_count >= number_of _samples")
       {
           int i;
           for (i=0;<fifo_count;i++))
           {
               ADC_DATA[i]= ADC_TSC (0x100);// FIFO0DATA
           }
           返回 fifo_count;
       }
   }

void ADC_Init (void)

   /*启用 TSC_ADC 时钟模块*/
   while (!(CM_PER_ADC_TSC 和0x2))
       CM_PER_ADC_TSC |= 0x2;

   ADC_TSC (0x48)=~(0xFFF << 16);// ADCRANGE max = 0xFFF、min = 0

   ADC_Init_Steps();
   ADC_Enable (0);
   ADC_RELET_Fifos ();

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您在 ARM 上运行什么软件?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    此代码在 PRU 而非 ARM 上运行。
    在 ARM 上、我们运行的是 TI 版本的 Linux。
    Linux AM335x-EVM 4.9.41-rt23-gc038d21a22 #2挤占 RT 监视器12月4日10:56:51 PST 2017 armv7l GNU/Linux
    这些行已添加到我们正在使用的器件树中
    tscadc{(&T)
    ADC{
    TI、ADC 通道=<0 1 2>;
    };
    };
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Daniel、您好!

    1) 1)您能否描述 ADC 测试的硬件设置以及测量电压的位置?
    2) 2)我不确定我是否理解"另一个观察结果:中心0.9V 与上面和下面的值之间的差值为0.002V 或28计数。"

    快速代码注释:这些行实际上不会保留模式和样本平均值吗?
    ADC_TSC (0x64)&=(0x1F);// STEPCONFIG1:清除模式和采样平均值
    ADC_TSC (0x6C)&=(0x1F);// STEPCONFIG2:清除模式和采样平均值
    ADC_TSC (0x74)&=(0x1F);// STEPCONFIG3:清除模式和采样平均值

    此致、
    Nick
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Nick:

    下面电路的输出端进入 BBB 上的335模拟引脚 P9.40。 该输出以0.9VDC 为中心。  

    电压可以升高或降低。 对于该测试、我们测量了0.571或1.227。

    0.9V - 0.571V = 0.329V
    1.227V - 0.9V = 0.327V

    因此、一个方向的电压差为0.329V、另一个方向的电压差为0.327V。 这是0.002V (0.329 - 0.327)的差异

    如果我们使用 FIFO 中的值来查看相同的数学运算、我们可以看到:

    1895 - 1057 = 838
    2705 - 1895 = 810

    因此、在一个方向上计数的差异为838、而在另一个方向上计数的差异为810。 这是28 (838 - 810)的差异。  我刚才观察到电压差为0.002V (2mV)、但这在我们的12位 ADC 中显示为28的数字差。 在1.8V 范围内感觉不正确的应用。 1 ADC 值应为0.012V 对吧? (2^12-1)/1.8V=0.0123、将其乘以28即可得到0.345V、而不是我们预期的0.002V。

    此外、0.9V 直流电感上升至1895计数、而不是2048。

    请提供建议。

    我刚才观察到电压差为0.002V (2mV)、但这在我们的12位 ADC 中显示为28的数字差。 在1.8V 范围内感觉不正确的应用。 1 ADC 值应为0.012V 对吧? (2^12-1)/1.8V=0.0123、将其乘以28即可得到0.345V、而不是我们预期的0.002V。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Daniel、您好!

    您在单端模式而不是差分模式下使用 ADC。 如果您设置 SEL_INM = VREFN (0x8)而不是设置 SEL_INP 的同一通道、您的行为是否会改变?

    此致、
    Nick
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Nick、我一直在与 Dan 一起处理这个问题。 您建议的更改对 ADC 值没有影响。 (清除步骤配置寄存器很好)我进行了清除更改并按如下方式更改了 SEL_INM 的配置。

    ADC_TSC (0x6C)&=~(0x1F);// STEPCONFIG2:清除模式和采样平均值
    ADC_TSC (0x6C)|=// STEPCONFIG2:
    (
    (3 << 2)// 8个样本平均调试 du
    |(1 << 19)//通道 ID 1 SEL_INP
    |(8 << 15)//(0 << 15)//通道 ID 1 SEL_INM
    |(0 < 0)//启用软件、单次触发
    )

    我没有设置 Diff 位 CNTRL 位--我找不到它的定义。

    此外、也未设置 SEL_RFM_SWC_1_0。 它是默认 VSSA

    还有其他想法吗?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Dan & Doug、您好!

    1) 1)为了清除步进配置寄存器、是否有任何原因不仅仅将整个寄存器设置为默认值0x0、以便我们确切地知道设置了哪些位?
    2) 2)该行是否影响结果?
    ADC_TSC (0x48)= 0xFFF << 16;//ADC_TSC (0x48)=~(0xFFF << 16);// ADCRANGE max = 0xFFF、min = 0

    此致、
    Nick
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Nick:

    我们将整个寄存 器设置为默认值0、并根据您的建议添加此值- ADC_TSC (0x48)= 0xFFF << 16;//ADC_TSC (0x48)=~(0xFFF << 16);// ADCRANGE max = 0xFFF、min = 0:结果完全相同。 我们接下来可以尝试什么?

    当我们更改输入时、值会发生变化、因此我们似乎正在读取正确的值、对吧? 我们感到惊讶的是、差分变化也没有影响任何东西。  

    我们没有设置 Diff CNTRL 位--我们找不到它的定义--你能不能建议吗?


    此外、也未设置 SEL_RFM_SWC_1_0。 它是默认 VSSA -这是什么以及应该是什么?

    我们只想读取单端模拟值-您能否提供一个列表、列出允许我们读取的所有寄存器设置?  

    谢谢- Dan 和 Doug

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Dan & Doug、您好!

    1) 1)我忘记了您在器件树中定义了 ADC。 这意味着系统使用 Linux 驱动程序来设置 ADC。 我们仅支持访问 ADC 的 Linux 驱动程序或访问 ADC 的 PRU、而不支持两者-因此您需要从器件树中注释 ADC 定义、以确保 Linux 不会与后台的 ADC 混淆。

    2)
    *如果位值为0、则差分控制为单端控制-我可以在 AM437x TRM 和 AM335x TRM 中的其他寄存器中找到它。
    *由于 STEPCONFIG 中的 Range_check=0、ADCRANGE 看起来不像执行任何操作
    * SEL_RFM 和 SEL_RFP 是对 AN[7:0]输入通道进行采样的 ADC 的 VDD 和 VSS 电压轨。 我很确定默认值是可以的、但我要进行双校验。

    现在、您是否可以通过注释器件树中的 ADC 定义来禁用 Linux 驱动程序? Linux 驱动程序可能会执行一些额外的设置、需要全部添加额外的代码来启用时钟等-如果是这样、请告诉我。

    此致、
    Nick
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    注释掉&tscadc 并重建/重新安装.dTB 文件无效。  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Doug 和 Dan、您好!

    好的、让我们备份一下。

    1) 1)您能否验证 Linux 驱动程序是否读取了正确的电压值? (确保没有硬件设置问题)

    确保在 DTS 文件中定义了 ADC、以便 Linux 驱动程序可以运行。 查看 Linux 内核 ADC 用户指南的"使用情况"部分。  

    2) 2) ADC_TSC ()是如何定义的? 作为一个宏、作为一个函数? [确保编译器不会优化诸如 (void) ADC_TSC (0x200)的调用;]

    此致、  

    Nick

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Doug 和 Dan、您好!

    我希望在你们的最后能够解决问题 我将此标记为"已关闭"、但如果我们有任何帮助、请发布回复!

    此致、
    Nick