Очень медленная запись SPI STM32 - PullRequest
1 голос
/ 12 марта 2019

В настоящее время я пишу код для записи на ЖК-экране пиксель за пикселем.Код работает нормально, однако скорость обработки кода невероятно низкая.Цель состоит в том, чтобы просто написать число на экране ЖКД, поэтому я использую функцию «переключатель» с «циклом for» для считывания каждого бита, который я активирую.Мне интересно, если кто-то может сказать мне способ ускорить мой код ...

int * switch_library_number_1 (int num, int octet) {

switch(num)
{

case 0 : ;
    int number_0 [] = {0x80, 0x08,
              0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x88,
              0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, ...};

        int * pNumber_0 = &number_0[octet];

        return pNumber_0;
          break;

case 1 : ;
    int number_1 [] = {0x80, 0x08,
              0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x88, ...};

    int * pNumber_1 = &number_1[octet];

    return pNumber_1;
      break;
}

Тогда это доходит до девятивот так, я не думаю, что вам нужно показывать все дела.Плюс, даже если я удалил большинство из них, у меня есть 522 байта по номеру.Остальная часть кода выглядит следующим образом:

int main(void)
{
ADC_Initialization();
SPI_Initialization();
int nombre_octet = 522;
int premier_nombre;
int deuxieme_nombre;

while(1)
{
    GPIOA->BSRRL = CS;
    for(int i = 0; i < nombre_octet; i++)
    {
        write_spi(*switch_library_number_1(0, i));
    }
    GPIOA -> BSRRH = CS;

    for(int i = 0; i < 100; i++)
            {
            }

    GPIOA->BSRRL = CS;
    for(int i = 0; i < nombre_octet; i++)
    {
        write_spi(*switch_library_number_2(1, i));
    }
    GPIOA -> BSRRH = CS;

    }
}

Наконец, вот функция write_SPI, но из-за ее простоты я не думаю, что это проблема.

void write_spi(char data)
{
    SPI1->DR = data;

    while (!(SPI1->SR & SPI_I2S_FLAG_TXE));
    while (!(SPI1->SR & SPI_I2S_FLAG_RXNE));
    while (SPI1->SR & SPI_I2S_FLAG_BSY);
}

Спасибо заранее!

Ответы [ 2 ]

1 голос
/ 13 марта 2019

Мне очень нравится, как вы разбили свой код на три фрагмента. Я могу предложить улучшения для каждого из них:

switch_library_number_1 ()

  • Это может быть просто двумерный массив, number[][] или, если number_0, number_1 ... не имеют одинаковую длину, это может быть массив указателей на них. Там должны быть проверки на действительные num и offset. Это может быть незначительное улучшение скорости.
  • Ваши number_0 ... массивы находятся в стеке и доступны для чтения и записи. Сделайте их const, чтобы они не использовали оперативную память.
  • В настоящее время вы возвращаете указатель на ячейку памяти в стеке - это обычно не работает, если это происходит случайно или случайно. Вы не должны получать доступ к данным стека, когда вы находитесь вне области действия (функции), где они были определены. static const сделает это безопасным, так как его больше не будет в стеке.

основной цикл :

  • Немного странно вызывать switch_library_number_1/2 на каждой итерации цикла. Вы знаете, что ваши данные будут просто в массиве. Возможно, это можно заменить на write_spi(number[0][i]);, если массив number настроен правильно. Это должно дать вам некоторое улучшение скорости, так как это очень упрощает выборку данных.
  • Похоже, у вас занятый цикл. Это сложная практика (держу пари, 100 - предположение, и обратите внимание, что компилятор может оптимизировать этот цикл). Если возможно, используйте библиотеку с функцией задержки или таймер для получения точных задержек. Является ли это фактическим требованием ведомого SPI?

write_spi (char char) :

  • char должно быть unsigned char здесь. char могут быть подписаны или не подписаны, поэтому, когда вы используете их как байты (не фактические строковые символы), вы должны указать подпись.
  • Кажется, вы ожидаете окончания передачи каждого байта, что безопасно, но немного медленно. Обычно это можно переписать в более быструю альтернативу wait_for_SPI_ready_for_TX; SPI_TX, где вам нужно только подождать перед отправкой следующего байта. Обратите внимание, что вам также нужно будет дождаться полной передачи байта, прежде чем снова поднимать CS. Это может быть большим улучшением скорости.

Некоторые другие вещи, которые следует учитывать:

  • Каковы фактические часы SPI? Может быть огромное улучшение скорости, если увеличить часы.
  • Как вы измерили это как "медленный"? Указывает ли это на медленные части кода (что же тогда? Если не очевидно из C, для чего они собираются?)
  • У вас есть осциллограф / логический анализатор для просмотра реальных сигналов на проводе? Это может предоставить полезные данные.
0 голосов
/ 13 марта 2019

У меня была похожая проблема с контроллером Cortex-M3 серии STM32F207, когда я наблюдал за линией TX через генератор, я увидел, что отключение CHIP_SELECT заняло слишком много времени для установки после того, как все данные были отправлены. Я понял это имеет отношение к элементам управления флагами. Так что я немного поиграю с флагами элементов управления. Вот как у меня все получилось;

static void SPI_Send(uint16_t len,uint8_t* data)
{
   uint16_t i;

   for(i = 0;i<len;i++)
   {        
     SPI_I2S_SendData(SPI1,*(data+i));
     while(!(SPI1->SR & SPI_SR_TXE));   
   }    
   while(SPI1->SR & SPI_SR_BSY);
   CHIP_SEL_DISABLE;
}

Я полагаю, что это медленно, потому что вы также проверяете «Буфер приема не пуст», где вам не нужно.

...