Страница 1 из 1

КАРАУЛ... Массивы глючат (Решено)

Добавлено: Сб ноя 06, 2010 01:18:26
krysun
....толи лыжи не едут (
Пример:

Код: Выделить всё

x=massiv[5];   //Работает
//********************
x=massiv[i];   //НЕ работает

Листинг:

Код: Выделить всё

#include <mega162.h>
#include <delay.h>
interrupt [PCINT1] void pin_change_isr1(void)
{}
int a=0b10000000;    // масска
int digit[10]={           
0b00111111,               // 0
0b00000110,               // 1
0b01011011,               // 2
0b01001111,               // 3
0b01100110,               // 4
0b01101101,               // 5
0b01111101,               // 6
0b01111101,               // 7
0b01111111,               // 8
0b01101111,               // 9
};
void main(void)
{
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
PORTB=0x00;
DDRB=0xB7;
PORTD=0x00;
DDRD=0x08;
GICR|=0x10;
PCMSK1=0x0F;
MCUCR=0x00;
EMCUCR=0x00;
GIFR=0x10;
TIMSK=0x00;
ETIMSK=0x00;
ACSR=0x80;
#asm("sei")
while (1)
      {
      char i,j;
      for (j=0;j<10;j++){ 
        PORTB.0=0;              //Врубаем ОЕ
        for(i=0;i<=7;i++)
        {
        PORTB.5=digit[j]&a;     // DATA - с "[j]" не работает (а с цыфрой, напр."[5]"-ok
        PORTB.7=1;PORTB.7=0;    // Дергаем CLOCK
        a=a>>1;                 // смещаем маску
        if (a==0b00000000) {a=0b10000000;}; // проверяем маску
        }
        PORTB.0=1;              //Вырубаем ОЕ
      }     
      delay_ms(1000);
      };
}


Не могу прочитать значения в цикле for массива по указанному переменной индексу.
Как быть?

Re: КАРАУЛ... Массивы глючат ((

Добавлено: Сб ноя 06, 2010 03:51:27
DX168B

Код: Выделить всё

int digit[6]={0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5};    //Наш массив.
int a = 0;    // Это будет нашим индексом для массива
int data;    //Суда мы впишем считанный байт из массива

int main()
{
   DDRA = 0xFF;    //Порт А настроим на выход.
   a = 2;    //Например нам надо считать второй байт из массива (0xF1)
   for(int i = 0; i < a; i++){data = digit[i];}    //Вытащим его из массива.
   PORTA = data;    //И например отправим его (байт из массива) в Порт А
   ...............    // и т.д.
   ......
   .....
}

Ещё у меня работало даже такое:

Код: Выделить всё

int digit[6]={0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5};    //Наш массив.
int a = 0;    // Это будет нашим индексом для массива

int main()
{
   DDRA = 0xFF;    //Порт А настроим на выход.
   a = 3;    //Например нам надо считать третий байт из массива (0xF2)
   PORTA = digit[a];    //И например отправить его (байт из массива) в Порт А
   ...............    // и т.д.
   ......
   .....
}

И без извратов. :) :)

----------
Попробуй так:

Код: Выделить всё

  while(1)
  {
        for (int j = 0; j < 10; j++)
        {
               PORTB.0 << 0;              //Врубаем ОЕ
               for(int i = 0; i <= 7; i++)
               {
                       PORTB.5 = digit[j]&a;     //
                       PORTB.7 << 1;
                       PORTB.7 << 0;    // Дергаем CLOCK
                       a = a >> 1;                 // смещаем маску
                       if (a == 0b00000000) {a = 0b10000000;} // проверяем маску
               }
               PORTB.0 << 1;              //Вырубаем ОЕ
        }     
        _delay_ms(1000);
  }

Можно ещё попробовать вынести переменные i и j в объявление глобальных переменных (до функции main() так же, как массив и переменная a). И не обязательно, чтобы они были char типа. Один фиг туда число записывается.

Re: КАРАУЛ... Массивы глючат ((

Добавлено: Сб ноя 06, 2010 08:13:04
lix
Всегда девятку выводит? _delay_ms надо в цикл по j поместить.

Re: КАРАУЛ... Массивы глючат ((

Добавлено: Сб ноя 06, 2010 08:17:40
lix
а еще тип значение массива digits лучше сделать unsigned char для экономии флеш и добавить FLASH чтобы этот массив не занимал место в оперативке.

Re: КАРАУЛ... Массивы глючат ((

Добавлено: Вс ноя 07, 2010 01:52:18
krysun
lix писал(а):Всегда девятку выводит? _delay_ms надо в цикл по j поместить.

Да нет, не всегда... Всегда разные числа (рандомные в том числе). Вопрос в чтении массива по индексу...
Примерчики почитал, сейчас запустю свою махину, проверю)
Спасибо.
ЗЫ: С делеем правы.... Кроме девятки предыдущих просто не увижу) Но... Как говорится, наступил бы еще и на эти грабли)

Re: КАРАУЛ... Массивы глючат ((

Добавлено: Вс ноя 07, 2010 02:21:03
krysun
Ничего не вышло.....
Кстати, на объявление переменной непосредственно в цикле

Код: Выделить всё

      for (int v = 0; v < 10; v++){}

пишет следующее:
Error: C:\cvavr2\my_project\tvister\1.c(94): undefined symbol 'int'
Error: C:\cvavr2\my_project\tvister\1.c(94): undefined symbol 'v'
Error: C:\cvavr2\my_project\tvister\1.c(94): undefined symbol 'v'


Благим матом, короче :(

Re: КАРАУЛ... Массивы глючат ((

Добавлено: Вс ноя 07, 2010 02:44:59
krysun
И вроде бы все правильно.
И код должен работать, и объявление, в принципе, нормальное.
А нет же.... Не пашет.
Не читает он индекс как цифру.... Не хочет выводить биты.
Паника.

Re: КАРАУЛ... Массивы глючат ((

Добавлено: Вс ноя 07, 2010 09:57:55
DrWatson
Куда данные-то выводятся (регистр сдвига? какой? TICxx? какой?) далее к каким пинам что подключено (DI - PINB.5, CLK - PINB.7, OE - PINB.0 - что за OE, как в даташите описан? где LD (LOAD и т.п.))?

Re: КАРАУЛ... Массивы глючат ((

Добавлено: Вс ноя 07, 2010 10:19:40
van_de_luxe

Код: Выделить всё

int a=0b10000000;    // масска
int digit[10]=           

лучше объяви как volatile unsigned char

Re: КАРАУЛ... Массивы глючат ((

Добавлено: Вс ноя 07, 2010 10:27:05
avreal
DX168B писал(а):И не обязательно, чтобы они были char типа. Один фиг туда число записывается.
Я даже более жёстко выражусь — «лучше, чтобы они были не char, поскольку туда число записывается».
В зависимости от контроллера/компилятора char может оказаться как знаковым, так и беззнаковым, поэтому если нужен просто «короткий» счётчик или там переменная для хранения малых чисел, то ндо явно указать знаковость — unsigned char или signed char.
Для упрощения раньше просто писались для себя typedef-ы

Код: Выделить всё

typedef unsigned char uchar;
typedef signed char schar;
По нынешним временам для унификации стоит применять стандартизованные начиная с C99 типы фиксированного размера.

Код: Выделить всё

#include <stdint.h>

uint8_t small_counter;
Даже если компилятор не соответствует стандарту С99, стоит написать свои typedef-ы для этих стандартизованных типов.

Re: КАРАУЛ... Массивы глючат ((

Добавлено: Вс ноя 07, 2010 19:28:54
DX168B
Ставь AVR Studio 4 и WinAVR. Там хоть таких багов с обьявлениями переменных нет.
На конструкцию, типа for (int i = 0; i < 10; i++) компилятор у меня не ругается.
Но ругается на такое: PORB.3 = 1;

Re: КАРАУЛ... Массивы глючат ((

Добавлено: Вс ноя 07, 2010 20:26:43
Murav
DX168B писал(а):На конструкцию, типа for (int i = 0; i < 10; i++) компилятор у меня не ругается.

Такие конструкции появились только в стандарте C99(ну и в C++ откуда собственно они и пришли), который очень многие копиляторы не поддерживают. А GCC - поддерживает.
DX168B писал(а):Но ругается на такое: PORB.3 = 1;

А это - расширение языка, которое добавлено в некоторых компиляторах. Например в CVAVR.

Re: КАРАУЛ... Массивы глючат ((

Добавлено: Вс ноя 07, 2010 23:02:10
avreal
Если бы ещё кое-что приятное из С99 в С++ пришло, было бы вообще хорошо.

Re: КАРАУЛ... Массивы глючат ((

Добавлено: Пн ноя 08, 2010 01:01:51
krysun
Хм, за ответы спасибо!

Значит, стоит забросить CVAVR и переходить на WinAVR?

Ну да ладно. Но интересует вопрос: "Как???" же все-таки объявить массив и обратится к нему по "small_counter" индексу (в подцикле for цикла for, сори за каламбур), что-бы прочитать данные?

На вопрос КУДА, и ЧЕРЕЗ ЧТО я вывожу, скажу:
mega162 -> HC244n -> HC4094 -> 3-и 7SEG индикатора.
Я поднимал тему по иному вопросу этого же девайса....
В итоге тоже ничего не вышло. 4094 подключен к mega162 по SPI.
Выводить получается, но как-то все "раком".
При:

Код: Выделить всё

SPI(7); //например

на все три индикатора выводятся эти "семерки".

Вот темка:
http://forum.radiokot.ru/viewtopic.php?f=20&t=36422
Можете ознакомится.

ps: Толкать биты по одному и таким образом зажигать нужные цыфры "без проблемм".
Использовать же SPI, или хотя-бы массив с маской - кукиш.
Вот и ломаю голову.
А дальше еще и со звуком разбиратся ((

Re: КАРАУЛ... Массивы глючат ((

Добавлено: Пн ноя 08, 2010 09:14:46
ARV
я дам "странные" советы...

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

Код: Выделить всё

#define MAXIMUM 32
unsigned char massiv[MAXIMUM];
static void send_byte(unsigned char byte); // функцию сами сделайте

int main(void){
   unsigned char i;
   for(i=0; i< MAXIMUM; i++){
      send_byte(massiv[i]);
   }
}


для выдачи отдельных битов байта посоветую использовать такой вариант маски:

Код: Выделить всё

unsigned char mask;
for(mask=0x01; mask; mask <<=1){
   // тут "накладываете" mask на передаваемый байт и т.п.
}
разумеется, сдвиг маски и ее начальное значение определяются тем, со старшего или младшего бита вы выдаете число (мой пример - с младшего)

для работы с битами не пользуйтесь фичами типа PORTB.0, а используйте метод, который работает правильно ВСЕГДА и на ЛЮБОМ компиляторе:

Код: Выделить всё

PORTB |= (1<<BIT_NUMBER); // для установки бита BIT_NUMBER
PORTB &= ~(1<<BIT_NUMBER); // для сброса бита BIT_NUMBER
if(PINB & (1<<BIT_NUMBER)) {
   // для проверки значения бита BIT_NUMBER
}


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

Re: КАРАУЛ... Массивы глючат ((

Добавлено: Пн ноя 08, 2010 09:31:06
krysun
Спасибо, чудненькие советы.
Просто кроме CVAVR ничем не пользовался....

Re: КАРАУЛ... Массивы глючат ((

Добавлено: Пн ноя 08, 2010 11:51:56
avreal
ARV писал(а):

Код: Выделить всё

#define MAXIMUM 32
unsigned char massiv[MAXIMUM];
static void send_byte(unsigned char byte); // функцию сами сделайте

int main(void){
   unsigned char i;
   for(i=0; i< MAXIMUM; i++){
      send_byte(massiv[i]);
   }
}

мне кажется, когда вы сделаете "красивым" свой код - проблема пропадет, т.к. ее причина именно (по моему мнению) в неаккуратности, что затрудняет поиск ошибки.
+1
Могу только добавить для борцунов за каждй такт и каждый байт — в примере кода выше функция send_byte объявлена static не зря. Компилятор теперь знает, что из других файлов она не вызывается, поэтому может подставить её тело по месту вызова («проинлайнить»), и не хранить рядом ещё одно тело этой функции на случай вызова снаружи. В результате размер и скорость будут таки же, как и для кода, вручную вписанного в тело цикла, но читаемость текста прораммы сильно увеличится, что, как уже говорилось, приводит к уменьшению числа ошибок и к ускорению поиска оставшихся.

Для компилятора, удволетворяющего станадрту C99 можно ещё «тонко намекнуть»

Код: Выделить всё

static inline void send_byte(unsigned char byte);

Re: КАРАУЛ... Массивы глючат ((

Добавлено: Сб ноя 13, 2010 23:35:54
krysun
Проблема решилась. Ваши примеры и советы работают 100%. Это у меня лыжи не едут.
В mega162 в FUSE-ах было выставлено M161C=0 (режим совместимости с mega161 МК).
При вызове SPI("что-то") несколько раз (или любой другой функции вывода), зацикливался только 1-й вызов.
Потому и выводились на все индикаторы одинаковые цыфры.

Как FUSE снял, так сразу все и заработало.

Возьмите на заметку.

Спасибо большое за помощь! :beer:

Ах, да. С массива тоже все "ОК". (И все из-за того же FUSE-а)