Обсуждаем контроллеры компании Atmel.
Ответить

Avr-gcc, указатели при работе с avr и переферией

Чт фев 08, 2018 20:49:27

Atmel_Studio 7, "Си",Proteus 8, Atmega 8, ds3231... вроде ничего не забыл

Добрый вечер, Коты и Киски. Скажите пжалста, есть какие то ... ограничения в использовании Си-шных указателей в авр-ах?
Я почему спрашиваю-то. Хотел я забашить 1у функцию для TWI, чтобы править всеми !!! в ней было все, что нужно для работы с аппаратами, управляемыми этим протоколом(пока она только под ds3231, но это только пока), хотябы режим мастер-слайв. Но, что б грузить/выгружать данные сразу массивами. Что б их доставить в функцию, понятно, использую указатель. Имя устройства и адрес ячейки летит из простых констант(и долетают они корректно). Однако, дальше он делает бяку. Когда в цикле впрягаются в TWDR, по очереди, данные из массива- по дебагеру I2C в протеусе, вижу на месте первого отправленного байта непонятное число, а все остальные данные как бы сдвигаются на +1, в нумерации массива. Даже когда я пытался начать отправлять не с 0-го а, предположим, с 3-го - летит это самое число, а потом уже 3ий байт и последующие ( оно почти всегда одинаковое, меняется в зависимости от положения в коде, адрес массива, наверное. Однако, непонятно как оно туда попадает, непонятно :dont_know: )
вставлю пока проблемный огрызок кода:
Код:
 - это из main.c , данные набиты от балды
   int confclc[] = {0x04,0x12,0x06};
   _write_m(DS3231,B_W,0x0E,2,confclc);


Код:
 - это из хедера
void _write_m (int slaveAddr, int wrFLAG, uint8_t addPACK, int num_pack, int *wPACK)
{

int g=0;

      //-------- START
       TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
       while(!(TWCR & (1<<TWINT))); // ожидания освобождения шины
       if((TWSR & 0xF8) != TW_START);

      //------- SEND ADDRESS
       uint8_t sendaddr = slaveAddr +wrFLAG ;
       TWDR = sendaddr;
       TWCR =(1<<TWINT|1<<TWEN);
       while(!(TWCR & (1<<TWINT)));
       //  if ((TWSR & 0xF8) != TW_MT_SLA_ACK);

      //------- SEND ADDRESS BYTE

       TWDR = addPACK;
      TWCR =(1<<TWINT|1<<TWEN);
      while(!(TWCR & (1<<TWINT)));

       TWDR = wPACK;
      TWCR =(1<<TWINT|1<<TWEN);
      while(!(TWCR & (1<<TWINT)));

      switch (wrFLAG) //

      //------- WRITE/READ
      {
         case 0b00000000 :   //  запись в устройство
            for (g=0;g<num_pack;g++)       //0 < 1 -- цикл идет
            {
            TWDR= wPACK[g];
            TWCR =(1<<TWINT|1<<TWEN);
            while(!(TWCR & (1<<TWINT)));
            if ((TWSR & 0xF8) != TW_MT_DATA_ACK);
            }
         break;

         case 0b00000001 :
         while (g<num_pack) // нет ничего пока, да и сфинкс с ним

         break;
      }
      //------ STOP
       TWCR =(1<<TWINT)|(1<<TWSTO)|(1<<TWEN);


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

Re: Avr-gcc, указатели при работе с avr и переферией

Чт фев 08, 2018 21:33:23

Catdawr писал(а):Когда в цикле впрягаются в TWDR, по очереди, данные из массива- по дебагеру I2C в протеусе, вижу на месте первого отправленного байта непонятное число,
Этот регистр двойной. В него кладутся данные для отправки и из него читаются полученные данные. Не знаю как с I2С, но с SPI (там тоже двойной регистр) Протеус в отладке значение регистра данных адекватно не отображает, хотя сама программа работает правильно.

Re: Avr-gcc, указатели при работе с avr и переферией

Чт фев 08, 2018 23:26:18

Код:
TWDR = wPACK;

Это зачем? Вот это и есть бяка (отправляешь младшие 8 бит адреса массива confclc).

ЗЫ.
I)
Код:
 switch (wrFLAG) //

      //------- WRITE/READ
      {
         case 0b00000000 :   //  запись в устройство
...
         break;

         case 0b00000001 :
...
         break;
      }


Зачем? Так же понятнее (ну и более правильное имя переменной wrFlag - это rdFlag (в ней истина, когда операция чтения))
Код:
if (wrFLAG) {
...
} else {
...
}

II) Зачем slaveAddr, wrFLAG num_pack и *wPACK двухбайтовые?
III) В чем смысл?
Код:
 if ((TWSR & 0xF8) != TW_MT_DATA_ACK);

Re: Avr-gcc, указатели при работе с avr и переферией

Пт фев 09, 2018 07:44:47

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

Re: Avr-gcc, указатели при работе с avr и переферией

Пт фев 09, 2018 20:03:17

и правда. в этом беда -
Код:
      TWDR = wPACK;
      TWCR =(1<<TWINT|1<<TWEN);
      while(!(TWCR & (1<<TWINT)));

Как обычно, косяк на ровном месте. Спасибо большое отозвавшимся
Ответить