Datasheet
0/1 フォーマット
|値|HIGH/LOW|概要|時間|誤差|
|:--|:--|:--|:--|:--|:--|
|T0H| 0 |high voltage time| 0.40us | ±150ns |
|T1H| 1 |high voltage time | 0.8us | ±150ns |
|T0L| 0 |low voltage time | 0.85us | ±150ns |
|T1L| 1 |low voltage time | 0.45us | ±150ns |
|RES| |low voltage time Above | 50µs |

データフォーマット
24bitの色データ
Green(8bit) | Red(8bit) | Blue(8bit) |
---|

データ構造
50usのRETが続いた場合、新しいデータとみなす。1つめのデータは、LED1が抜き取り発色する。2つめのデータは、2番目のLED2が抜き取り発色する。50us以内でデータを結合し、流すだけでマイコンが自分のデータを抜き出し発色する。

Delay
delayMicroseconds()
は、2usのdelayが可能。これだと遅すぎる。
ArduinoのUNOのクロックは、16MHz
1/16MHz = 0.0625us
1周期 0.0625us。
割り込みMacro
sei()
cli()
をつかって、処理中割り込みを防ぐ。
ArduinoのPORT
Sample
12個のLEDを光らすサンプルですが、変色、うまく色が出せない。
# define PORTA1_HIGH 0b1
# define PORTA1_LOW 0b0
# define BYTENUMBER 8
# define NUBEROFLED 12
const uint8_t bitShift = BYTENUMBER - 1 ;
uint8_t colorData[36] = {5,5,5,
5,5,5,
5,5,5,
5,5,5,
5,5,5,
5,5,5,
5,5,5,
5,5,5,
5,5,5,
5,5,5,
5,5,5,
5,5,5};
void setup() {
DDRC = 1; // PORTCを出力に
PORTC = 0b0; // PORTCに 00000000を設定(全部LOW)
}
void loop() {
sei();
for(int i = 0; i<NUBEROFLED; i++){
send(colorData[i*3], colorData[i*3+1], colorData[i*3+2]);
}
cli();
reset();
delay(100);
}
void send(uint8_t g, uint8_t r, uint8_t b){
for(int i = 0; i < BYTENUMBER; i++){
if(g & (1 << (bitShift-i))){
led_one();
} else {
led_zero();
}
}
for(int i = 0; i < BYTENUMBER; i++){
if(r & 1 << ((bitShift-i))){
led_one();
} else {
led_zero();
}
}
for(int i = 0; i < BYTENUMBER; i++){
if(b & 1 << ((bitShift-i))){
led_one();
} else {
led_zero();
}
}
}
void led_zero(){
// HIGH: 0.35us
PORTC |= PORTA1_HIGH; //T 2
asm(" nop"); //T 3
asm(" nop"); //T 4
asm(" nop"); //T 5
asm(" nop"); //T 6 6 * 0.0625 = 0.375us
// LOW: 0.8us
PORTC &= PORTA1_LOW; //T 8
asm(" nop"); //T 9
asm(" nop"); //T 10
asm(" nop"); //T 11
asm(" nop"); //T 12
asm(" nop"); //T 13
asm(" nop"); //T 14
asm(" nop"); //T 15
asm(" nop"); //T 16
asm(" nop"); //T 17
asm(" nop"); //T 18
asm(" nop"); //T 19 13 * 0.0625 = 0.8125us
}
void led_one(){
// HIGH 0.7us
PORTC |= PORTA1_HIGH; // T 2
asm(" nop"); // T 3
asm(" nop"); // T 4
asm(" nop"); // T 5
asm(" nop"); // T 6
asm(" nop"); // T 7
asm(" nop"); // T 8
asm(" nop"); // T 9
asm(" nop"); // T 10
asm(" nop"); // T 11 11 * 0.0625 = 0.6875us
// LOW 0.6us
PORTC &= PORTA1_LOW; // T 13
asm(" nop"); // T 14
asm(" nop"); // T 15
asm(" nop"); // T 16
asm(" nop"); // T 17
asm(" nop"); // T 18
asm(" nop"); // T 19
asm(" nop"); // T 20
//asm(" nop"); // T 21 10 * 0.0625 = 0.625
}
void reset(){
PORTC &= PORTA1_LOW;
for(int i = 0; i < 60; i++){
asm(" nop");
asm(" nop");
asm(" nop");
asm(" nop");
asm(" nop");
asm(" nop");
asm(" nop");
asm(" nop");
asm(" nop");
asm(" nop");
}
}
実行結果
highは狙った通りの状態になっていますが、lowは長くなる。24bit間の時間が3000usとなり大きく遅延する。LEDはRest状態だと勘違いしLEDがチラツキ始める。
原因
クロックは正常に動いているが、ビットを出力する前後に遅延があり、if文などの条件分岐やビット演算に時間がかかる。