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.

[参考译文] ADS1256:CAN#39;t 获得正确的转换值

Guru**** 2551110 points
Other Parts Discussed in Thread: ADS1256

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

https://e2e.ti.com/support/data-converters-group/data-converters/f/data-converters-forum/683567/ads1256-can-t-get-right-values-of-conversion

器件型号:ADS1256

您好!

我有 一个 ADS1256 、我想通过 SPI 连接到微控制器 STM32F107RCT6。

我编写了驱动程序、但仍然无法获得正确的转换结果。

首先、我的原理图:

R1-R4是具有 COef 的分压器。 8.

R5-R6和 C1-C3 -抗混叠滤波器。

其他元件符合数据表。

SPI 和 MCU 配置:

和驱动程序代码:

/***********

*文件名 :main.c
*说明 主要方案机构

**本通知适用于此文件
的所有部分*,它们不在注释对 USER CODE BEGIN 和
* USER CODE END 之间。 此文件的其他部分、
无论是*由用户插入还是由软件开发工具
插入*、均归其各自的版权所有者所有。
*
*版权所有(c) 2018 STMicroelectronics
*
*只要
满足以下条件、就允许以源代码和二进制形式重新分发和使用**。
1. 重新分发源代码必须保留上述版权声明
* 此条件列表和以下免责声明。
* 2. 以二进制形式重新分发必须复制上述版权声明
* 本条件列表和文档中的以下免责声明
* 和/或随分发提供的其他材料。
* 3. STMicroelectronics 的名称及其贡献者的名称
*都不是 可用于认可或推广从本软件派生的产品
* 未经特定的事先书面许可。
*
*本软件由版权所有者和贡献者"按原样"提供
*、*不

承担任何明示或暗示的保证、包括但不限于*适销性和特定用途适用性的暗示保证。 在任何情况下、版权持有人或贡献者
都不对任何直接、间接、偶然、特殊、模范、
或相应的*损害(包括但不限于采购替代产品或
*服务;丧失使用、数据或利润; 但是
*由于
使用
本软件*而以任何方式产生的任何责任理论(无论是合同、严格责任、*或侵权行为(包括疏忽或其他))、即使被告知可能会造成此类损害。
*
*
*/*
包括:------------------------------------------------------- */
#include "main.h"
#include "stm32f1xx_hal.h"
#include "stdio.h"

//用户代码 begin 包括*/
#define CS_ON ()HAL_GPIO_WritePin (CS_GPIO_Port、CS_Pin、GPIO_RESET)//启用
PIN #CS CS_OFF (CS_Pin)---
和 CS_PRIVE---

*/
SPI_HandleTypeDef hspi3;
/*用户代码 begin PV */
/* private 变量------------------------------------------------------- /uint8_t
spiTxBuf[10],spiRxBuf[3];//发送和接收缓冲区
int32_t 结果;//转换结果变量
//用户代码末尾 PV */*

私有函数原型--------- /void
SystemClock_Config (void);
static void MX_GPIO_Init (void);
static void MX_SPI3_Init (void);

/*用户代码 begin PFP *//*
私有函数原型--- /*

用户代码末尾 PFP */*

用户代码开始0 */*

用户代码结束0 */

int main (void)
{/*

用户代码开始1 */*

用户代码结束1 */*/* MCU

配置------ //

//*复位所有外设,初始化闪存接口和 SysTick。 */
HAL_Init();

//用户代码 begin Init */

//*用户代码 end Init */

//*配置系统时钟*/
SystemClock_Config();

//*用户代码 begin sysinit */

//*用户代码 end sysinit *//

////*初始化所有已配置的外设*/
mx_GPIO_Init
();mx_SPI3*

/ userInit *
CS_ON();//启用 CS
spiTxBuf[0]= 0xFE;//设置复位命令地址
HAL_SPI_transmit (&hspi3、spiTxBuf、1、50);//通过 SPI 发送缓冲器
CS_OFF ();//禁用 CS

CS_ON();//启用 CS
spiTxBuf[0]= 0x0F;//设置 SDATAC 命令地址
HAL_SPI_transmit (&hspi3、spiTxBuf、1、50);//通过 SPI 发送缓冲器
CS_OFF ();//禁用 CS

CS_ON();//启用 CS
spiTxBuf[0]= 0x50;//设置 WREG 命令地址+状态寄存器的地址
HAL_SPI_transmit (&hspi3、spiTxBuf、1、50);//通过 SPI 发送缓冲器
spiTxBuf[0]=3;//设置要写入的寄存器数量
HAL_SPI_transmit (&hspi3、spiTxBuf、1、50);//通过 SPI 发送缓冲器
spiTxBuf[0]= 0x00;//状态- MSB;禁用自动校准;禁用缓冲器;DRDY
spiTxBuf[1]=0x01;// MUX - AIN0为正、AIN1为负
spiTxBuf[2]=0x00;// ADCON -时钟输出禁用;传感器检测禁用;PGA = 1
spiTxBuf[3]=0xF0;// DRATE - 30000 SPS
HAL_SPI_transmit (&hspi3、spiTxBuf、4、50);//通过 SPI 发送缓冲器
cs_off();//禁用 CS
/*用户代码 end 2 */

/* Infinite loop */
*用户代码在*/
while (1)
{

//



*/*用户代码 end while *///*用户代码 begin 3 */ CS_on ();//启用 CS spiTxBuf[0]= 0xFC;//设置命令地址 sync_50
、spi1、tf_spi1、transmit spi_spi_pixBuf (1) //通过 SPI
CS_OFF ()发送缓冲器;//禁用 CS

CS_ON ();//启用 CS
spiTxBuf[0]= 0x00;//设置唤醒命令地址
HAL_SPI_transmit (&hspi3、spiTxBuf、1、50);
CS_OFF (); //禁用 CS

CS_ON ();//启用 CS
spiTxBuf[0]=0x01;//设置 RDATA 命令地址
HAL_SPI_transmit (&hspi3、spiTxBuf、1、50);//通过 SPI
HAL_delay (1)发送缓冲区;//延迟1ms
HAL_SPI_receive (&hspi3
;SPIxBuf

= 0
结果;// SPIxBuf = 0;//结果= 0 = 0;SPIxCs = 0 = 0;SPi_receive
结果= spiRxBuf[1];
结果=结果<< 8;
结果= spiRxBuf[2];

HAL_delay (100);
}
//*用户代码结束3 *

}

//}//**系统时钟配置
*/
void SystemClock_Config (void)
{

RCC_OscInitTypeDef RCC_InitStruct;
RCC_OscitClk_Struct; RCC_OscitTrulkClt;

/**初始化 CPU、AHB 和 APB 总线时钟
RCC_OscInitStruct.OscatorType
= RCC_OSCILLStruct_HSE;RCC_OscInitStruct.HSEState
= RCC_HSE_ON;RCC_OscInitSStruct.HSEPreDIVValue
= RCC_HSE_OsciviV_DIV5;
RCC_PREDIV_RCC_RDIV1
;RCC_RDIV_RDIV_RDIV1;RCC_RDIVITSource_RDIV1 = RCC_RDIVIT_RDIVIT_RDIVIT_RDIV_RDIVIT_RDIVIT_RDIV_RIC_RIC_
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscitStruct.PLLLMUL = RCC_PLL_MUL9;RCC_PLL2_RPLL2.ON
= RCC_PLL2.PLL2.PLL2.PLL2.ON;RCC_RCC_PLL2.PLL2.PLL2.PLL2.ON = RCC_RIC_PLLT_PLL2.ON

RCC_OscInitStruct.PLL2.HSEPrediv2Value = RCC_HSE_PREDIV2_DIV5;
IF (HAL_RCC_OscConfig (&RCC_OscInitStructt)!= HAL_OK)
{
_Error_Handler (__file__、__line__);
}

/**初始化 CPU、AHB 和 APB 总线时钟
//
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKd = RCC_SYSCLCD_CLKDIV1

;RCC_CLKCLKCLKCLKDIV1 = RCC_CLKCLK1;RCC_CLKCLKCLKCLKCLKCLKCLKDIVDD_CLK_CLKCLK_CLKCLK_CLKCLKCLK_CLK_CLKCLK_CLK_CLK_CLKDIVDD.CLK_CLK_CLK_CLKCLK

if (HAL_RCC_ClockConfig (&RCC_ClkInitStruct, flash_latit_2)!= HAL_OK)
{
_Error_Handler (__file__、__line__);
}

/**配置 SysTick 中断时间
*/
HAL_SysTK_Config (HAL_RCC_GetHCLKFreq ()/1000);

/**配置 SysTick
*/
HAL_SysTK_CLKSourceConfig (SysTK_CLKSOURCE_HCLK);

/**配置 SysTick 中断时间
*/
_ HAL_RCC_PLLI2S_ENABLE ();

* SysTick _IRQn 中断配置*/
HAL_NVIC_setPriority (SysTick _IRQn、0、0);
}

// SPI3 init 函数*
静态空 MX_SPI3_Init (void)
{

*/* SPI3参数配置*、SPI3、SPI3_Inspiarity


= spi3;spi3 Inspi3;spi_inspi3 inspi3 inspi3;spi3 inspi3 inspi_spi3 inspi3 inspi3 inspi3 inspi3 inspi3;spi3 inspi3 inspi_spi3 inspi3 inspi3 inspi3 inspi_spi3


hspi3.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi3.Init.NSS = SPI_NSS_Soft;
hspi3.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
hspi3.Init.FirstBit = SPI_FIRSTBIT_BADDRESCAST_32;
禁用 TITMDS_InTIDT_TIMESCAST_32;hTITMDSBIT = SPI_InTIDT_DIT3_InTIDE.InTDITIDT_DITDIT
hspi3.Init.CRCCalacimal = SPI_CRCCALLion_disable;
hspi3.Init.CRCPolynomial = 10;
if (HAL_SPI_Init (&hspi3)!= HAL_OK)
{
_Error_Handler (__file__、__line__);
}

//**

将引脚配置为
*模拟
*输入
*输出
* EVENT_OUT
* EXTI
*/
static void MX_GPIO_Init (void)
{

GPIO_InitTypeDef GPIO_InitStructure;

// GPIO 端口时钟启用*/
_ HAL_RCC_GPIOD_CLK_ENABLE();
_ HAL_RCC_GPIO_ENABLE_GPIO_PIN_TRUTE_GPIO_ENABLE_GPIO_TRUTE_PIN_PIN_GPIO_ENTRUTE_GPIO_ENTRUTE_GPIO_PIN_GPIO_ENTRUTRIP_PIN_GPIO_ENTRIP_PIN_GPIO_ENTRIP_PIN_GPIO_ENTRIP_PIN_PIN_PIN_GPIO_ENABLE_GPIO_ENTRIP_PIN_GPIO_ENTRIP_PIN_PIN_GPIO_ENTRIP_GPIO_ENTRIP_PIN_GPIO_ENTRIP_PIN_PIN_PIN_GPIO_ENTRIP_PIN_PIN_PIN_PIN_GPIO_ENTRIP_PIN_PIN_PIN_PIN_GPIO_ENTRIP_PIN_PIN_PIN_PIN_PIN_PIN_PIN_PIN_PIN_PIN_PIN_PIN_PIN_














/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
@brief 在发生错误时执行此函数。
*@param None
*@retval None
*/
void _Error_Handler (char * file、int 行)
{
//*用户代码 begin Error_Handler_debug */
////*用户可以添加自己的实现来报告 HAL 错误返回状态*/
while (1)
{
}
//////*用户代码 end Error_Handler_debug */
}

#ifdef use_full_assert

//
*@brief 报告源文件的名称和源代码行号
* 发生了 assert_param 错误的位置。
*@param 文件:指向源文件名的指针
*@param 行:assert_param 错误行源代码*
@retval 无
*/
void assert_failed (uint8_t*文件、uint32_t 行)
{
//*用户代码 begin 6 *
////*用户可以添加自己的实现来报告文件名和行号,
示例:printf ("错误的参数值:第%d\r\n"行上的文件%s、文件、行)*/
*用户代码结束6 */

}

#endif

//*
@}
*/

*
@}
*/*}*/

/******** (c)版权所有 STMicroelectronics ***** 文件末尾****/ 

HAL_SPI_Transmit 的代码:

/**
*@brief 在阻塞模式下发送大量数据
*@param hspi:指向包含
*的 SPI_HandleTypeDef 结构的指针 SPI 模块的配置信息。
*@param pData:指向数据缓冲区的指针
*@param 大小:要发送的数据量
*@param 超时:超时持续时间
*@retval HAL 状态
*/
HAL_StatusTypeDef HAL_SPI_Transmit (SPI_HandleTypeDef * hspi、uint8_t * pData、uint16_t Size、Uint32_spi_t


= hspi_state_transmit *(SPI_Handle_t = hspi * hspi * hspi)* hspi_t timeout = pData

if ((pData =NULL)||(size ==0))
{
返回 HAL_ERROR;
}

/*检查参数*/
ASSERT_param (is_SPI_DIRECTIONAL_2LINES_OR_1LINE (hspi->Init.DIRECTION));

/*进程锁定*/
_HAL_LOCK (hspi);

/*配置通信*/
hspi->State = HAL_SPI_State_Busy_TX;
hspi->ErrorCode = HAL_SPI_ERROR_NONE;

hspi->pTxBuffPtr = pData;
hspi->TxXferSize =大小;
hspi->TxXferCount =大小;

/*Init 字段不用于句柄为零*/
hspi->TxISR = 0;
hspi->RxISR = 0;
hspi->pRxBuffPtr =空;
hspi->RxXferSize = 0;
hspi->RxXferCount = 0;

/*重置 CRC 计算*/
if (hspi->Init.CRCalcanc= SPI_CRCALLion_ENABLE)
{
SPI_RESET_CRC (hspi);
}

if (hspi->Init.direction = SPI_DIRECT_1LINE)
{
/*配置通信方向:1行*/
SPI_1LINE_TX (hspi);
}

/*检查 SPI 是否已启用*/
if ((hspi->instance->CR1 &SPI_CR1_SPE)!= SPI_CR1_SPE)
{
/*启用 SPI 外设*/
_HAL_SPI_ENABLE (hspi);
}

/*以8位模式发送数据*/
if (hspi->Init.DataSize =SPI_DATASIZE _8bit)
{
if (((hspi->Init.Mode = SPI_MODE_SLAVE)||(hspi->TxXferCount = 0x01))
{
hspi->instance->DR =(*hspi->pTxBuffPtr++);
hspi->TxXferCount--;
}

while (hspi->TxXferCount >0)
{
/*等待 TXE 标志设置为发送数据*/
if (SPI_WaitOnFlagUntilTimeout (hspi、SPI_FLAG_TXE、复位、超时)!= HAL_OK)
{
返回 HAL_TIMEOUT;
}
hspi->instance->DR =(*hspi->pTxBuffPtr++);
hspi->TxXferCount--;
}
/*启用 CRC 传输*/
if (hspi->Init.CRCalcanc= SPI_CRCALLion_ENABLE)
{
SET_BIT (hspi->实例->CR1、SPI_CR1_CRCNEXT);
}
}
/*以16位模式发送数据*/
其他
{
if (((hspi->Init.Mode = SPI_MODE_SLAVE)||(hspi->TxXferCount = 0x01))
{
hspi->instance->DR =*((uint16_t*) hspi->pTxBuffPtr);
hspi->pTxBuffPtR+=2;
hspi->TxXferCount--;
}

while (hspi->TxXferCount >0)
{
/*等待 TXE 标志设置为发送数据*/
if (SPI_WaitOnFlagUntilTimeout (hspi、SPI_FLAG_TXE、复位、超时)!= HAL_OK)
{
返回 HAL_TIMEOUT;
}
hspi->instance->DR =*((uint16_t*) hspi->pTxBuffPtr);
hspi->pTxBuffPtR+=2;
hspi->TxXferCount--;
}
/*启用 CRC 传输*/
if (hspi->Init.CRCalcanc= SPI_CRCALLion_ENABLE)
{
SET_BIT (hspi->实例->CR1、SPI_CR1_CRCNEXT);
}
}

/*等待 TXE 标志设置为发送数据*/
if (SPI_WaitOnFlagUntilTimeout (hspi、SPI_FLAG_TXE、复位、超时)!= HAL_OK)
{
SET_BIT (hspi->ErrorCode、HAL_SPI_ERROR_FLAG);
返回 HAL_TIMEOUT;
}

/*在禁用 SPI 之前等待 BUSY 标志被复位*/
if (SPI_WaitOnFlagUntilTimeout (hspi、SPI_FLAG_BSY、设置、超时)!= HAL_OK)
{
SET_BIT (hspi->ErrorCode、HAL_SPI_ERROR_FLAG);
返回 HAL_TIMEOUT;
}

/*在2线通信模式下清除超频标志,因为接收到的信号不是读取的*/
if (hspi->Init.direction = SPI_DIRECT_2LINE)
{
_HAL_SPI_CLEAR_OVRFLAG (hspi);
}

hspi->State = HAL_SPI_State_ready;

/*进程解锁*/
_HAL_UNLOCK (hspi);

返回 HAL_OK;
}
否则
{
返回 HAL_BUSY;
}
} 

HAL_SPI_Receive 代码:

/**
*@brief 在阻塞模式下接收大量数据。
*@param hspi:指向包含
*的 SPI_HandleTypeDef 结构的指针 SPI 模块的配置信息。
*@param pData:指向数据缓冲区的指针
*@param size:要接收的数据量
*@param Timeout:超时持续时间
*@retval HAL status
*/
HAL_StatusTypeDef HAL_SPI_Receive (SPI_HandleTypeDef * hspi、uint8_t * pData、uint16_t size、Uint32_t

if)
= uint_t pio_t timeout (spi_t)
#endif /* use_spi_crc */
uint32_t tickstart = 0U;
HAL_StatusTypeDef 错误代码= HAL_OK;

if ((hspi->Init.Mode = SPI_MODE_MASTER)&(hspi->Init.Direction = SPI_Direction_2LINES)
){
hspi->State = HAL_SPI_State_Busy_RX;
/*调用发送/接收函数,在 Tx 线路上发送虚拟数据并在 CLK 线路上生成时钟*/
返回 HAL_SPI_TransmitReceive (hspi、pData、pData、size、Timeout);
}

//*进程锁定*/
_ HAL_LOCK (hspi);

//用于超时管理的初始化
*/ tickstart = HAL_GetTick();

if (hspi-> State!= HAL_SPI_State_ready
)
错误代码= HAL_BUSY;
转至错误;
}

if ((pData == NULL)||(size == 0U)
){
错误代码= HAL_ERROR;
转至错误;
}/*

设置事务信息*/
hspi->状态 = HAL_SPI_State_Busy_RX;
hspi->ErrorCode = HAL_SPI_ERROR_none;
hspi->pRxBuffPtr =(uint8_t *) pData;
hspi->RxXferSize = size;
hspi->RxXferCount = size;

/ISR Init 字段未在 Txdx 中使用;nrxdrxux = 0ux 0ux 0ux = t;t = nrxdrxnrxnrxferSize = 0ux 0ux 0ux (0ux



=空;
hspi->TxISR =空;

#if (USE_SPI_CRC!= 0U)
//重置 CRC 计算*/
if (hspi->Init.CRCalculation =SPI_CRCALLion_enable)
{
SPI_RESET_CRC (hspi);
/*完成此操作是为了在最新数据之前处理 CRCNEXT */
hspi->RxXferCount->;
}
#endif /* USE_SPI_CRC */

//配置通信方向:1Line */
if (hspi->Init.Direction =SPI_Direction_1LINE)
{
SPI_1LINE_RX (hspi);
}

//检查 SPI 是否已启用*/
if ((hspi->instance->CR1 & SPI_CR1_SPE)!= SPI_CR1_SPE)
{
/*启用 SPI 外设*/
_HAL_SPI_ENABLE (hspi);
}

/*以8位模式接收数据*/
if (hspi->Init.DataSize =SPI_DATASIZE _8bit)
{
/*传输循环*/
while (hspi->RxXferCount >0U)
{
/*检查 RXNE 标志*/
if (__HAL_SPI_GET_flag (hspi、SPI_FLAG_RXNE))
{
/*读取接收到的数据*/
(*(uint8_t *) pData)=*(_io uint8_t *)&hspi->instance->DR;
pData += sizeof (uint8_t);
hspi->RxXferCount--;
}
其他
{
/*超时管理*/
if ((Timeout =0U)||((Timeout !=HAL_MAX_DELAY)&&((HAL_GetTick ()-tickstart)>= Timeout)))
{
错误代码= HAL_TIMEOUT;
转至错误;
}
}

}
否则
{
/*传输循环*/
while (hspi->RxXferCount >0U)
{
/*检查 RXNE 标志*/
if (__HAL_SPI_GET_flag (hspi、SPI_FLAG_RXNE))
{
*((uint16_t*)pData)=hspi->instance->DR;
pData += sizeof (uint16_t);
hspi->RxXferCount--;
}
其他
{
/*超时管理*/
if ((Timeout =0U)||((Timeout !=HAL_MAX_DELAY)&&((HAL_GetTick ()-tickstart)>= Timeout)))
{
错误代码= HAL_TIMEOUT;
转至错误;
}
}

}

#if (USE_SPI_CRC!= 0U)
//
if (hspi->Init.CRCalcinc== SPI_CRCALLion_enable)
{
/*在最新数据之前冻结 CRC */
SET_BIT (hspi->instance->CR1、SPI_CR1_CRCNEXT);

/*读取最新数据*/
if (SPI_WaitFlagStateUtilTimeout (hspi、SPI_FLAG_RXNE、设置、超时、tickstart)!= HAL_OK)
{
/*尚未收到最新数据*/
错误代码= HAL_TIMEOUT;
转至错误;
}

/*在16位模式下接收最后一个数据*/
if (hspi->Init.DataSize =SPI_DATASIZE _16BIT)
{
*((uint16_t*)pData)=hspi->instance->DR;
}
/*在8位模式下接收最后一个数据*/
其他
{
(*(uint8_t *) pData)=*(_io uint8_t *)&hspi->instance->DR;
}

/*等待 CRC 数据*/
if (SPI_WaitFlagStateUtilTimeout (hspi、SPI_FLAG_RXNE、设置、超时、tickstart)!= HAL_OK)
{
SET_BIT (hspi->ErrorCode、HAL_SPI_ERROR_CRC);
错误代码= HAL_TIMEOUT;
转至错误;
}

/*读取 CRC 以刷新 DR 和 RXNE 标志*/
tmpreg=hspi->实例->DR;
/*以避免 GCC 警告*/
未使用(tmpreg);
}
#endif /* use_spi_crc */

/*检查事务的结束*/
if ((hspi->Init.Mode == spi_mode_master)&&((hspi->Init.Direction =SPI_Direction_1LINE)||(hspi->Inons_direction =spi_RXONES=2)

/*禁用 SPI 外设*/
_HAL_SPI_DISABLE (hspi);
}

#if (USE_SPI_CRC!= 0U)
/*检查是否发生 CRC 错误*/
if (__HAL_SPI_GET_flag (hspi、SPI_FLAG_CRCR)!=复位)
{
/*检查 CRC 错误是否有效(要应用或不应用解决方法)*/
if (SPI_ISCRCErrorValid (hspi)== SPI_VALIDE_CRC_ERROR)
{
SET_BIT (hspi->ErrorCode、HAL_SPI_ERROR_CRC);

/*重置 CRC 计算*/
SPI_RESET_CRC (hspi);
}
其他
{
_HAL_SPI_CLEAR_CRCERRFLAG (hspi);
}
}
#endif //

if (hspi->ErrorCode!= HAL_SPI_ERROR_NONE)
{
错误代码= HAL_ERROR;
}

错误:
hspi->State = HAL_SPI_State_ready;
__HAL_UNLOCK (hspi);
返回错误代码;
} 

因此、变量结果等于0、或显示随机变化的值。

我出了什么问题?

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

    欢迎访问 TI E2E 论坛!

    我很想看到输出数据、即使它看起来是随机的。 在某些情况下、我们可以从错误数据中确定问题。 此外、您是否曾尝试在示波器或逻辑分析仪上探测 SPI 通信?

    我没有看到您共享的原理图有任何问题。 请确保使用电阻输入启用输入缓冲器;否则、尝试对非缓冲数据进行采样可能会导致明显的增益误差。

    请给我一天时间来浏览您的代码、看看我是否可以在那里找到任何问题、但我仍然建议尝试探测 SPI 信号、如果可以的话、也可以与我们分享这些屏幕截图...

    此致、
    Chris
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好 Chris、
    遗憾的是、我没有示波器和逻辑分析仪。
    我将尝试使用启用的模拟缓冲器运行器件、并显示一些具体结果。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Stanislav、

    我仔细检查了您的代码、发现了几个可能导致 ADC 读数错误的地方...

    1. 在发生/DRDY 中断之前读取数据...

      CS_ON ();//启用 CS
      spiTxBuf[0]= 0x00;//设置唤醒命令地址
      HAL_SPI_transmit (&hspi3、spiTxBuf、1、50);
      CS_OFF (); //禁用 CS
      
      //[CHRIS]在读取数据
      
      CS_ON 之前等待/DRDY 变为低电平;//启用 CS
      spiTxBuf[0]=0x01;//设置 RDATA 命令地址
      HAL_SPI_transmit (&hspi3、spiTxBuf、1、50);//通过 SPI
      HAL_delay (1)发送缓冲区;//通过
      SPI_transmit (&spi3、spi_conversion)
      ;/spi3、SPIxBuf (1、SPI_dimal (接收);/spi_3) //禁用 CS 
      在您的代码中、您会立即尝试在执行 WAKEUP 命令后读取数据。 此时、ADC 没有足够的时间完成转换、数据将无效。 因此、在尝试读取数据之前、您需要轮询或等待/DRDY 下降沿中断。


    2. 连接多个 ADC 数据字节时出错...

      结果= spiRxBuf[0];
      结果=结果<< 8;
      结果= spiRxBuf[1];//在此处执行'|='
      结果=结果<< 8;
      结果= spiRxBuf[2];//在此处执行'|=' 
      此代码当前会覆盖结果中存储的数据。 在尝试将"spiRxBuff[1]和"spiRxBuff[0]字节串联到结果中时、需要执行"|="操作。

      此外:还请记住、您要将有符号24位数字存储到有符号32位数据类型中... 因此、考虑对 ADC 的转换结果进行符号扩展以计入负数(否则、当24位实际为负时、32位数将显示为正)。


    3. 这可能是也可能不是问题、但当您将/CS 设置为低电平时、您可能需要在发送任何 SPI 数据之前在代码中插入一个小延迟。 通常、如果在/CS 变为低电平后过早进行 SPI 通信、ADC 可能会误解该通信。 可能是"HAL_SPI_Transmit ()"函数具有内置延迟、足以在/CS 低电平和第一个 SCLK 上升沿之间留出一定的时间延迟;但是、如果不是、您可能需要添加 ADS1256所需的"t3"延迟。

      另外、请注意"RDATA"命令与时钟输出数据之间所需的"T6"延迟。 同样,"HAL_SPI_Transmit ()"函数可以提供此延迟,但自己强制执行此延迟可能更安全。


    我希望这会有所帮助、如果进行上述任何更改都能解决您的问题、请告诉我!

    此致、
    Chris

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

    您好 Chris、

    我添加了 T6和 T3延迟。 变量"result"的错误是一个拼写错误、在测试程序中、我使用了"|="。

    我应该使用哪种类型的变量"结果"来获得最佳性能?

    我编写了2个不同的代码变体:

    在第一个中、DRDY 设置为简单输入、因此 main 看起来是这样的

    int main (void)
    {
    
    /*用户代码 begin 1 */
    
    /*用户代码 end 1 */
    
    /* MCU 配置------------------------------------------------------- //
    
    //*复位所有外设,初始化闪存接口和 SysTick。 */
    HAL_Init();
    
    //用户代码 begin Init */
    
    //*用户代码 end Init */
    
    //*配置系统时钟*/
    SystemClock_Config();
    
    //*用户代码 begin sysinit */
    
    //*用户代码 end sysinit *//
    
    ////*初始化所有已配置的外设*/
    mx_GPIO_Init
    ();mx_SPI3*
    
    / userInit *
    CS_ON();//启用 CS 
    延迟(T3);//延迟 T3 spiTxBuf[0]= 0xFE;//设置复位命令地址 HAL_SPI_transmit (&hspi3、spiTxBuf、1、50);//通过 SPI 发送缓冲器 CS_OFF ();//禁用 CS CS_ON();//启用 CS
    延迟(T3);//延迟 T3 spiTxBuf[0]= 0x0F;//设置 SDATAC 命令地址 HAL_SPI_transmit (&hspi3、spiTxBuf、1、50);//通过 SPI 发送缓冲器 CS_OFF ();//禁用 CS CS_ON();//启用 CS
    延迟(T3);//延迟 T3 spiTxBuf[0]= 0x50;//设置 WREG 命令地址+状态寄存器的地址 HAL_SPI_transmit (&hspi3、spiTxBuf、1、50);//通过 SPI 发送缓冲器 spiTxBuf[0]=3;//设置要写入的寄存器数量 HAL_SPI_transmit (&hspi3、spiTxBuf、1、50);//通过 SPI 发送缓冲器 spiTxBuf[0]= 0x00;//状态- MSB;禁用自动校准;禁用缓冲器;DRDY spiTxBuf[1]=0x01;// MUX - AIN0为正、AIN1为负 spiTxBuf[2]=0x00;// ADCON -时钟输出禁用;传感器检测禁用;PGA = 1 spiTxBuf[3]=0xF0;// DRATE - 30000 SPS HAL_SPI_transmit (&hspi3、spiTxBuf、4、50);//通过 SPI 发送缓冲器 CS_off();//禁用 CS /*用户代码 end 2 */ /* Infinite loop */ //*用户代码在*/ while (1) { //用户代码在*/ //*用户代码开始3时结束*/ CS_on ();//启用 CS
    delay (T3);// delay T3 spitxBuf[0]= 0xFC;//设置同步命令地址 HAL_SPI_transmit (&hspi3、spiTxBuf、1、50);//通过 SPI CS_OFF ()发送缓冲区;//禁用 CS CS_ON();//启用 CS
    delay (T3);// delay T3 spiTxBuf[0]= 0x00;//设置唤醒命令地址 HAL_SPI_transmit (&hspi3、spiTxBuf、1、50); CS_off (); //禁用 CS

    while (HAL_GPIO_ReadPin (DRDY_GPIO_Port、DRDY_Pin)=GPIO_PIN_SET){}// DRDY 引脚的读取电平(如果设置为高电平)-等待 CS_ON ();//启用 CS
    delay (T3);// delay T3 spiTxBuf[0]= 0x01;//设置 RDATA 命令地址 HAL_SPI_transmit (&hspi3、spiTxBuf、1、50);//通过 SPI delay (T6)发送缓冲区;// delay T6 HAL_SPI_receive (&hspi3、spiBuf、1) ;// result = 0; //通过 SPIxBuf = 0;// result = 0;// result = 0;//结果 = 0;//结果= 0;//结果= 0 = 0;// 结果=结果<< 8; 结果|= spiRxBuf[2]; HAL_DELAY (100); }//* 用户代码结束3 */ }


    对于使用无限循环的测试、可以、但我想使用外部中断执行转换。 在第二种变体中、我使用下降沿配置了 EXTI 等 DRDY。

    但我无法确定、应该将 SYNC+WAKEUP+RDATA 放入 IRQ 处理器中、还是仅将 RDATA 和 SYNC+WAKEUP 放入 main 中?

    int main (void)
    {
    
    /*用户代码 begin 1 */
    
    /*用户代码 end 1 */
    
    /* MCU 配置------------------------------------------------------- //
    
    //*复位所有外设,初始化闪存接口和 SysTick。 */
    HAL_Init();
    
    //用户代码 begin Init */
    
    //*用户代码 end Init */
    
    //*配置系统时钟*/
    SystemClock_Config();
    
    //*用户代码 begin sysinit */
    
    //*用户代码 end sysinit *//
    
    ////*初始化所有已配置的外设*/
    mx_GPIO_Init
    ();mx_SPI3*
    
    / userInit *
    CS_ON();//启用 CS
    延迟(T3);//延迟 T3
    spiTxBuf[0]= 0xFE;//设置复位命令地址
    HAL_SPI_transmit (&hspi3、spiTxBuf、1、50);//通过 SPI 发送缓冲器
    CS_OFF ();//禁用 CS
    
    CS_ON();//启用 CS
    延迟(T3);//延迟 T3
    spiTxBuf[0]= 0x0F;//设置 SDATAC 命令地址
    HAL_SPI_transmit (&hspi3、spiTxBuf、1、50);//通过 SPI 发送缓冲器
    CS_OFF ();//禁用 CS
    
    CS_ON();//启用 CS
    延迟(T3);//延迟 T3
    spiTxBuf[0]= 0x50;//设置 WREG 命令地址+状态寄存器的地址
    HAL_SPI_transmit (&hspi3、spiTxBuf、1、50);//通过 SPI 发送缓冲器
    spiTxBuf[0]=3;//设置要写入的寄存器数量
    HAL_SPI_transmit (&hspi3、spiTxBuf、1、50);//通过 SPI 发送缓冲器
    spiTxBuf[0]= 0x00;//状态- MSB;禁用自动校准;禁用缓冲器;DRDY
    spiTxBuf[1]=0x01;// MUX - AIN0为正、AIN1为负
    spiTxBuf[2]=0x00;// ADCON -时钟输出禁用;传感器检测禁用;PGA = 1
    spiTxBuf[3]=0xF0;// DRATE - 30000 SPS
    HAL_SPI_transmit (&hspi3、spiTxBuf、4、50);//通过 SPI 发送缓冲器
    cs_off();//禁用 CS
    /*用户代码末尾2 */
    
    /* Infinite loop */
    //*用户代码在*/
    while (1)
    {//*
    
    
    
    //*用户代码结束,而*/*用户代码开始3 */
    
    }
    //*用户代码结束3 */
    
    }时开始 
    /*用户代码 begin 4 */
    void HAL_GPIO_EXTI_Callback (uint16_t GPIO_Pin)
    {
    //防止未使用的参数编译警告*/
    unused (GPIO_Pin);
    //注意:当需要回调时,不应修改此函数,
    HAL_GPIO_EXTI_Callback 可在用户文件
    中实现*
    
    CS_ON ();//启用 CS
    delay (T3);// delay T3
    spitxBuf[0]= 0xFC;//设置同步命令地址
    HAL_SPI_transmit (&hspi3、spitxBuf、1、50);//通过 SPI
    CS_off ()发送缓冲区;//禁用 CS
    
    CS_ON ();//启用 CS
    延迟(T3);//延迟 T3
    spitxBuf[0]= 0x00;//设置唤醒命令地址
    HAL_SPI_transmit (&hspi3、spitxBuf、1、50);
    CS_OFF (); //禁用 CS
    
    CS_ON ();//启用 CS
    延迟(T3);//延迟 T3
    spiTxBuf[0]= 0x01;//设置 RDATA 命令地址
    HAL_SPI_transmit (&hspi3、spiTxBuf、1、50);//通过 SPI
    延迟(T6)发送缓冲区;//延迟 T6_spi_transmit (&spi3
    
    
    
    、SPIxBuf);//通过 SPI 接收 SPIxBuf (= 0、SPIxBuf);//接收 SPIx3、SPI[spi_OFF;//接收转换结果
    结果=结果<< 8;
    结果|= spiRxBuf[1];
    结果=结果<< 8;
    结果|= spiRxBuf[2];
    } 

    我将在明天进行测试。

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

    您好 Stanislav、

    添加额外延迟是否改善了转换结果?

    关于您应该用于"结果"的数据类型、这可能是个人偏好问题。 我喜欢使用"int32_t"类型、因为我可以对 ADC 代码进行符号扩展、使其进入32位数据类型。 您可以在此处看到一个相关示例:
      

    [引用用户="Stanislav Osintsev"]

    对于使用无限循环的测试、可以、但我想使用外部中断执行转换。 在第二种变体中、我使用下降沿配置了 EXTI 等 DRDY。

    但我无法确定、应该将 SYNC+WAKEUP+RDATA 放入 IRQ 处理器中、还是仅将 RDATA 和 SYNC+WAKEUP 放入 main 中?

    [/报价]

    这也由您决定、以及您希望如何构建代码。 一般来说、如果系统中有很多中断、最好保持 IRQ 处理程序的快速。 我可以这样做的方法是在中断中设置全局标志、以指示发生了/DRDY、然后在主循环中可以检查此标志并执行 SYNC + WAKEUP + RDATA 命令。 这种类型的实现与状态机类似、通过让主循环决定接下来要执行的操作、您可以避免在长 IRQ 处理程序进程运行时 SPI 通信在命令或数据读取中间停止的情况。

    此致、
    Chris

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

    您好 Chris。
    很抱歉、我在一周内没有参加活动。
    我进行了测试。 在进行所有更改后、ADC 输出端的值为85xx (32、96、56...)。

    从 我的角度来看、我注意到一件事、对于 ads1256、我必须使用 CPOL - 0和 CPHA - 1Edge、但对于此配置、输出值始终为0。 但是、如果我将 CPOL 更改为1、那么我将接收到85xx 值、这与输入电压无关。

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

    您必须使用正确的 SPI 模式(模式1)进行通信。 如果您在空闲状态下使用高时钟极性、则所有数据都将不正确。 验证通信的最佳方法是使用示波器或逻辑分析仪进行检查。 如果您无法使用此功能、则需要首先能够读取 ADS1256寄存器的默认设置。 如果寄存器值正确、则尝试写入寄存器、然后读回它们、并验证结果是否符合预期。 然后、您需要验证您认为写入寄存器的内容是器件的响应方式。

    如果您仍然遇到问题、您确实需要找到示波器。

    此致、
    Bob B