2015-07-28 6 views
0

Я строю систему для управления большой строкой светодиодов RGB WS2812, для которых требуется высокочастотный (800 кГц) сигнал данных.Перестановка последовательных данных в параллельные данные в C

Моя система, которая в настоящее время осуществляется на STM32F3 выглядит следующим образом:

Input: 
PC (UART) -> DMA -> Memory 

Output: 
Memory -> DMA -> GPIO 

Проблема у меня в том, что в настоящее время я только передачи данных для одной светодиодной полосы (одного GPIO) по USART и сохранение этих данных в буфере uint8_t. Однако из-за того, что данные DMA, перемещаемые из памяти в GPIO, должны иметь минимум 1 байт данных, мне нужно преобразовать поток бит USART в поток байтов. Что-то вроде этого:

USART Data: 
    R G B 
{0xFF, 0xAA, 0x00} 

DMA Source: 
{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,  //R 
0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,  //G 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}  //B 

Теперь проблема в том, что у меня есть очень ограниченные тактовых циклов, чтобы переставить эти данные для DMA.

Я надеюсь, что у кого-то есть какой-то алгоритм, который будет эффективно перестраивать эту память. В противном случае я могу попытаться избавиться от UART DMA и сделать чтение/переупорядочение данных на основе прерываний. Как это происходит?

Мой единственный вариант - увеличить пропускную способность моих данных с ПК до 8 раз, что это сейчас в основном передать в кучу 0s.

Любые предложения?

ответ

1

Вы можете попробовать что-то вроде этого:

unsigned char array[] = {0x00, 0x01, 0x02, 0x03, 0xa0, 0xa5}; 

int i,j; 
for (j = 0; j < sizeof(array); j++) { 
    printf("array[%d] (0x%02x) bits: ", j, array[j]); 
    for (i = 0; i < 8; i++) { 
     printf("%d ", (array[j] >> i & 0x01)); 
    } 
    printf("\n"); 
} 

Это выходы:

массив [0] (0х00) бит: 0 0 0 0 0 0 0 0
массив [1] (0x01) бит: 1 0 0 0 0 0 0 0
бит [2] (0x02) бит: 0 1 0 0 0 0 0 0
массив [3] (0x03) бит: 1 1 0 0 0 0 0 0
бит [4] (0xa0): 0 0 0 0 0 1 0 1 массив [5] (0xA5) биты: 1 0 1 0 0 1 0 1

с обратной биты заменить внутренний контур с

for (i = 7; i >= 0; i--) { 
    printf("%d ", (array[j] >> i & 0x01)); 
} 

массив [0] (0x00) биты: 0 0 0 0 0 0 0 0
массив [1] (0x01) бит: 0 0 0 0 0 0 0 1
массива [2] (0x02) бит: 0 0 0 0 0 0 1 0
array [3] (0x03) бит: 0 0 0 0 0 0 1 1
массив [4] (0xa 0) биты: 1 0 1 0 0 0 0 0
массив [5] (0xA5) биты: 1 0 1 0 0 1 0 1

Вам не нужно будет внешний цикл. Этот цикл имитирует ваш DMA. В принципе, внутренний цикл динамически создает маску и проверяет этот бит и выводит 1, если он установлен, и 0, если это не так. Затем вы можете вывести это на GPIO. Вы должны иметь возможность настроить прерывание, чтобы каждая байтовая передача DMA выполняла код выше в ISR.

Еще лучше, канава DMA и просто это произойдет при прерываниях UART.

+0

Спасибо, что я закончил работу с USART DMA – spizzak