LINUX.ORG.RU

Объясните, где я налажал

 , , , ,


0

1

Есть у меня «умные» RGB-светодиоды — WS2812. Сейчас тыкаю STM32 с libopencm3.
Проблема в том, что светодиоды светят только белым (255, 255, 255). Полагаю, что все нули, которые я им посылаю, интерпретируются как единицы. Вероятно, у меня какие-то проблемы с таймингами.
Светодиоды запитаны от блока питания 5V, микроконтроллер от 3.3V, земля общая.
Код:

#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>

int t0h = 3; // 0.375us (0.35±0.15us datasheet)
int t1h = 6; // 0.750us (0.70±0.15us datasheet)
int t0l = 7; // 0.875us (0.80±0.15us datasheet)
int t1l = 5; // 0.625us (0.60±0.15us datasheet)

void clock_setup() {
    rcc_clock_setup_in_hse_8mhz_out_72mhz();

    /* Enable GPIOA clock. */
    rcc_periph_clock_enable(RCC_GPIOA);
}

void gpio_setup() {
    /* Set GPIO3 (in GPIO port A) to 'output push-pull'. */
    gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
              GPIO_CNF_OUTPUT_PUSHPULL, GPIO3);
}

void sleep(int cycles) {
    int i;  
    for (i = 0; i < cycles; i++)
        __asm__("nop");
}

void send_h() {
    gpio_set(GPIOA, GPIO3);
    sleep(t1h);
    gpio_clear(GPIOA, GPIO3);
    sleep(t1l);
}

void send_l() {
    gpio_set(GPIOA, GPIO3);
    sleep(t0h);
    gpio_clear(GPIOA, GPIO3);
    sleep(t0l);
}

void main() {
    clock_setup();
    gpio_setup();

    while (1) {
        int led, bit;
        for (led = 0; led < 5; led++) {
            // green
            for (bit = 0; bit < 8; bit++) {
                    send_l();
            }
            // red
            for (bit = 0; bit < 8; bit++) {
                    send_h();
            }
            // blue
            for (bit = 0; bit < 8; bit++) {
                    send_h();
            }
        }

        sleep(400); // tres
    }
}
cast ncrmnt, так как у него светодиоды из той же партии

★★★★★

Последнее исправление: CYB3R (всего исправлений: 1)

Я тупо заюзал libws2812, есть в antares. Такой делей, как у тебя может неправильно тайминги выдерживать - смотри времянку осциллом.

ncrmnt ★★★★★
()
Ответ на: комментарий от ncrmnt

libws2812

Всё, что нагуглил — AVR. В antares ничего с таким названием не нашёл.

Такой делей, как у тебя может неправильно тайминги выдерживать - смотри времянку осциллом.

Сейчас именно этим и занимаюсь, но единицы и нули выглядят правильно.
Не может быть проблем из-за разного напряжения?

CYB3R ★★★★★
() автор топика
Ответ на: комментарий от CYB3R

как делать кошерный делей?

На таймере, вестимо.

Только вот что я не пойму: ты зачем управление светодиодами делаешь ногодрыгом? Тяжелое детство аврщика что ли?

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

P.S. Посмотри на мою псевдоаппаратную реализацию 1-wire на таймере и ПДП: возможно, поможет.

А ногодрыгом переставай заниматься. Не дело это для взрослых мужиков!

Eddy_Em ☆☆☆☆☆
()
    for (i = 0; i < cycles; i++)
        __asm__("nop");

Ты это серьезно? А ничего, что эта шняга дает задержки с точностью ±два бегемота? Прерывание вклинится — и привет!

Тебе действительно нужно пересматривать подход к мелкоконтроллерам и выкидывать из головы аврщину!

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от ncrmnt

Есть, но он показывает какие-то странные вещи. Сейчас я заменил все sleep(...) на sleep(1), на осциллографе это выглядит, примерно как 0.6us high, 0.8us low. Хотя, должны быть одинаковые значения, так как и там, и там 1.

CYB3R ★★★★★
() автор топика
Последнее исправление: CYB3R (всего исправлений: 1)
Ответ на: комментарий от Eddy_Em

Тяжелое детство аврщика что ли?

AT2313 — наше всйо!

CYB3R ★★★★★
() автор топика
Ответ на: комментарий от CYB3R

Да сделай ты уже на таймере с ПДП! Куча ресурсов же освободится. Сначала данные, которые надо передать, преобразуешь, заполняя буфер длительностей импульсов. Т.к. у тебя одинаковая длительность единички и нуля, ARR один и тот же, менять надо только CCR.

Eddy_Em ☆☆☆☆☆
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.