Страница 1 из 1

Передача данных через SPI ATmega8

Добавлено: Пт янв 07, 2022 22:15:54
Stalin1897
Доброго времени суток. При написании курсовой возникла проблема. Мне нужно передать двумерный массив по шине SPI на матрицу из WS2812. Передача идет, но загорается только первый светодиод, причем даже не тем цветом каким должен. Код прикреплю тут, также архив с проектом авр и протеус тоже прикреплю. Код написан на си

Код: Выделить всё

#define F_CPU 16000000UL
#include <avr/io.h>
#include <avr/interrupt.h>

unsigned int picture_1[64][3] =
{
	{0, 0, 0},//black
	{0, 0, 0},
	{0, 0, 0},
	{0, 0, 0},
	{0, 0, 0},
	{0, 0, 0},
	{161, 141, 103},//koga
	{0, 0, 0},//line 1
	{0, 0, 0},
	{0, 0, 0},
	{0, 0, 0},
	{0, 0, 0},
	{0, 0, 0},
	{255, 0, 0},//red
	{0, 0, 0},
	{0, 0, 0},//line 2
	{0, 0, 0},
	{0, 0, 0},
	{51, 23, 3},//haire
	{51, 23, 3},
	{0, 0, 0},
	{255, 0, 0},
	{0, 0, 255},
	{51, 23, 3},//line 3
	{255, 0, 0},
	{255, 0, 0},
	{161, 141, 103},
	{161, 141, 103},
	{51, 23, 3},
	{251, 255, 0},//yellow
	{0, 0, 255},//blue
	{0, 0, 0,},//line 4
	{255, 0, 0},
	{255, 0, 0},
	{51, 23, 3},
	{161, 141, 103},
	{161, 141, 103},
	{0, 0, 255},
	{0, 0, 255},
	{0, 0, 0},//line 5
	{255, 0, 0},
	{255, 0, 0},
	{0, 0, 0},
	{51, 23, 3},
	{161, 141, 103},
	{0, 0, 255},
	{0, 0, 255},
	{0, 0, 0},//line 6
	{255, 255, 255},//white
	{255, 0, 0},
	{161, 141, 103},
	{51, 23, 3},
	{161, 141, 103},
	{251, 255, 0},
	{0, 0, 255},
	{51, 23, 3},//line 7
	{0, 0, 0,},
	{255, 0, 0},
	{0, 0, 0},
	{161, 141, 103},
	{0, 0, 0},
	{0, 0, 0},
	{0, 0, 255},
	{0, 0, 0}//line 8
};
	
void USART_init()
{
	UBRRL = 31;
	UCSRB = (1<<TXEN) | (1<<RXEN);
	UCSRC = (1 << URSEL) | (3<<UCSZ0);
}

void SPI_init()
{
	DDRD |= (1<<5);
	PORTD |= (1<<5);
	DDRB |= (1<<3) | (1<<5) | (1<<4) | (1<<1) | (1<<2);
	PORTB |= (1<<0) | (1<<1) | (1<<2);
	SPCR |= (1<<SPE) | (1<<MSTR) | (1<<CPHA);
	SPSR |= (1<<SPI2X);
	SPDR = 0;
}

void Write()
{
	unsigned int element;
	for (int i = 0; i < 64; i++)
	{
		for (int o = 0; o < 3; o++)
		{
			element = picture_1[i][o];
			SPDR = element;
			while(!(SPSR & (1<<SPIF)));
		}
	}
}

int main(void)
{
	USART_init();
	SPI_init();
	while(1)
	{
		Write();
	}
}

Re: Передача данных через SPI ATmega8

Добавлено: Сб янв 08, 2022 00:10:05
aleksey_1184
Боюсь вас огорчить но где вы вычитали про приямую передачу через SPI, у ws2812 свой протокол передачи данных, конечно можно затействовать и SPI например с модулем DMA и CLC у pic микроконтроллеров, а так лучше ногодрыгом:

Код: Выделить всё

//------------------------------------------------------------------------------//
void SHOW(void){
     ptr = leds;
        
    for(uint16_t t =0;t<NUM_LEDS*3;t++){
        uint8_t color = *ptr;
        ptr++;
       
        for(uint8_t t=8;t>0;t--){
            if((color&(1<<7)) !=0){
                Dout_PORT = 1;
                NOP();
                NOP();
                NOP();
                NOP();
                NOP();
                NOP();
                Dout_PORT = 0;
            }
            else{
                Dout_PORT = 1;
                NOP();
                NOP();
                NOP();
                Dout_PORT = 0;
            }
            color = color<<1;
        }
    }
    return;
}
задержки подбирать взависимости от частоты МК,в моем случаи 64 мГц, они указоны в описании на ws2812 https://amperkot.ru/static/3236/uploads ... asheet.pdf.

Re: Передача данных через SPI ATmega8

Добавлено: Сб янв 08, 2022 00:44:57
VNS
[uquote="Stalin1897",url="/forum/viewtopic.php?p=4156572#p4156572"]по шине SPI на матрицу из WS2812.[/uquote]
Прочтите внимательно данную статью и Вам станет понятно, как правильно управлять светодиодом (WS2812B) при помощи SPI.
http://www.getchip.net/posts/119-umnye- ... neopixels/

Re: Передача данных через SPI ATmega8

Добавлено: Сб янв 08, 2022 11:12:52
Stalin1897
Спасибо за советы. Проблему с передачей решил, теперь проблема с цветами) во первых цвета разные, во вторых адресовка идет как-то странно. В массив выставляю весь один цвет, первые 4 элемента оставляю черными. И получается что в начале да пикселя черные и где-то в середине два пикселя черные, хотя по моей логике должны быть первые 4 подряд. Может кто-то сталкивался с этим?

Re: Передача данных через SPI ATmega8

Добавлено: Сб янв 08, 2022 11:20:00
BOB51
Есть прожка под ассемблером для программного ногодрыга.
Ограничение - тактовая МК не ниже 16 МГц.
(и готовый работоспособный проект под аттини 25/45/85)
8)

Re: Передача данных через SPI ATmega8

Добавлено: Сб янв 08, 2022 12:18:37
aleksey_1184
[uquote="Stalin1897",url="/forum/viewtopic.php?p=4156739#p4156739"]Проблему с передачей решил, теперь проблема с цветами) во первых цвета разные, во вторых адресовка идет как-то странно. В массив выставляю весь один цвет, первые 4 элемента оставляю черными. И получается что в начале да пикселя черные и где-то в середине два пикселя черные, хотя по моей логике должны быть первые 4 подряд.[/uquote]
Какая задержка между передачами данных в ленту И Структура цвета соответствует 7 странице описания?

Re: Передача данных через SPI ATmega8

Добавлено: Сб янв 08, 2022 15:46:26
Stalin1897
Структуру соблюдал. Первый элемент зеленый, потом красный, и потом синий. Но суть сама в том что пиксели которые я забил на начало разбросаны. А задержку не могу посмотреть через осцилограф, ибо дикая просадка фпс во время работы проекта, почему не знаю

Добавлено after 1 hour 56 minutes 3 seconds:
В ходе экспериментов выяснил, что как будто бы он передает ячейки массива через одну и дублирует их под конец массива. Ну или не дублирует, а передает пропущенные изначально

Re: Передача данных через SPI ATmega8

Добавлено: Сб янв 08, 2022 16:01:17
aleksey_1184
вытак и нехотите почитать datasheet на ws2812, а там сказано Note: Follow the order of GRB to sent data and the high bit sent at first. Ну итак навсякий случий поставте задержку перед отправкой данных в ws2812 d 50 мкС. В интернете полно примеров работы адрисных лент например на платворме ардуино, почемубы не посмотреть что там и что увас.

Re: Передача данных через SPI ATmega8

Добавлено: Сб янв 08, 2022 16:50:02
Stalin1897
Да я понимаю что посылка должна составлять 1,25 мкС. Я сейчас просто не понимаю как мне первоначальный массив преобразовать в такой, чтобы он читался через SPI. Потому что на передачу одного бита для WS2812 нужен пакет из 3-4 битов от SPI. Легче было бы сделать на UART и не париться, но на UART у меня должен еще терминал стоять. Боюсь буду проблемы с адресацией

Re: Передача данных через SPI ATmega8

Добавлено: Сб янв 08, 2022 17:10:15
aleksey_1184
Для начала попробуйте организавать передачу данны через ногодрыг, убедитесь что все работаетс настройками предварительной насройки данных. Увожаемый VNS выше дал ссылку на работу с SPI, но как по мне это костыль и такли пренципиально использовать SPI?

Re: Передача данных через SPI ATmega8

Добавлено: Сб янв 08, 2022 18:28:21
Stalin1897
Препод сказал делать через SPI. Если есть еще какие-то варианты кроме UARTа то готов выслушать. А ногодрыг это как, а то не совсем понимаю?:)

Добавлено after 55 minutes 47 seconds:
Написал другую функцию, по той статье сверху. Получилось кнш лучше чем было, но все равно там остались абсолютно не те цвета, какие мне были нужны. На выходе должен получиться Марио. Может быть кривой косой, но точно не такой как у меня сейчас. картинку не могу закинуть почему-то

Код: Выделить всё

void Write_2()
{
	unsigned int a;
	for (int i = 0; i < 64; i++)
	{
		for (int o = 0; o < 3; o++)
		{
			for (int s = 0; s < 8; s++)
			{
				switch(s)
				{
					case 0:
						if ((picture_1[i][o] & 0b10000000) == 0b10000000)
							SPDR = 252;
						else 
							SPDR = 224;
						break;
					case 1:
						if ((picture_1[i][o] & 0b01000000) == 0b01000000)
							SPDR = 252;
						else
							SPDR = 224;
						break;
					case 2:
						if ((picture_1[i][o] & 0b00100000) == 0b00100000)
							SPDR = 252;
						else
							SPDR = 224;
						break;
					case 3:
						if ((picture_1[i][o] & 0b00010000) == 0b00010000)
							SPDR = 252;
						else
							SPDR = 224;
						break;
					case 4:
						if ((picture_1[i][o] & 0b00001000) == 0b00001000)
							SPDR = 252;
						else
							SPDR = 224;
						break;
					case 5:
						if ((picture_1[i][o] & 0b00000100) == 0b00000100)
							SPDR = 252;
						else
							SPDR = 224;
						break;
					case 6:
						if ((picture_1[i][o] & 0b00000010) == 0b01000010)
							SPDR = 252;
						else
							SPDR = 224;
						break;
					case 7:
						if ((picture_1[i][o] & 0b00000001) == 0b00000001)
							SPDR = 252;
						else
							SPDR = 224;
						break;
				}
				while(!(SPSR & (1<<SPIF)));
			}
		}
	}
}


Re: Передача данных через SPI ATmega8

Добавлено: Сб янв 08, 2022 18:59:37
aleksey_1184
В самом начале я показао функцию SHOW это и есть ногодрыг при передачи массива, присмотритесь к картинке, там вроде все ясно указоно как формировать 0 и 1 при передачи данных.

Re: Передача данных через SPI ATmega8

Добавлено: Сб янв 08, 2022 19:01:18
Stalin1897
Картинку я тоже понял, но я блин не могу понять что мне надо сделать с массивом чтобы он мог по нормальному отправиться. В последней функции я просто сравниваю каждый бит отдельно и отправляю 0 или 1 соотвественно, что по моей логике должно быть верно. Но видимо не верно

Re: Передача данных через SPI ATmega8

Добавлено: Сб янв 08, 2022 19:34:48
aleksey_1184
За одну передачу по SPI три бита массива, по картинке все видно, вам нужно сделать три проверки проверку что передается 0 или еденица записать эти три значения в передаваемый регистр и отправить по SPI, если не секрет чем так достали препода? В общем вам нужен будет еще один буфер который будет передоваться по SPI и в нем будет в районе от 6 до 12 байт, взависимости от скорости SPI, для передачи одного пикселя.

Re: Передача данных через SPI ATmega8

Добавлено: Сб янв 08, 2022 20:11:07
Stalin1897
Все, разобрался, спасибо вам большое, все четко и красиво получается) а насчет препода не знаю, он всей группе решил испортить новогодние выходные)

Re: Передача данных через SPI ATmega8

Добавлено: Сб янв 08, 2022 20:31:25
aleksey_1184
удачи.