이것은 AVR (Arduino 하드웨어) 용 WS2812B RGB LED 스트립 드라이브 코드입니다. 내 코드의 일부를 최적화하는 컴파일러에 몇 가지 문제가 있습니다. -O1, -O2, -Os
, 동일한 결과를 보았습니다. 지연이 작동하지 않기 때문에 -O0
을 사용할 수 없습니다.상수 값을 사용할 때 매크로 부분이 최적화 됨
매크로
다음내 ws_driverm.h
파일입니다
#pragma once
#include <util/delay_basic.h>
#include <avr/io.h>
#include "lib/pins.h"
#define WS_T_1H 800
#define WS_T_1L 450
#define WS_T_0H 200
#define WS_T_0L 850
#define WS_T_LATCH 7000
/** Latch and display the RGB values */
#define ws_show(io) do { pin_low(io_pack(io)); delay_ns_c(WS_T_LATCH, 0); } while(0)
/** Send one byte to the RGB strip */
#define ws_send_byte(io, bb) do { \
for (int8_t __wsba_i = 7; __wsba_i >= 0; --__wsba_i) { \
if (bb & (1 << __wsba_i)) { \
pin_high(io_pack(io)); delay_ns_c(WS_T_1H, -2); \
pin_low(io_pack(io)); delay_ns_c(WS_T_1L, -10); \
} else { \
pin_high(io_pack(io)); delay_ns_c(WS_T_0H, -2); \
pin_low(io_pack(io)); delay_ns_c(WS_T_0L, -10); \
} \
} \
} while(0)
/** Send RGB color to the strip */
#define ws_send_rgb(io, r, g, b) do { \
ws_send_byte(io_pack(io), g); \
ws_send_byte(io_pack(io), r); \
ws_send_byte(io_pack(io), b); \
} while(0)
실패 나는 그것이 매크로 것에 대해 행복하지 않다,하지만 내 모든 시도 등의 IO 포트, 포트 주소로 포인터를 사용 할 수 있습니다.
io
은 내 핀 처리 시스템의 일부이며, 무시해도됩니다. 질문과 관련이 없습니다.
문제 여기
는 예상대로 작동, 내가 변경, 또는 휘발성을 표시하기 위해 보장 변수를 사용하는 경우 (주 단위) 문제
입니다 :
volatile uint8_t r = 0;
volatile uint8_t g = 255;
volatile uint8_t b = 0;
ws_send_rgb(PIN_WS, r, g, b);
ws_show(PIN_WS);
// results in GREEN color
변수가 휘발성이 아니거나 숫자를 매크로 호출에 넣으면 작동하지 않습니다.
uint8_t r = 0;
uint8_t g = 255;
uint8_t b = 0;
ws_send_rgb(PIN_WS, r, g, b);
ws_show(PIN_WS);
// results in YELLOW color
같은 결과 : 그것은 일정 제로의 경우
이ws_send_rgb(PIN_WS, 0, 255, 0);
ws_show(PIN_WS);
// results in YELLOW color
분명히 매크로에 의해 생성 된 코드가 어떤 이유로, 멀리 최적화되어 (적어도 그렇게 보이는 - 나는 이유는 정말 모르겠어요 LED가 노란색으로 표시됨).
재미있는 : ->0
대신 1
을 사용하면 예상대로 작동합니다.
내 매크로에 어떤 문제가 있으며 어떻게 해결할 수 있습니까? 더러운 해결 방법은 현재까지 유효합니다.
'PIN_WS'정의 란 무엇이며 'pin_low','iopack' 및 'delay_ns_c' 정의 방법은 무엇입니까? – ouah
그들은 몇 가지 매크로를 속임수로 사용하고 있습니다. 여기에 전체 pins.h 파일을 붙여 넣는 것이 좋은지 잘 모르겠습니다. 기본적으로 IO 포트 (PORTB)에 비트를 씁니다. 본질적으로,'pin_high (PIN_WS)'는'do {((휘발성) uint8_t * ((0x05) + 0x20)))} = = (1 << 0); } while (0);'전처리기에 의해 씹어 먹은 후. 아니면, 인간이 읽을 수있는,'PORTB | = (1 << 0); – MightyPork
그것은 실패한 코드의 어셈블러리스트를 보는 것이 드러날 것이다. – Armali