|
本帖最后由 eddiewwm 于 2019-2-7 23:01 编辑
LGT群友 Zyleon 的一個LGT8F684P 軟串口輸入控制WS2812 LED範例: - #include <pic.h>
- #include "lgt8f684p.h"
- #define _XTAL_FREQ 16000000 * 2 // 16MHz, (4 / 2T) = 2
- //#define ws2812_pin RC0
- #define rx_pin RA6
- bit rx_en;
- unsigned char rx_recieve;
- unsigned char rx_recieve_count = 8;
- unsigned char recieved_data[6];
- unsigned char rx_GRB;
- unsigned char ws2812_prepared;
- const unsigned char hue_ring[] @0x200 = {0, 255, 0, 64, 255, 0, 128, 255, 0, 192, 255, 0, 255, 255, 0, 255, 192, 0, 255, 128, 0, 255, 64, 0, 255, 0, 0, 255, 0, 64, 255, 0, 128, 255, 0, 192, 255, 0, 255, 192, 0, 255, 128, 0, 255, 64, 0, 255, 0, 0, 255, 0, 64, 255,0, 128, 255, 0, 192, 255, 0, 255, 255, 0, 255, 192, 0, 255, 128, 0, 255, 64};
- void RXInit(void);
- void ws2812Init(void);
- void ws2812Send(unsigned char unused, unsigned char G, unsigned char R, unsigned char B);
- void RXInit(void)
- {
-
- ANSEL = 0x00; // IO pins digital mode
- TRISA |= 1 << 6; // Set rx_pin(RA6) to input
- WPUA |= 1 << 6; // Pull-up rx_pin(RA6)
- OSCCON = 0x71; // Set frequency 1/1 prescaler
- OPTION_REG = 0x02; // Set Timer 0 1/8 prescaler
- CMCON0 = 0x07; // Disable internal comparator
- BGEN = 1; // Disable internal reference voltage
- ADCON1 = 3; // Set differential amplification sampling
- __delay_ms(100);
- INTCON = 0xC8; // Enable global/peripheral/RA interrupt
- IOCA |= 1 << 6; // Enable rx_pin(RA6) level change interrupt
-
- }
- void ws2812Init(void)
- {
-
- ANSEL = 0x00;
- TRISC = 0;
- PORTC = 0;
- rx_GRB = 0;
- ws2812_prepared = 0;
-
- }
- void ws2812Send(unsigned char unused, unsigned char G, unsigned char R, unsigned char B)
- {
-
- unsigned char i = 0;
- #asm
- bcf STATUS, 5
- movlw 8;
- movwf ws2812Send@i;
- ws2812SetGreen:
- bsf 7, 0;
- btfsc ws2812Send@G, 7;
- goto $+3;
- nop;
- bcf 7, 0;
- goto $+1;
- bcf 7, 0;
- rlf ws2812Send@G, f;
- decfsz ws2812Send@i, f;
- goto ws2812SetGreen;
- movlw 8;
- movwf ws2812Send@i;
- ws2812SetRed:
- bsf 7, 0;
- btfsc ws2812Send@R, 7;
- goto $+3;
- nop;
- bcf 7, 0;
- goto $+1;
- bcf 7, 0;
- rlf ws2812Send@R, f;
- decfsz ws2812Send@i, f;
- goto ws2812SetRed;
- movlw 8;
- movwf ws2812Send@i;
- ws2812SetBlue:
- bsf 7, 0;
- btfsc ws2812Send@B, 7;
- goto $+3;
- nop;
- bcf 7, 0;
- goto $+1;
- bcf 7, 0;
- rlf ws2812Send@B, f;
- decfsz ws2812Send@i, f;
- goto ws2812SetBlue;
- #endasm
-
- }
- void main(void)
- {
-
- RXInit();
- GIE = 0;
- ws2812Init();
-
- ws2812Send(0, 128, 128, 128);
- __delay_ms(1000);
- ws2812Send(0, 255, 0, 0);
- __delay_ms(100);
- ws2812Send(0, 0, 255, 0);
- __delay_ms(100);
- ws2812Send(0, 0, 0, 255);
- __delay_ms(100);
- for (unsigned char i = 0; i < 5; i++)
- {
- for (unsigned char j = 0; j < 72; j += 3)
- {
- ws2812Send(0, hue_ring[0 + j], hue_ring[1 + j], hue_ring[2 + j]);
- __delay_ms(30);
- }
- }
- for (unsigned char i = 0; i < 200; i += 8)
- {
- ws2812Send(0, i, i, i);
- __delay_ms(10);
- }
-
- GIE = 1;
- while(1)
- {
- if (rx_en);
- if (ws2812_prepared)
- {
- unsigned char G_rx = (recieved_data[0] << 4) + recieved_data[1];
- unsigned char R_rx = (recieved_data[2] << 4) + recieved_data[3];
- unsigned char B_rx = (recieved_data[4] << 4) + recieved_data[5];
- ws2812Send(0, G_rx, R_rx, B_rx);
- ws2812_prepared = 0;
- }
- }
-
- }
- void interrupt pinLevelChange(void)
- {
-
- if (T0IE && T0IF)
- {
- T0IF = 0;
- TMR0 = 256 - 104 + 2;
- if (rx_recieve_count)
- {
- rx_recieve >>= 1;
- if (rx_pin) rx_recieve |= 0x80;
- rx_recieve_count--;
- }
- else
- {
- if ((rx_recieve >= '0') && (rx_recieve <= '9')) recieved_data[rx_GRB] = rx_recieve - '0';
- else if ((rx_recieve >= 'A') && (rx_recieve <= 'F')) recieved_data[rx_GRB] = rx_recieve - 'A' + 10;
- else recieved_data[rx_GRB] = 0;
- if (++rx_GRB == 6)
- {
- ws2812_prepared = 1;
- rx_GRB = 0;
- }
- rx_en = 0;
- T0IE = 0;
- IOCA |= 1 << 6; // Enable rx_pin(RA6) level change interrupt
- }
- }
-
- else if (RAIF && (IOCA & 1 << 6) && (rx_pin == 0))
- {
- rx_en = 1;
- IOCA &= ~(1 << 6); // Disable rx_pin(RA6) level change interrupt
- TMR0 = 256 - 156 + 5;
- T0IF = 0;
- T0IE = 1;
- rx_recieve_count = 8;
- rx_recieve = 0;
- }
-
- else T0IE = 0;
-
- T0IF = 0;
- RAIF = 0;
-
- }
复制代码
上例在MPLAB IDE v8.92 運行下有報錯,更改以下後克服:
ws2812Send@i equ 0x72; //count buffer
bcf status, 5;
範例內的 ws2812 的驅力波形時序 時間也跟ws2812規格書要求("1":H0.85us+L0.4us,"0": H0.4us+L0.85us)有差異,現量出來的是:"1":H0.72us+L0.62us,"0": H0.5us+L1.0us。更改ws2812Send()內的asm結構,得到更接近的波形時序:"1":H0.76us+L0.52us,"0": H0.38us+L0.88us。 - #include <pic.h>
- #include "lgt8f684p.h"
- #define _XTAL_FREQ 16000000 * 2 // 16MHz, (4 / 2T) = 2
- //#define ws2812_pin RC0
- #define rx_pin RA6
- bit rx_en;
- unsigned char rx_recieve;
- unsigned char rx_recieve_count = 8;
- unsigned char recieved_data[6];
- unsigned char rx_GRB;
- unsigned char ws2812_prepared;
- const unsigned char hue_ring[] @0x200 = {0, 255, 0, 64, 255, 0, 128, 255, 0, 192, 255, 0, 255, 255, 0, 255, 192, 0, 255, 128, 0, 255, 64, 0, 255, 0, 0, 255, 0, 64, 255, 0, 128, 255, 0, 192, 255, 0, 255, 192, 0, 255, 128, 0, 255, 64, 0, 255, 0, 0, 255, 0, 64, 255, 0, 128, 255, 0, 192, 255, 0, 255, 255, 0, 255, 192, 0, 255, 128, 0, 255, 64};
- void RXInit(void);
- void ws2812Init(void);
- void ws2812Send(unsigned char unused, unsigned char G, unsigned char R, unsigned char B);
- void RXInit(void) {
- ANSEL = 0x00; // IO pins digital mode
- TRISA |= 1 << 6; // Set rx_pin(RA6) to input
- WPUA |= 1 << 6; // Pull-up rx_pin(RA6)
- OSCCON = 0x71; // Set frequency 1/1 prescaler
- OPTION_REG = 0x02; // Set Timer 0 1/8 prescaler
- CMCON0 = 0x07; // Disable internal comparator
- BGEN = 1; // Disable internal reference voltage
- ADCON1 = 3; // Set differential amplification sampling
- __delay_ms(100);
- INTCON = 0xC8; // Enable global/peripheral/RA interrupt
- IOCA |= 1 << 6; // Enable rx_pin(RA6) level change interrupt
- }
- void ws2812Init(void) {
- ANSEL = 0x00;
- TRISC = 0;
- PORTC = 0;
- rx_GRB = 0;
- ws2812_prepared = 0;
- }
- void ws2812Send(unsigned char unused, unsigned char G, unsigned char R, unsigned char B) {
- unsigned char i = 0;
- #asm
- ws2812Send@i equ 0x72; //count buffer
- bcf status, 5;
- movlw 8;
- movwf ws2812Send@i;
- ws2812SetGreen:
- //0.125us(1H6+1L4)==>0.75us+0.5us,
- //0.125us(0H3+0L7)==>0.38us+0.88us
- bsf 7, 0; //1H1, 0H1, 1
- btfsc ws2812Send@G, 7; //1H2, 0H3, 1/2
- goto $ + 2; //1H4, ---, 1
- bcf 7, 0; //---, 0L1, 1
- nop; //1H5, 0L2, 1
- rlf ws2812Send@G, f; //1H6, 0L3, 1
- bcf 7, 0; //1L1, 0L4, 1
- decfsz ws2812Send@i, f;//1L2, 0L5, 1/2
- goto ws2812SetGreen; //1L4, 0L7, 2
- movlw 8;
- movwf ws2812Send@i;
- ws2812SetRed:
- bsf 7, 0;
- btfsc ws2812Send@R, 7;
- goto $ + 2;
- bcf 7, 0;
- nop;
- rlf ws2812Send@R, f;
- bcf 7, 0;
- decfsz ws2812Send@i, f;
- goto ws2812SetRed;
- movlw 8;
- movwf ws2812Send@i;
- ws2812SetBlue:
- bsf 7, 0;
- btfsc ws2812Send@B, 7;
- goto $ + 2;
- bcf 7, 0;
- nop;
- rlf ws2812Send@B, f;
- bcf 7, 0;
- decfsz ws2812Send@i, f;
- goto ws2812SetBlue;
- #endasm
- }
- void main(void) {
- RXInit();
- GIE = 0;
- ws2812Init();
-
- ws2812Send(0, 128, 128, 128);
- __delay_ms(1000);
- ws2812Send(0, 255, 0, 0);
- __delay_ms(100);
- ws2812Send(0, 0, 255, 0);
- __delay_ms(100);
- ws2812Send(0, 0, 0, 255);
- __delay_ms(100);
- for (unsigned char i = 0; i < 5; i++) {
- for (unsigned char j = 0; j < 72; j += 3) {
- ws2812Send(0, hue_ring[0 + j], hue_ring[1 + j], hue_ring[2 + j]);
- __delay_ms(30);
- }
- }
- for (unsigned char i = 0; i < 200; i += 8) {
- ws2812Send(0, i, i, i);
- __delay_ms(10);
- }
- GIE = 1;
- while (1) {
- if (rx_en);
- if (ws2812_prepared) {
- unsigned char G_rx = (recieved_data[0] << 4) + recieved_data[1];
- unsigned char R_rx = (recieved_data[2] << 4) + recieved_data[3];
- unsigned char B_rx = (recieved_data[4] << 4) + recieved_data[5];
- ws2812Send(0, G_rx, R_rx, B_rx);
- ws2812_prepared = 0;
- }
- }
- }
- void interrupt pinLevelChange(void) {
- if (T0IE && T0IF) {
- T0IF = 0;
- TMR0 = 256 - 104 + 2;
- if (rx_recieve_count) {
- rx_recieve >>= 1;
- if (rx_pin) rx_recieve |= 0x80;
- rx_recieve_count--;
- } else {
- if ((rx_recieve >= '0') && (rx_recieve <= '9')) recieved_data[rx_GRB] = rx_recieve - '0';
- else if ((rx_recieve >= 'A') && (rx_recieve <= 'F')) recieved_data[rx_GRB] = rx_recieve - 'A' + 10;
- else recieved_data[rx_GRB] = 0;
- if (++rx_GRB == 6) {
- ws2812_prepared = 1;
- rx_GRB = 0;
- }
- rx_en = 0;
- T0IE = 0;
- IOCA |= 1 << 6; // Enable rx_pin(RA6) level change interrupt
- }
- } else if (RAIF && (IOCA & 1 << 6) && (rx_pin == 0)) {
- rx_en = 1;
- IOCA &= ~(1 << 6); // Disable rx_pin(RA6) level change interrupt
- TMR0 = 256 - 156 + 5;
- T0IF = 0;
- T0IE = 1;
- rx_recieve_count = 8;
- rx_recieve = 0;
- } else T0IE = 0;
- T0IF = 0;
- RAIF = 0;
- }
复制代码
|
|