Например TDA7294

Форум РадиоКот • Просмотр темы - DMA+SPI+STM32f103. Трабл с прерыванием.
Форум РадиоКот
Здесь можно немножко помяукать :)



Текущее время: Пн июн 17, 2019 23:55:55

Часовой пояс: UTC + 3 часа [ Летнее время ]


ПРЯМО СЕЙЧАС:



Начать новую тему Ответить на тему  [ Сообщений: 21 ]  1,  
Автор Сообщение
Не в сети
 Заголовок сообщения: DMA+SPI+STM32f103. Трабл с прерыванием.
СообщениеДобавлено: Чт ноя 02, 2017 15:06:52 
Встал на лапы

Зарегистрирован: Сб янв 11, 2014 22:25:55
Сообщений: 100
Рейтинг сообщения: 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;
   }
      
}


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: DMA+SPI+STM32f103. Трабл с прерыванием.
СообщениеДобавлено: Пт ноя 03, 2017 11:39:25 
Поставщик валерьянки для Кота

Карма: 16
Рейтинг сообщений: 312
Зарегистрирован: Вт ноя 27, 2007 12:32:06
Сообщений: 2176
Откуда: 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.


Вернуться наверх
 
JLCPCB, всего $2 за 10 ПП любого цвета!

Более 600 000 заказчиков по всему миру! Более 10 000 заказов в день!

Скидка до $20 на доставку для первого заказа:https://jlcpcb.com/quote

Не в сети
 Заголовок сообщения: Re: DMA+SPI+STM32f103. Трабл с прерыванием.
СообщениеДобавлено: Ср ноя 08, 2017 14:57:50 
Встал на лапы

Зарегистрирован: Сб янв 11, 2014 22:25:55
Сообщений: 100
Рейтинг сообщения: 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;
    }
  }



Вернуться наверх
 
PCBWay - всего $5 за 10 печатных плат, первый заказ для новых клиентов БЕСПЛАТЕН

Сборка печатных плат от $88 + БЕСПЛАТНАЯ доставка по всему миру + трафарет

Онлайн просмотровщик Gerber-файлов от PCBWay
Не в сети
 Заголовок сообщения: Re: DMA+SPI+STM32f103. Трабл с прерыванием.
СообщениеДобавлено: Чт ноя 09, 2017 08:28:48 
Друг Кота
Аватар пользователя

Карма: 28
Рейтинг сообщений: 143
Зарегистрирован: Пн июл 28, 2008 23:12:01
Сообщений: 3465
Рейтинг сообщения: 0
Столкнулся с магией: написал всю эту либилерду в КОКОСЕ и она заработала!!! В Кейле же прерываний как не было так и нет! За что меня так наказали?


Стартап подключен?


Вернуться наверх
 
Приглашаем на вебинар «Создание беспроводных устройств на системах-на-кристалле семейства SimpleLink компании TI»

Компания Компэл, совместно с Texas Instruments приглашают 26 июня принять участие в вебинаре, где инженер по применению беспроводных технологий компании TI расскажет, как на новых беспроводных системах можно реализовать несколько полезнейших в повседневной жизни функций для ваших устройств.
С развитием элементной базы TI становится возможной реализация более удобных, функциональных и безопасных систем, недоступных ранее.
Вебинар проводит инженер по применению беспроводных технологий в TI Мари Хернес(будет дублированный перевод).
Подробнее>>
Не в сети
 Заголовок сообщения: Re: DMA+SPI+STM32f103. Трабл с прерыванием.
СообщениеДобавлено: Пн ноя 13, 2017 07:50:07 
Встал на лапы

Зарегистрирован: Сб янв 11, 2014 22:25:55
Сообщений: 100
Рейтинг сообщения: 0
dosikus, в точку! Большое спасибо!


Вернуться наверх
 
Старт складской программы по Wi-Fi/Bluetooth-чипам ESP8266 и ESP32 от Espressif

На склад КОМПЭЛ поступили чипы, модули и отладочные платы от компании Espressif Systems на базе ESP8266 и ESP32. Стоимость всех изделий данной линейки - в 2-3 раза ниже ближайших аналогов, чипы занимают минимальное место на плате, энергоэффективны и универсальны в применении.
Продукция компании популярна как среди инженеров-любителей, так и в среде разработчиков-профессионалов, которые уже смогли по достоинству оценить её качество.
Подробнее...
Не в сети
 Заголовок сообщения: Re: DMA+SPI+STM32f103. Трабл с прерыванием.
СообщениеДобавлено: Вт окт 09, 2018 13:27:27 
Встал на лапы

Зарегистрирован: Сб янв 11, 2014 22:25:55
Сообщений: 100
Рейтинг сообщения: 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 байт - он их выкидывает.


Вернуться наверх
 


Не в сети
 Заголовок сообщения: Re: DMA+SPI+STM32f103. Трабл с прерыванием.
СообщениеДобавлено: Вт окт 09, 2018 13:51:02 
Друг Кота
Аватар пользователя

Карма: 28
Рейтинг сообщений: 143
Зарегистрирован: Пн июл 28, 2008 23:12:01
Сообщений: 3465
Рейтинг сообщения: 0
Код:
DMA1->IFCR = DMA_IFCR_CHTIF4;


Вернуться наверх
 


Не в сети
 Заголовок сообщения: Re: DMA+SPI+STM32f103. Трабл с прерыванием.
СообщениеДобавлено: Вт окт 09, 2018 14:06:22 
Встал на лапы

Зарегистрирован: Сб янв 11, 2014 22:25:55
Сообщений: 100
Рейтинг сообщения: 0
Не, не помогло. Перенёс передачу по USART прямо в прерывание - ноль реакции. Он даже не заходит в прерывание.


Вернуться наверх
 
Prist.ru предлагает скидку всем частным лицам при покупке приборов АКИП, GW Instek, APPA (кроме осциллографов АКИП-4115/1А, GDS-71102)!

Интересные новинки уже на складе:

Осциллограф АКИП-4126Е

Многоканальные источники питания серии GPP

Не в сети
 Заголовок сообщения: Re: DMA+SPI+STM32f103. Трабл с прерыванием.
СообщениеДобавлено: Вт окт 09, 2018 14:43:25 
Опытный кот

Карма: 13
Рейтинг сообщений: 138
Зарегистрирован: Вс июн 19, 2016 10:32:03
Сообщений: 792
Рейтинг сообщения: 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);
}


Вернуться наверх
 
Купить электронные компоненты в LCSC

Отправка со склада через 4 часа после заказа!
900 000 пользователей, 3000+ заказов в день!
Зарегистрируйтесь сегодня и получите скидку 8 долларов на первый заказ!
Не в сети
 Заголовок сообщения: Re: DMA+SPI+STM32f103. Трабл с прерыванием.
СообщениеДобавлено: Вт окт 09, 2018 14:47:07 
Встал на лапы

Зарегистрирован: Сб янв 11, 2014 22:25:55
Сообщений: 100
Рейтинг сообщения: 0
Тоже мимо(


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: DMA+SPI+STM32f103. Трабл с прерыванием.
СообщениеДобавлено: Вт окт 09, 2018 14:50:00 
Опытный кот

Карма: 13
Рейтинг сообщений: 138
Зарегистрирован: Вс июн 19, 2016 10:32:03
Сообщений: 792
Рейтинг сообщения: 0
Тоже мимо(

Не мимо, просто помимо этой ошибки есть и другие :)


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: DMA+SPI+STM32f103. Трабл с прерыванием.
СообщениеДобавлено: Вт окт 09, 2018 15:06:33 
Встал на лапы

Зарегистрирован: Сб янв 11, 2014 22:25:55
Сообщений: 100
Рейтинг сообщения: 0
На передачу не влияет точно порядок, сперва dma или spi было включено


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: DMA+SPI+STM32f103. Трабл с прерыванием.
СообщениеДобавлено: Вт окт 09, 2018 15:11:24 
Опытный кот

Карма: 13
Рейтинг сообщений: 138
Зарегистрирован: Вс июн 19, 2016 10:32:03
Сообщений: 792
Рейтинг сообщения: 0
На передачу не влияет точно порядок, сперва dma или spi было включено

При чем тут порядок, у тебя вызов SPI_SendData() сбрасывает SPI_CR2_RXDMAEN.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: DMA+SPI+STM32f103. Трабл с прерыванием.
СообщениеДобавлено: Вт окт 09, 2018 16:35:49 
Друг Кота
Аватар пользователя

Карма: 28
Рейтинг сообщений: 143
Зарегистрирован: Пн июл 28, 2008 23:12:01
Сообщений: 3465
Рейтинг сообщения: 0
Приоритеты прерываний выстави...


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: DMA+SPI+STM32f103. Трабл с прерыванием.
СообщениеДобавлено: Вт окт 09, 2018 19:14:32 
Открыл глаза
Аватар пользователя

Карма: 5
Рейтинг сообщений: 15
Зарегистрирован: Пн июл 04, 2016 17:51:22
Сообщений: 70
Откуда: Россия, Омск
Рейтинг сообщения: 0
У меня аналогично не работает корректно приём данных посредством DMA. Из того, что удалось выяснить во время отладки - SPI модуль ЖДЁТ, пока в SPI->TDR будут положены новые данные.
При приёме можете попробовать инициализировать DMA1_Channel5, но без смещения адреса буфера (например постоянно читать байт в котором будет 0xFF или ноль), после этого настроить Channel4 и разрешить их работу.
У меня в коде аналогичный костыль.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: DMA+SPI+STM32f103. Трабл с прерыванием.
СообщениеДобавлено: Вт окт 09, 2018 20:07:03 
Опытный кот

Карма: 13
Рейтинг сообщений: 138
Зарегистрирован: Вс июн 19, 2016 10:32:03
Сообщений: 792
Рейтинг сообщения: 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).


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: DMA+SPI+STM32f103. Трабл с прерыванием.
СообщениеДобавлено: Ср окт 10, 2018 07:25:36 
Встал на лапы

Зарегистрирован: Сб янв 11, 2014 22:25:55
Сообщений: 100
Рейтинг сообщения: 0
!!!
Цитата:
При чем тут порядок, у тебя вызов SPI_SendData() сбрасывает SPI_CR2_RXDMAEN.
!!! :facepalm:

Всё пошло, поехало! Спасибо!


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: DMA+SPI+STM32f103. Трабл с прерыванием.
СообщениеДобавлено: Вс апр 21, 2019 20:43:49 
Потрогал лапой паяльник

Карма: 2
Рейтинг сообщений: 9
Зарегистрирован: Ср окт 19, 2011 09:48:27
Сообщений: 374
Откуда: Мать городов русских
Рейтинг сообщения: 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
}

_________________
Хорошему коту и в декабре - март :)


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: DMA+SPI+STM32f103. Трабл с прерыванием.
СообщениеДобавлено: Пн апр 22, 2019 14:43:04 
Встал на лапы

Зарегистрирован: Сб янв 11, 2014 22:25:55
Сообщений: 100
Рейтинг сообщения: 0
А Вы DMA перезапускаете после срабатывания прерывания? Хочется увидеть функцию передачи


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: DMA+SPI+STM32f103. Трабл с прерыванием.
СообщениеДобавлено: Пн апр 22, 2019 17:15:35 
Потрогал лапой паяльник

Карма: 2
Рейтинг сообщений: 9
Зарегистрирован: Ср окт 19, 2011 09:48:27
Сообщений: 374
Откуда: Мать городов русских
Рейтинг сообщения: 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
}

_________________
Хорошему коту и в декабре - март :)


Вернуться наверх
 
Показать сообщения за:  Сортировать по:  Вернуться наверх
Начать новую тему Ответить на тему  [ Сообщений: 21 ]  1,  

Часовой пояс: UTC + 3 часа [ Летнее время ]


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 7


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB
Extended by Karma MOD © 2007—2012 m157y
Extended by Topic Tags MOD © 2012 m157y