Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: STM32F107RCT6 + ADS1256
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
remixx
Пытаюсь подключить ADS1256 (АЦП) к 107-мому по SPI .
Схему подключения, настройки МК и SPI, даташит АЦП - приложил.
Ну и собственно сам код:
Код
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
** This notice applies to any and all portions of this file
* that are not between comment pairs USER CODE BEGIN and
* USER CODE END. Other portions of this file, whether
* inserted by the user or by software development tools
* are owned by their respective copyright owners.
*
* COPYRIGHT© 2018 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f1xx_hal.h"

/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "math.h"
#include <string.h>
#include <errno.h>

#define CS_ON() HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET) // Vkluchenie ADC
#define CS_OFF() HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET) // Vikluchenie ADC
#define ADS_DRDY (HAL_GPIO_ReadPin(DRDY_GPIO_Port, DRDY_Pin)==GPIO_PIN_SET) // Proverka gotovnosti ADC
/* USER CODE END Includes */

/* Private variables ---------------------------------------------------------*/
SPI_HandleTypeDef hspi3;

/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
uint8_t aTxBuffer[1]={0}; // Buffer dlya otpravlyaemih dannih
uint8_t aRxBuffer[3]={0,0,0}; // Buffer dlya prinimaemih dannih
uint32_t result;
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_SPI3_Init(void);

/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/

/* Funkciya inicializacii ADC */
void ADS1256_Init(void)
{
CS_ON(); // Aktiviruem ADC
HAL_Delay(100);
aTxBuffer[0]=0xFE; // Ukazivaem adres commandi RESET
HAL_SPI_Transmit(&hspi3, (uint8_t*)aTxBuffer, 1, 50); // Posilaem komandy RESET (sbrasivaem ADC k defoltnim nastroykam)
HAL_Delay(100);

aTxBuffer[0]=0xFC;// Ukazivaem adres commandi SYNC
HAL_SPI_Transmit(&hspi3, (uint8_t*)aTxBuffer, 1, 50); // Posilaem komandy SYNC (sinhronizaciya ADC s signalom na vivode SCLK)
aTxBuffer[0]=0x00; // Ukazivaem adres commandi WAKEUP
HAL_SPI_Transmit(&hspi3, (uint8_t*)aTxBuffer, 1, 50); // Posilaem komandy WAKEUP (v sootvetstvii s datasheet)

aTxBuffer[0]=0x50 | 0x00; // Ukazivaem adress registra s kotorogo nachinaetsa zapis (STATUS)
HAL_SPI_Transmit(&hspi3, (uint8_t*)aTxBuffer, 1, 50); // Peredaem adress pervogo registra
aTxBuffer[0]=3; // Ukazivaem kolichestvo registrov v kotorie budem zapisivat (zapisivaetsa 1 + TO KOLICHESTVO KOTOROE UKAZIVAEM, V DANOM SLUCHAE POLUCHAETSA 1+3=4)
HAL_SPI_Transmit(&hspi3, (uint8_t*)aTxBuffer, 1, 50); // Peredaem kolichesto registrov

aTxBuffer[0]=0x04; // Ukazivaem dannie, kotorie neobhodimo zapisat v pervyi registr (STATUS) - ustanavlivaem poryadok chteniya so starshego bayta (MSB), vkluchaem avto-kalibrovky, vikluchaem analogovyi buffer, dubliruem vivod DRDY
HAL_SPI_Transmit(&hspi3, (uint8_t*)aTxBuffer, 1, 50); // Peredaem dannie v registr STATUS
/* while(ADS_DRDY) {}; // Vozmojno nujno dlya ojidaniya zaversheniya avtokalibrovki */

aTxBuffer[0]=0x00 | 0x01; // Ukazivaem dannie, kotorie neobhodimo zapisat vo vtoroy registr (MUX) - vkluchaem vhod AIN0 kak POSITIVE, AIN1 kak NEGATIVE
HAL_SPI_Transmit(&hspi3, (uint8_t*)aTxBuffer, 1, 50); // Peredaem dannie v registr MUX

aTxBuffer[0]=0x00; // Ukazivaem dannie, kotorie neobhodimo zapisat v tretyi registr (ADCON) - otkluchaem CLK0/CLK1, otkluchaem datchik opredeleniya istochnika toka, ustanavlivaem vnutrennyi usilitel v 64 raza
HAL_SPI_Transmit(&hspi3, (uint8_t*)aTxBuffer, 1, 50); // Peredaem dannie v registr ADCON

aTxBuffer[0]=0x82; // Ukazivaem dannie, kotorie neobhodimo zapisat v chetvertyi registr (DRATE) - zadaem skorost raboti ADC (kolichestvo viborok v sekundu), v dannom sluchae 100 SPS
HAL_SPI_Transmit(&hspi3, (uint8_t*)aTxBuffer, 1, 50); // Peredaem dannie v registr DRATE

HAL_Delay(100); //min=50*(1/fCLKIN)=50*(1/7.68MHZ)=6500ns;max=whatever

CS_OFF(); // Vikluchaem ADC
HAL_Delay(100);
}

/* Funkciya polucheniya rezultata ODNOGO preobrazovaniya */
uint32_t ADS1256ReadData(void)
{
uint32_t sum=0;

CS_ON(); // Aktiviruem ADC

aTxBuffer[0]=0x01; // Ukazivaem adres commandi READ DATA
HAL_SPI_Transmit(&hspi3, (uint8_t*)aTxBuffer, 1, 50); // Posilaem komandy READ DATA (chtenie rezultata ODNOGO preobrazovaniya)
HAL_SPI_Receive(&hspi3, (uint8_t*)aRxBuffer, 3, 50); // Schitivaem poluchennyi rezultat (3 bayta)

sum = aRxBuffer[0];
sum = sum << 8; // Poetomy, posle kajdogo poluchennogo bayta provodim smeshenie na 8
sum |= aRxBuffer[1];
sum = sum << 8;
sum |= aRxBuffer[2];

CS_OFF(); // Vikluchaem ADC
return sum; // Vozvrashaem znachenie poluchennogo rezultata
}
/* USER CODE END PFP */

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
* @brief The application entry point.
*
* @retval None
*/
int main(void)
{
/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

/* MCU Configuration----------------------------------------------------------*/

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();

/* USER CODE BEGIN Init */

/* USER CODE END Init */

/* Configure the system clock */
SystemClock_Config();

/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */

/* Initialize all configured peripherals */
MX_GPIO_Init();

MX_SPI3_Init();
/* USER CODE BEGIN 2 */
HAL_Delay(100);
ADS1256_Init();
HAL_Delay(100);
/* USER CODE END 2 */

/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
result = ADS1256ReadData();
while (ADS_DRDY) {}
/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */

}
/* USER CODE END 3 */

}

/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{

RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;

/**Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV5;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.Prediv1Source = RCC_PREDIV1_SOURCE_PLL2;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
RCC_OscInitStruct.PLL2.PLL2State = RCC_PLL2_ON;
RCC_OscInitStruct.PLL2.PLL2MUL = RCC_PLL2_MUL8;
RCC_OscInitStruct.PLL2.HSEPrediv2Value = RCC_HSE_PREDIV2_DIV5;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}

/**Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}

/**Configure the Systick interrupt time
*/
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

/**Configure the Systick
*/
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

/**Configure the Systick interrupt time
*/
__HAL_RCC_PLLI2S_ENABLE();

/* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

/* SPI3 init function */
static void MX_SPI3_Init(void)
{

/* SPI3 parameter configuration*/
hspi3.Instance = SPI3;
hspi3.Init.Mode = SPI_MODE_MASTER;
hspi3.Init.Direction = SPI_DIRECTION_2LINES;
hspi3.Init.DataSize = SPI_DATASIZE_8BIT;
hspi3.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi3.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi3.Init.NSS = SPI_NSS_SOFT;
hspi3.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
hspi3.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi3.Init.TIMode = SPI_TIMODE_DISABLE;
hspi3.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi3.Init.CRCPolynomial = 7;
if (HAL_SPI_Init(&hspi3) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}

}

/** Configure pins as
* Analog
* Input
* Output
* EVENT_OUT
* EXTI
*/
static void MX_GPIO_Init(void)
{

GPIO_InitTypeDef GPIO_InitStruct;

/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();

/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET);

/*Configure GPIO pin : DRDY_Pin */
GPIO_InitStruct.Pin = DRDY_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(DRDY_GPIO_Port, &GPIO_InitStruct);

/*Configure GPIO pin : CS_Pin */
GPIO_InitStruct.Pin = CS_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(CS_GPIO_Port, &GPIO_InitStruct);
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
* @brief This function is executed in case of error occurrence.
* @param file: The file name as string.
* @param line: The line in file as a number.
* @retval None
*/
void _Error_Handler(char *file, int line)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
while(1)
{
}
/* USER CODE END Error_Handler_Debug */
}

#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/**
* @}
*/

/**
* @}
*/

/************************ © COPYRIGHT STMicroelectronics *****END OF FILE****/


В итоге во входной буфер приходят только нулевые значения.
Если посылать команду RDATAC (т.е. выполнять не единичное преобразование, а сделать так, чтобы АЦП постоянно слал 24 бита один за другим), результат такой же.

Не понимаю в чем проблема, не правильная инициализация или схема?

Нажмите для просмотра прикрепленного файла

Нажмите для просмотра прикрепленного файла
inventor
SPI вы правильно настроили?
1) для начала соединить MISO с MOSI что приходит ну и саму настройку SPI - правильно ноги затактированы
2) Проверьте фазу SPI - там 4 возможных режима
3) Проверьте чтобы CS начинался до транзакций и заканчивался после них через небольшую задержку
remixx
Цитата(inventor @ Apr 12 2018, 10:31) *
SPI вы правильно настроили?
1) для начала соединить MISO с MOSI что приходит ну и саму настройку SPI - правильно ноги затактированы
2) Проверьте фазу SPI - там 4 возможных режима
3) Проверьте чтобы CS начинался до транзакций и заканчивался после них через небольшую задержку

GPIO для SPI3 куб настраивает в файле stm32f1xx_hal_msp.c, включенном в проект. Его содержимое:
Код
/**
  ***************************************************************************
***
  * File Name          : stm32f1xx_hal_msp.c
  * Description        : This file provides code for the MSP Initialization
  *                      and de-Initialization codes.
  ***************************************************************************
***
  ** This notice applies to any and all portions of this file
  * that are not between comment pairs USER CODE BEGIN and
  * USER CODE END. Other portions of this file, whether
  * inserted by the user or by software development tools
  * are owned by their respective copyright owners.
  *
  * COPYRIGHT(c) 2018 STMicroelectronics
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ***************************************************************************
***
  */
/* Includes ------------------------------------------------------------------*/
#include "stm32f1xx_hal.h"

extern void _Error_Handler(char *, int);
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */
/**
  * Initializes the Global MSP.
  */
void HAL_MspInit(void)
{
  /* USER CODE BEGIN MspInit 0 */

  /* USER CODE END MspInit 0 */

  __HAL_RCC_AFIO_CLK_ENABLE();

  HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);

  /* System interrupt init*/
  /* MemoryManagement_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(MemoryManagement_IRQn, 0, 0);
  /* BusFault_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(BusFault_IRQn, 0, 0);
  /* UsageFault_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(UsageFault_IRQn, 0, 0);
  /* SVCall_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(SVCall_IRQn, 0, 0);
  /* DebugMonitor_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DebugMonitor_IRQn, 0, 0);
  /* PendSV_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(PendSV_IRQn, 0, 0);
  /* SysTick_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);

    /**ENABLE: Full SWJ (JTAG-DP + SW-DP): Reset State
    */
  __HAL_AFIO_REMAP_SWJ_ENABLE();

  /* USER CODE BEGIN MspInit 1 */

  /* USER CODE END MspInit 1 */
}

void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{

  GPIO_InitTypeDef GPIO_InitStruct;
  if(hspi->Instance==SPI3)
  {
  /* USER CODE BEGIN SPI3_MspInit 0 */

  /* USER CODE END SPI3_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_SPI3_CLK_ENABLE();
  
    /**SPI3 GPIO Configuration    
    PC10     ------> SPI3_SCK
    PC11     ------> SPI3_MISO
    PC12     ------> SPI3_MOSI
    */
    GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_12;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_11;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    __HAL_AFIO_REMAP_SPI3_ENABLE();

  /* USER CODE BEGIN SPI3_MspInit 1 */

  /* USER CODE END SPI3_MspInit 1 */
  }

}

void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi)
{

  if(hspi->Instance==SPI3)
  {
  /* USER CODE BEGIN SPI3_MspDeInit 0 */

  /* USER CODE END SPI3_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_SPI3_CLK_DISABLE();
  
    /**SPI3 GPIO Configuration    
    PC10     ------> SPI3_SCK
    PC11     ------> SPI3_MISO
    PC12     ------> SPI3_MOSI
    */
    HAL_GPIO_DeInit(GPIOC, GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12);

  /* USER CODE BEGIN SPI3_MspDeInit 1 */

  /* USER CODE END SPI3_MspDeInit 1 */
  }

}

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

/**
  * @}
  */

/**
  * @}
  */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/


Проблема походу не в коде. На схеме отсутствует кварц, а в дш он есть. Детали уже приобрел, во вторник протестирую вместе с ним.
inventor
Цитата(remixx @ Apr 13 2018, 05:46) *
Проблема походу не в коде. На схеме отсутствует кварц, а в дш он есть. Детали уже приобрел, во вторник протестирую вместе с ним.


можно с ноги контроллера протактировать
remixx
Вернулся к работе, но после всех корректировок так ничего и не изменилось)
Может быть я неправильно настраиваю CPOL и CPHA?
Приложил картинку передачи сигналов из ДШ.
По-моему в настройках SPI нужно устанавливать CPOL - 0, CPHA - 1Edge.
Еще кстати заметил, что в настройках выводов SCK и MOSI заданы как AF, а MISO как Input. А разве MISO не должен тоже задаваться как AF?
Нажмите для просмотра прикрепленного файла
haker_fox
QUOTE (remixx @ May 7 2018, 16:43) *
Может быть я неправильно настраиваю CPOL и CPHA?
Приложил картинку передачи сигналов из ДШ.

Фазировку шины проверьте осциллографом, и сравните картинку с даташитом.

А также (я работал с ADS1247, ADS131E04):
1. Проверьте, что тактовая частота SPI укладывается в допустимые.
2. Проверьте, что сигнал CS удерживается в низком уровне на время передачи кода команды и её аргументов (некоторые МК дёргают CS после передачи каждого байта, так работать не будет).
3. Считайте значения регистров по-умолчанию из АЦП, по ним можно сразу проверить, работает ли шина или нет. Я таким образом детектирую наличие АЦП на шине, и его косвенную исправность.
4. Проверьте, что CS опускается в ноль чуть раньше передачи данных по шине, и поднимается в 1 - чуть позже. Эти времена уточнить по даташиту. Я просто сделал 1 мс с большим запасом.
5. Ну и банально: проверьте уровни всхем питаний, доходят ли сигналы шины до АЦП и т.п.
Stanislav_S
В общем случае надо смотреть такие вещи:
- правильно настроить SPI - режим 1
- очень внимательно прочитать ДШ на АЦП на предмет команд, работы SPI и особенно важно не упустить задержки, коих там много и без их соблюдения нормальной работы не будет!
- выбросить HAL и написать нормально - это самый лучший путь, АЦП достаточно сложный в плане работы (для новичка конечно).
А так могу сказать, что АЦП работает - у меня в текущем проекте их 3 штуки на плате и все прекрасно работает.
remixx
Цитата(haker_fox @ May 7 2018, 09:16) *
Фазировку шины проверьте осциллографом, и сравните картинку с даташитом.

А также (я работал с ADS1247, ADS131E04):
1. Проверьте, что тактовая частота SPI укладывается в допустимые.
2. Проверьте, что сигнал CS удерживается в низком уровне на время передачи кода команды и её аргументов (некоторые МК дёргают CS после передачи каждого байта, так работать не будет).
3. Считайте значения регистров по-умолчанию из АЦП, по ним можно сразу проверить, работает ли шина или нет. Я таким образом детектирую наличие АЦП на шине, и его косвенную исправность.
4. Проверьте, что CS опускается в ноль чуть раньше передачи данных по шине, и поднимается в 1 - чуть позже. Эти времена уточнить по даташиту. Я просто сделал 1 мс с большим запасом.
5. Ну и банально: проверьте уровни всхем питаний, доходят ли сигналы шины до АЦП и т.п.


1. Насколько я понимаю рабочая частота АЦП определяется кварцем? В таком случае она равна 8 МГц. Частоту SPI беру с очень большим запасом (1.125 МГц, картинка ниже).
2. А такое наблюдается даже если дергаешь CS программно?
3. Попробую.
4. По задержкам ниже представил код с исправлениями.
5. Проверил, по питанию все уровне в норме.

Цитата(Stanislav_S @ May 7 2018, 10:19) *
В общем случае надо смотреть такие вещи:
- правильно настроить SPI - режим 1
- очень внимательно прочитать ДШ на АЦП на предмет команд, работы SPI и особенно важно не упустить задержки, коих там много и без их соблюдения нормальной работы не будет!
- выбросить HAL и написать нормально - это самый лучший путь, АЦП достаточно сложный в плане работы (для новичка конечно).
А так могу сказать, что АЦП работает - у меня в текущем проекте их 3 штуки на плате и все прекрасно работает.


1. Настройку SPI выполняю только в кубе, ниже рисунок с параметрами из 1 поста. Нужно ли кроме этого что-то настраивать еще?

Нажмите для просмотра прикрепленного файла

2. После доработок получился вот такой код с учетом задержек:
Код
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration----------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_SPI3_Init();
  /* USER CODE BEGIN 2 */
      DWT_Delay_Init();

      CS_ON(); // Enable CS
      DWT_Delay_us(10); // Задержка t3. По ДШ её может и не быть (0 нс), но небольшую все-таки сделал - 10 мкс. Пробовал и больше (1 мс).
      spiTxBuf[0]=0xFE; // Set RESET command address
      HAL_SPI_Transmit(&hspi3, spiTxBuf, 1, 50); // Transmit buffer via SPI
      CS_OFF(); // Disable CS

      CS_ON(); // Enable CS
      DWT_Delay_us(10); // Задержка t3.
      spiTxBuf[0]=0x0F; // Set SDATAC command address
      HAL_SPI_Transmit(&hspi3, spiTxBuf, 1, 50); // Transmit buffer via SPI
      CS_OFF(); // Disable CS

      CS_ON(); // Enable CS
      DWT_Delay_us(10); // Задержка t3.
      spiTxBuf[0]=0x50; // Set WREG command address + address of STATUS register
      HAL_SPI_Transmit(&hspi3, spiTxBuf, 1, 50); // Transmit buffer via SPI
      spiTxBuf[0]=3; // Set number of registers to be written
      HAL_SPI_Transmit(&hspi3, spiTxBuf, 1, 50); // Transmit buffer via SPI
      spiTxBuf[0]=0x02; // STATUS - MSB; Disable auto-calibration; Disable buffer; DRDY
      spiTxBuf[1]=0x01; // MUX - AIN0 as POSITIVE, AIN1 as NEGATIVE
      spiTxBuf[2]=0x00; // ADCON - Clock out disable; Sensor detect disable; PGA = 1
      spiTxBuf[3]=0xF0; // DRATE - 30000 SPS
      HAL_SPI_Transmit(&hspi3, spiTxBuf, 4, 50); // Transmit buffer via SPI
      CS_OFF(); // Disable CS
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {

  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */
      CS_ON(); // Enable CS
      DWT_Delay_us(10); // Задержка t3.
      spiTxBuf[0]=0xFC; // Set SYNC command address
      HAL_SPI_Transmit(&hspi3, spiTxBuf, 1, 50); // Transmit buffer via SPI
      CS_OFF(); // Disable CS

      CS_ON(); // Enable CS
      DWT_Delay_us(10); // Задержка t3.
      spiTxBuf[0]=0x00; // Set WAKEUP command address
      HAL_SPI_Transmit(&hspi3, spiTxBuf, 1, 50);
      CS_OFF(); // Disable CS

      while(HAL_GPIO_ReadPin(DRDY_GPIO_Port, DRDY_Pin)==GPIO_PIN_SET) {} // Read level of DRDY pin, if it's set to HIGH - wait

      CS_ON(); // Enable CS
      DWT_Delay_us(10); // Задержка t3.
      spiTxBuf[0]=0x01; // Set RDATA command address
      HAL_SPI_Transmit(&hspi3, spiTxBuf, 1, 50); // Transmit buffer via SPI
      DWT_Delay_us(10);  // Задержка t6. По Дш = 50/fCLK. У меня fCLK = 8 МГц, откуда t6 = 6,25 мкс. Беру с запасом - 10 мкс.
      HAL_SPI_Receive(&hspi3, spiRxBuf, 3, 50); // Receive result of conversion via SPI
      CS_OFF(); // Disable CS

      result = spiRxBuf[0];
      result = result << 8;
      result |= spiRxBuf[1];
      result = result << 8;
      result |= spiRxBuf[2];

      LCD_PrintInt(result);
  }
  /* USER CODE END 3 */

}


Единственное чего не делаю, это задержек после отправки и получения SPI. Как мне казалось внутри этих функций есть проверка флагов окончания передачи, попробую добавить задержки после них.
haker_fox
QUOTE (remixx @ May 8 2018, 12:14) *
1. Насколько я понимаю рабочая частота АЦП определяется кварцем? В таком случае она равна 8 МГц. Частоту SPI беру с очень большим запасом (1.125 МГц, картинка ниже).

Кварцем определяется работа микроконтроллера. Частота АЦП - совсем другая, см. даташит.
QUOTE (remixx @ May 8 2018, 12:14) *
Единственое чего не делаю, это задержек после отправки и получения SPI. Как мне казалось внутри этих функций есть проверка флагов окончания передачи, попробую добавить задержки после них.

Если у вас нет осциллографа, либо логического анализатора, то отладить обмен на шине конечно можно методом проб и ошибок, но лучше найдите один из этих приборов. Иначе можно долго отлаживать.


Кстати, думаю, что публиковать длиннющие куски кода смысла нет, т.к. реализация либы spi чуть ли не индивидуальная у каждого микроконтроллера, и версии. Поэтому лучше приведите диаграммы с шины. Но для этого нужен осциллограф, либо анализатор.
remixx
Есть отдельный кварц на АЦП.
Все заработало! Похоже проблема была именно в режиме SPI (0, 2Edge).
Всем спасибо.
haker_fox
QUOTE (remixx @ May 10 2018, 15:15) *
Есть отдельный кварц на АЦП.

В следующий раз приводите вместе с кодом и полную схему подключения, т.к. на вашей УГО АЦП неполное.
QUOTE (remixx @ May 10 2018, 15:15) *
Все заработало! Похоже проблема была именно в режиме SPI (0, 2Edge).

Странно. Либо вы редко занимались отладкой, либо проблема была не только в этом, т.к. времени прошло несколько дней с того времени, как вам посоветовали проверить режим. Ну, а слово "похоже" говорит, что логического анализатора у вас нет. Заведите. На алиэксресс купите самый недорогой. Он вам сэкономит кучу времени при отладке интерфейсов.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2024 Invision Power Services, Inc.