まずはMCCでクロックを内蔵オシレーター8MHzx4PLLの32MHzに設定して、RA2を出力に設定してソースファイルを生成(Generate)。
main.cにビット0を送る関数((void) send_bit0(void))とビット1を送る関数((void) send_bit1(void))をアセンブラで書いて、メインループで次のように send_bit0(); だけにして、まずは send_bit0(); が正しく動くかを確認。
send_bit0を実装
while (1) {
// Green
send_bit0();
send_bit0();
send_bit0();
send_bit0();
send_bit0();
send_bit0();
send_bit0();
send_bit0();
// Red
send_bit0();
send_bit0();
send_bit0();
send_bit0();
send_bit0();
send_bit0();
send_bit0();
send_bit0();
// Blue
send_bit0();
send_bit0();
send_bit0();
send_bit0();
send_bit0();
send_bit0();
send_bit0();
send_bit0();
__delay_us(50);
}
最初、全部(16個)のLEDがMAXで白く発光して「どういう事だよ…」となったけど、よく調べたらクロックが8MHzになっててx4PLLされてなかったりして、ちゃんと32MHzで動くようにして再度調整。調整した結果がコレ。
void send_bit0(void)
{
// 0.5, 2.0us
// 4, 16 insts
#asm
movlb 2 ; BANK 2
bsf 12, 2 ; LATA, 2
nop
movlb 2 ; BANK 2
bcf 12, 2 ; LATA, 2
nop
nop
nop
nop
nop
nop
nop
nop
#endasm
}
send_bit1を実装
(void)send_bit1(void)
も調整。
void send_bit1(void)
{
// 1.2, 1.3us
// 10, 10 insts
#asm
movlb 2 ; BANK 2
bsf 12, 2 ; LATA, 2
nop
nop
nop
nop
nop
nop
nop
nop
nop
movlb 2 ; BANK 2
bcf 12, 2 ; LATA, 2
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
#endasm
}
結果としてwhileループの最後の__delay_us(50);
も__delay_us(70);
に調整。
最初のうちは24ビットしか送ってないのにLEDが2つ光ったりしてタイミングの調整が大変だった。でも、意外にもアセンブラで書いたのは (void)send_bit0(void)
と (void)send_bit1(void)
の2つだけで動いた。
send_byteを実装
続いて1バイトを送信する void send_byte(unsigned char b)
を書いた。
void send_byte(unsigned char b)
{
if (b & 0x80) {
send_bit1();
} else {
send_bit0();
}
if (b & 0x40) {
send_bit1();
} else {
send_bit0();
}
if (b & 0x20) {
send_bit1();
} else {
send_bit0();
}
if (b & 0x10) {
send_bit1();
} else {
send_bit0();
}
if (b & 0x08) {
send_bit1();
} else {
send_bit0();
}
if (b & 0x04) {
send_bit1();
} else {
send_bit0();
}
if (b & 0x02) {
send_bit1();
} else {
send_bit0();
}
if (b & 0x01) {
send_bit1();
} else {
send_bit0();
}
}
main.cファイル
今回のmain.cのファイルです。
MCCで生成したmain.cを差し替えると、次のような感じで光ります。
アニメーションはしません。