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.

[参考译文] CC2674R10:在连接 BLE 时、通过 SPI 获取错误的 ADC 数据以读取传感器

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

https://e2e.ti.com/support/wireless-connectivity/bluetooth-group/bluetooth/f/bluetooth-forum/1294711/cc2674r10-get-the-wrong-adc-data-through-spi-to-read-sensor-when-connecting-ble

器件型号:CC2674R10
主题中讨论的其他器件:AFE4960TMP117

大家好、

我正在从事 ECG 设计、尝试 通过 SPI 读取 AFE4960数据并将数据发出。

我将 CC1354 project_zero 示例迁移到 CC2674、并使用多传感器中的温度服务、通过 BLE 传输 ECG 信号。 来自 AFE 的 ADC 数据为128个样本(浮点型)。 我将数据发出32次、每次16个字节。 我只需修改 (UArg) profile_readSensor 函数即可读取 AFE4960。 下面是一些代码。

 

bStatus_t TMP117Profile_init(I2C_Handle *pHandle)
{
  bStatus_t status = SUCCESS;
  if ((pHandle == NULL) || (*pHandle == NULL))
  {
    return INVALIDPARAMETER;
  }

  // Store pointer to i2c handle
  pI2cHandle = pHandle;

  // Initialize params
  OPT3001_Params_init(&opt3001Params);
  // Enable sensor
  status  = TMP117Profile_enable();
//  status  = 0;

  // Register with common sensors module


  // Register with common sensors module
  if (status == SUCCESS)
  {
    status = Sensors_registerCbs(TMP117_SERV_UUID, processCBs);
  }

  if (status == SUCCESS)
  {
    // Add service
    status = TMP117_AddService();
  }

  if (status == SUCCESS)
  {
    // Register callbacks with service
    status = TMP117_RegisterProfileCBs(&sensorServiceCBs);
  }

  spiffs_file fd;
  spiffs_config fsConfig;
  //uint8_t errFlag=0;

  Display_init();
  display = Display_open(Display_Type_UART, NULL);
  uint8_t         transmitBuffer[MSGSIZE]={0x00,0x00,0x00,0x08};
  uint8_t         receiveBuffer[MSGSIZE];
  bool            transferOK;

  GPIO_setConfig(CONFIG_ADC_RDY, GPIO_CFG_IN_PD | GPIO_CFG_IN_INT_RISING);
  GPIO_setCallback(CONFIG_ADC_RDY, ADCRDYFxn0);

  GPIO_write(CONFIG_AFE_RST, 0);
  usleep(50);
  GPIO_write(CONFIG_AFE_RST, 1);
  GPIO_write(CONFIG_GPIO_CS, 1);
  //for(uint8_t i=0;i<8;i++)
  //{
   //   transmitBuffer[i]=i;
 // }
  SPI_init();  // Initialize the SPI driver
  SPI_Params_init(&spiParams);  // Initialize SPI parameters
  spiParams.frameFormat = SPI_POL0_PHA0;
  /* See device-specific technical reference manual for supported speeds */
  spiParams.bitRate     = 10000000;
  spiParams.dataSize = 8;       // 8-bit data size
  Log_info0("Starting the AFE4960 example\n---------------------------------------------------");

  GPIO_enableInt(CONFIG_ADC_RDY);

#ifdef test_ecg
    /*software reset AFE4960*/
    errFlag=biosensor_SPI_config(CONFIG_SPI_0,0x00,0x08,&spiParams,&spiTransaction);
    errFlag=biosensor_SPI_config(CONFIG_SPI_0,0x01,0x00,&spiParams,&spiTransaction);
    errFlag=biosensor_SPI_config(CONFIG_SPI_0,0x00,0x02,&spiParams,&spiTransaction);

    /*measurement mode config*/
    errFlag=biosensor_SPI_config(CONFIG_SPI_0,0x0a,0x84004a,&spiParams,&spiTransaction);
    /*clock tree config */
    errFlag=biosensor_SPI_config(CONFIG_SPI_0,0xbf,0x012682,&spiParams,&spiTransaction);
    /*clock config ,see table 7-9*/
    errFlag=biosensor_SPI_config(CONFIG_SPI_0,0xc0,0x120e20,&spiParams,&spiTransaction);
    /*Bio-Z excitation config fEXC_BIOZ=1Hz */
    errFlag=biosensor_SPI_config(CONFIG_SPI_0,0xcc,0x001f40,&spiParams,&spiTransaction);
    /*DAC output swing config ±256mV */
    errFlag=biosensor_SPI_config(CONFIG_SPI_0,0xcd,0x000402,&spiParams,&spiTransaction);
    /*Bio-z output at ECG1 and ECG2*/
    errFlag=biosensor_SPI_config(CONFIG_SPI_0,0xcb,0x000065,&spiParams,&spiTransaction);
    /*128kHz don't output at GPIO2*/
    errFlag=biosensor_SPI_config(CONFIG_SPI_0,0x4b,0x000100,&spiParams,&spiTransaction);
    /*enablt interrupt output at GPIO2*/
    errFlag=biosensor_SPI_config(CONFIG_SPI_0,0x29,0x080000,&spiParams,&spiTransaction);
    /*test signal input at ECG1 and ECG2*/
    errFlag=biosensor_SPI_config(CONFIG_SPI_0,0xc8,0x010184,&spiParams,&spiTransaction);
    /*count RAC=96*/
    errFlag=biosensor_SPI_config(CONFIG_SPI_0,0xc1,0x000080,&spiParams,&spiTransaction);
    /*REG_NUM_TS=1 and TS0, TS1 */
    errFlag=biosensor_SPI_config(CONFIG_SPI_0,0xc4,0x000001,&spiParams,&spiTransaction);
    /*TS0=E, TS1=E*/
    errFlag=biosensor_SPI_config(CONFIG_SPI_0,0xc2,0x000009,&spiParams,&spiTransaction);
    /*FIFO_RDY interrupt on ADC_RDY pin*/
    errFlag=biosensor_SPI_config(CONFIG_SPI_0,0x42,0x081fe0,&spiParams,&spiTransaction);
    /*FIFO_RDY interrupt on ADC_RDY pin*/
    //errFlag=biosensor_SPI_config(CONFIG_SPI_0,0x02,0x000001,&spiParams,&spiTransaction);
    /*selct page 0*/
    errFlag=biosensor_SPI_config(CONFIG_SPI_0,0x01,0x000000,&spiParams,&spiTransaction);
    /*clr count*/
    errFlag=biosensor_SPI_config(CONFIG_SPI_0,0x00,0x000002,&spiParams,&spiTransaction);
    /*enable fifo */
    errFlag=biosensor_SPI_config(CONFIG_SPI_0,0x00,0x000040,&spiParams,&spiTransaction);
    /*enable timer*/
    errFlag=biosensor_SPI_config(CONFIG_SPI_0,0x1d,0xC00000,&spiParams,&spiTransaction);
#endif
    Log_info0("finish configuration---------------------------------------------------");
//  if (dataRDY!=0)
//  {
//      dataRDY=0;
//      GPIO_disableInt(CONFIG_ADC_RDY);
//      errFlag=biosensor_SPIFIFO_readout(CONFIG_SPI_0,0xff,385,&spiParams,&spiTransaction);

    // Create one-shot clock for periodic sensor reading event
    if (status == SUCCESS)
    {
    uint8_t period = 0;
    TMP117_GetParameter(TMP117_PERIOD_ID, &period);
    Util_constructClock(&clkPeriodic, Sensors_clockHandler,
                        period * SENSOR_PERIOD_RESOLUTION, 0,
                        false, (UArg)profile_readSensor);    // Read the AFE4960 adc data by spi
//    GPIO_enableInt(CONFIG_ADC_RDY);
    profile_initialized = TRUE;
    Log_info0("TMP117 Profile Initialized");
    }
  else
  {
    Log_error1("TMP117 Profile failed to initialize with status 0x%x", status);
  }

  return status;
}

static bStatus_t profile_readSensor(uint8_t *params)
{
  if (dataRDY!=0) // When data ready, dataRDY = 1
     {
        dataRDY=0;
        GPIO_disableInt(CONFIG_ADC_RDY); // disable the interrupt
        errFlag=biosensor_SPIFIFO_readout(CONFIG_SPI_0,0xff,385,&spiParams,&spiTransaction);// read the adc data and store in ADCdatareceiveBuffer
    for(char i=0;i<128;i++)                                                                  // transfer the data to float *128
               {
           ADCdataconvert[i]=(uint32_t)((ADCdatareceiveBuffer[3*i+1]&(0xff))<<16)|
                   (uint32_t)((ADCdatareceiveBuffer[3*i+2]&(0xff))<<8)|
                   (uint32_t)((ADCdatareceiveBuffer[3*i+3]&(0xff)));
           mid=(uint32_t)(ADCdataconvert[i]&0x800000);
 //          mid=ADCdataconvert[i];
           if(mid!=0x800000)
               {
               adcdata[i]=(float)(ADCdataconvert[i]*0.0004768)*(float)1.1;

               }
           else
               {
               adcdata[i]=(float)((16777215-ADCdataconvert[i])*0.0004768)*(float)(-1.1);

               }
 //          adcdata[i] = adcdata[i]/10;
//           Display_printf(display, 0, 0, "%f", adcdata[i]);
               }
    for(char ii=0;ii<32;ii++)
    {

//    lux = 0.0121*lux+362.48;

    // Set profile value (and notify if notifications are enabled)
    TMP117_SetParameter(TMP117_DATA_ID, 16, &adcdata[ii*4]);            // send the 16 byte data BY BLE
    Log_info1("ECG count: %d", adcdata[ii*4]);
//    Log_info1("ECG value: %d", adcdata[ii]);
    // Start the next period
Util_startClock(&clkPeriodic);
  }
    GPIO_enableInt(CONFIG_ADC_RDY);
     }
  return SUCCESS;
}
 

该程序在 未与移动应用程序连接时运行良好。 我可以在 CCS 中显示的 adcdata [128]中获得所需的波形。 请参阅下面的 pic。 adcdata [128]被作为 正弦波加载  

但是、当我将电路板与移动应用相连接时、从 ADC 读取的数据出错。  ADC 缓冲区中有如此多的重复数据。 您能在这里提供一些建议吗? 如何进行正确的数据传输?

马修

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

    Matthew、您好!

    感谢您与我们联系。

    我知道当 CC2674器件与电话连接时、ADCdataconvert []表中存储的数据不符合预期。

    您能否查看以下内容、以便我们更好地了解可能发生的情况?

    -在未建立连接时,您是否可以确认 ADCdataconvert []表包含正确的数据?

    -您能否使用逻辑分析仪来验证是否执行了正确的 SPI 操作? 您是否看到传感器输出了正确的 SPI 数据?

    -您能否检查 SPI 缓冲区中的数据是否与传感器输出的数据匹配?

    除此之外,我觉得 profile_readSensor ()函数是在 SWI 上下文中执行的。 是正确的假设吗?
    Profile_readSensor()不应在 SWI 上下文中执行,而应在任务上下文中执行。 我之所以这么说、是因为该处理量和对栈函数的调用(在 TMP117_SetParameter 中完成)不应在 SWI 上下文中完成。
    simple_peripheral 示例展示了如何在任务上下文中执行时钟处理程序函数 (请参阅 clkPeriodic、SimplePeripheral_clockHandler 以及最终的 SP_PERIOD_EVT)。

    我希望这将有所帮助、

    此致、

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    profile_readSensor ()不应在 SWI 上下文中执行,而应在任务上下文中执行

    您好、Clement、
    你的意思是我需要把  profile_readSensor ()作为回调函数放在 Util_structClock 函数 的 Clock_Func Ptr clockCB 中,以便进行数据处理和栈调用?

    马修

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

    Matthew、您好

    您的意思是我需要把  profile_readSensor ()作为 UTIL_structClock 函 数的 Clock_Func Ptr clockCB 中的回调函数来进行数据处理和栈调用吗?

    不完全是-因为这仍会导致在 SWI 上下文中执行处理并调用堆栈。

    建议使用一个将事件布置为回调函  数的函数,该函数位于 Util_structClock 函数的 Clock_Func Ptr clockCB 中。 上述函数发布的事件随后应在任务上下文中执行。
    我再次建议参考 simple_peripheral 示例、更具体地说来 clkPeriodic、SimplePeripheral_clockHandler、最后是 SP_PERIOD_EVT。

    此致、

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

    您好、Clement、

    感谢您的指导,它的工作是使这个   profile_readSensor () 在任务上下文中,广播数据是正确的, ADC 读数也是好的。 但这里还有一个问题:

    1.通过通知 App_Process Ccofg,我 在该特征中有256字节,它可以通过无线发送前20字节的数据,并由应用接收。 。 是否有建议将所有这些数据发送出去?  

    2.来自 ADC 的数据每128ms 更新一次, 如果发现我的程序,读取和发送数据的速度很慢,我该如何使其快速读取更新的数据?

    非常感谢

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

    Matthew、您好!

    很高兴看到您的问题现已解决!

    您是否愿意与我们分享为使其正常工作而实施的更改?

    请将该主题标记为已解决、然后使用您的新问题打开一个新主题。 这样其他读者可以从我们的讨论中受益。

    感谢您的理解。

    此致、