[PIC®/AVR®/dsPIC®产品] PIC12F1822_Led_Strip

[复制链接]
 楼主| 598330983 发表于 2024-9-28 13:02 | 显示全部楼层 |阅读模式
游客,如果您要查看本帖隐藏内容请回复


  1. /****************************************************************************************************************
  2. * PIC12F1822 WS2812b RC Led Strip Project

  3. - Version 1.0
  4. - 2 April 2020
  5. - Project settings are defined in the system.h file
  6. - based on work from https://github.com/DzikuVx/drone_led_strip_controller

  7. Copyright 2020 Patrick Tissot
  8. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General
  9. Public License as published by the Free Software Foundation, either version 2 of the License, or (at your
  10. option) any later version.

  11. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
  12. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13. for more details.  You should have received a copy of the GNU General Public License along with this program.
  14. If not, see <http://www.gnu.org/licenses/>.

  15. Development Environment
  16.        To compile this you need:
  17.         - XC8 2.20 PRO or higher (www.microchip.com) with -s optimization for size
  18.         - Microchip MPLAB X IDE Version 5.35 or higher (www.microchip.com)
  19. ***************************************************************************************************************/

  20. // Global includes
  21. #include <xc.h>
  22. #include <stdint.h>

  23. // #pragma config statements should precede project file includes.
  24. // Use project enums instead of #define for ON and OFF

  25. // CONFIG1
  26. #pragma config FOSC = INTOSC    // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)
  27. #pragma config WDTE = ON        // Watchdog Timer Enable (WDT enabled)
  28. #pragma config PWRTE = ON       // Power-up Timer Enable (PWRT enabled)
  29. #pragma config MCLRE = ON       // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
  30. #pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
  31. #pragma config CPD = OFF        // Data Memory Code Protection (Data memory code protection is disabled)
  32. #pragma config BOREN = ON       // Brown-out Reset Enable (Brown-out Reset enabled)
  33. #pragma config CLKOUTEN = OFF   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
  34. #pragma config IESO = OFF       // Internal/External Switchover (Internal/External Switchover mode is disabled)
  35. #pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is disabled)

  36. // CONFIG2
  37. #pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
  38. #pragma config PLLEN = ON       // PLL Enable (4x PLL enabled)
  39. #pragma config STVREN = ON      // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
  40. #pragma config BORV = HI        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), high trip point selected.)
  41. #pragma config LVP = ON         // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)

  42. #define _XTAL_FREQ          32000000UL


  43. /*
  44. *  Structure of the LED array
  45. *
  46. * cRGB:     RGB  for WS2812S/B/C/D, SK6812, SK6812Mini, SK6812WWA, APA104, APA106
  47. * cRGBW:    RGBW for SK6812RGBW
  48. */
  49. struct cRGB  { uint8_t g; uint8_t r; uint8_t b; };

  50. // Change this setting based on your LED strip length (be aware of RAM size limitation!)
  51. #define NUM_PIXELS          8

  52. // Assembly function used to send the 24bits info to WS2812 leds
  53. void send_frame(void);

  54. // System definitions
  55. #define FCY                 8000000UL
  56. #define TMR0_PRESCALER      256
  57. // 32 MHz / 4 = 8 MHz => 0.125 �s instruction cycle

  58. #define TICK                1       // 1ms interrupt Tick rate
  59. #define COUNT               (FCY/1000000UL*TICK*1000/TMR0_PRESCALER)
  60. #if (COUNT > 255)
  61. #error "Change TMR0 prescaler or FCY"
  62. #endif
  63. #define TMR0_RELOAD         (255-COUNT)

  64. // Hardware mapping definitions
  65. // LED PIN is fixed to RA2 (see Send_Frame.asm)
  66. #define INPUT_PIN           RA5     // connected to PWM output from RC receiver or left floating
  67. #define LED_MULTIPLIER      4
  68. #define BUTTON_PIN          RA4     // connected to push button (to ground), uses internal pull-up
  69. #define SLEEP_TIME          40
  70. #define SPEED_MAX           20
  71. #define SPEED_MID           10
  72. #define COLORS              7
  73. #define LONG_PUSH_THRESHOLD 20
  74. #define MAX_CYCLE           255
  75. #define MODES               11
  76. #define PWM_PRESS_MIN       1750    // pulse 1750ms mini to detect "button" press through RC
  77. #define PWM_PRESS_MAX       2200    // pulse 2200ms max to detect "button" press through RC
  78. #define PWM_SPEED_MIN       800     // pulse 800ms maps to minimum speed (led pattern change) through RC
  79. #define PWM_SPEED_MAX       1500    // pulse 1500ms maps to maximum speed (led pattern change) through RC

  80. // EEPROM parameters
  81. #define EEPROM_MODE_ADDRESS     0
  82. #define EEPROM_COLOR_ADDRESS    1
  83. #define EEPROM_SPEED_ADDRESS    2

  84. // State machine used for button press decoding
  85. #define IDLE                0
  86. #define PRESS               1
  87. #define SHORTPRESS          2
  88. #define LONGPRESS           3

  89. // COLOR patterns (can be adjusted if necessary)
  90. const uint8_t colors[COLORS][3] = {
  91.     {1, 0, 0}, // RED
  92.     {0, 1, 0}, // GREEN
  93.     {0, 0, 1}, // BLUE
  94.     {1, 0, 1}, // PURPLE
  95.     {1, 1, 0}, // YELLOW
  96.     {0, 1, 1}, // CYAN
  97.     {1, 1, 1} // WHITE
  98. };

  99. // Globals

  100. volatile uint8_t COLOR;
  101. volatile uint8_t count;

  102. struct cRGB currentColor;
  103. struct cRGB off;
  104. struct cRGB background;
  105. struct cRGB output[NUM_PIXELS] __at(0x40); // force LED array to be at fixed RAM address (for assembly routine taking care of LED refresh)
  106. uint8_t my_brightness = 250; // this can be changed to accomodate lower brightness level

  107. uint8_t previous_mode;
  108. uint8_t mode = 0;
  109. uint8_t pushStartCycle;
  110. uint8_t i;
  111. uint8_t previous_colorIndex;
  112. uint8_t colorIndex = 0;
  113. uint8_t cycle = 0;
  114. uint8_t currentCycle;
  115. uint16_t previous_speed;
  116. uint16_t speed;

  117. uint8_t controllState;

  118. // these variables will be accessed under interrupt, need to be declared as volatile
  119. volatile uint16_t risingStart = 0;
  120. volatile uint16_t channelLength = 0;
  121. volatile uint8_t timer_1ms;


  122. // running average of data (using 20% new value / 80% old value)
  123. uint16_t smooth(uint16_t data, uint16_t smoothedVal) {
  124.     smoothedVal = ((data * 2) / 10) + (smoothedVal * 8) / 10;

  125.     return smoothedVal;
  126. }

  127. // Interrupt Service Request handler
  128. void __interrupt() isr(void) {
  129.     // Is this interrupt on change pin interrupting?
  130.     if (IOCIE && IOCIF) {
  131.         IOCIF = 0;
  132.         IOCAF = 0;
  133.         TMR1ON = 0;
  134.         if (INPUT_PIN) { // rising edge detected
  135.             risingStart = TMR1;
  136.         } else { // falling edge detected
  137.             uint16_t val;
  138.             if (TMR1 > risingStart)
  139.                 val = TMR1 - risingStart;
  140.             else
  141.                 val = (65535U - risingStart) + TMR1;
  142.             // val now contains PPM pulse duration
  143.             channelLength = smooth(val, channelLength);
  144.             // to get channel value, perform some filtering
  145.         }
  146.         TMR1ON = 1;
  147.     }
  148.    
  149.     // Is this timer1 interrupting?
  150.     if (TMR0IE && TMR0IF) {
  151.         // Reset the timer1 interrupt flag
  152.         TMR0IF = 0;
  153.         TMR0 = TMR0_RELOAD; // reload timer 0 for next TICK interrupt period
  154.         LATAbits.LATA1 ^= 1; // for debug and interrupt monitoring
  155.         timer_1ms = 1;
  156.     }
  157. }

  158. // Init System timer (TMR0) used by Application for TICK generation
  159. void Init_Timer(void) {
  160.     // Configure Timer 0 for system timer
  161.     TMR0IF = 0; // Clean TMR0 flag
  162.     T0CS = 0; // clock source = internal system clock

  163.     // prescaler
  164.     PSA = 0; // prescaler assigned to TMR0
  165.     OPTION_REGbits.PS = 0b111; // Prescaler 1:256
  166.     TMR0 = TMR0_RELOAD; // reload value = TICK ms

  167.     // Enable System Timer Interrupts
  168.     TMR0IE = 1; // Enable TMR0 Interrupt
  169. }

  170. // Configure Timer 2 for Delay routine
  171. void Init_Timer2(void) {
  172.     T2CON = 0b00110000; // prescaler 1/8 gives 1 us resolution
  173. }

  174. // Duration is a multiple of 1 us
  175. // this routine will block until the time is ellapsed (only interrupts are allowed)
  176. void delay_us(uint8_t duration) {
  177.     if (duration > 5)
  178.         PR2 = duration - 4; // compensate for function overhead
  179.     else
  180.         PR2 = 1;
  181.     TMR2 = 0; // reset Timer2
  182.     TMR2IF = 0;
  183.     TMR2ON = 1; // start Timer2
  184.     while (!TMR2IF)
  185.         NOP();
  186.     TMR2ON = 0; // shutdown Timer2
  187. }

  188. // Duration is a multiple of 1 ms
  189. void delay_ms(uint16_t duration) {
  190.     uint16_t j;
  191.     for (j = 0; j < (duration * 10); j++) {
  192.         delay_us(100);
  193.         CLRWDT();
  194.     }
  195. }

  196. // Routine to write a single byte into EEPROM space
  197. void DATAEE_WriteByte(uint8_t bAdd, uint8_t bData) {
  198.     uint8_t GIEBitValue = 0;

  199.     EEADRL = bAdd; // Data Memory Address to write
  200.     EEDATL = bData; // Data Memory Value to write
  201.     EECON1bits.EEPGD = 0; // Point to DATA memory
  202.     EECON1bits.CFGS = 0; // Deselect Configuration space
  203.     EECON1bits.WREN = 1; // Enable writes

  204.     GIEBitValue = INTCONbits.GIE;
  205.     INTCONbits.GIE = 0; // Disable INTs
  206.     EECON2 = 0x55;
  207.     EECON2 = 0xAA;
  208.     EECON1bits.WR = 1; // Set WR bit to begin write
  209.     // Wait for write to complete
  210.     while (EECON1bits.WR) {
  211.     }

  212.     EECON1bits.WREN = 0; // Disable writes
  213.     INTCONbits.GIE = GIEBitValue;
  214. }

  215. // Routine to read a single byte from EEPROM space
  216. uint8_t DATAEE_ReadByte(uint8_t bAdd) {
  217.     EEADRL = bAdd; // Data Memory Address to read
  218.     EECON1bits.CFGS = 0; // Deselect Configuration space
  219.     EECON1bits.EEPGD = 0; // Point to DATA memory
  220.     EECON1bits.RD = 1; // EE Read
  221.     NOP(); // NOPs may be required for latency at high frequencies
  222.     NOP();

  223.     return (EEDATL);
  224. }

  225. // Initialize I/O ports
  226. void Init_Ports(void) {
  227.     nWPUEN = 0; // PortA pull-ups enabled by individual PORT Latch values
  228.     ANSELA = 0; // all pins digital
  229.     WPUA = 0b00111000; // disable Weak pull-ups on outputs
  230.     LATA = 0; // this will turn ON debug LED
  231.     TRISA = 0b00111000; // Output bits RA0, RA2
  232.     IOCAP = 0b00100000; // RA5 triggers interrupt for both rising and falling changes
  233.     IOCAN = 0b00100000;
  234.     IOCIF = 0;
  235.     IOCIE = 1;
  236. }

  237. //
  238. void setColor(void) {
  239.     currentColor.r = colors[colorIndex][0] * my_brightness;
  240.     currentColor.g = colors[colorIndex][1] * my_brightness;
  241.     currentColor.b = colors[colorIndex][2] * my_brightness;

  242.     background.r = colors[colorIndex][0] * 50;
  243.     background.g = colors[colorIndex][1] * 50;
  244.     background.b = colors[colorIndex][2] * 50;
  245. }

  246. // This will turn off all LEDs on the strip
  247. void modeOff(void) {
  248.     for (i = 0; i < NUM_PIXELS; i++) {
  249.         output[i] = off;
  250.     }
  251. }

  252. // This will turn on all LEDs on the strip (with currentcolor setting)
  253. void modeOn(void) {
  254.     for (i = 0; i < NUM_PIXELS; i++) {
  255.         output[i] = currentColor;
  256.     }
  257. }

  258. // returns
  259. uint8_t getDivider(uint8_t denom, uint8_t cycle) {
  260.     return cycle / denom;
  261. }

  262. // This will turn on one single led in the strip in sequence
  263. void modeSingleWander(void) {
  264.     currentCycle = getDivider(2, currentCycle);

  265.     for (i = 0; i < NUM_PIXELS; i++) {
  266.         output[i] = background;
  267.     }

  268.     output[currentCycle % NUM_PIXELS] = currentColor;
  269. }

  270. // this will turn on 3 consecutive leds in the strip in sequence
  271. void modeRapid(void) {
  272.     for (i = 0; i < NUM_PIXELS; i++) {
  273.         output[i] = background;
  274.     }

  275.     if (currentCycle == NUM_PIXELS << 2) {
  276.         cycle = 0;
  277.         currentCycle = 0;
  278.     }

  279.     if (currentCycle < NUM_PIXELS) {
  280.         output[currentCycle % NUM_PIXELS] = currentColor;

  281.         if (currentCycle + 1 < NUM_PIXELS) {
  282.             output[(currentCycle + 1) % NUM_PIXELS] = currentColor;
  283.         }
  284.         if (currentCycle + 2 < NUM_PIXELS) {
  285.             output[(currentCycle + 2) % NUM_PIXELS] = currentColor;
  286.         }
  287.     }
  288. }

  289. // this will turn on 2 consecutive leds in the strip in sequence
  290. void modeBoldWander(void) {
  291.     currentCycle = getDivider(2, currentCycle);

  292.     for (i = 0; i < NUM_PIXELS; i++) {
  293.         output[i] = background;
  294.     }

  295.     output[currentCycle % NUM_PIXELS] = currentColor;
  296.     output[(currentCycle + 1) % NUM_PIXELS] = currentColor;
  297. }

  298. // this will turn on 4 consecutive leds in the strip in sequence
  299. void modeBolderWander(void) {
  300.     currentCycle = getDivider(2, currentCycle);

  301.     for (i = 0; i < NUM_PIXELS; i++) {
  302.         output[i] = off;
  303.     }

  304.     output[currentCycle % NUM_PIXELS] = currentColor;
  305.     output[(currentCycle + 1) % NUM_PIXELS] = currentColor;
  306.     output[(currentCycle + 2) % NUM_PIXELS] = currentColor;
  307.     output[(currentCycle + 3) % NUM_PIXELS] = currentColor;
  308. }

  309. // this will turn on 2 opposite leds in the strip in sequence
  310. void modeDoubleWander(void) {
  311.     currentCycle = getDivider(2, currentCycle);

  312.     for (i = 0; i < NUM_PIXELS; i++) {
  313.         output[i] = off;
  314.     }

  315.     output[currentCycle % NUM_PIXELS] = currentColor;
  316.     output[(MAX_CYCLE - currentCycle) % NUM_PIXELS] = currentColor;
  317. }

  318. // this will turn on 2 leds (with gap in between) in the strip in sequence
  319. void modeChase(void) {
  320.     currentCycle = getDivider(2, currentCycle);

  321.     for (i = 0; i < NUM_PIXELS; i++) {
  322.         output[i] = off;
  323.     }

  324.     output[currentCycle % NUM_PIXELS] = currentColor;
  325.     output[(currentCycle + (NUM_PIXELS / 2)) % NUM_PIXELS] = currentColor;
  326. }

  327. // this will flash all leds in the strip
  328. void modeFlash(void) {
  329.     currentCycle = getDivider(2, currentCycle);

  330.     struct cRGB state = off;

  331.     if ((currentCycle % 16 == 12) || (currentCycle % 16 == 15)) {
  332.         state = currentColor;
  333.     }

  334.     for (i = 0; i < NUM_PIXELS; i++) {
  335.         output[i] = state;
  336.     }
  337. }

  338. // this will progressively turn ON and OFF (breathing effect) all leds in the strip
  339. void modeBreathing(void) {
  340.     struct cRGB my_color;
  341.     uint16_t value;
  342.     currentCycle = currentCycle & 0x3F;
  343.     if (currentCycle > 31)
  344.         currentCycle = 63 - currentCycle;
  345.     value = (uint16_t)(currentCycle * currentCycle) >> 2;
  346.     currentCycle = value;
  347.     my_color.r = colors[colorIndex][0] * currentCycle;
  348.     my_color.g = colors[colorIndex][1] * currentCycle;
  349.     my_color.b = colors[colorIndex][2] * currentCycle;
  350.     for (i = 0; i < NUM_PIXELS; i++) {
  351.         output[i] = my_color;
  352.     }
  353. }

  354. // this will display a rainbow effect on the led strip
  355. void modeRainbow(void) {
  356.     static uint8_t offset;
  357.     struct cRGB my_color;
  358.     uint8_t index;

  359.     for (i = 0; i < NUM_PIXELS; i++) {
  360.         index = (i + offset) & 0x07;
  361.         my_color.r = colors[index][0] * 85;
  362.         my_color.g = colors[index][1] * 85;
  363.         my_color.b = colors[index][2] * 85;
  364.         output[i] = my_color;
  365.     }
  366.     if (currentCycle % 5 == 0)
  367.         offset++;
  368. }

  369. uint8_t abs_u8(int8_t value) {
  370.     if (value < 0)
  371.         return (-value);
  372.     else
  373.         return (value);
  374. }

  375. // do actual work
  376. void loop(void) {
  377.     // Test RC input pulse duration
  378.    
  379.     // first, compare pulse to speed control range
  380.     if ((channelLength > PWM_SPEED_MIN) && (channelLength < PWM_SPEED_MAX)) {
  381.         speed = ((channelLength - PWM_SPEED_MIN) * SPEED_MAX) / (PWM_SPEED_MAX - PWM_SPEED_MIN);
  382.     }

  383.     // then compare pulse to "button" press threshold (or actual button press)
  384.     if (((channelLength > PWM_PRESS_MIN) && (channelLength < PWM_PRESS_MAX)) || (BUTTON_PIN == 0)) {
  385.         if (controllState == IDLE) {
  386.             controllState = PRESS;
  387.             pushStartCycle = cycle;
  388.         }
  389.     }

  390.     // decide button status based on previous state
  391.     if ((channelLength < 1750) && (BUTTON_PIN == 1)) {
  392.         if (controllState == PRESS) {
  393.             controllState = SHORTPRESS;
  394.         }
  395.         if (controllState == LONGPRESS) {
  396.             controllState = IDLE;
  397.         }
  398.     }

  399.     // if button is pressed
  400.     if (controllState == PRESS) {
  401.         // and this is a long press
  402.         if (abs_u8(cycle - pushStartCycle) > LONG_PUSH_THRESHOLD) {
  403.             // Change color procedure
  404.             colorIndex++;

  405.             if (colorIndex == COLORS) {
  406.                 colorIndex = 0;
  407.             }
  408.             
  409.             setColor();
  410.             cycle = 0;
  411.             pushStartCycle = 0;
  412.             controllState = LONGPRESS;
  413.         }
  414.     }

  415.     // if button is short pressed
  416.     if (controllState == SHORTPRESS) {
  417.         if (abs_u8(cycle - pushStartCycle) > 2) {
  418.             // Change mode procedure
  419.             mode++;

  420.             if (mode == MODES) {
  421.                 mode = 0;
  422.             }
  423.             
  424.             cycle = 0;
  425.             pushStartCycle = 0;
  426.             controllState = IDLE;
  427.         }
  428.     }
  429.    
  430.     // memorize currentcycle
  431.     currentCycle = cycle;
  432.    
  433.     // based on selected operating mode, dispatch to appropriate LED display routine
  434.     switch (mode) {
  435.         case 0:
  436.             modeOn();
  437.             break;

  438.         case 1:
  439.             modeSingleWander();
  440.             break;

  441.         case 2:
  442.             modeBoldWander();
  443.             break;

  444.         case 3:
  445.             modeDoubleWander();
  446.             break;

  447.         case 4:
  448.             modeChase();
  449.             break;

  450.         case 5:
  451.             modeFlash();
  452.             break;

  453.         case 6:
  454.             modeBolderWander();
  455.             break;

  456.         case 7:
  457.             modeRapid();
  458.             break;

  459.         case 8:
  460.             modeBreathing();
  461.             break;

  462.         case 9:
  463.             modeRainbow();
  464.             break;

  465.         case 10:
  466.             modeOff();
  467.             break;

  468.     }
  469.    
  470.     // Update LEDs
  471.     send_frame();
  472.     cycle++;
  473.    
  474.     // wait for next frame to display
  475.     delay_ms(SLEEP_TIME - speed);
  476. }

  477. // Set up the timer for input capture
  478. void Init_Timer1(void) {
  479.     T1CON = 0b00110001; // Timer1 clock source is instruction clock (FOSC/4)
  480.     // 1:8 Prescale value (1us timebase), Timer 1 ON
  481. }

  482. // Main Rountine (the application)
  483. //DOM-IGNORE-BEGIN
  484. //                    _          __ __
  485. //    _ __ ___   __ _(_)_ __    / / \ \
  486. //   | '_ ` _ \ / _` | | '_ \  | |   | |
  487. //   | | | | | | (_| | | | | | | |   | |
  488. //   |_| |_| |_|\__,_|_|_| |_| | |   | |
  489. //                              \_\ /_/

  490. void main(void) {
  491.     // Set up the IO pins
  492.     Init_Ports();
  493.     OSCCON = 0b01110000; //Setup internal oscillator for 32MHz = 8M x 4

  494.     Init_Timer2();
  495.     Init_Timer1();
  496.    
  497.     // try to restore previous operating mode from EEPROM
  498.     mode = DATAEE_ReadByte(EEPROM_MODE_ADDRESS);
  499.     if (mode >= MODES) {
  500.         mode = 0;
  501.     }
  502.     previous_mode = mode;

  503.     // try to restore previous color mode from EEPROM
  504.     colorIndex = DATAEE_ReadByte(EEPROM_COLOR_ADDRESS);
  505.     if (colorIndex >= COLORS) {
  506.         colorIndex = 0;
  507.     }
  508.     previous_colorIndex = colorIndex;

  509.     // try to restore previous speed setting from EEPROM
  510.     speed = DATAEE_ReadByte(EEPROM_SPEED_ADDRESS);
  511.     if (speed > SPEED_MAX) {
  512.         speed = SPEED_MID;
  513.     }
  514.     previous_speed = speed;

  515.     // prepare LED strip
  516.     setColor();
  517.     controllState = IDLE;

  518.     Init_Timer();

  519.     // Enable the interrupts
  520.     PEIE = 1;
  521.     GIE = 1;

  522.     // Program Main loop
  523.     while (1) {
  524.         // If 1ms timer expired, then launch loop
  525.         if (timer_1ms) {
  526.             timer_1ms = 0;
  527.             loop();
  528.         }
  529.         
  530.         // is it time to save current settings to EEPROM?
  531.         if (cycle == 255) {
  532.             // if mode changed since last save, then store in EEPROM
  533.             if (mode != previous_mode) {
  534.                 previous_mode = mode;
  535.                 DATAEE_WriteByte(EEPROM_MODE_ADDRESS, mode);
  536.             }
  537.             // if color changed since last save, then store in EEPROM
  538.             if (colorIndex != previous_colorIndex) {
  539.                 previous_colorIndex = colorIndex;
  540.                 DATAEE_WriteByte(EEPROM_COLOR_ADDRESS, colorIndex);
  541.             }
  542.             // if speed changed since last save, then store in EEPROM
  543.             if (speed != previous_speed) {
  544.                 previous_speed = speed;
  545.                 DATAEE_WriteByte(EEPROM_SPEED_ADDRESS, speed);
  546.             }
  547.         }
  548.     }
  549. }


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
734774645 发表于 2024-9-28 17:00 | 显示全部楼层
看一下附件。这个芯片有点奇怪,很多公开的操作时序跟手册上是不同的,包括那个地址。有人说是隐藏了一个标准I2C的地址,那么这个官方的说明在哪儿呢。
xinpian101 发表于 2024-9-28 20:54 | 显示全部楼层
这是用定时器实现的?
哈根达斯uz 发表于 2024-9-30 16:06 来自手机 | 显示全部楼层
Assembly function used to send the 24bits info to WS2812 leds
KCCHEN 发表于 2024-10-1 08:10 | 显示全部楼层
看看
您需要登录后才可以回帖 登录 | 注册

本版积分规则

266

主题

5573

帖子

22

粉丝
快速回复 在线客服 返回列表 返回顶部