Форум РадиоКот • Просмотр темы - DMA+SPI+STM32f103. Трабл с прерыванием.
Сообщения без ответов | Активные темы
Страница 1 из 2
[ Сообщений: 21 ]
,
Автор
Сообщение
Alex-Elektron
Заголовок сообщения: DMA+SPI+STM32f103. Трабл с прерыванием.
Добавлено: Чт ноя 02, 2017 14:06:52
Зарегистрирован: Сб янв 11, 2014 21:25:55Сообщений: 113
Рейтинг сообщения: 0
Доброго. Настраиваю связку DMA+SPI на чтение. Проблема в том, что прога не заходит в прерывание по окончании приёма DMA. Но при этом SPI посылает запрос на чтение и принимает ответ от микрухи (смотрел логическим анализатором). Может, кто заметит, в чём косяк? (Возможно, на SPL и HAL было бы быстрее и проще, но я их не люблю). Код следующий:
Код:
uint8_t dma_answ[5] = {0}; void clock_init(){ RCC->CFGR &= ~(RCC_CFGR_PLLSRC | RCC_CFGR_SW); RCC->CR &= ~RCC_CR_PLLON; RCC->CFGR |= RCC_CFGR_SW_PLL; RCC->CFGR &= ~RCC_CFGR_PLLMULL; RCC->CFGR |= RCC_CFGR_PLLMULL9;// | RCC_CFGR_PLLSRC ; RCC->CR |= RCC_CR_PLLON | RCC_CR_HSEON; while((RCC->CR & RCC_CR_PLLRDY)==0); } void SPI_Init(uint8_t lsbFirst, uint8_t clockPol, uint8_t clockEdg){ RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; // Тактирование альтернативных функций включено RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; // Тактирование порта А включено //------- TEST-PIN ---------- GPIOA->CRH |= GPIO_CRH_MODE12; // Выход, 50 МГц GPIOA->CRH &= ~GPIO_CRH_CNF12; // Общего назначения, push-pull GPIOA->BSRR = GPIO_BSRR_BR12; //---------- //------- CS-PIN ---------- GPIOA->CRL |= GPIO_CRL_MODE4; // Выход, 50 МГц GPIOA->CRL &= ~GPIO_CRL_CNF4; // Общего назначения, push-pull GPIOA->BSRR = GPIO_BSRR_BS4; // Высокий уровень //---------- //------- SCK-PIN ---------- GPIOA->CRL |= GPIO_CRL_MODE5; // Выход, 50 МГц GPIOA->CRL &= ~GPIO_CRL_CNF5; GPIOA->CRL |= GPIO_CRL_CNF5_1; // Альтернативная функция, push-pull //---------- //------- MISO-PIN ---------- GPIOA->CRL &= ~GPIO_CRL_MODE6; // Вход GPIOA->CRL &= ~GPIO_CRL_CNF6; GPIOA->CRL |= GPIO_CRL_CNF6_1; // Альтернативная функция, pull-up/pull-down GPIOA->BSRR = GPIO_BSRR_BS6; // Высокий уровень //---------- //------- MOSI-PIN ---------- GPIOA->CRL |= GPIO_CRL_MODE7; // Выход, 50 МГц GPIOA->CRL &= ~GPIO_CRL_CNF7; GPIOA->CRL |= GPIO_CRL_CNF7_1; // Альтернативная функция, push-pull //---------- SPI1->CR1 = 0x0000; // Обнуляем регистр конфигурации SPI1 SPI1->CR2 = 0x0000; // Обнуляем регистр конфигурации SPI1 RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; // Тактирование SPI1 включено SPI1->CR1 = SPI_CR1_SSI | SPI_CR1_SSM | SPI_CR1_MSTR; // Программное управление выводом CS, SPI1 в режиме ведущего if(!lsbFirst) SPI1->CR1 &= ~SPI_CR1_LSBFIRST; // Старшим битом вперёд else SPI1->CR1 |= SPI_CR1_LSBFIRST; // Младшим битом вперёд if(!clockPol) SPI1->CR1 &= ~SPI_CR1_CPOL; // 0 - когда отпущена else SPI1->CR1 |= SPI_CR1_CPOL; // 1 - когда отпущена if(!clockEdg) SPI1->CR1 &= ~SPI_CR1_CPHA; // Выборка по переднему фронту else SPI1->CR1 |= SPI_CR1_CPHA; // Выборка по заднему фронту SPI1->CR2 |= SPI_CR2_RXDMAEN; SPI1->CR1 |= SPI_CR1_BR_1 | SPI_CR1_BR_0 ; // Выбор делителя частоты тактирования шины APB2 (fAPB/16 = 2.25 МГц) SPI1->CR1 |= SPI_CR1_SPE; // Работа SPI1 разрешена NVIC_EnableIRQ(SPI1_IRQn); } void dma_spi_recive( uint8_t* data, uint8_t bytesNumber ){ RCC->AHBENR = RCC_AHBENR_DMA1EN; DMA1_Channel2->CCR = 0x0F; DMA1_Channel2->CPAR = (uint32_t) & SPI1->DR; DMA1_Channel2->CMAR = (uint32_t) dma_answ; DMA1_Channel2->CNDTR = bytesNumber; DMA1_Channel2->CCR |= DMA_CCR2_PL_0 | DMA_CCR2_MINC | DMA_CCR2_TCIE | DMA_CCR2_EN; NVIC_EnableIRQ(DMA1_Channel2_IRQn); } uint8_t SPI_Read( uint8_t data, uint8_t bytesNumber ){ dma_spi_recive(dma_answ, bytesNumber); ADI_PART_CS_LOW; while (!(SPI1->SR & SPI_SR_TXE)); SPI1->DR = data; for(uint8_t byte = 0; byte < bytesNumber; byte++ ) { while (!(SPI1->SR & SPI_SR_TXE)); SPI1->DR = 0x00; } while ( SPI1->SR & SPI_SR_BSY ); ADI_PART_CS_HIGH; return 1; } uint8_t SPI_Read( uint8_t data, uint8_t bytesNumber ){ dma_spi_recive(dma_answ, bytesNumber); ADI_PART_CS_LOW; while (!(SPI1->SR & SPI_SR_TXE)); SPI1->DR = data; for(uint8_t byte = 0; byte < bytesNumber; byte++ ) { while (!(SPI1->SR & SPI_SR_TXE)); SPI1->DR = 0x00; } while ( SPI1->SR & SPI_SR_BSY ); ADI_PART_CS_HIGH; return 1; } uint32_t AD7190_GetRegisterValue(uint8_t registerAddress){ uint8_t registerWord = 0; uint32_t buffer = 0; registerWord = AD7190_COMM_READ | AD7190_COMM_ADDR( registerAddress ); //-- Проверяем, какой длины считываемый регистр ---------- if( registerAddress == AD7190_REG_STAT || registerAddress == AD7190_REG_ID || registerAddress == AD7190_REG_GPOCON ) // если регистры однобайтные { SPI_Read(registerWord, 1); } else // если регистры трёхбайтные { SPI_Read(registerWord, 3); } //---------- return buffer; } unsigned char AD7190_Init(void){ unsigned char status = 1; unsigned long regVal = 0; AD7190_Reset(); regVal = AD7190_GetRegisterValue(AD7190_REG_ID); if( regVal != ID_AD7190) { return status = 0; } GPIOA->BSRR = GPIO_BSRR_BS12; // Высокий уровень return status ; } void AD7190_Reset(void){ for( uint8_t byte = 0; byte <6; byte++ ) { while (!(SPI1->SR & SPI_SR_TXE)); SPI1->DR = 0xFF; } // Посылаем 40 импульсов для сброса TIME_DelayUs(920); } int main(){ clock_init(); for(uint32_t i=0; i<720000; i++); SPI_Init(0, 1, 1); usart_init(); AD7190_Init(); AD7190_GetRegisterValue(AD7190_REG_CONF); __enable_irq (); while(1){ } } void DMA1_Channel2_IRQHandler(void){ if(DMA1->ISR & DMA_ISR_TCIF2){ DMA1_Channel2->CCR &= ~DMA_CCR2_EN; // Flag = 1; if(!(GPIOA->IDR & GPIO_IDR_IDR12)) GPIOA->BSRR = GPIO_BSRR_BS12; else GPIOA->BSRR = GPIO_BSRR_BR12; DMA1->IFCR = DMA_IFCR_CGIF2; } }
Вернуться наверх
Реклама
uk8amk
Заголовок сообщения: Re: DMA+SPI+STM32f103. Трабл с прерыванием.
Добавлено: Пт ноя 03, 2017 10:39:25
Поставщик валерьянки для Кота
Карма: 16
Рейтинг сообщений: 329
Зарегистрирован: Вт ноя 27, 2007 11:32:06Сообщений: 2222Откуда: Tashkent
Рейтинг сообщения: 0
Я увидел ошибку конфигурации DMA. Канал нельзя настраивать когда он включён.
Цитата:
In order to reload a new number of data items to be transferred into the DMA_CNDTRx register, the DMA channel must be disabled.
Вернуться наверх
Реклама
Alex-Elektron
Заголовок сообщения: Re: DMA+SPI+STM32f103. Трабл с прерыванием.
Добавлено: Ср ноя 08, 2017 13:57:50
Зарегистрирован: Сб янв 11, 2014 21:25:55Сообщений: 113
Рейтинг сообщения: 0
Да, безусловно. Там должно было быть
Код:
DMA1_Channel2->CCR = 0x00;
.
Исправил, подчистил код, та же фигня - прерывания от DMA не происходит. Никакого. Даже ошибки передачи. Может, что-то где-то ещё надо разрешать? Прерывания по завершению транзакции DMA разрешены, глобальные разрешены.
Код:
#include "stm32f10x.h" // Device header #include "AD7190.h" #include "TIME.h" #define DMA_EN DMA1_Channel2->CCR |= DMA_CCR2_EN #define DMA_DIS DMA1_Channel2->CCR &= ~DMA_CCR2_EN //--------- SPI ------- volatile uint8_t SpiByteCnt = 0; uint8_t SpiDataRX[5] = {0}; uint8_t dma_answ[5] = {0}; void clock_init(){ RCC->CFGR &= ~(RCC_CFGR_PLLSRC | RCC_CFGR_SW); RCC->CR &= ~RCC_CR_PLLON; RCC->CFGR |= RCC_CFGR_SW_PLL; RCC->CFGR &= ~RCC_CFGR_PLLMULL; RCC->CFGR |= RCC_CFGR_PLLMULL9; RCC->CR |= RCC_CR_PLLON | RCC_CR_HSEON; while((RCC->CR & RCC_CR_PLLRDY)==0); } void usart_init(){ RCC->APB2ENR |= RCC_APB2ENR_USART1EN; //USART1 Clock ON RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_AFIOEN; // GPIOA Clock ON. Alter function clock ON USART1->BRR = 0xEA6; // Bodrate for 9600 on 72Mhz USART1->CR1 |= USART_CR1_UE | USART_CR1_TE; // USART1 ON, TX ON, RX ON GPIOA->CRH &= ~GPIO_CRH_CNF9; // Clear CNF bit 9 GPIOA->CRH |= GPIO_CRH_CNF9_1; // Set CNF bit 9 to 10 - AFIO Push-Pull GPIOA->CRH |= GPIO_CRH_MODE9_0; // Set MODE bit 9 to Mode 01 = 10MHz GPIOA->CRH &= ~GPIO_CRH_CNF10; // Clear CNF bit 9 GPIOA->CRH |= GPIO_CRH_CNF10_0; // Set CNF bit 9 to 01 = HiZ GPIOA->CRH &= ~GPIO_CRH_MODE10; // Set MODE bit 9 to Mode 01 = 10MHz // NVIC_EnableIRQ(USART1_IRQn); // USART1 interrupt enable } void usart_tx(uint8_t data){ USART1->DR = data; while(!(USART1->SR & USART_SR_TC)); } uint8_t SPI_Init(uint8_t lsbFirst, uint8_t clockPol, uint8_t clockEdg){ RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; // Тактирование альтернативных функций включено RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; // Тактирование порта А включено //------- TEST-PIN ---------- GPIOA->CRH |= GPIO_CRH_MODE12; // Выход, 50 МГц GPIOA->CRH &= ~GPIO_CRH_CNF12; // Общего назначения, push-pull GPIOA->BSRR = GPIO_BSRR_BR12; //---------- //------- CS-PIN ---------- GPIOA->CRL |= GPIO_CRL_MODE4; // Выход, 50 МГц GPIOA->CRL &= ~GPIO_CRL_CNF4; // Общего назначения, push-pull GPIOA->BSRR = GPIO_BSRR_BS4; // Высокий уровень //---------- //------- SCK-PIN ---------- GPIOA->CRL |= GPIO_CRL_MODE5; // Выход, 50 МГц GPIOA->CRL &= ~GPIO_CRL_CNF5; GPIOA->CRL |= GPIO_CRL_CNF5_1; // Альтернативная функция, push-pull //---------- //------- MISO-PIN ---------- GPIOA->CRL &= ~GPIO_CRL_MODE6; // Вход GPIOA->CRL &= ~GPIO_CRL_CNF6; GPIOA->CRL |= GPIO_CRL_CNF6_1; // Альтернативная функция, pull-up/pull-down GPIOA->BSRR = GPIO_BSRR_BS6; // Высокий уровень //---------- //------- MOSI-PIN ---------- GPIOA->CRL |= GPIO_CRL_MODE7; // Выход, 50 МГц GPIOA->CRL &= ~GPIO_CRL_CNF7; GPIOA->CRL |= GPIO_CRL_CNF7_1; // Альтернативная функция, push-pull //---------- RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; // Тактирование SPI1 включено SPI1->CR1 = SPI_CR1_SSI | SPI_CR1_SSM | SPI_CR1_MSTR; // Программное управление выводом CS, SPI1 в режиме ведущего if(!lsbFirst) SPI1->CR1 &= ~SPI_CR1_LSBFIRST; // Старшим битом вперёд else SPI1->CR1 |= SPI_CR1_LSBFIRST; // Младшим битом вперёд if(!clockPol) SPI1->CR1 &= ~SPI_CR1_CPOL; // 0 - когда отпушена else SPI1->CR1 |= SPI_CR1_CPOL; // 1 - когда отпущена if(!clockEdg) SPI1->CR1 &= ~SPI_CR1_CPHA; // Выборка по переднему фронту else SPI1->CR1 |= SPI_CR1_CPHA; // Выборка по заднему фронту SPI1->CR1 |= SPI_CR1_BR_1 | SPI_CR1_BR_0; // Выбор делителя частоты тактирования шины APB2 (fAPB/16 = 2.25 МГц) SPI1->CR1 |= SPI_CR1_SPE; // Работа SPI1 разрешена SPI1->CR2 = SPI_CR2_RXDMAEN; return 1; } void dma_spi_recive( uint8_t bytesNumber ){ RCC->AHBENR = RCC_AHBENR_DMA1EN; DMA1_Channel2->CCR = 0x00; DMA1_Channel2->CPAR = (uint32_t) & SPI1->DR; DMA1_Channel2->CMAR = (uint32_t) dma_answ; DMA1_Channel2->CNDTR = bytesNumber; DMA1_Channel2->CCR |= DMA_CCR2_PL_0 | DMA_CCR2_MINC | DMA_CCR2_TCIE; NVIC_EnableIRQ(DMA1_Channel2_IRQn); } int main(){ uint8_t init = 0, registerWord[5] = {0}; clock_init(); SPI_Init(0, 1, 1); usart_init(); __enable_irq (); while(1){ if(!init){ for( uint8_t byte = 0; byte <6; byte++ ){ while (!(SPI1->SR & SPI_SR_TXE)); SPI1->DR = 0xFF; } while ( SPI1->SR & SPI_SR_BSY ); TIME_DelayUs(920); registerWord[0] = AD7190_COMM_READ | AD7190_COMM_ADDR( AD7190_REG_ID ); ADI_PART_CS_LOW; while (!(SPI1->SR & SPI_SR_TXE)); SPI1->DR = registerWord[0]; while ( SPI1->SR & SPI_SR_BSY ); dma_spi_recive(1); DMA_EN; init = 1; } } } void DMA1_Channel2_IRQHandler (void) { if(DMA1->ISR & DMA_ISR_TCIF2){ ADI_PART_CS_HIGH; if(!(GPIOA->IDR & GPIO_IDR_IDR12)) GPIOA->BSRR = GPIO_BSRR_BS12; else GPIOA->BSRR = GPIO_BSRR_BR12; DMA_DIS; NVIC_DisableIRQ(DMA1_Channel2_IRQn); DMA1->IFCR = DMA_IFCR_CGIF2; } }
Добавлено after 3 hours 48 minutes 37 seconds: Столкнулся с магией: написал всю эту либилерду в КОКОСЕ и она заработала!!! В Кейле же прерываний как не было так и нет! За что меня так наказали? Код, который работает в КОКОСЕ
Код:
#include "stm32f10x.h" #define AD7195_CS_HIGH GPIOA->BSRR |= GPIO_BSRR_BS4 #define AD7195_CS_LOW GPIOA->BSRR |= GPIO_BSRR_BR4 #define DMA_SPI_TX_ENABLE DMA1_Channel3->CCR |= DMA_CCR3_EN; #define DMA_SPI_TX_DISABLE DMA1_Channel3->CCR &= ~DMA_CCR3_EN; #define DMA_SPI_RX_ENABLE DMA1_Channel2->CCR |= DMA_CCR2_EN; #define DMA_SPI_RX_DISABLE DMA1_Channel2->CCR &= ~DMA_CCR3_EN; uint8_t GlobalVar_SPI_Received = 0, get[5]; void GPIO_INIT(){ RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; // Тактирование альтернативных функций включено RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; // Тактирование порта А включено //------- TEST-PIN ---------- GPIOA->CRH |= GPIO_CRH_MODE12; // Выход, 50 МГц GPIOA->CRH &= ~GPIO_CRH_CNF12; // Общего назначения, push-pull GPIOA->BSRR = GPIO_BSRR_BR12; //---------- //------- CS-PIN ---------- GPIOA->CRL |= GPIO_CRL_MODE4; // Выход, 50 МГц GPIOA->CRL &= ~GPIO_CRL_CNF4; // Общего назначения, push-pull GPIOA->BSRR = GPIO_BSRR_BS4; // Высокий уровень //---------- //------- SCK-PIN ---------- GPIOA->CRL |= GPIO_CRL_MODE5; // Выход, 50 МГц GPIOA->CRL &= ~GPIO_CRL_CNF5; GPIOA->CRL |= GPIO_CRL_CNF5_1; // Альтернативная функция, push-pull //---------- //------- MISO-PIN ---------- GPIOA->CRL &= ~GPIO_CRL_MODE6; // Вход GPIOA->CRL &= ~GPIO_CRL_CNF6; GPIOA->CRL |= GPIO_CRL_CNF6_1; // Альтернативная функция, pull-up/pull-down GPIOA->BSRR = GPIO_BSRR_BS6; // Высокий уровень //---------- //------- MOSI-PIN ---------- GPIOA->CRL |= GPIO_CRL_MODE7; // Выход, 50 МГц GPIOA->CRL &= ~GPIO_CRL_CNF7; GPIOA->CRL |= GPIO_CRL_CNF7_1; // Альтернативная функция, push-pull //---------- AD7195_CS_HIGH; } void SPI_INIT(){ RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; // Тактирование SPI1 включено SPI1->CR1 = SPI_CR1_SSI | SPI_CR1_SSM | // Программное управление выводом CS SPI_CR1_BR_1 | SPI_CR1_BR_0 | // Выбор делителя частоты тактирования шины APB2 SPI_CR1_CPOL | SPI_CR1_CPHA | SPI_CR1_MSTR; // 1 - когда CLK отпущена, выборка по заднему фронту, SPI1 в режиме ведущего SPI1->CR1 |= SPI_CR1_SPE; // Работа SPI1 разрешена } void dma_spi_tx(uint8_t * data, uint16_t size) { RCC->AHBENR |= RCC_AHBENR_DMA1EN; DMA1_Channel3->CPAR = (uint32_t) & SPI1->DR; DMA1_Channel3->CMAR = (uint32_t) data; DMA1_Channel3->CNDTR = size; DMA1_Channel3->CCR = DMA_CCR3_PL_0 | DMA_CCR3_MINC | DMA_CCR3_DIR | DMA_CCR3_TCIE; SPI1->CR2 |= SPI_CR2_TXDMAEN; NVIC_EnableIRQ(DMA1_Channel3_IRQn); } void SPI_SendData(uint8_t *data, uint8_t size) { dma_spi_tx(data, size); AD7195_CS_LOW; DMA_SPI_TX_ENABLE; } void dma_spi_rx(uint8_t * data, uint16_t size) { RCC->AHBENR |= RCC_AHBENR_DMA1EN; DMA1_Channel2->CPAR = (uint32_t) & SPI1->DR; DMA1_Channel2->CMAR = (uint32_t) data; DMA1_Channel2->CNDTR = size; DMA1_Channel2->CCR = DMA_CCR2_PL_0 | DMA_CCR2_MINC | DMA_CCR2_TCIE; SPI1->CR2 |= SPI_CR2_RXDMAEN; NVIC_EnableIRQ(DMA1_Channel2_IRQn); } void SPI_ReciveData(uint8_t *data, uint8_t size) { dma_spi_rx(data, size); AD7195_CS_LOW; DMA_SPI_RX_ENABLE; } int main(void){ uint8_t spi_data[]={0x60}; __enable_irq (); GPIO_INIT(); SPI_INIT(); for( uint8_t byte = 0; byte <6; byte++ ){ while (!(SPI1->SR & SPI_SR_TXE)); SPI1->DR = 0xFF; } while ( SPI1->SR & SPI_SR_BSY ); for(uint32_t i=0; i<72000; i++); SPI_SendData(spi_data, 1); while(1){ } } void DMA1_Channel3_IRQHandler(void) { if (DMA1->ISR & DMA_ISR_TCIF3) { while ( SPI1->SR & SPI_SR_BSY ); AD7195_CS_HIGH; DMA_SPI_TX_DISABLE; SPI1->CR2 |= SPI_CR2_TXDMAEN; SPI_ReciveData(get, 1); while (!(SPI1->SR & SPI_SR_TXE)); SPI1->DR = 0x00; DMA1->IFCR = DMA_IFCR_CTCIF3; } } void DMA1_Channel2_IRQHandler(void) { if (DMA1->ISR & DMA_ISR_TCIF2) { while ( SPI1->SR & SPI_SR_BSY ); AD7195_CS_HIGH; GPIOA->BSRR |= GPIO_BSRR_BS12; GlobalVar_SPI_Received = 1; DMA_SPI_RX_DISABLE; DMA1->IFCR = DMA_IFCR_CTCIF2; } }
Вернуться наверх
Реклама
dosikus
Заголовок сообщения: Re: DMA+SPI+STM32f103. Трабл с прерыванием.
Добавлено: Чт ноя 09, 2017 07:28:48
Друг Кота
Карма: 30
Рейтинг сообщений: 155
Зарегистрирован: Пн июл 28, 2008 22:12:01Сообщений: 3604
Рейтинг сообщения: 0
Столкнулся с магией: написал всю эту либилерду в КОКОСЕ и она заработала!!! В Кейле же прерываний как не было так и нет! За что меня так наказали?
Стартап подключен?
Вернуться наверх
Реклама
Организация питания на основе надежных литиевых аккумуляторов EVE и микросхем азиатского производства
Качественное и безопасное устройство, работающее от аккумулятора, должно учитывать его физические и химические свойства, профили заряда и разряда, их изменение во времени и под влиянием различных условий, таких как температура и ток нагрузки. Мы расскажем о литий-ионных аккумуляторных батареях EVE и нескольких решениях от различных китайских компаний, рекомендуемых для разработок приложений с использованием этих АКБ. Представленные в статье китайские аналоги помогут заменить продукцию западных брендов с оптимизацией цены без потери качества.
Подробнее>>
Alex-Elektron
Заголовок сообщения: Re: DMA+SPI+STM32f103. Трабл с прерыванием.
Добавлено: Пн ноя 13, 2017 06:50:07
Зарегистрирован: Сб янв 11, 2014 21:25:55Сообщений: 113
Рейтинг сообщения: 0
dosikus , в точку! Большое спасибо!
Вернуться наверх
Реклама
Реклама
Новый аккумулятор EVE серии PLM для GSM-трекеров, работающих в жёстких условиях (до -40°С)
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
Подробнее>>
Alex-Elektron
Заголовок сообщения: Re: DMA+SPI+STM32f103. Трабл с прерыванием.
Добавлено: Вт окт 09, 2018 12:27:27
Зарегистрирован: Сб янв 11, 2014 21:25:55Сообщений: 113
Рейтинг сообщения: 0
Прошу помощи! Всё тот же DMA. Работает в связке с SPI 2. Причём данные передаёт прекрасно, со свистом. Но прерывание по приёму не работает. Стартап подключен. Настройки периферии:
1. GPIO
Код:
void spi2_gpio_init(void){ RCC->APB2ENR |= RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_AFIOEN; //------- CS_OLED, RESET_OLED, POWER_OLED, D/C#_OLED ---------- GPIOB->CRH |= (GPIO_CRH_MODE12 | GPIO_CRH_MODE11 | GPIO_CRH_MODE10); // Выход, 50 МГц GPIOB->CRH &= ~(GPIO_CRH_CNF12 | GPIO_CRH_CNF11 | GPIO_CRH_CNF10); // Общего назначения, push-pull GPIOB->CRL |= GPIO_CRL_MODE2; // Выход, 50 МГц GPIOB->CRL &= ~GPIO_CRL_CNF2; // Общего назначения, push-pull GPIOB->BSRR = GPIO_BSRR_BS12; // Высокий уровень //---------- //--- CS_FLASH, CS_EEPROM ---------- GPIOC->CRL |= (GPIO_CRL_MODE5 | GPIO_CRL_MODE4); // Выход, 50 МГц GPIOC->CRL &= ~(GPIO_CRL_CNF5 | GPIO_CRL_CNF4); // Общего назначения, push-pull GPIOC->BSRR = GPIO_BSRR_BS5 | GPIO_BSRR_BS4; // Высокий уровень //---------- //--- SCK, MOSI ---------- GPIOB->CRH |= (GPIO_CRH_MODE13 | GPIO_CRH_MODE15); // Выход, 50 МГц GPIOB->CRH &= ~(GPIO_CRH_CNF13 | GPIO_CRH_CNF15); GPIOB->CRH |= (GPIO_CRH_CNF13_1 | GPIO_CRH_CNF15_1); // Альтернативная функция, push-pull //---------- //------- MISO-PIN ---------- GPIOB->CRH &= ~GPIO_CRH_MODE14; // Вход GPIOB->CRH &= ~GPIO_CRH_CNF14; GPIOB->CRH |= GPIO_CRH_CNF14_0; // floating //----------
2. SPI2
Код:
/* * 2-line unidirectional data mode * CRC disabled * 8bit data format * Full duplex * Software slave management enabled * MSB transmitted first * fPCLK/2 * Master configuration * SCK to 1 when idle * The second clock transition is the first data capture edge */ void spi_init(void){ RCC->APB1ENR |= RCC_APB1ENR_SPI2EN; SPI2->CR1 = SPI_CR1_SSM | SPI_CR1_SSI | SPI_CR1_BR_0 | SPI_CR1_MSTR | SPI_CR1_CPOL | SPI_CR1_CPHA | SPI_CR1_SPE; GPIOB->BSRR = GPIO_BSRR_BS13; //SCK pull-up }
3. DMA_TX
Код:
void dma_spi2_tx(uint8_t *data, uint16_t size) { RCC->AHBENR |= RCC_AHBENR_DMA1EN; DMA1_Channel5->CCR = 0; DMA1_Channel5->CPAR = (uint32_t) &SPI2->DR; //Указываем адрес периферии DMA1_Channel5->CMAR = (uint32_t) &data[0]; //Указываем адрес в памяти DMA1_Channel5->CNDTR = size; //Количество пересылаемых значений DMA1_Channel5->CCR = DMA_CCR5_DIR | //Указываем направление передачи данных, из памяти в периферию DMA_CCR5_MINC | //Адрес памяти инкрементируем после каждой пересылки. DMA_CCR5_PL | //Приоритет - очень высокий DMA_CCR5_TCIE | //Разрешаем прерывание по окончанию передачи DMA_CCR5_EN; //Разрешаем работу 4-го канала DMA SPI2->CR2 = SPI_CR2_TXDMAEN; NVIC_EnableIRQ(DMA1_Channel5_IRQn); }
4. DMA_RX
Код:
void dma_spi2_rx(uint8_t *data, uint16_t size) { RCC->AHBENR |= RCC_AHBENR_DMA1EN; DMA1_Channel4->CCR = 0; DMA1_Channel4->CPAR = (uint32_t) &SPI2->DR; //Указываем адрес периферии DMA1_Channel4->CMAR = (uint32_t) &data[0]; //Указываем адрес в памяти DMA1_Channel4->CNDTR = size; //Количество пересылаемых значений DMA1_Channel4->CCR = DMA_CCR4_MINC | //Адрес памяти инкрементируем после каждой пересылки. DMA_CCR4_PL | //Приоритет - очень высокий DMA_CCR4_HTIE | //Разрешаем прерывание по передаче половины буфера DMA_CCR4_TCIE | //Разрешаем прерывание по окончанию передачи DMA_CCR4_TEIE | //Разрешаем прерывание по окончанию передачи DMA_CCR4_EN; //Разрешаем работу 4-го канала DMA SPI2->CR2 = SPI_CR2_RXDMAEN; NVIC_EnableIRQ(DMA1_Channel4_IRQn); }
5. Приём/отправка данных
Код:
void SPI_SendData(uint8_t *data, uint16_t size) { dma_spi2_tx(data, size); } void SPI_ReciveData(uint8_t *data, uint16_t size) { dma_spi2_rx(data, size); SPI_SendData(data, size); }
6. Обработчик прерываний по окончанию передачи
Код:
void DMA1_Channel5_IRQHandler() { if (DMA1->ISR & DMA_ISR_TCIF5 ) { while(!(SPI2->SR & SPI_SR_TXE)); while (SPI2->SR & SPI_SR_BSY); All_Modules_Deselect(); DMA1_Channel5->CCR &= ~DMA_CCR5_EN; SPI2->CR2 &= ~ SPI_CR2_TXDMAEN; DMA1->IFCR |= DMA_IFCR_CTCIF5; } }
7. Обработчик прерываний по окончанию приёма
Код:
void DMA1_Channel4_IRQHandler(void) { if (DMA1->ISR & DMA_ISR_HTIF4 ) { // Уведомляем, что данные приняты GlobalVar_SPI_Received = 1; DMA1_Channel4->CCR &= ~DMA_CCR4_EN; DMA1->IFCR |= DMA_IFCR_CHTIF4; } if (DMA1->ISR & DMA_ISR_TCIF4 ) { // Уведомляем, что данные приняты GlobalVar_SPI_Received = 1; DMA1_Channel4->CCR &= ~DMA_CCR4_EN; DMA1->IFCR |= DMA_IFCR_CTCIF4; } if (DMA1->ISR & DMA_ISR_TEIF4 ) { // Уведомляем, что данные приняты GlobalVar_SPI_Received = 1; DMA1_Channel4->CCR &= ~DMA_CCR4_EN; DMA1->IFCR |= DMA_IFCR_CTEIF4; } }
Проверку приёма делаю по переменной GlobalVar_SPI_Received. Если она =1, то выкидываем принятые данные в USART. Но прикол в том, что МК не входит в прерывание void DMA1_Channel4_IRQHandler(void). Чего здесь не хватает? По логам ответ от внешнего флеша идёт, запрашиваю 512 байт - он их выкидывает.
Вернуться наверх
Реклама
dosikus
Заголовок сообщения: Re: DMA+SPI+STM32f103. Трабл с прерыванием.
Добавлено: Вт окт 09, 2018 12:51:02
Друг Кота
Карма: 30
Рейтинг сообщений: 155
Зарегистрирован: Пн июл 28, 2008 22:12:01Сообщений: 3604
Рейтинг сообщения: 0
Код:
DMA1->IFCR = DMA_IFCR_CHTIF4;
Вернуться наверх
Реклама
Alex-Elektron
Заголовок сообщения: Re: DMA+SPI+STM32f103. Трабл с прерыванием.
Добавлено: Вт окт 09, 2018 13:06:22
Зарегистрирован: Сб янв 11, 2014 21:25:55Сообщений: 113
Рейтинг сообщения: 0
Не, не помогло. Перенёс передачу по USART прямо в прерывание - ноль реакции. Он даже не заходит в прерывание.
Вернуться наверх
Реклама
Reflector
Заголовок сообщения: Re: DMA+SPI+STM32f103. Трабл с прерыванием.
Добавлено: Вт окт 09, 2018 13:43:25
Поставщик валерьянки для Кота
Карма: 20
Рейтинг сообщений: 253
Зарегистрирован: Вс июн 19, 2016 09:32:03Сообщений: 2090
Рейтинг сообщения: 0
5. Приём/отправка данных
Код:
void SPI_SendData(uint8_t *data, uint16_t size) { dma_spi2_tx(data, size); // SPI2->CR2 = SPI_CR2_TXDMAEN; } void SPI_ReciveData(uint8_t *data, uint16_t size) { dma_spi2_rx(data, size); // SPI2->CR2 = SPI_CR2_RXDMAEN; SPI_SendData(data, size); }
Вернуться наверх
Реклама
Alex-Elektron
Заголовок сообщения: Re: DMA+SPI+STM32f103. Трабл с прерыванием.
Добавлено: Вт окт 09, 2018 13:47:07
Зарегистрирован: Сб янв 11, 2014 21:25:55Сообщений: 113
Рейтинг сообщения: 0
Вернуться наверх
Reflector
Заголовок сообщения: Re: DMA+SPI+STM32f103. Трабл с прерыванием.
Добавлено: Вт окт 09, 2018 13:50:00
Поставщик валерьянки для Кота
Карма: 20
Рейтинг сообщений: 253
Зарегистрирован: Вс июн 19, 2016 09:32:03Сообщений: 2090
Рейтинг сообщения: 0
Тоже мимо(
Не мимо, просто помимо этой ошибки есть и другие
Вернуться наверх
Alex-Elektron
Заголовок сообщения: Re: DMA+SPI+STM32f103. Трабл с прерыванием.
Добавлено: Вт окт 09, 2018 14:06:33
Зарегистрирован: Сб янв 11, 2014 21:25:55Сообщений: 113
Рейтинг сообщения: 0
На передачу не влияет точно порядок, сперва dma или spi было включено
Вернуться наверх
Reflector
Заголовок сообщения: Re: DMA+SPI+STM32f103. Трабл с прерыванием.
Добавлено: Вт окт 09, 2018 14:11:24
Поставщик валерьянки для Кота
Карма: 20
Рейтинг сообщений: 253
Зарегистрирован: Вс июн 19, 2016 09:32:03Сообщений: 2090
Рейтинг сообщения: 0
На передачу не влияет точно порядок, сперва dma или spi было включено
При чем тут порядок, у тебя вызов SPI_SendData() сбрасывает SPI_CR2_RXDMAEN.
Вернуться наверх
dosikus
Заголовок сообщения: Re: DMA+SPI+STM32f103. Трабл с прерыванием.
Добавлено: Вт окт 09, 2018 15:35:49
Друг Кота
Карма: 30
Рейтинг сообщений: 155
Зарегистрирован: Пн июл 28, 2008 22:12:01Сообщений: 3604
Рейтинг сообщения: 0
Приоритеты прерываний выстави...
Вернуться наверх
AlanDrakes
Заголовок сообщения: Re: DMA+SPI+STM32f103. Трабл с прерыванием.
Добавлено: Вт окт 09, 2018 18:14:32
Нашел транзистор. Понюхал.
Карма: 5
Рейтинг сообщений: 21
Зарегистрирован: Пн июл 04, 2016 16:51:22Сообщений: 196Откуда: Россия, Омск
Рейтинг сообщения: 0
У меня аналогично не работает корректно приём данных посредством DMA. Из того, что удалось выяснить во время отладки - SPI модуль ЖДЁТ, пока в SPI->TDR будут положены новые данные. При приёме можете попробовать инициализировать DMA1_Channel5, но без смещения адреса буфера (например постоянно читать байт в котором будет 0xFF или ноль), после этого настроить Channel4 и разрешить их работу. У меня в коде аналогичный костыль.
Вернуться наверх
Reflector
Заголовок сообщения: Re: DMA+SPI+STM32f103. Трабл с прерыванием.
Добавлено: Вт окт 09, 2018 19:07:03
Поставщик валерьянки для Кота
Карма: 20
Рейтинг сообщений: 253
Зарегистрирован: Вс июн 19, 2016 09:32:03Сообщений: 2090
Рейтинг сообщения: 0
УИз того, что удалось выяснить во время отладки - SPI модуль ЖДЁТ, пока в SPI->TDR будут положены новые данные.
Что же тут удивительного?
In reception, a DMA request is issued each time RXNE is set to 1. The DMA then reads the SPI_DR register (this clears the RXNE flag).
Вернуться наверх
Alex-Elektron
Заголовок сообщения: Re: DMA+SPI+STM32f103. Трабл с прерыванием.
Добавлено: Ср окт 10, 2018 06:25:36
Зарегистрирован: Сб янв 11, 2014 21:25:55Сообщений: 113
Рейтинг сообщения: 0
!!! Цитата:
При чем тут порядок, у тебя вызов SPI_SendData() сбрасывает SPI_CR2_RXDMAEN.
!!! Всё пошло, поехало! Спасибо!
Вернуться наверх
Frogfot
Заголовок сообщения: Re: DMA+SPI+STM32f103. Трабл с прерыванием.
Добавлено: Вс апр 21, 2019 19:43:49
Карма: 2
Рейтинг сообщений: 10
Зарегистрирован: Ср окт 19, 2011 08:48:27Сообщений: 443Откуда: Мать городов русских
Рейтинг сообщения: 0
Короче, наступил на свои грабли - запустил на F103 SPI + DMA - 1 раз входит в прерывание от DMA и всё
Код:
void Init_DMA5 (void) // SPI2 Transmitte { RCC->AHBENR |= RCC_AHBENR_DMA1EN; // Enable Clock DMA1 DMA1_Channel5->CCR = 0x0000; // Disable DMA DMA1_Channel5->CPAR = (uint32_t)&(SPI2->DR); // Periferal Adress DMA1_Channel5->CMAR = (uint32_t)&(ScreenBuf [(AdressLED << 4)]); // Memory Adress DMA1_Channel5->CNDTR = DMA_BUFF_SIZE; // Number of data to transfer DMA1_Channel5->CCR = DMA_CCR1_DIR | // Data transfer direction - Read from memory DMA_CCR1_MINC | // Memory increment mode enabled DMA_CCR1_TCIE | // Transfer complete interrupt enable DMA_CCR1_EN; // Enable DMA1 SPI2->CR2 |= SPI_CR2_TXDMAEN; // Tx buffer DMA enabled NVIC_EnableIRQ(DMA1_Channel5_IRQn); // Enable Interrupt DMA1 channel CH5 in NVIC NVIC_SetPriority(DMA1_Channel5_IRQn,14); }
Код:
void DMA1_Channel5_IRQnHandler (void) { static u16 CntDMA1CH5; if (CntDMA1CH5++ & 0x00F0) { GPIOA->BSRR = GPIO_BSRR_BR12; } // PA12 - LED RED else { GPIOA->BSRR = GPIO_BSRR_BS12; } while (!(SPI2->SR & SPI_SR_TXE)); while (SPI2->SR & SPI_SR_BSY); if (DMA1->ISR & DMA_ISR_TCIF5) // Check Transfer Complete flag { DMA1->IFCR |= DMA_IFCR_CTCIF5; // Clear Transfer Complete flag } DMA1->IFCR |= DMA_IFCR_CGIF5; // Channel 5 Global interrupt clear }
_________________ Хорошему коту и в декабре - март
Вернуться наверх
Alex-Elektron
Заголовок сообщения: Re: DMA+SPI+STM32f103. Трабл с прерыванием.
Добавлено: Пн апр 22, 2019 13:43:04
Зарегистрирован: Сб янв 11, 2014 21:25:55Сообщений: 113
Рейтинг сообщения: 0
А Вы DMA перезапускаете после срабатывания прерывания? Хочется увидеть функцию передачи
Вернуться наверх
Frogfot
Заголовок сообщения: Re: DMA+SPI+STM32f103. Трабл с прерыванием.
Добавлено: Пн апр 22, 2019 16:15:35
Карма: 2
Рейтинг сообщений: 10
Зарегистрирован: Ср окт 19, 2011 08:48:27Сообщений: 443Откуда: Мать городов русских
Рейтинг сообщения: 0
А Вы DMA перезапускаете после срабатывания прерывания? Хочется увидеть функцию передачи
Код:
// ---------- void ReStart_DMA5 (void) // SPI2 Transmitte { DMA1_Channel5->CCR &= ~DMA_CCR1_EN; // Disable DMA DMA1_Channel5->CPAR = (uint32_t) &(SPI2->DR); // Periferal Adress DMA1_Channel5->CMAR = (uint32_t) &(ScreenBuf [(AdressLED << 4)]); // Memory Adress DMA1_Channel5->CNDTR = DMA_BUFF_SIZE; // Number of data to transfer DMA1_Channel5->CCR |= DMA_CCR1_EN; // Enable DMA }
_________________ Хорошему коту и в декабре - март
Вернуться наверх
Страница 1 из 2
[ Сообщений: 21 ]
,
Кто сейчас на форуме
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 36
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения