Перейти к содержанию
    

Доброго времени суток

Подскажите пожалуйста, что я делаю не так в настройке DMA для SPI для отправки

без DMA работает

void SPI3_Init()
{
// SPI3
	RCC->APB1ENR |= RCC_APB1ENR_SPI3EN;
    RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN;
    
    SPI3->CR1 =  0 << SPI_CR1_DFF_Pos  // Размер кадра 8 бит
        | 0<<SPI_CR1_LSBFIRST_Pos   // MSB first
        | 1<<SPI_CR1_SSM_Pos        // Программное управление SS
        | 1<<SPI_CR1_SSI_Pos        // SS в высоком состоянии
        | 0x00<<SPI_CR1_BR_Pos      // Скорость передачи = Fpclk/2
        | 1<<SPI_CR1_MSTR_Pos       // Режим Master
        | 0<<SPI_CR1_CPOL_Pos
        | 0<<SPI_CR1_CPHA_Pos;
    
    SPI3->CR2 = SPI_CR2_TXDMAEN;   // Отправка через DMA
    
    SPI3->CR1 |= SPI_CR1_SPE;       // Включаем SPI3
}
void SPI3_Send(volatile uint8_t *data, uint16_t len)
{
    //DMA1 Stream 7 SPI3_TX
        
    DMA1_Stream7->CR = 0;
    DMA1_Stream7->CR |= 0x01    << DMA_SxCR_PSIZE_Pos;  // SPI data register is 16 bit
    DMA1_Stream7->CR |= 0x00    << DMA_SxCR_MSIZE_Pos;  // memory size is 8bit
    DMA1_Stream7->CR |= DMA_SxCR_MINC;                  // memory increment
    DMA1_Stream7->CR |= 0x01    << DMA_SxCR_DIR_Pos;    // memory to peripheral
    DMA1_Stream7->CR |= 0x03    << DMA_SxCR_PL_Pos;     // Priority level
    DMA1_Stream7->PAR = (uint32_t)(&SPI3->DR);
    DMA1_Stream7->M0AR = (uint32_t)data;
    DMA1_Stream7->NDTR = len;
    DMA1_Stream7->FCR = 0;							// Настройка FIFO буфера
    
    DMA1_Stream7->CR |= DMA_SxCR_EN;
}
................
volatile uint8_t data[3] = {1,2,3};
while(1) SPI3_Send(data,3);
    

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Может быть стоит дождаться окончания передачи DMA? Если в бесконечном цикле постоянно перенастраивать, то канал скорее всего встанет в ошибку. Надо смотреть статус регистр.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В F4 DMA контроллер работает несколько отлично от того же F1. Если источник 8 бит, а назначение 16 бит, то из памяти будет два чтения и одна запись. При этом первый байт попадет в младшие [7..0] бит SPI, а второй в старшие [15..8], при этом передач должно быть кратно 2. Но насколько я понимаю хотелось не этого, нужно изменить размер назначения в 8 bit.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Возможно не стоит настройки последовательно записывать в регистр CR, а сформировать в переменной и разом записать значение CR. А что показывает отладчик, что в итоге попало в регистры DMA контроллера?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В своих исходниках вижу установленный в 1 бит SPI->CR2.SSOE.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 часа назад, Reystlin сказал:
    
    SPI3->CR2 = SPI_CR2_TXDMAEN;   // Отправка через DMA

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Желательно использовать макрос _VAL2FLD(field, value) для заполнения полей регистра, он позволяет избежать ошибки переполнения. DMA кроме номера потока (в названии), имеет номер канала - по которому принимает управление на запись/чтение CHSEL[3:0]. Информация о каналах DMA находится Reference manual для вашего мк.

 Регистр DMAx_Streamx->CR имеет 19 обязательных полей для заполнения, буквально 19 строк. Каждый раз печатать одинаковые буквы весьма утомительно, одинаковые буквы для любого дма. Проще один раз напечатать запись в переменную всех обязательных полей, и при copy/paste - удалять ненужное в данный момент. Удалять проще чем печатать заново.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

13 минут назад, AVI-crak сказал:

Желательно использовать макрос _VAL2FLD(field, value) для заполнения полей регистра, он позволяет избежать ошибки переполнения. DMA кроме номера потока (в названии), имеет номер канала - по которому принимает управление на запись/чтение CHSEL[3:0]. Информация о каналах DMA находится Reference manual для вашего мк.

 Регистр DMAx_Streamx->CR имеет 19 обязательных полей для заполнения, буквально 19 строк. Каждый раз печатать одинаковые буквы весьма утомительно, одинаковые буквы для любого дма. Проще один раз напечатать запись в переменную всех обязательных полей, и при copy/paste - удалять ненужное в данный момент. Удалять проще чем печатать заново.

Канал 0

какие я регистры не заполнил из обязательных?

19 минут назад, Сергей Борщ сказал:

 

уже исправлено

SPI3->CR1 = 0<<SPI_CR1_DFF_Pos  //Размер кадра 8 бит
    | 0<<SPI_CR1_LSBFIRST_Pos     //MSB first
    | 1<<SPI_CR1_SSM_Pos          //Программное управление SS
    | 1<<SPI_CR1_SSI_Pos          //SS в высоком состоянии
    | 0x04<<SPI_CR1_BR_Pos        //Скорость передачи: F_PCLK/32
    | 1<<SPI_CR1_MSTR_Pos         //Режим Master (ведущий)
    | 0<<SPI_CR1_CPOL_Pos | 0<<SPI_CR1_CPHA_Pos; //Режим работы SPI: 0
  
  
  SPI3->CR2 |= 1<<SPI_CR2_TXDMAEN_Pos;
  SPI3->CR2 |= 1<<SPI_CR2_SSOE_Pos;
  SPI3->CR2 |= 1<<SPI_CR2_RXDMAEN_Pos;
  SPI3->CR1 |= 1<<SPI_CR1_SPE_Pos; //Включаем SPI
    volatile uint8_t data[3] = {1,2,3};
    SPI3_Send(data,3);

Спасибо

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Инициализация DMA сейчас выглядит вот так

 //DMA1 Stream 7 SPI3_TX channel 0
        
    DMA1_Stream7->CR = 0;
    
    DMA1_Stream7->PAR = (uint32_t)(&SPI3->DR);
    DMA1_Stream7->M0AR = (uint32_t)data;
    DMA1_Stream7->NDTR = len;
    DMA1_Stream7->FCR = 0;							// Настройка FIFO буфера
    
    DMA1_Stream7->CR = 
     (0x00) << DMA_SxCR_CHSEL_Pos       // Выбор канала
    |(0x00) << DMA_SxCR_MBURST_Pos      //
    |(0x00) << DMA_SxCR_PBURST_Pos      //
    |0      << DMA_SxCR_CT_Pos          // Текущий буфер
    |0      << DMA_SxCR_DBM_Pos         // Двойной буфер
    |(0x03) << DMA_SxCR_PL_Pos          // Приоритет
    |0      << DMA_SxCR_PINCOS_Pos      // Инкремент адреса периферии
    |(0x00) << DMA_SxCR_MSIZE_Pos       // Размер данных в памяти 8 бит
    |(0x00) << DMA_SxCR_PSIZE_Pos       // Размер данных в периферии 8 бит
    |1      << DMA_SxCR_MINC_Pos        // Инкремент адреса памяти
    |0      << DMA_SxCR_PINC_Pos        // Инкремент адреса периферии
    |0      << DMA_SxCR_CIRC_Pos        // Циркуляционный режим
    |(0x01) << DMA_SxCR_DIR_Pos         // Направление данных из памяти в периферию
    |0      << DMA_SxCR_PFCTRL_Pos      // DMA управляет процессом
    |0      << DMA_SxCR_TCIE_Pos        // Прерывание по окончанию передачи
    |0      << DMA_SxCR_HTIE_Pos        // Прерывание по половине передачи
    |0      << DMA_SxCR_TEIE_Pos        // Прерывание по ошибке передачи
    |0      << DMA_SxCR_DMEIE_Pos       // Прерывание по 
    |1      << DMA_SxCR_EN_Pos;         // Активация DMA

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

О чем вообще тема, если автор даже вопроса никакого не задал?

Нам что, гадать, отправляет МК какой-то мусор, вообще ничего не отправляет, или что?

Пока что я вижу открытые окна отладчика, кои открытыми быть не должны при штатной работе DMA и SPI.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

SPI вообще ничего не отправляет, если отправку делаю через DMA. ни один из выводов SPI не дергается.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

То есть пример SPI_FullDuplex_ComDMA
This example shows how to perform SPI data buffer
ransmission/reception between two boards via DMA.

работает, а Ваш код не работает ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...