Pinboard II. Ethernet модуль на базе ENC28J60

Для связи с сетью для Pinboard II была разработана сетевуха :) Вот такой вот модуль:


Можете скачать 3D проект и повертеть Google Sketchup или повертеть в 3D можно с Google Warehouse.

 

Железо
Построено все на базе микросхемы ENC28J60. Несмотря на изрядный размер Errata, она пользуется популярностью за счет дешевизны, доступности и большого разнообразия корпусов. Бывает даже в DIP. Я же применил ssop-28.
 

Схема включения типовая, без каких либо заморочек:

 

Общается микросхема с микроконтроллером по SPI, линии SPI выведены на боковой разъем. Питание берет с MainPower и пропускает через собственный стабилизатор LD1117-3.3. Для удобства, LED индикаторы коннекта можно вывести либо на RJ-45 разьем, как обычно принято, либо на LED4 и LED5 демоплаты, что стоят возле разъема расширения. Переключение диодов делается джамперами.
 

Фишкой модуля является то, что он может работать независимо, без демоплаты Pinboard. Для этого мы снимаем контроллерный модуль и одеваем его сверху на нашу сетевуху. Там под него уже готова посадочная площадка.
 

При этом шинные выводы (RX, TX, SDA, SCL, MISO, MOSI, SCK) модуля садятся на шины платы через краевой разъем (надо будет только перекинуть перемычки на коммутаторе, выбрав другое направление).
 

Также на модуле стоит разъем под SD карту. Т.к. наличие интернета подразумевает и построение вебсерверов, а раз так, то не помешают дополнительные обьемы памяти, SD карта как раз пригодится. На модуле, есть и разъем питания, со своим стабилизатором для CPU_POWER2.
 

Таким образом, можно использовать сей блок либо в составе демоплаты, как сетевую карту.
 


 

А можно, нацепив нужный процессор, превратить в маленькое самодостаточное устройство, подняв на нем вебсервер или клиент.
 


 

А неиспользованные линии, выходящие с бокового разъема применить для управления внешними устройствами. Например релюшками. Подав питание питание 5…9 вольт постоянного тока. На борту платы уже стоит стабилизатор и защита от переполюсовки.
 
 

Печатная плата доступна для повторения и изменения, на условиях неизменения маркировки названий и копирайтов, а также обязательной ссылке на эту статью (в случае публикации где-либо самостоятельно изготовленного устройства, сделанного на базе этого проекта).

 
 

Доступен в нашем магазине

Немного практики, для самых маленьких
Покажу пример работы этого модуля. Позажигаем диодами с компа. Чтобы далеко не ходить, за основу был взят досконально разжеваный стек от LifeLover из сообщества. Причем его минималистичный вариант, работающий только как UDP сервер. Он будет ловить пакеты от компа, если пакет содержит «А» — зажигаем первый диод. Если «а» — гасим первый диод. B и С точно таким же образом отвечают за другие два диода.
 

Подробно работу стека TCP/IP и работу конкретно с ENC28J60, а также разные технические детали я описывать не буду, т.к. в серии постов все было описано до мелочей. Расскажу лишь как всю эту кучу кода подвязать к своему проекту.
 

Эта инфа будет архиполезна тем, кто в Си еще делает первые робкие шаги и толком не знает, что и как там происходит, как цеплять чужой код и как с ним обращаться вообще, как там все движется от функции к функции внутри, и как разворачивается матрешка из вложенных пакетов стека TCP/IP
 

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

 

Чтобы студия искала сорцы в своей папке. Теперь бросим туда файлы с либой. Там же, но на вкладке General, выставим тактовую частоту контроллера:


 

Это :

  • enc28j60.c и enc28j60.h — комплект функций для работы с микросхемой ENC28J60. Занимается ее инициализацией, настраивает MAC адрес, а также принимает/получает сырые пакеты.
  • lan.c и lan.h — комплект функций по разматыванию пакетов, сортировке из по типам и реакции на некоторые из них (ARP, ICMP) — более подробней о каждой функции из этого набора — в цикле статей.

 

Файлы надо скопировать в папку к проекту и добавить в наше дерево проектов. С-файлы к группе Source, а h-файлы в группу Header.


 

Теперь студия знает, что они у нас есть.
 

Хидеры библиотеки надо прописать в исходнике. Добавив к общим инклюдникам. Примерно как у меня:
 

1
2
3
4
5
6
7
8
9
10
11
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avrlibtypes.h>
#include <avrlibdefs.h>
#include <avr/pgmspace.h>
#include <avr/wdt.h>
#include <util/delay.h>
#include <stdlib.h>
 
#include <enc28j60.h>
#include <lan.h>

Осталось добавить Callback функцию.

1
2
3
4
5
6
7
8
9
10
void udp_packet(eth_frame_t *frame, uint16_t len)
{
ip_packet_t *ip = (void*)(frame->data);
udp_packet_t *udp = (void*)(ip->data);
uint8_t *data = udp->data;
 
// Тут пропишем наш экшн потом.
 
 
}

 

Ее можно прописать выше или ниже main функции. Кому как больше нравится.
 

Например, так:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/wdt.h>
#include <util/delay.h>
#include <stdlib.h>
#include <enc28j60.h>
#include <lan.h>
 
 
void udp_packet(eth_frame_t *frame, uint16_t len)
{
ip_packet_t *ip = (void*)(frame->data);
udp_packet_t *udp = (void*)(ip->data);
uint8_t *data = udp->data;
 
// Тут будет всякий экшн по приходу пакета. 
 
}
 
int main(void)
{
 
}

Все, на этом, по идее уже все должно компиляться. Т.е. проект рабочий, осталось только сконфигурировать и запустить.
 

Конфигурация
Открываем enc28j60.h и сразу же видим вначале следующую байду:

1
2
3
4
5
6
#define ENC28J60_SPI_DDR	DDRB
#define ENC28J60_SPI_PORT	PORTB
#define ENC28J60_SPI_CS		(1<<PB4)
#define ENC28J60_SPI_MOSI	(1<<PB5)
#define ENC28J60_SPI_MISO	(1<<PB6)
#define ENC28J60_SPI_SCK	(1<<PB7)

 

Пояснений, думаю, не требуется. Тут прописаны выводы SPI для работы с ENC28J60. Поскольку у нас используется аппаратный SPI, то они должны совпадать с выводами SPI ни контроллере. Исключение вывод CS — он может быть выбран произвольно, но на том же порту *
 

Для MEGA16/32 оставляем все как есть. Тут все ок.
 

Теперь открываем файл lan.h, а там:

1
2
3
4
5
6
7
/*
 * Config
 */
#define WITH_ICMP
#define MAC_ADDR		{0x00,0x13,0x37,0x01,0x23,0x45}
#define IP_ADDR			inet_addr(192,168,2,222)
#define IP_PACKET_TTL		64

 

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

Делаем инициализацию

1
lan_init();

Это функция из lan.c, но по факту она запускает функцию enc28j60_init(mac_addr); передавая ей MAC адрес, а та, в свою очередь, запихивает в ENC28J60 разные конфигурационные данные, подготавливая к работе. Подробней о ENC28J60 — в статье цикла.
 

Эзернет готов к работе. Теперь наша задача периодически опрашивать ENC28J60 на предмет наличия данных запуская функцию lan_poll();.
 

1
2
3
4
while(1)
	{
	lan_poll();
	}

 

Понятно, что пример примитивный и тут кроме этого ничего нет. Но ведь бывает и иначе? Куда вешать lan_poll? А по барабану. Можно в главном цикле проворачивать, можно по таймеру запускать. Только не стоит делать это в обработчике прерываний. Т.к. lan_poll за собой тащит весь эзернет стек, так что работает не быстро. Главное запускать ее не реже чем приходят пакеты, иначе не успеешь выгрести и буфер у ENC28J60 переполнится, данные потеряются.
 

А так.. я пробовал делать опрос lan_poll раз в две секунды. Работает, с откликом в те самые две секунды. Особенно забавно смотрятся пинги. Можно на работе сделать такую затычку вместо своего компа, а потом пойти пугать местного эникейщика пингами в несколько секунд до соседней машины.
 

Аппаратное западло в офисе это очень интересная тема, но вернемся все же к lan_poll. Эта функция, в свою очередь, вызвает функцию чтения enc28j60_recv_packet(net_buf, sizeof(net_buf)), которая выковыривает из ENC28J60 буфер с данными, пихая его в глобальную переменную net_buf и, если длина вытащенного буфера не равна нулю, вызывает функцию eth_filter(frame, len);, передавая ей указатель на этот буфер и длину его.
 

Буфер, по сути, это массив байтов определенной длины. В памяти он лежит в переменной net_buf. Но таскать данные с него неудобно, проще, если какой либо функции потребуются данные с него, передать указатель (читай адрес его начала в ОЗУ) на буфер. Этот указатель носит имя frame
 

1
eth_frame_t *frame = (void*)net_buf;

 

Данные в буфере лежат сплошным куском. Без какого либо деления. Но благодаря тому, что мы задали тип указателя как хитрую структуру типа eth_frame_t
 

вида:
 

1
2
3
4
5
6
typedef struct eth_frame {
	uint8_t to_addr[6];
	uint8_t from_addr[6];
	uint16_t type;
	uint8_t data[];
} eth_frame_t;

 

Где четко указано данные какого размера после чего лежат. Таким образом, мы можем зная указатель и его тип вычислить адрес любого поля. Точнее за нас это делает компилятор, мы же только указываем ему, что нас интересует, почти человеческим языком.
 

Как то так:

1
frame->type

Взяли и достали кусок буфера отвечающий за тип пойманного пакета.
 

И вот вся эта радость передается в eth_filter(frame, len);, а он уже занимается сортировкой данных.
 

Там тоже все просто:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void eth_filter(eth_frame_t *frame, uint16_t len)
{
	if(len >= sizeof(eth_frame_t))
	{
		switch(frame->type)
		{
		case ETH_TYPE_ARP:
			arp_filter(frame, len - sizeof(eth_frame_t));
			break;
		case ETH_TYPE_IP:
			ip_filter(frame, len - sizeof(eth_frame_t));
			break;
		}
	}
}

 

Приходит наш фрейм, проверяется его длина. А дальше обычным CASE определяет тип и передает пакет дальше. Либо в arp_filter если это ARP пакет, либо в ip_filter — если речь об IP пакете. При этом декларируемая длина пакета len укорачивается на размер заголовка.
 

В ARP_filter сразу же формируется обратный пакет и отсылается обратно функцией eth_reply(frame, sizeof(arp_message_t));, поглядите на это сами, в исходниках.
 

А вот в ip_filter продолжается разбор полетов. Там либо идем в обработку ICMP пакета, либо в UDP filter. И вот мы почти в самом конце путешествия пакета, в функции

1
2
3
4
5
6
7
8
9
10
11
void udp_filter(eth_frame_t *frame, uint16_t len)
{
	ip_packet_t *ip = (void*)(frame->data);
	udp_packet_t *udp = (void*)(ip->data);
 
	if(len >= sizeof(udp_packet_t))
	{
		udp_packet(frame, ntohs(udp->len) - 
			sizeof(udp_packet_t));
	}
}

 

А тут, внимание, матрешка из указателей! Помните у нас была структура eth_frame_t и в самом конце нее было поле data[]?
 

Собственно эта data и есть содержимое пакета, а все что выше заголовки. В этом пакете может быть другой пакет, может быть что угодно. Раз мы тут, значит внутри ip пакет. У него есть свои заголовки и своя структура. И все это лежит в data.
 

Cоздаем еще один укзатель, ip, типа ip_packet_t и привязываем его к адресу секции frame->data. Теперь мы можем по человечески потрошить по структуре ip_packet’a секцию data из eth_frame.
 

Но сам ip нас мало интересует, все что надо там, мы взяли в ip_filter. Потому мы на секцию данных* ip пакета нацеливаем указатель типа udp_packet, чтобы разворошить и эту коробочку. Чтобы выдрать из нее длину данных пакета и всякие заголовки. Вот так:

1
udp_packet_t *udp = (void*)(ip->data);

 

И вот мы ,наконец то, вызываем ту самую Callback функцию udp_packet, которую мы прописали в самом начале нашего повествования, там, где я еще пометил место будущего экшна. Вернемся к ней, итак:
 

1
2
3
4
5
6
7
8
9
void udp_packet(eth_frame_t *frame, uint16_t len)
{
ip_packet_t *ip = (void*)(frame->data);
udp_packet_t *udp = (void*)(ip->data);
uint8_t *data = udp->data;
 
// Тут будет наш экшн.
 
}

 

Вначале идет потрошение матрешки нашего фрейма, достается в начале ip, потом UDP и только потом указателю data присваиваем секцию data из udp пакета.
 

Вот оно МИАААААСООО! А параметр len, который нам достался с прошлого уровня — это вес этого мяса в байтах. Именно это нам хотел сказать клиент, пиная нам UDP пакеты.
 

Что же такое data? А это указатель, считай, массив. Мы можем брать его байты, например, через индекс. Вот так:
 

1
2
data[i]
, где 0 <= i < len

 

Все, задача, собственно, решена. Поскольку у нас там идет обычный ASCII символ, указывающий что нам делать, то добавляем тупейший case:

1
2
3
4
5
6
7
8
9
10
11
12
13
switch(data[0])
	{
	case 'A': ON_LED1; 	break;
	case 'a': OFF_LED1;	break;
 
	case 'B': ON_LED2; 	break;
	case 'b': OFF_LED2;	break;
 
	case 'C': ON_LED3; 	break;
	case 'c': OFF_LED3;	break;
 
	default:	break;
	}

 

Ну и, наконец, отчитаемся о проделаной работе, выдав обратно строку с ответом, что пакет получен:

Создадим строку в флеш памяти:

1
uint8_t	PROGMEM message[] = "AVR UDP Server - OK \n";

 

С помощью функции копирования данных с флеша в ОЗУ (из avr/pgmspace.h), прямо в область data нашего пакета.

1
memcpy_P(data, message, sizeof(message));

 

И пнем его туда откуда пришел. udp_reply сама поменяет адреса кому-куда, по цепочке завернет всю эту матрешку в эзернет фрейм и пнет обратно.
 

1
udp_reply(frame, sizeof(message));

Весь исходник выглядит так:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/wdt.h>
#include <util/delay.h>
#include <stdlib.h>
#include <enc28j60.h>
#include <lan.h>
 
 
#define 	LED1 		4
#define 	LED2		5
#define		LED3		7
#define 	LED_PORT 	PORTD
#define 	LED_DDR		DDRD
 
 
#define ON_LED1		do{LED_PORT |=1<<LED1;} while(0)
#define ON_LED2		do{LED_PORT |=1<<LED2;} while(0)
#define ON_LED3		do{LED_PORT |=1<<LED3;} while(0)
 
#define OFF_LED1	do{LED_PORT &=~(1<<LED1);} while(0)
#define OFF_LED2	do{LED_PORT &=~(1<<LED2);} while(0)
#define OFF_LED3	do{LED_PORT &=~(1<<LED3);} while(0)
 
 
 
uint8_t PROGMEM message[] = "AVR UDP Server - OK \n";
 
void udp_packet(eth_frame_t *frame, uint16_t len)
{
ip_packet_t *ip = (void*)(frame->data);
udp_packet_t *udp = (void*)(ip->data);
uint8_t *data = udp->data;
 
switch(data[0])
	{
	case 'A': ON_LED1; 	break;
	case 'a': OFF_LED1;	break;
 
	case 'B': ON_LED2; 	break;
	case 'b': OFF_LED2;	break;
 
	case 'C': ON_LED3; 	break;
	case 'c': OFF_LED3;	break;
 
	default:	break;
	}
 
memcpy_P(data, message, sizeof(message));
udp_reply(frame, sizeof(message));
}
 
 
int main(void)
{
LED_PORT = 0;
LED_DDR = 1<<LED1 | 1<<LED2 | 1<<LED3;
 
lan_init();
sei();
 
 
 
while(1)
	{
	lan_poll();
	}
}

 

Все, компилируем, прошиваем, запускаем. Не забываем подключить диодики на выводы. На Pinboard II для этого надо только джамперы набросить. Вот так:
 


 

Теперь запускаем cmd.exe и пробуем попинговать наш сервачоГ:
 


 

Возьмем в руки инструмент контроля. Рекомендую дивную утилитку NetCat. Она позволяет слать пакеты заданного типа по указанному адресу. Запускаем nc.exe и указываем ключи -u — используем UDP, IP адрес и номер порта. Адрес который указан, а порт произвольно, скажем 1234.
 

Шлем «А» — зажигается первый диодик. Шлем «a» — гаснет. То же для b и с. А в ответ сервер шлет нам нашу строчку, что все ок.
 


 

Красота.
 

Теперь, понимая общий принцип, наверняка сможете размотать и разобраться и в более сложных примерах.

82 thoughts on “Pinboard II. Ethernet модуль на базе ENC28J60”

  1. Фишкой модуля является то, что он может работать независимо, без демоплаты Pinboard.

    Какая избыточность >_< Да и модуль получается здоровый, страшновато такой вешать на плату (особенно учитывая, что туда потом еще тяжеленный кабель воткнется). Но надо признать, в автономном варианте оно выглядит прикольно.

    Алсо параллельные резючки к диодам ты странно прицепил. Эррата иначе рекомендует. А глюк этот такой, что хрен так просто поймешь можно так делать или нет. Еще одна фишка — диоды на модуле и на плате оказываются подключенными в разной полярности, а от этого зависит режим дуплекса при старте микросхемы.

    Исключение вывод CS — он может быть выбран произвольно, но на том же порту

    Тут есть милый сюрприз от атмела для тех, кто забил на чтение даташита, раздел про SPI (ну а что, с SPI работает драйвер ENC28J60, чего там еще изучать…). Если заюзать в качестве CS не SS, то нужно его или подтягивать, или переключать на выход, иначе он заглушит SPI-модуль.

    а порт произвольно, скажем 1234.

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

    1. Ну я тоже опасался за разъем, но встает как влитой. Он же торцом в край платы ложится. Так что нормально стоит.

      Что странного?
      Place a resistor in parallel with the LED. The resistor value needed is not critical. Resistors between 1 k and 100 k are recommended.

      Про полярность диодов — это не баг. Это фича. Можно будет экспериментировать с разными комбинациями выбирая дуплекс. Хотя я бы не полагался на эти извратские виды конфигурации и делал конфигурацию вручную.

  2. Подав питание питание 5…9 вольт постоянного тока. На борту платы уже стоит стабилизатор и защита от переполюсовки.

    А он от 9В не сдохнет? Все же LM1117 не самый мощный стабилизатор, а вот ENC28J60 жрет от 250мА и больше. Ток-то он такой вытянет, конечно, а мощность?

      1. есть вариант у тебя архивнуть весь свой сайт как есть целиком и выложить где нибудь что бы можно было почитать в офлайн. (А то офлайнэкспроллером это будет долго). — извини за маленький офтоп. (И я по любому покупаю, скажешь когда и сколько надо будет опалить).

  3. У меня такой вопрос: зачем нужен интернет модуль для таких слабых микроконтроллеров, как atmega, atxmega и тд. ? Все равно же на них не запустишь интернет страницы, даже если установишь TFT дисплей. Выходит, что единственное применение интернет-модуля — это вывод вирусов в интернет и доставка информации на компьютер ?

    1. Для всего, на что хватит фантазии:
      1) Устройств с управлением через ЛС/интернет, в том числе через веб-интерфейс.
      2) Мостов Ethernet-чтотоеще (RS232, RS485) — это вообще кажись самая востребованная область.
      3) Устройств, использующих интернет/интранет сервисы (часики с синхронизацией по NTP, нечто с оповещением через email/IM/etc и так далее).

      1. 1. Круто и полезно! пример как-раз и реализован Дихалтом
        2. Мост Ethernet-RS485 купил бы сразу, реализация простейшая, на компе ставится программа Com2Com или Com2TCP (я её видел в трее даже в терминале на газпромовской автоматической заправке, вероятно бензиноналивалка ею управляется через TCP-UDP). Для своих целей покупаем Moxa NPort 5030 за 150$
        3. Часики проще делать через GPS, а бегущую строку можно через Ethernet подключить.

        И кстати, если достаточно памяти можно прошивать контроллер по локальной сети, типа Ethernet загрузчика сделать, ничем не хуже USB загрузчика )))

    2. get-запросом посылать телеметрию с кучи датчиков прямо на сервак, который будет аккуратно собирать инфу в БД для обработки другими приложениями, можно например всякие красивые графики рисовать автоматически
      при этом сервак может находится вообще в другой стране, круто же

  4. Сколько ни писали про Errata ENC28J60, мне везёт — модуль трудится в двух NTP-часах (там траффик конечно, мизерный), и в модуле управления операторским краном (а вот там опрос постоянный), тьфу-тьфу. И резистор Rbias никогда точно не подбирал :-P

  5. Здравствуйте DI HALT,
    хочу обговорить с вами возможность реализации одного заказа. Подскажите как с вами можна связатьс? почта, скайп, QIP?

    З.Ы. Извините что не по теме.

  6. Команда халявщиков требует продолжения банкета!
    — реализация виртуального СОМ порта с утилитой COM2TCP что шлет UDP пакеты из виртуального COM порта
    — Ethernet бутлоадер

    А для того чтобы заставить побегать админов в неуправляемой сети, открываются бесконечные возможности, можно на ходу менять mac- IP адреса, вызывать конфликты IP, рассылать широковещательный мусор, эдакий набор разрушающий сеть в спичечном коробке, в куче проводов или в коммуникационном шкафу найти его нерально :)

  7. Я извиняюсь за свой тупизм, но прочитав данное чтиво несколько раз не понял… Хватит ли мне этого устройства для управления микрухи через интернет!?!? что для это надо прошивать, только микруху, и как вообще организовать связь через интернет с микрухой??

        1. Пока нет. Печатки на них только сделали, но еще даже не привезли. Везут морем из Китая, так что будут к концу августа. Ну еще несколько дней на сборку первых экземпляров.

  8. Если я правильно понял то с помощью ENC28J60 . Можно подключиться к любому уже готовому устройству. И управлять им в режиме реального времени? (Разумееться при наличии разработанного специально для этих целей ПО )

  9. DI, на сколько микруха надежна? В сообществе писалось про множество багов в онном. На носу проект управления устройствами по сети где требуется сверхнадежность.
    Для более простых целей хочу заказать модуль. Штук шесть за раз можно будет купить?

    1. Баги есть, в эррата они все описаны. А также методы их обхода. По поводу сверхнадежности… Не знаю, от требований зависит. Я видел на ней промышленные решения. Сверхнадежный ли они? Не знаю.

      Да хоть десять. Их сейчас много в наличии. Оплата возможна безналом.

  10. Модуль вставлять в пинбоард как есть или нужно джамперы перевтыкать? Сетевая карта компа должна обнаружить сеть? Сделал все по статье а результат- ноль. Залил в микроконтроллер прошивку, подключил модуль к пинбоарду, втыкнул эзернет кабель, но к сожалению ничего не пошло. компьютер сеть не видит,пинга нет

    1. На модуле надо джамперы воткнуть на spi шину, чтобы подключить модуль к шине. На самой плате эзернета все уже включено как нужно. Еще может потребоваться кроссовер кабель. Если подключать без свитча.

        1. GSM в разработке. Судя по последним сообщениям товарища dcoder’a в его твиттере оно уже близко к завершению. По поводу блутуза еще не знаю стоит ли. Может на каком модуле сделаю примочку.

      1. Спасибо за ответ, я, честно говоря, даже не подумал об SPI — она-ж не микроконтроллер, да и контактов у неё — 9, а не 4 :-) (ну, да, да, 6 — ей же ещё кушать надо).
        Кстати, а плата может работать только с SD или SDHC тоже поддерживаются?

        P.S. Cтатья всё же нужна, хотя, зная про SPI, информацию найти и не сложно.

        1. НУ я не зря ссылался на цикл статей lifelover’a там есть и работа с этой карточкой (все в свете поднятия вебсервера) у него там правда не такой модуль, свой, самодельный, но полный аналог этого. Ищи, там все есть подробно расписано.

  11. DI, может быть ты подскажешь.
    Скачал проект из статьи, залил hex без изменений, контроллер тот же, отладка Pinboard 1.1. Плату делал по вышеприведённой схеме с изменениями: другой разъём с трансами (lu1t516-43 LF), нет SD карточки. Чисто ENC с обвязкой. Подключил через свитч. Устройство в сети не появилось. Соответственно, на ping не отвечает: PING: сбой передачи. General failure. Но в то же время ENC пересылает контроллеру все сетевые пакеты от других приложений(браузер, антивирус, …) Не знаю, что ещё попробовать?

  12. Почему то студия ругается на эту строку:
    uint8_t PROGMEM message[] = «AVR UDP Server — OK \n»;

    Выдает вот это:
    error: variable ‘message’ must be const in order to be put into read-only section by means of ‘__attribute__((progmem))’

    Версии применяемого мной софта:
    AVR Studio 4.19
    Toolchain 3.4.1

  13. кстати программатор который на плате 2ftbb говно полнейшее — шьет через раз .задолбался я его «резетовать» постоянно. достал свой старенький типа stk 500 (его клон,там ft232rl+atmega8513) прекрасно все шьется через ту же студию… а тот в топку его!!))

Добавить комментарий