Přeji hezký večer.
Hraji si s programovatelnými RGB Pololu LED páskami, kdde posláním 24-bit adresy se zvolí barva LED.
Knihovnu jsem se snažil napsat, ale nejsem tak dobrý, tak jsem nějakou stáhnul.
Funguje velice dobře až na jednu věc.
Používám ATMEGA64 a když to zkouším použít pro PORTA,B,C,D,E tak to funguje ale pro porty F a G ne.
Dočetl jsem se, že porty F a G jsou v takzvaných extended registrech, ale nevím jak to v knihovně změnit aby to fungovalo.
Zde je funkce, která to zpracovává.
[code]
/** The rgb_color struct represents the color for an 8-bit RGB LED.
Examples:
Black: (rgb_color){ 0, 0, 0 }
Pure red: (rgb_color){ 255, 0, 0 }
Pure blue: (rgb_color){ 0, 255, 0 }
Pure green: (rgb_color){ 0, 0, 255 }
White: (rgb_color){ 255, 255, 255} */
typedef struct rgb_color
{
unsigned char red, green, blue;
} rgb_color;
/** led_strip_write sends a series of colors to the LED strip, updating the LEDs.
The colors parameter should point to an array of rgb_color structs that hold the colors to send.
The count parameter is the number of colors to send.
This function takes about 1.1 ms to update 30 LEDs.
Interrupts must be disabled during that time, so any interrupt-based library
can be negatively affected by this function.
Timing details at 20 MHz (the numbers slightly different at 16 MHz and 8MHz):
0 pulse = 400 ns
1 pulse = 850 ns
“period” = 1300 ns
*/
void attribute((noinline)) led_strip_write(rgb_color * colors, unsigned int count)
{
// Set the pin to be an output driving low.
LED_STRIP_PORT &= ~(1<<LED_STRIP_PIN);
LED_STRIP_DDR |= (1<<LED_STRIP_PIN);
cli(); // Disable interrupts temporarily because we don’t want our pulse timing to be messed up.
while(count–)
{
// Send a color to the LED strip.
// The assembly below also increments the ‘colors’ pointer,
// it will be pointing to the next color at the end of this loop.
asm volatile(
“ld tmp_reg, %a0+\n”
“ld tmp_reg, %a0\n”
“rcall send_led_strip_byte%=\n” // Send red component.
“ld tmp_reg, -%a0\n”
“rcall send_led_strip_byte%=\n” // Send green component.
“ld tmp_reg, %a0+\n”
“ld tmp_reg, %a0+\n”
“ld tmp_reg, %a0+\n”
“rcall send_led_strip_byte%=\n” // Send blue component.
“rjmp led_strip_asm_end%=\n” // Jump past the assembly subroutines.
// send_led_strip_byte subroutine: Sends a byte to the LED strip.
"send_led_strip_byte%=:\n"
"rcall send_led_strip_bit%=\n" // Send most-significant bit (bit 7).
"rcall send_led_strip_bit%=\n"
"rcall send_led_strip_bit%=\n"
"rcall send_led_strip_bit%=\n"
"rcall send_led_strip_bit%=\n"
"rcall send_led_strip_bit%=\n"
"rcall send_led_strip_bit%=\n"
"rcall send_led_strip_bit%=\n" // Send least-significant bit (bit 0).
"ret\n"
// send_led_strip_bit subroutine: Sends single bit to the LED strip by driving the data line
// high for some time. The amount of time the line is high depends on whether the bit is 0 or 1,
// but this function always takes the same time (2 us).
"send_led_strip_bit%=:\n"
#if F_CPU == 8000000
“rol tmp_reg\n” // Rotate left through carry.
#endif
“sbi %2, %3\n” // Drive the line high.
#if F_CPU != 8000000
“rol tmp_reg\n” // Rotate left through carry.
#endif
#if F_CPU == 16000000
“nop\n” “nop\n”
#elif F_CPU == 20000000
“nop\n” “nop\n” “nop\n” “nop\n”
#elif F_CPU != 8000000
#error “Unsupported F_CPU”
#endif
"brcs .+2\n" "cbi %2, %3\n" // If the bit to send is 0, drive the line low now.
#if F_CPU == 8000000
“nop\n” “nop\n”
#elif F_CPU == 16000000
“nop\n” “nop\n” “nop\n” “nop\n” “nop\n”
#elif F_CPU == 20000000
“nop\n” “nop\n” “nop\n” “nop\n” “nop\n”
“nop\n” “nop\n”
#endif
"brcc .+2\n" "cbi %2, %3\n" // If the bit to send is 1, drive the line low now.
"ret\n"
"led_strip_asm_end%=: "
: "=b" (colors)
: "0" (colors), // %a0 points to the next color to display
"I" (_SFR_IO_ADDR(LED_STRIP_PORT)), // %2 is the port register (e.g. PORTC)
"I" (LED_STRIP_PIN) // %3 is the pin number (0-8)
);
// Uncomment the line below to temporarily enable interrupts between each color.
//sei(); asm volatile("nop\n"); cli();
}
sei(); // Re-enable interrupts now that we are done.
_delay_us(80); // Send the reset signal.
}
[/code]
Chyba je určitě v tomto
"I" (_SFR_IO_ADDR(LED_STRIP_PORT)), // %2 is the port register (e.g. PORTC)
"I" (LED_STRIP_PIN) // %3 is the pin number (0-8)
Pomůžete prosím?