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

Обсуждаем контроллеры компании Atmel.
Ответить
Родился
Сообщения: 10
Зарегистрирован: Пт янв 07, 2022 22:10:14

Сообщение 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();
	}
}
Вложения
Курсовая работа. Светодиодное табло на управляемых матрицах WS2812.zip
(65.56 КБ) 97 скачиваний
Реклама
Нашел транзистор. Понюхал.
Сообщения: 172
Зарегистрирован: Сб сен 15, 2018 19:04:00

Сообщение 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.
Реклама
VNS
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1633
Зарегистрирован: Пт дек 10, 2021 12:48:46
Откуда: Тюмень

Сообщение VNS »

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

Сообщение Stalin1897 »

Спасибо за советы. Проблему с передачей решил, теперь проблема с цветами) во первых цвета разные, во вторых адресовка идет как-то странно. В массив выставляю весь один цвет, первые 4 элемента оставляю черными. И получается что в начале да пикселя черные и где-то в середине два пикселя черные, хотя по моей логике должны быть первые 4 подряд. Может кто-то сталкивался с этим?
Реклама
Эиком - электронные компоненты и радиодетали
Друг Кота
Аватара пользователя
Сообщения: 15674
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

Есть прожка под ассемблером для программного ногодрыга.
Ограничение - тактовая МК не ниже 16 МГц.
(и готовый работоспособный проект под аттини 25/45/85)
8)
Реклама
Нашел транзистор. Понюхал.
Сообщения: 172
Зарегистрирован: Сб сен 15, 2018 19:04:00

Сообщение aleksey_1184 »

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

Сообщение Stalin1897 »

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

Добавлено after 1 hour 56 minutes 3 seconds:
В ходе экспериментов выяснил, что как будто бы он передает ячейки массива через одну и дублирует их под конец массива. Ну или не дублирует, а передает пропущенные изначально
Нашел транзистор. Понюхал.
Сообщения: 172
Зарегистрирован: Сб сен 15, 2018 19:04:00

Сообщение aleksey_1184 »

вытак и нехотите почитать datasheet на ws2812, а там сказано Note: Follow the order of GRB to sent data and the high bit sent at first. Ну итак навсякий случий поставте задержку перед отправкой данных в ws2812 d 50 мкС. В интернете полно примеров работы адрисных лент например на платворме ардуино, почемубы не посмотреть что там и что увас.
Родился
Сообщения: 10
Зарегистрирован: Пт янв 07, 2022 22:10:14

Сообщение Stalin1897 »

Да я понимаю что посылка должна составлять 1,25 мкС. Я сейчас просто не понимаю как мне первоначальный массив преобразовать в такой, чтобы он читался через SPI. Потому что на передачу одного бита для WS2812 нужен пакет из 3-4 битов от SPI. Легче было бы сделать на UART и не париться, но на UART у меня должен еще терминал стоять. Боюсь буду проблемы с адресацией
Нашел транзистор. Понюхал.
Сообщения: 172
Зарегистрирован: Сб сен 15, 2018 19:04:00

Сообщение aleksey_1184 »

Для начала попробуйте организавать передачу данны через ногодрыг, убедитесь что все работаетс настройками предварительной насройки данных. Увожаемый VNS выше дал ссылку на работу с SPI, но как по мне это костыль и такли пренципиально использовать SPI?
Родился
Сообщения: 10
Зарегистрирован: Пт янв 07, 2022 22:10:14

Сообщение 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)));
			}
		}
	}
}

Нашел транзистор. Понюхал.
Сообщения: 172
Зарегистрирован: Сб сен 15, 2018 19:04:00

Сообщение aleksey_1184 »

В самом начале я показао функцию SHOW это и есть ногодрыг при передачи массива, присмотритесь к картинке, там вроде все ясно указоно как формировать 0 и 1 при передачи данных.
Вложения
119-spi_ws2812b.jpg
(21.19 КБ) 76 скачиваний
Родился
Сообщения: 10
Зарегистрирован: Пт янв 07, 2022 22:10:14

Сообщение Stalin1897 »

Картинку я тоже понял, но я блин не могу понять что мне надо сделать с массивом чтобы он мог по нормальному отправиться. В последней функции я просто сравниваю каждый бит отдельно и отправляю 0 или 1 соотвественно, что по моей логике должно быть верно. Но видимо не верно
Нашел транзистор. Понюхал.
Сообщения: 172
Зарегистрирован: Сб сен 15, 2018 19:04:00

Сообщение aleksey_1184 »

За одну передачу по SPI три бита массива, по картинке все видно, вам нужно сделать три проверки проверку что передается 0 или еденица записать эти три значения в передаваемый регистр и отправить по SPI, если не секрет чем так достали препода? В общем вам нужен будет еще один буфер который будет передоваться по SPI и в нем будет в районе от 6 до 12 байт, взависимости от скорости SPI, для передачи одного пикселя.
Родился
Сообщения: 10
Зарегистрирован: Пт янв 07, 2022 22:10:14

Сообщение Stalin1897 »

Все, разобрался, спасибо вам большое, все четко и красиво получается) а насчет препода не знаю, он всей группе решил испортить новогодние выходные)
Нашел транзистор. Понюхал.
Сообщения: 172
Зарегистрирован: Сб сен 15, 2018 19:04:00

Сообщение aleksey_1184 »

удачи.
Ответить

Вернуться в «AVR»