Версия для печати темы
Форум разработчиков электроники ELECTRONIX.ru _ ARM, 32bit _ STM32F107RCT6 + ADS1256
Автор: remixx Apr 11 2018, 04:14
Пытаюсь подключить ADS1256 (АЦП) к 107-мому по SPI .
Схему подключения, настройки МК и SPI, http://electronix.ru/redirect.php?http://www.ti.com/lit/ds/symlink/ads1255.pdf - приложил.
Ну и собственно сам код:
Код
/**
******************************************************************************
* @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 Apr 12 2018, 10:31
SPI вы правильно настроили?
1) для начала соединить MISO с MOSI что приходит ну и саму настройку SPI - правильно ноги затактированы
2) Проверьте фазу SPI - там 4 возможных режима
3) Проверьте чтобы CS начинался до транзакций и заканчивался после них через небольшую задержку
Автор: remixx Apr 13 2018, 02:46
Цитата(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 Apr 13 2018, 11:51
Цитата(remixx @ Apr 13 2018, 05:46)
Проблема походу не в коде. На схеме отсутствует кварц, а в дш он есть. Детали уже приобрел, во вторник протестирую вместе с ним.
можно с ноги контроллера протактировать
Автор: remixx May 7 2018, 08:43
Вернулся к работе, но после всех корректировок так ничего и не изменилось)
Может быть я неправильно настраиваю CPOL и CPHA?
Приложил картинку передачи сигналов из ДШ.
По-моему в настройках SPI нужно устанавливать CPOL - 0, CPHA - 1Edge.
Еще кстати заметил, что в настройках выводов SCK и MOSI заданы как AF, а MISO как Input. А разве MISO не должен тоже задаваться как AF?
Автор: haker_fox May 7 2018, 09:16
QUOTE (remixx @ May 7 2018, 16:43)
Может быть я неправильно настраиваю CPOL и CPHA?
Приложил картинку передачи сигналов из ДШ.
Фазировку шины проверьте осциллографом, и сравните картинку с даташитом.
А также (я работал с ADS1247, ADS131E04):
1. Проверьте, что тактовая частота SPI укладывается в допустимые.
2. Проверьте, что сигнал CS удерживается в низком уровне на время передачи кода команды и её аргументов (некоторые МК дёргают CS после передачи каждого байта, так работать не будет).
3. Считайте значения регистров по-умолчанию из АЦП, по ним можно сразу проверить, работает ли шина или нет. Я таким образом детектирую наличие АЦП на шине, и его косвенную исправность.
4. Проверьте, что CS опускается в ноль чуть раньше передачи данных по шине, и поднимается в 1 - чуть позже. Эти времена уточнить по даташиту. Я просто сделал 1 мс с большим запасом.
5. Ну и банально: проверьте уровни всхем питаний, доходят ли сигналы шины до АЦП и т.п.
Автор: Stanislav_S May 7 2018, 10:19
В общем случае надо смотреть такие вещи:
- правильно настроить SPI - режим 1
- очень внимательно прочитать ДШ на АЦП на предмет команд, работы SPI и особенно важно не упустить задержки, коих там много и без их соблюдения нормальной работы не будет!
- выбросить HAL и написать нормально - это самый лучший путь, АЦП достаточно сложный в плане работы (для новичка конечно).
А так могу сказать, что АЦП работает - у меня в текущем проекте их 3 штуки на плате и все прекрасно работает.
Автор: remixx May 8 2018, 04:14
Цитата(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 May 8 2018, 06:13
QUOTE (remixx @ May 8 2018, 12:14)
1. Насколько я понимаю рабочая частота АЦП определяется кварцем? В таком случае она равна 8 МГц. Частоту SPI беру с очень большим запасом (1.125 МГц, картинка ниже).
Кварцем определяется работа микроконтроллера. Частота АЦП - совсем другая, см. даташит.
QUOTE (remixx @ May 8 2018, 12:14)
Единственое чего не делаю, это задержек после отправки и получения SPI. Как мне казалось внутри этих функций есть проверка флагов окончания передачи, попробую добавить задержки после них.
Если у вас нет осциллографа, либо логического анализатора, то отладить обмен на шине конечно можно методом проб и ошибок, но лучше найдите один из этих приборов. Иначе можно долго отлаживать.
Кстати, думаю, что публиковать длиннющие куски кода смысла нет, т.к. реализация либы spi чуть ли не индивидуальная у каждого микроконтроллера, и версии. Поэтому лучше приведите диаграммы с шины. Но для этого нужен осциллограф, либо анализатор.
Автор: remixx May 10 2018, 07:15
Есть отдельный кварц на АЦП.
Все заработало! Похоже проблема была именно в режиме SPI (0, 2Edge).
Всем спасибо.
Автор: haker_fox May 10 2018, 08:45
QUOTE (remixx @ May 10 2018, 15:15)
Есть отдельный кварц на АЦП.
В следующий раз приводите вместе с кодом и полную схему подключения, т.к. на вашей УГО АЦП неполное.
QUOTE (remixx @ May 10 2018, 15:15)
Все заработало! Похоже проблема была именно в режиме SPI (0, 2Edge).
Странно. Либо вы редко занимались отладкой, либо проблема была не только в этом, т.к. времени прошло несколько дней с того времени, как вам посоветовали проверить режим. Ну, а слово "похоже" говорит, что логического анализатора у вас нет. Заведите. На алиэксресс купите самый недорогой. Он вам сэкономит кучу времени при отладке интерфейсов.
Русская версия Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)