Страница 1 из 1
Atmega8515 + Spi
Добавлено: Чт окт 30, 2014 17:00:40
shilvlad
Доброго времени суток, друзья.
Всю голову себе сломал об следующую проблему.
Прикручиваю atmega8515 через SPI к W5100. Столкнулся с проблемами в самом начале - в процессе обучения микроконтроллера инициализировать SPI и передать байт.
Делаю инициализацию так:
Код: Выделить всё
void SPI_Init(void)
{
DDRB |= (1<<SPI_MOSI)|(1<<SPI_SCK)|(1<<SPI_SS)|(0<<SPI_MISO);
PORTB |= (1<<SPI_MOSI)|(1<<SPI_SCK)|(1<<SPI_SS)|(1<<SPI_MISO);
SPCR = 0b01110000;
SPSR = 0b00000000;
}
Передачу байта так:
Код: Выделить всё
void SPI_WriteByte(uint8_t data)
{
PORTB &= ~(1<<SPI_SS);
SPDR = data;
while(!(SPSR & (1<<SPIF)));
PORTB |= (1<<SPI_SS);
}
В результате стандартной процедуры записи команд в W5100 (к слову, с ардуиной работает) он работать не начал. После долгих мучений появилось подозрение, что я не так что-то с SPI делаю (я, в целом, раньше обходился UART'ом).
Для проверки подозрений накидали для ардуины скетч, который все что получает по SPI выплевывает в ардуиновский Serial. Прицепили мой МК к ардуине - выплевывает в Serial какую-то лажу. Тут я вообще перестал понимать что происходит.
В связи с чем, помогите. Может я какую-то детскую ошибку совершаю. Поглядите, правильно ли я инициализирую SPI и посылаю байт.
Заранее благодарю.
Re: Atmega8515 + Spi
Добавлено: Чт окт 30, 2014 18:30:46
COKPOWEHEU
А Протеус что говорит?
Re: Atmega8515 + Spi
Добавлено: Чт окт 30, 2014 21:41:20
Halex
COKPOWEHEU писал(а):А Протеус ...?
А что в Протеусе есть модель W5100? Что-то за почти десятилетний срок пользования не наблюдал... А со SPI дебаггером выплюнет то, что "доктор прописал".
2 shilvlad А Вы до конца уверены, что бит
DORD в
SPCR должен стоять??? Вроде как, судя по шиту на W5100, первым едет MSB. МоГет быть здесь "собака порылась"?

Re: Atmega8515 + Spi
Добавлено: Чт окт 30, 2014 22:50:21
Ser60
Halex прав. Но помимо этого, зачем Вы дергаете каждый раз CS при передаче байта? Следует эту линию опустить перед передачей первого байта из группы байтов команды и поднять только после передачи всей группы, см. стр. 2 в ДШ. Подробнее см. в статье ниже. Она, правда, для W5200, но с W5100 аналогично.
http://radiokot.ru/circuit/digital/measure/114/
Re: Atmega8515 + Spi
Добавлено: Пт окт 31, 2014 00:28:13
shilvlad
Протеусовский SPI Debugger говорит что я что-то не так делаю (см картинку DORD1.jpg) (При этом DORD = 1)
При DORD=0 картинка DORD2.jpg
Код: Выделить всё
void SPI_Init(void){
DDRB |= (1<<SPI_MOSI)|(1<<SPI_SCK)|(1<<SPI_SS)|(0<<SPI_MISO);
PORTB |= (1<<SPI_MOSI)|(1<<SPI_SCK)|(1<<SPI_SS)|(1<<SPI_MISO);
SPCR = 0b01110000;
SPSR = 0b00000000;
}
void SPI_WriteByte(uint8_t data){
PORTB &= ~(1<<SPI_SS);
SPDR = data;
while(!(SPSR & (1<<SPIF)));
PORTB |= (1<<SPI_SS);
}
int main (void){
SPI_Init();
while(1){
_delay_ms(500);
SPI_WriteByte(0x48);
_delay_ms(50);
SPI_WriteByte(0x49);
_delay_ms(50);
SPI_WriteByte(0x49);
_delay_ms(50);
SPI_WriteByte(0x48);
_delay_ms(50);
SPI_WriteByte(0x21);
_delay_ms(50);
}
}
За DORD - спасибо. Завтра еще раз попробую.
2 Ser60
Задача с W5100 свелась у меня к проверке того, что передается по SPI. Как мне правильно подсказали, при DORD=0 SPI debugger кажет более кошерный результат, но Ардуинка подключенная SLAVE'ом к моему агрегату плюется в Serial какой-то лажей. Причем двубайтовой (двубайтовость меня заставляет в себе сомневаться сильнее всего).
Завтра на свежую голову еще попрыгаю вокруг SPI и помурыжу Вас еще
Re: Atmega8515 + Spi
Добавлено: Пт окт 31, 2014 10:08:10
shilvlad
Друзья, с учетом Ваших замечаний написана функция записи:
Что бы было понятно где затуп происходит добавил везде вывод номера выполненной команды.
Виснет на строке после "WR - 4".
Надеюсь на Вашу помощь...
Код: Выделить всё
void W5100_Write(uint16_t addr,uint8_t data){
// Activate the CS pin
SPI_PORTX &= ~(1<<SPI_SS);
USART_PrintStr("WR - 1");
// Start Wiznet W5100 Write OpCode transmission
SPDR = WIZNET_WRITE_OPCODE;
USART_PrintStr("WR - 2");
// Wait for transmission complete
while(!(SPSR & (1<<SPIF)));
USART_PrintStr("WR - 3");
// Start Wiznet W5100 Address High Bytes transmission
SPDR = (addr & 0xFF00) >> 8;
USART_PrintStr("WR - 4");
// Wait for transmission complete
while(!(SPSR & (1<<SPIF)));
USART_PrintStr("WR - 5");
// Start Wiznet W5100 Address Low Bytes transmission
SPDR = addr & 0x00FF;
USART_PrintStr("WR - 6");
// Wait for transmission complete
while(!(SPSR & (1<<SPIF)));
USART_PrintStr("WR - 7");
// Start Data transmission
SPDR = data;
USART_PrintStr("WR - 8");
// Wait for transmission complete
while(!(SPSR & (1<<SPIF)));
USART_PrintStr("WR - 9");
// CS pin is not active
SPI_PORTX |= (1<<SPI_SS);
USART_PrintStr("WR - 10");
}
Забыл добавить. Судя по протеусу записывается все по ГОСТ

Re: Atmega8515 + Spi
Добавлено: Пт окт 31, 2014 11:27:32
shilvlad
Если вдруг кому-либо будет не лень читать, вот мой, уже до неприличия упрощенный, код:
Код: Выделить всё
#define F_CPU 8000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
// USART
//////////////////////////////////////////////////////////
void USART_Init( unsigned int baud ){
UBRRH = (unsigned char)(baud>>8);
UBRRL = (unsigned char)baud;
UCSRB = (1<<RXEN)|(1<<TXEN)|(1 << RXCIE );
UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
}
void USART_Transmit(unsigned char data){
while ( !( UCSRA & (1<<UDRE)) );
UDR = data;
}
void USART_PrintStr(char * str){
int i =0;
while(str[i] != 0){
USART_Transmit(str[i]);
i++;
}
USART_Transmit(10);
USART_Transmit(13);
}
// SPI
//////////////////////////////////////////////////////////
#define SPI_PORTX PORTB
#define SPI_DDRX DDRB
#define SPI_MOSI 5
#define SPI_MISO 6
#define SPI_SCK 7
#define SPI_SS 0
void SPI_Init(void){
DDRB |= (1<<SPI_MOSI)|(1<<SPI_SCK)|(1<<SPI_SS)|(0<<SPI_MISO);
PORTB |= (1<<SPI_MOSI)|(1<<SPI_SCK)|(1<<SPI_SS)|(1<<SPI_MISO);
//SPCR = 0b01010000;
//SPSR = 0b00000000;
SPCR = (1<<SPE)|(1<<MSTR);
SPSR |= (1<<SPI2X);
}
// W5100 RW functions
/////////////////////////////////////////////////////////////////
#define WIZNET_WRITE_OPCODE 0xF0
#define WIZNET_READ_OPCODE 0x0F
void W5100_Write(uint16_t addr,uint8_t data){
// Activate the CS pin
SPI_PORTX &= ~(1<<SPI_SS);
// Start Wiznet W5100 Write OpCode transmission
SPDR = WIZNET_WRITE_OPCODE;
// Wait for transmission complete
while(!(SPSR & (1<<SPIF)));
// Start Wiznet W5100 Address High Bytes transmission
SPDR = (addr & 0xFF00) >> 8;
// Wait for transmission complete
while(!(SPSR & (1<<SPIF)));
// Start Wiznet W5100 Address Low Bytes transmission
SPDR = addr & 0x00FF;
// Wait for transmission complete
while(!(SPSR & (1<<SPIF)));
// Start Data transmission
SPDR = data;
// Wait for transmission complete
while(!(SPSR & (1<<SPIF)));
// CS pin is not active
SPI_PORTX |= (1<<SPI_SS);
}
unsigned char W5100_Read(unsigned int addr){
// Activate the CS pin
SPI_PORTX &= ~(1<<SPI_SS);
// Start Wiznet W5100 Read OpCode transmission
SPDR = WIZNET_READ_OPCODE;
// Wait for transmission complete
while(!(SPSR & (1<<SPIF)));
// Start Wiznet W5100 Address High Bytes transmission
SPDR = (addr & 0xFF00) >> 8;
// Wait for transmission complete
while(!(SPSR & (1<<SPIF)));
// Start Wiznet W5100 Address Low Bytes transmission
SPDR = addr & 0x00FF;
// Wait for transmission complete
while(!(SPSR & (1<<SPIF)));
// Send Dummy transmission for reading the data
SPDR = 0x00;
// Wait for transmission complete
while(!(SPSR & (1<<SPIF)));
// CS pin is not active
SPI_PORTX |= (1<<SPI_SS);
return(SPDR);
}
// W5100 Initialization
//////////////////////////////////////////////////////////
#define MR 0x0000 // Mode Register
#define GAR 0x0001 // Gateway Address: 0x0001 to 0x0004
#define SUBR 0x0005 // Subnet mask Address: 0x0005 to 0x0008
#define SAR 0x0009 // Source Hardware Address (MAC): 0x0009 to 0x000E
#define SIPR 0x000F // Source IP Address: 0x000F to 0x0012
#define RMSR 0x001A // RX Memory Size Register
#define TMSR 0x001B // TX Memory Size Register
void W5100_Init(void)
{
// Ethernet Setup
unsigned char mac_addr[] = {0x00,0x16,0x36,0xDE,0x58,0xF6};
unsigned char ip_addr[] = {192,168,2,10};
unsigned char sub_mask[] = {255,255,255,0};
unsigned char gtw_addr[] = {192,168,2,1};
// Setting the Wiznet W5100 Mode Register: 0x0000
W5100_Write(MR,0x80); // MR = 0b10000000;
_delay_ms(10);
// Setting the Wiznet W5100 Gateway Address (GAR): 0x0001 to 0x0004
USART_PrintStr("Setting GW");
W5100_Write(GAR + 0,gtw_addr[0]);
W5100_Write(GAR + 1,gtw_addr[1]);
W5100_Write(GAR + 2,gtw_addr[2]);
W5100_Write(GAR + 3,gtw_addr[3]);
_delay_ms(10);
USART_PrintStr("Checking GW");
if(W5100_Read(GAR+0) != gtw_addr[0] && W5100_Read(GAR+1) != gtw_addr[1] && W5100_Read(GAR+2) != gtw_addr[2] && W5100_Read(GAR+3) != gtw_addr[3]) {
USART_PrintStr("GW - Not set");
}
else USART_PrintStr("GW - Set");
// Setting the Wiznet W5100 Source Address Register (SAR): 0x0009 to 0x000E
W5100_Write(SAR + 0,mac_addr[0]);
W5100_Write(SAR + 1,mac_addr[1]);
W5100_Write(SAR + 2,mac_addr[2]);
W5100_Write(SAR + 3,mac_addr[3]);
W5100_Write(SAR + 4,mac_addr[4]);
W5100_Write(SAR + 5,mac_addr[5]);
_delay_ms(1);
// Setting the Wiznet W5100 Sub Mask Address (SUBR): 0x0005 to 0x0008
W5100_Write(SUBR + 0,sub_mask[0]);
W5100_Write(SUBR + 1,sub_mask[1]);
W5100_Write(SUBR + 2,sub_mask[2]);
W5100_Write(SUBR + 3,sub_mask[3]);
_delay_ms(1);
// Setting the Wiznet W5100 IP Address (SIPR): 0x000F to 0x0012
W5100_Write(SIPR + 0,ip_addr[0]);
W5100_Write(SIPR + 1,ip_addr[1]);
W5100_Write(SIPR + 2,ip_addr[2]);
W5100_Write(SIPR + 3,ip_addr[3]);
_delay_ms(1);
// Setting the Wiznet W5100 RX and TX Memory Size, we use 2KB for Rx/Tx 4 channels
W5100_Write(0x001A,0x55);
W5100_Write(0x001B,0x55);
}
////////////////////////////////////////////////////////////
int main (void)
{
USART_Init(8);
SPI_Init();
unsigned char gtw_addr[] = {192,168,2,1};
W5100_Write(MR,0x80); // MR = 0b10000000;
_delay_ms(100);
W5100_Write(GAR + 0,gtw_addr[0]);
_delay_ms(100);
if(W5100_Read(GAR+0) != gtw_addr[0]) {
USART_PrintStr("GW0 - Not set");
}
else USART_PrintStr("GW0 - Set");
}
Поправьте меня, если я не прав. Вот такая конструкция может ведь быть индикатором успешной записи в w5100:
Код: Выделить всё
W5100_Write(GAR + 0,gtw_addr[0]);
_delay_ms(100);
if(W5100_Read(GAR+0) != gtw_addr[0]) {
USART_PrintStr("GW0 - Not set");
}
else USART_PrintStr("GW0 - Set");
На Вас одна надежда. Чувствую, впадаю в тупку.
Re: Atmega8515 + Spi
Добавлено: Пт окт 31, 2014 16:09:37
mail_robot
отдохни денек-другой. Со мной такое тоже бывало. Потом решение приходит как по волшебству. Не зря предки вещали - утро вечера мудреннее
Re: Atmega8515 + Spi
Добавлено: Пт окт 31, 2014 16:43:03
Mishany
#include <avr/interrupt.h> вижу
sei(); не нашел.
Сам недавно сталкнулся с SPI режим Master
с прерываниями отказывался работать, убрал прерывания заработало, но есть одно НО после передачи n-быйт МК виснет, т.е. есть функция передачи 20 символов (1-й строки) на дисплей, 4 строки передается на 5 строке мк виснет, пока не победил. (проверял в железе, контролировал LOGIC-U, (USBee))
грешу на while(!(SPSR & (1<<SPIF))); ощущение что SPIF несбрасывается после передачи байта.
Re: Atmega8515 + Spi
Добавлено: Пт окт 31, 2014 17:22:55
shilvlad
Mishany писал(а):#include <avr/interrupt.h> вижу
sei(); не нашел.
Сам недавно сталкнулся с SPI режим Master
с прерываниями отказывался работать, убрал прерывания заработало, но есть одно НО после передачи n-быйт МК виснет, т.е. есть функция передачи 20 символов (1-й строки) на дисплей, 4 строки передается на 5 строке мк виснет, пока не победил. (проверял в железе, контролировал LOGIC-U, (USBee))
Это не при делах. Удалить забыл.
Mishany писал(а):грешу на while(!(SPSR & (1<<SPIF))); ощущение что SPIF несбрасывается после передачи байта.
А вот у меня замечена ерунда такая, что виснет на while(!(SPSR & (1<<SPIF))). Причем на произвольных байтах, в произвольных местах. Еще одна загадка.
Re: Atmega8515 + Spi
Добавлено: Пт окт 31, 2014 18:20:44
Mishany
засекал логическим анализатором при передачи 8 битов пропуски тактов
вот пример
Спойлер

уж не знаю как там на аппаратном уровне все происходит, но может аппаратный счетчик 8-ми тактов не срабатывает?
более наглядно:
Спойлер

c картинками это я лох

пропусков тактового нет до 4 MHz, анализатор пропускал импульсы поднял разрешение до 4х вместо 2х
Re: Atmega8515 + Spi
Добавлено: Вс ноя 02, 2014 14:06:42
Mishany
у себя обнаружил причину зависаниев нехватка оперативки