Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Помогите прочесь адрес
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
$ilent
На руках имеется некий трансмиттер нанопар3561 который общается с контроллером по SPI. У него по адресу 0х01 лежит идентификатор встроенного контроллера.
Формат протокола следующий:
<instruction><address><data>
<instruction> - 0x81 - запись одного байта
<instruction> - 0х01 - чтение одного байта
Как я понимаю:

unsigned char nano_data_trans[]=
{
0x01, 0x01
};

char i;
char pin;
char len_nano_data = sizeof(nano_data_trans) / sizeof(nano_data_trans[0]);

void int0_isr(void)
{
spi_init();
for ( i=0; i<len_nano_data; i++)
{
SPDR = nano_data_trans[i];
while (!(SPSR & (1<<SPIF)));
}
pin = SPDR;
}

после отправки инструкции и адреса переменная "pin" должна содержать искомый ответ, но второй конец этой палки заключается в клоках контроллера: их всего два на каждый передаваемый байт, где взять третий для привязки ответа?
ArtemK
Отправляйте на SPI и третий байт. Когда контроллер будет выталкивать на MOSI третий байт, из MISO в приемный буфер затолкнется ваша <data> от трансмиттера. Т.е. Ваш код нужно модифицировать, например так:

unsigned char nano_data_trans[]=
{
0x01, 0x01, 0x00
};

char i;
char pin;
char len_nano_data = sizeof(nano_data_trans) / sizeof(nano_data_trans[0]);

void int0_isr(void)
{
spi_init();
for ( i=0; i<len_nano_data; i++)
{
SPDR = nano_data_trans[i];
while (!(SPSR & (1<<SPIF)));
}
pin = SPDR;
}
$ilent
Логика ясна, но не лепа. Что же это получается, если мне нужно прочесть не 1 байт, а 512?
BVU
Цитата($ilent @ Feb 27 2006, 16:22) *
Логика ясна, но не лепа. Что же это получается, если мне нужно прочесть не 1 байт, а 512?

Все 'лепо', почитайте как работает SPI.
http://www.mct.net/faq/spi.html
Вы должны управлять ведомым (Slave) по SCK от ведущий (Master), что бы получить ответные данные (идеология Master-Slave). Передачу данных может инициализировать только ведущий SPI.
ArtemK
Цитата
Что же это получается, если мне нужно прочесть не 1 байт, а 512?


Например вот так, если не использовать прерывания. В функцию передается указатель на буфер и кол-во читаемых байт.

Код
void SPIReadNBytes(char Buffer[], const unsigned short Length)
{
  unsigned short i;
  for (i = 0; i < Length; i++)
  {
    SPDR = 0x00;
    while (!(SPSR & (1<<SPIF)));
    Buffer[i] = SPDR;
  }
}
$ilent
Появился новый вопрос:
есть некий массив и его длинна, как передать в функцию для отправки по SPI это массив?
просто записью SPDR = trans[i]; не пойдёт - таких массивов несколько, т.е. хочу эот отправлю, хочу другой.
Код ниже передаёт длинну и первую ячейку массива... =(

unsigned char trans[]=
{
0x81, 0x03, 0x86, //Power On/Off 16 MHz Clock and Quartz
0x81, 0x04, 0x00, //Reset Digital Baseband and 16 MHz Clock
0x81, 0x29, 0x80, //External Power Amplifier Controls
0x81, 0x34, 0x4B, //RF Local Oscillator Controls
};
char len_trans = sizeof(trans) / sizeof(trans[0]); // размер массива init


#pragma interrupt_handler int0_isr:2
void int0_isr(void)
{
transmit(len_trans, trans[i]);
}

void transmit(a, cool.gif
{
spi_init();
for (i=0; i<a; i++)
{
SPDR = b;
while (!(SPSR & (1<<SPIF)));
}
disable_spi();
}
beer_warrior
Код
void transmit(char* p, int len)
{
while(len) //пока длина не ноль
   {
   while (!(SPSR & (1<<SPIF))); //проверили готовность
   SPDR = *p; // отравить данные по адресу р
   p++;          // след. адрес
   i--;             // уменьшить длину
   }
}

main()
{
char array_A[] = {...};
char array_B[] = {...};

transmit(char array_A, sizeof(char array_A));
transmit(char array_B, sizeof(char array_B));

}


Возможны некоторые неточности, но идея полжна быть ясна.
$ilent
Цитата(beer_warrior)
Возможны некоторые неточности, но идея полжна быть ясна.

Спасибки, идея дейсвительно та, поправил - заработало... Спасибо.
$ilent
Подскажите пожалуйста на счёт битов защиты и конфигурации?
Мега16 прочёл биты, контроллер мне выдал - CKSEL0-3 = 1110.
Ни чего не менял кроме CKSEL0-3 = 1111 - установил бит0, после чего контроллер перестал реагировать...
Что случилось и как это вылечить???
Igor26
Цитата($ilent @ Mar 22 2006, 11:08) *
Подскажите пожалуйста на счёт битов защиты и конфигурации?
Мега16 прочёл биты, контроллер мне выдал - CKSEL0-3 = 1110.
Ни чего не менял кроме CKSEL0-3 = 1111 - установил бит0, после чего контроллер перестал реагировать...
Что случилось и как это вылечить???

Вы настроили Мегу на работу от внешнего кварца. Подключите его и кристалл снова можно программировать.
$ilent
Цитата(Igor26 @ Mar 22 2006, 12:42) *
Вы настроили Мегу на работу от внешнего кварца. Подключите его и кристалл снова можно программировать.

Дык он подключен но не генерит. Остался послединий рабочий МК, надо его заустить от внешнего - боюсь экспериентировать...
Igor26
Цитата($ilent @ Mar 22 2006, 13:40) *
Цитата(Igor26 @ Mar 22 2006, 12:42) *

Вы настроили Мегу на работу от внешнего кварца. Подключите его и кристалл снова можно программировать.

Дык он подключен но не генерит. Остался послединий рабочий МК, надо его заустить от внешнего - боюсь экспериентировать...

Тогда попробуйте на XTAL1 подать частоту от внешнего источника(пару-тройку мгц.) и снова попробовать запрограммировать. Если у Вас МЕГА в дипе, то мы могли где-нибудь пересечся и я попробовал бы её реанимировать в параллельном программаторе.
$ilent
Цитата(Igor26 @ Mar 22 2006, 14:45) *
Тогда попробуйте на XTAL1 подать частоту от внешнего источника(пару-тройку мгц.) и снова попробовать запрограммировать. Если у Вас МЕГА в дипе, то мы могли где-нибудь пересечся и я попробовал бы её реанимировать в параллельном программаторе.

Опа, блин, я биты не установил, а выключил, а это значит External clock. Получается, что если я подам ему внешни генератор, он заведётся?
Igor26
Цитата($ilent @ Mar 22 2006, 15:03) *
Цитата(Igor26 @ Mar 22 2006, 14:45) *

Тогда попробуйте на XTAL1 подать частоту от внешнего источника(пару-тройку мгц.) и снова попробовать запрограммировать. Если у Вас МЕГА в дипе, то мы могли где-нибудь пересечся и я попробовал бы её реанимировать в параллельном программаторе.

Опа, блин, я биты не установил, а выключил, а это значит External clock. Получается, что если я подам ему внешни генератор, он заведётся?

Так точно.
$ilent
Цитата(Igor26 @ Mar 22 2006, 15:15) *
Так точно.

уф, один завелся... спасиб мил человек...
$ilent
Появилась еще одна проблемка:
массив который мне необходимо передать очень громадный - компилятор ругается.
Массив организоват просто:
unsigned char init0[]=
{
---Его размер: 9К---
};
Где он распологается, что ему не хватает места?
Куда мне его покласть и как это зделать, чтоб места зватило?
$ilent
Нашёл сам, всем спасибо...
$ilent
Появился еще один вопрос:
Код
есть 2 массива:
const unsigned char cmd[]=
{0x81, 0x80,};
const unsigned char data[]=
{0x00,};
char len = sizeof(data) / sizeof(data[0]);
они посылаются этими вызовами по очереди
       transmit(cmd, sizeof(cmd));
       transmit(data, sizeof(data));
вот сюда:
void transmit(const unsigned char *p, int len)
{
    spi_init();
      while(len)
       {       
         SPDR = *p;
         p++;
         len--;
        while (!(SPSR & (1<<SPIF)));        
         data = SPDR;               
      }
    disable_spi();
}

смысл такой: Меняться может только массив дата: (от 1 до 128 байт),
но в зависимости от количества байт в этом массиве, должен меняться первый байт массива цмд: т.е.
0x01 читать 1 байт
0x81 писать 1 байт

0x05 читать 5 байт
0x85 писать 5 байт
вот мне и надо менять этот байтавтоматиески...

Фактически мне надо сложить этот первый байт заменив его:
#define wr 0x80
#define rd 0x00
с переменной лен, но практичеки не выходит.
Может кто знает как?
$ilent
помогите приз в слудующем вопросе:
за счёт того вызов "NTRXUpdate()" постоянно крутится в цикле, то при "падении" порта PORTD 2, 3, постоянно вызывается "SendCmd(1);, "SendCmd(1);" а необходимо всего один раз за одно подение порта (сколь бы оно не длилось). По прерыванию не подходит - виснем. Короче необходимо выполнять "SendCmd(1);" один раз за одно нажатие на кнопку. Вот. Помогите кто знает как.
Код
void main (void)
{
while(1)    
    {
        /*
         * Check for incomming packets
         */
    NTRXUpdate();
        if (!(PIND & (1 << PD2)))
           {
             SendCmd(1);
           }
        if (!(PIND & (1 << PD3)))
           {
             SendCmd(2);
           }
                }
}

void SendCmd (char value)
{
    switch (value)
    {        
        case 1:        txCmd();
                    break;
        case 2:     workCmd();
                    break;
        default:     break;
    }
}
char i=1;
void txCmd(void)
{

    i++;
        if ((i%2)==0)
             NTRXSendMessage (txCmdStart, sizeof(txCmdStart));
        else
             NTRXSendMessage (txCmdStop, sizeof(txCmdStop));
}
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.