реклама на сайте
подробности

 
 
3 страниц V   1 2 3 >  
Reply to this topicStart new topic
> Вопрос по битовым операциям в AtmelStudio
endasm
сообщение Aug 17 2012, 17:25
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 40
Регистрация: 9-07-12
Пользователь №: 72 673



Здравствуйте, несколько месяцев назад пересел с CodeVisionAVR на AtmelStudio, и соответственно возникло непонимание как работать с портами и выводить в них определенные биты из имеющегося байта и т.д.
Вот пример кода который был раньше написал в CodeVisionAVR : (Это функция вывода двоичного числа в регистр последовательного сдвига 74HC595)
Код
unsigned char bin_digits[10]=
                             {
                                 0b0000,    //0
                                 0b1000,    //1
                                 0b0100,    //2
                                 0b1100,    //3
                                 0b0010,    //4
                                 0b1010,    //5
                                 0b0110,    //6
                                 0b1110,    //7
                                 0b0001,    //8
                                 0b1001,    //9
                             };

void HC595_write(unsigned char d0, unsigned char d1, unsigned char d2, unsigned char d3, unsigned char d4, unsigned char d5)   //функция записи данных в регистр 74HC595 (используя PORTD.0=DS, PORTD.1=SH_CP, PORTD.2=ST_CP)
{
    unsigned char i,j;
    unsigned char dig[6];
    dig[0]=d0;
    dig[1]=d1;
    dig[2]=d2;
    dig[3]=d3;
    dig[4]=d4;
    dig[5]=d5;
    for(j=0;j<=5;j++)
    {
        for(i=0; i<=3; i++)                     //цикл для последовательного вывода 4 бит данных из массива
        {
            PORTD.0=bin_digits[dig[j]] & (1<<i);//выводим "текущий бит" в линию DS
            PORTD.1=1;                          //выводим "0" в линию SH_CP
            PORTD.1=0;                          //выводим "1" в линию SH_CP - считываем бит на входе регистра (считывание происходит по переднему фронту импульса на SH_CP)
        }
    }
    PORTD.2=1;                                  //выводим "1" в линию ST_CP - "защелкиваем данные" ("защелкивание" происходит по переднему фронту импульса на ST_CP)
    PORTD.2=0;                                  //выводим "0" в линию ST_CP
}


Я немного перепилил код для AtmelStudio:
Код
#define SH_CP 1
#define ST_CP 2
#define DS 0
unsigned char bin_digits[10]=
{
    0b0000,    //0
    0b1000,    //1
    0b0100,    //2
    0b1100,    //3
    0b0010,    //4
    0b1010,    //5
    0b0110,    //6
    0b1110,    //7
    0b0001,    //8
    0b1001,    //9
};

void HC595_write(unsigned char d0, unsigned char d1, unsigned char d2, unsigned char d3, unsigned char d4, unsigned char d5)   //функция записи данных в регистр 74HC595 (используя PORTD.0=DS, PORTD.1=SH_CP, PORTD.2=ST_CP)
{
    unsigned char i,j;
    unsigned char dig[6];
    dig[0]=d0;
    dig[1]=d1;
    dig[2]=d2;
    dig[3]=d3;
    dig[4]=d4;
    dig[5]=d5;
    for(j=0;j<=5;j++)
    {
        for(i=0; i<4; i++)                                    //цикл для последовательного вывода 4 бит данных из массива
        {
            PORTD|=(bin_digits[dig[j]] & (1<<i))<<DS;        //выводим "текущий бит" в линию DS
            PORTD&=(0<<SH_CP);                                //выводим "0" в линию SH_CP
            PORTD|=(1<<SH_CP);                                //выводим "1" в линию SH_CP - считываем бит на входе регистра (считывание происходит по переднему фронту импульса на SH_CP)
        }
    }
    PORTD|=(1<<ST_CP);                                        //выводим "1" в линию ST_CP - "защелкиваем данные" ("защелкивание" происходит по переднему фронту импульса на ST_CP)
    PORTD&=(0<<ST_CP);                                        //выводим "0" в линию ST_CP
}


И эта функция перестала работать. Я думаю что вся проблема в этой "PORTD|=(bin_digits[dig[j]] & (1<<i))<<DS;" строке. Вопрос - как в AtmelStudio вывести в конкретный бит порта один определенный бит из заданного ранее байта (в данном случае полу-байта, так как в массиве "bin_digits[10]" каждое число передается четырьмя битами) ?

Сообщение отредактировал endasm - Aug 17 2012, 17:26
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Aug 17 2012, 17:38
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(endasm @ Aug 17 2012, 20:25) *
Вопрос - как в AtmelStudio вывести в конкретный бит порта один определенный бит из заданного ранее байта?


Например так:
Код
void OutBitFromByte(unsigned char out_bit_num, unsigned char input_bit_num, unsigned char input_byte)
{
unsigned char port=PORTA;
port&=~(1<<out_bit_num);
if (input_byte&(1<<input_bit_num))
    port|=(1<<out_bit_num);
PORTA=port;
}

Можно еще через битовые поля в структурах.
Go to the top of the page
 
+Quote Post
endasm
сообщение Aug 17 2012, 18:55
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 40
Регистрация: 9-07-12
Пользователь №: 72 673



Не заработало. Что я написал не правильно?((
Код
#define SH_CP 1
#define ST_CP 2
#define DS 0
unsigned char bin_digits[10]=
{
    0b0000,    //0
    0b1000,    //1
    0b0100,    //2
    0b1100,    //3
    0b0010,    //4
    0b1010,    //5
    0b0110,    //6
    0b1110,    //7
    0b0001,    //8
    0b1001,    //9
};
void OutBitFromByte(unsigned char out_bit_num, unsigned char input_bit_num, unsigned char input_byte)
{
    unsigned char port=PORTD;
    port&=~(1<<out_bit_num);
    if (input_byte&(1<<input_bit_num))
    port|=(1<<out_bit_num);
    PORTD=port;
void HC595_write(unsigned char d0, unsigned char d1, unsigned char d2, unsigned char d3, unsigned char d4, unsigned char d5)   //функция записи данных в регистр 74HC595 (используя PORTD.0=DS, PORTD.1=SH_CP, PORTD.2=ST_CP)
{
    unsigned char i,j;
    unsigned char dig[6];
    dig[0]=d0;
    dig[1]=d1;
    dig[2]=d2;
    dig[3]=d3;
    dig[4]=d4;
    dig[5]=d5;
    for(j=0;j<=5;j++)
    {
        for(i=0; i<4; i++)                                    //цикл для последовательного вывода 4 бит данных из массива
        {
            OutBitFromByte(DS,i,bin_digits[dig[j]]);
            //PORTD|=(bin_digits[dig[j]] & (1<<i))<<PORTD0;        //выводим "текущий бит" в линию DS
            PORTD&=(0<<SH_CP);                                //выводим "0" в линию SH_CP
            PORTD|=(1<<SH_CP);                                //выводим "1" в линию SH_CP - считываем бит на входе регистра (считывание происходит по переднему фронту импульса на SH_CP)
        }
    }
    PORTD|=(1<<ST_CP);                                        //выводим "1" в линию ST_CP - "защелкиваем данные" ("защелкивание" происходит по переднему фронту импульса на ST_CP)
    PORTD&=(0<<ST_CP);                                        //выводим "0" в линию ST_CP
}
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Aug 17 2012, 19:07
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(endasm @ Aug 17 2012, 21:55) *
Не заработало. Что я написал не правильно?


Как минимум это:
Код
PORTD&=(0<<SH_CP);                                //выводим "0" в линию SH_CP

Так вы просто все линии порта обнуляете.

Попробуйте так:
Код
PORTD&=~(1<<SH_CP);                                //выводим "0" в линию SH_CP
Go to the top of the page
 
+Quote Post
C2000
сообщение Aug 17 2012, 19:11
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 321
Регистрация: 20-01-11
Из: г. Мытищи
Пользователь №: 62 366



Цитата(_Артём_ @ Aug 17 2012, 23:07) *
Как минимум это:
Код
PORTD&=(0<<SH_CP);                                //выводим "0" в линию SH_CP


Попробуйте так:
Код
PORTD&=~(1<<SH_CP);                                //выводим "0" в линию SH_CP


Сдвиг нуля это конечно оригинальная(бестолковая) операция!
Go to the top of the page
 
+Quote Post
endasm
сообщение Aug 17 2012, 19:19
Сообщение #6


Участник
*

Группа: Участник
Сообщений: 40
Регистрация: 9-07-12
Пользователь №: 72 673



Почему бестолковая, там же 1 была, вот на место той единицы "двигаем" ноль. Так всегда делал =)

Цитата(_Артём_ @ Aug 17 2012, 22:07) *
Как минимум это:
Код
PORTD&=(0<<SH_CP);                                //выводим "0" в линию SH_CP

Так вы просто все линии порта обнуляете.

Попробуйте так:
Код
PORTD&=~(1<<SH_CP);                                //выводим "0" в линию SH_CP

Нет не все, так как я сдвигаю 0 на значение "SH_CP" - тоесть на 1, и в итоге на втором бите порта имеем "0".
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Aug 17 2012, 19:57
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(endasm @ Aug 17 2012, 22:19) *
Почему бестолковая, там же 1 была, вот на место той единицы "двигаем" ноль.

Чо, звучит логично - задвинули на нужное место ноль.

Цитата(endasm @ Aug 17 2012, 22:19) *
Так всегда делал =)

И что работало?
Это новое слово в науке и технике!

Цитата(endasm @ Aug 17 2012, 22:19) *
Нет не все, так как я сдвигаю 0 на значение "SH_CP" - тоесть на 1, и в итоге на втором бите порта имеем "0".

Все несколько не так происходит: АВР не может задвигать врегистр порта бита.
Происходит так:
1)в какойто регистр (R0-R32) пишется число 0<<SH_CP, то есть ноль.
2)потом какой-нибудь командой (например STS ADD(PORTD),R16) регистр копируется в PORT.

Цитата(endasm @ Aug 17 2012, 22:19) *
Нет не все, так как я сдвигаю 0 на значение "SH_CP" - тоесть на 1, и в итоге на втором бите порта имеем "0".

У вас где-то такое работало? Приведите пример, что ли.
Может это PIC был? Хотя и там наврядли.
Go to the top of the page
 
+Quote Post
endasm
сообщение Aug 17 2012, 20:15
Сообщение #8


Участник
*

Группа: Участник
Сообщений: 40
Регистрация: 9-07-12
Пользователь №: 72 673



Хм, вы заставили меня задуматься, сейчас ещё раз всё перепроверю.

Да ладно вам, всё работает. Вот например кусок такой мигает светодиодом:
Код
#define SH_CP 0

int main(void)
{    
    DDRD=0b11111111;
    while(1)
    {
        PORTD|=(1<<SH_CP);
        _delay_ms(1000);
        PORTD&=(0<<SH_CP);
        _delay_ms(1000);
    }
}

Всё прекрасно сдвигается.

Сообщение отредактировал endasm - Aug 17 2012, 20:16
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Aug 17 2012, 20:30
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(endasm @ Aug 17 2012, 23:15) *
Да ладно вам, всё работает.

Шутим?

Цитата(endasm @ Aug 17 2012, 23:15) *
Вот например кусок такой мигает светодиодом:
Код
#define SH_CP 0

int main(void)
{    
    DDRD=0b11111111;
    while(1)
    {
        PORTD|=(1<<SH_CP);
        _delay_ms(1000);
        PORTD&=(0<<SH_CP);
        _delay_ms(1000);
    }
}

Если светодиод на порту PD0, то да, согласен, будет мигать. И что?

Цитата(endasm @ Aug 17 2012, 23:15) *
Всё прекрасно сдвигается.

Это не сдвиг.
Код:
Код
PORTD&=(0<<SH_CP);

можно понять как PORTD=PORTD&0;
Остальные биты регистра порта обнуляются тоже.
Посмотрите дизассемблером, если не верите.
Go to the top of the page
 
+Quote Post
endasm
сообщение Aug 17 2012, 20:38
Сообщение #10


Участник
*

Группа: Участник
Сообщений: 40
Регистрация: 9-07-12
Пользователь №: 72 673



Цитата(_Артём_ @ Aug 17 2012, 23:30) *
Шутим?


Если светодиод на порту PD0, то да, согласен, будет мигать. И что?


Это не сдвиг.
Код:
Код
PORTD&=(0<<SH_CP);

можно понять как PORTD=PORTD&0;
Остальные биты регистра порта обнуляются тоже.
Посмотрите дизассемблером, если не верите.

Аа, Вы абсолютно правы, только что проверил. Просто от работы в CodeVision с его PORTD.0 и т.д совсем я думать перестал. Сейчас всё поправлю и снова испробую.
Go to the top of the page
 
+Quote Post
=GM=
сообщение Aug 17 2012, 21:11
Сообщение #11


Ambidexter
*****

Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282



Можно так написать
Код
for(i=0;i<6;i++)
{
temp=dig[i];                          //temporary
for(j=0;j<4;j++)
{
  if(temp & 0x01) PORTD |= _BV(DS)    //DS=1
  else PORTD &= ~_BV(DS);             //or DS=0
  PORTD |= _BV(SH_CP);                //SH_CP=1        
  PORTD &=~_BV(SH_CP);                //SH_CP=0
  temp >>=1;                          //shift right
}
}


тогда массив bin_digits[10] не нужен


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
endasm
сообщение Aug 17 2012, 21:28
Сообщение #12


Участник
*

Группа: Участник
Сообщений: 40
Регистрация: 9-07-12
Пользователь №: 72 673



Да, исправил и всё работает. Функция выводит информацию в 74HC595. Но вот с остальным кодом тоже проблемы. Вообще-то я никак не доделаю часы, отображающие время при помощи газоразрядных ламп.
Схему и фотографии прилагаю. Написал весь код для них, но в итоге на лампы выводятся на первый взгляд случайные цифры, некоторые гаснут периодически.
Также прикрепил весь код для них. Может кто приблизительно скажет что может быть не так ? Код не очень большой.
http://dl.dropbox.com/u/42063417/IMG_0182.JPG
http://dl.dropbox.com/u/42063417/IMG_0184.JPG

Думаю что ошибка всё-таки заключается в программном способе реализации протокола I2C.
Эскизы прикрепленных изображений
Прикрепленное изображение
 

Прикрепленные файлы
Прикрепленный файл  Test_I2C.rar ( 44.29 килобайт ) Кол-во скачиваний: 21
 
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Aug 17 2012, 22:07
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(endasm @ Aug 18 2012, 00:28) *
Думаю что ошибка всё-таки заключается в программном способе реализации протокола I2C.

Наверняка. И зачем его вообше делать программным, если есть вполне ребочий аппаратный?

Код
void i2c_start(void)                                        //Функция генерации стартового условия
{
    DDRC|=(1<<SDA);                                            //Для I2C используем PORTC
    DDRC|=(1<<SCL);
    
    PORTC=(1<<SDA)|(1<<SCL);
    asm("nop");
    PORTC&=~(1<<SDA);
    asm("nop");
    PORTC&=~(1<<SCL);
}


Может, я ошибаюсь, но мне кажется что в i2с вывод единицы в порт не должен использоваться, только "0" и "Z".
Не знаю какая у вас тактовая, но есть такая особенность i2c - slave может задерживать передачу бита, удерживая SCL в 0. А в вашей программе биты тактируются как в spi, не глядя на состояние шины.
Go to the top of the page
 
+Quote Post
smk
сообщение Aug 18 2012, 06:12
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



Ксть документ по написанию кода для АВР - "AVR035". Поищите, будет очень Вам в помощь.


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post
endasm
сообщение Aug 18 2012, 06:13
Сообщение #15


Участник
*

Группа: Участник
Сообщений: 40
Регистрация: 9-07-12
Пользователь №: 72 673



Ну в I2C же только мастер тактирует ни смотря ни на что. И вот в один момент времени когда и SDA и SCL подняты - SDA опускается к нулю - стартовое условие (и небольшая задержка), потом и SCL опускается в 0.
Go to the top of the page
 
+Quote Post
ILYAUL
сообщение Aug 18 2012, 06:34
Сообщение #16


Профессионал
*****

Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339



А причём здесь , кто чего тактирует. Шина I2C использует несколько другой принцип общения с подчинёными устройствами. Вы с ним знакомились?


--------------------
Закон Мерфи:

Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
Go to the top of the page
 
+Quote Post
endasm
сообщение Aug 18 2012, 06:37
Сообщение #17


Участник
*

Группа: Участник
Сообщений: 40
Регистрация: 9-07-12
Пользователь №: 72 673



Цитата(=GM= @ Aug 18 2012, 00:11) *
Можно так написать
Код
for(i=0;i<6;i++)
{
temp=dig[i];                          //temporary
for(j=0;j<4;j++)
{
  if(temp & 0x01) PORTD |= _BV(DS)    //DS=1
  else PORTD &= ~_BV(DS);             //or DS=0
  PORTD |= _BV(SH_CP);                //SH_CP=1        
  PORTD &=~_BV(SH_CP);                //SH_CP=0
  temp >>=1;                          //shift right
}
}


тогда массив bin_digits[10] не нужен

ого, круто получилось )). Только я не пойму одного, в "temp" хранится десятичное число. Как же с ним производить такие операции можно? Разве не нужно в двоичный вид переводить?
Go to the top of the page
 
+Quote Post
ILYAUL
сообщение Aug 18 2012, 06:44
Сообщение #18


Профессионал
*****

Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339



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


--------------------
Закон Мерфи:

Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
Go to the top of the page
 
+Quote Post
endasm
сообщение Aug 18 2012, 06:46
Сообщение #19


Участник
*

Группа: Участник
Сообщений: 40
Регистрация: 9-07-12
Пользователь №: 72 673



Программный I2C был вынужденной мерой так как аппаратная его реализация мне сложновата.
Go to the top of the page
 
+Quote Post
ILYAUL
сообщение Aug 18 2012, 06:54
Сообщение #20


Профессионал
*****

Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339



Цитата(endasm @ Aug 18 2012, 10:46) *
Программный I2C был вынужденной мерой так как аппаратная его реализация мне сложновата.

Вы пишите на С , библиотек аппаратного I2C ...... куча. Только своё подставляй


--------------------
Закон Мерфи:

Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Aug 18 2012, 08:03
Сообщение #21


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (_Артём_ @ Aug 18 2012, 01:07) *
Может, я ошибаюсь, но мне кажется что в i2с вывод единицы в порт не должен использоваться, только "0" и "Z".
Именно. Автор наступил на грабли, по которым прошлись почти все создатели программного I2C. Вот в этой теме подробное объяснение. А вот еще одна на ту же тему.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
klop
сообщение Aug 19 2012, 07:26
Сообщение #22


Местный
***

Группа: Свой
Сообщений: 433
Регистрация: 28-02-06
Пользователь №: 14 788



Насколько я помню написание аппаратного I2C - там слайв может зтягивать клок(тянуть его в ноль). Это не везде используется но в стандарте есть.
Go to the top of the page
 
+Quote Post
endasm
сообщение Aug 20 2012, 11:41
Сообщение #23


Участник
*

Группа: Участник
Сообщений: 40
Регистрация: 9-07-12
Пользователь №: 72 673



Вот сделал аппаратную реализацию TWI. Но на лампах одни нули отображаются, при попытке прогнать прогу в AVR симуляторе он вообще зависает(. Где может быть ошибка?
PS: на осциллографе смотрю SDA и SCL - они всегда подняты.
Код
unsigned char twi(unsigned char action)
{
    switch(action)
    {
        case TWI_START:
        case TWI_RESTART:
        TWCR = _BV(TWSTA) | _BV(TWEN) | _BV(TWINT) | _BV(TWIE);
        break;
        case TWI_STOP:
        TWCR = _BV(TWSTO) | _BV(TWEN) | _BV(TWINT) | _BV(TWIE);
        break;
        case TWI_TRANSMIT:
        TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWIE);
        break;
        case TWI_RECEIVE_ACK:
        TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWEA)| _BV(TWIE);
        break;
        case TWI_RECEIVE_NACK:
        TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWIE);
        break;
    }
    if(action != TWI_STOP)while (!(TWCR & _BV(TWINT)));
    return (TWSR & 0b11111000);
}

unsigned char i2c_read(unsigned char adr_slave, unsigned char adr_byte)
{
    unsigned char readed_byte;
    twi(TWI_START);                                            //формируем сигнал START
    TWDR=adr_slave;                                            //загружаем адрес slave на запись
    twi(TWI_TRANSMIT);                                        //передаем адрес
    TWDR=adr_byte;                                            //загружаем адрес байта
    twi(TWI_TRANSMIT);                                        //передаем
    twi(TWI_RESTART);                                        //формируем рестарт (RESTART)
    TWDR=adr_slave|1;                                        //загружаем адрес DS1307 на чтение
    twi(TWI_TRANSMIT);                                        //передаем
    twi(TWI_RECEIVE_ACK);                                    //получаем подтверждение от slave
    readed_byte=TWDR;                                        //в "readed_byte" записываем принятый байт
    twi(TWI_RECEIVE_NACK);                                    //после чтения байта формируем NACK - больше данные не нужны
    twi(TWI_STOP);                                            //формируем сигнал STOP
    return readed_byte;
}

void i2c_send(unsigned char adr_slave, unsigned char adr_byte, unsigned char data_byte)
{
    twi(TWI_START);                                            //формируем сигнал START
    TWDR=adr_slave;                                            //загружаем адрес slave на запись
    twi(TWI_TRANSMIT);                                        //передаем адрес
    TWDR=adr_byte;                                            //загружаем адрес байта
    twi(TWI_TRANSMIT);                                        //передаем
    twi(TWI_RECEIVE_ACK);                                    //получаем подтверждение от slave
    TWDR=data_byte;                                            //загружаем байт данных
    twi(TWI_TRANSMIT);                                        //передаем
    twi(TWI_RECEIVE_ACK);                                    //
    twi(TWI_STOP);                                            //формируем сигнал STOP
}


Сообщение отредактировал endasm - Aug 20 2012, 12:52
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Aug 20 2012, 12:38
Сообщение #24


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(endasm @ Aug 20 2012, 14:41) *
при попытке прогнать прогу в AVR стимуляторе он вообще зависает(.

А вас JtagJci или AVRDragon? Тогда значит что-то неправильно.
Если просто симулятор, то чего вы хотите от него? Эмуляции вашей микросхемы?

Неправильно может быть вот что: значения прочитанные из TWSR нужно обрабатывать, а не тупо слать байты, невзирая на состояние шины.
Go to the top of the page
 
+Quote Post
endasm
сообщение Aug 20 2012, 13:11
Сообщение #25


Участник
*

Группа: Участник
Сообщений: 40
Регистрация: 9-07-12
Пользователь №: 72 673



Я хочу симуляции программы, что бы можно было видеть на каких выводах что и когда происходит.
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Aug 20 2012, 13:22
Сообщение #26


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(endasm @ Aug 20 2012, 16:11) *
Я хочу симуляции программы

Хотеть не вредно.
Пишите симулятор который поддерживает TWI или Может какой протеус симулирует что-нибудь...

Цитата(endasm @ Aug 20 2012, 16:11) *
что бы можно было видеть на каких выводах что и когда происходит.

Тут нужен логический анализатор или что-то навроде того.
Go to the top of the page
 
+Quote Post
endasm
сообщение Aug 20 2012, 13:40
Сообщение #27


Участник
*

Группа: Участник
Сообщений: 40
Регистрация: 9-07-12
Пользователь №: 72 673



Цитата(_Артём_ @ Aug 20 2012, 16:22) *
Хотеть не вредно.
Пишите симулятор который поддерживает TWI или Может какой протеус симулирует что-нибудь...


Тут нужен логический анализатор или что-то навроде того.

Я не знал что симулятор в Atmel Studio не работает с TWI. Просто там даже регистры TWI просматривать можно и всё такое.

Сообщение отредактировал endasm - Aug 20 2012, 13:41
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Aug 20 2012, 14:04
Сообщение #28


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(endasm @ Aug 20 2012, 16:40) *
Я не знал что симулятор в Atmel Studio не работает с TWI.

Он много чего не симулирует.
Могу дать вам простой совет: посмотрите на реализацию TWI master от атмела и возможно ошибки найдутся и вопросы отпадут.
Go to the top of the page
 
+Quote Post
ILYAUL
сообщение Aug 20 2012, 19:17
Сообщение #29


Профессионал
*****

Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339



Цитата(endasm @ Aug 20 2012, 17:11) *
Я хочу симуляции программы, что бы можно было видеть на каких выводах что и когда происходит.

Тогда все биты TWSR устанавливайте сами , ручками


--------------------
Закон Мерфи:

Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Aug 20 2012, 19:54
Сообщение #30


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(ILYAUL @ Aug 20 2012, 22:17) *
Тогда все биты TWSR устанавливайте сами , ручками

Так конечно можно пропихнуть i2c-пакет через симулятор, но чем это поможет? Потом также гадать почему не работает?

Мне кажется более разумным такое:
так как есть индикатор, то можно его задействовать для вывода отладочной информации:

Код
    unsigned char i2c_debug_log[DEBUG_BUFFER_SIZE];
    i2c_debug_log[0]=twi(TWI_START);            //формируем сигнал START
    TWDR=adr_slave;                    //загружаем адрес slave на запись
    i2c_debug_log[1]=twi(TWI_TRANSMIT);        //передаем адрес
    TWDR=adr_byte;                    //загружаем адрес байта
    i2c_debug_log[2]=twi(TWI_TRANSMIT);        //передаем

.....
    // вывод на индикатор
    for (i=0; i<DEBUG_BUFFER_SIZE; i++) {
        OutToIndicator(debug_log[i]);
        delay_ms(3000);
    }
    delay_ms(10000);


Лучше конечно ComPort подходит, но тоже вариант.
Go to the top of the page
 
+Quote Post
ILYAUL
сообщение Aug 20 2012, 20:43
Сообщение #31


Профессионал
*****

Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339



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


--------------------
Закон Мерфи:

Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Aug 20 2012, 21:05
Сообщение #32


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(ILYAUL @ Aug 20 2012, 23:43) *
Симмулятор - это почти всегда зло, но математику он помогает отлаживать.

Циклы посчитать, это - да, лучше в симуляторе. (Интересно он их без ошибок считает?)
В JTAG-е жаль нет счётчика циклов, очень бы не помешала такая фича.
Go to the top of the page
 
+Quote Post
endasm
сообщение Aug 20 2012, 23:10
Сообщение #33


Участник
*

Группа: Участник
Сообщений: 40
Регистрация: 9-07-12
Пользователь №: 72 673



Ура, всё заработало - часы исправно идут. Не хватало лишь вот такой строчки в функции вывода чисел на лампы "DDRD=(1<<DS)|(1<<SH_CP)|(1<<ST_CP);" :D
Вот весь код:
Код
#include <avr/io.h>
#include <util/twi.h>

#define DS 0
#define SH_CP 1
#define ST_CP 2

#define adr_ds1307    0b11010000                                //адресс на запись в ds1307

#define TWI_START            0
#define TWI_RESTART         1
#define TWI_STOP            2
#define TWI_TRANSMIT        3
#define TWI_RECEIVE_ACK     4
#define TWI_RECEIVE_NACK    5

unsigned char bin_digits[10]=
{
    0b0000,    //0
    0b1000,    //1
    0b0100,    //2
    0b1100,    //3
    0b0010,    //4
    0b1010,    //5
    0b0110,    //6
    0b1110,    //7
    0b0001,    //8
    0b1001,    //9
};

unsigned char twi(unsigned char action)
{
    switch(action)
    {
        case TWI_START:
        case TWI_RESTART:
        TWCR = (1<<TWSTA) | (1<<TWEN) | (1<<TWINT) | (1<<TWIE);
        break;
        case TWI_STOP:
        TWCR = (1<<TWSTO) | (1<<TWEN) | (1<<TWINT) | (1<<TWIE);
        break;
        case TWI_TRANSMIT:
        TWCR = (1<<TWEN) | (1<<TWINT) | (1<<TWIE);
        break;
        case TWI_RECEIVE_ACK:
        TWCR = (1<<TWEN) | (1<<TWINT) | (1<<TWEA)| (1<<TWIE);
        break;
        case TWI_RECEIVE_NACK:
        TWCR = (1<<TWEN) | (1<<TWINT) | (1<<TWIE);
        break;
    }
    if(action != TWI_STOP) while (!(TWCR & (1<<TWINT)));
    return (TWSR & 0b11111000);
}

unsigned char i2c_read(unsigned char adr_slave, unsigned char adr_byte)
{
    unsigned char readed_byte;
    twi(TWI_START);                                            //формируем сигнал START
    TWDR=adr_slave;                                            //загружаем адрес slave на запись
    twi(TWI_TRANSMIT);                                        //передаем адрес
    TWDR=adr_byte;                                            //загружаем адрес байта
    twi(TWI_TRANSMIT);                                        //передаем
    twi(TWI_RESTART);                                        //формируем рестарт (RESTART)
    TWDR=adr_slave|1;                                        //загружаем адрес DS1307 на чтение
    twi(TWI_TRANSMIT);                                        //передаем
    twi(TWI_RECEIVE_ACK);                                    //получаем подтверждение от slave
    readed_byte=TWDR;                                        //в "readed_byte" записываем принятый байт
    twi(TWI_RECEIVE_NACK);                                    //после чтения байта формируем NACK - больше данные не нужны
    twi(TWI_STOP);                                            //формируем сигнал STOP
    return readed_byte;
}

void i2c_send(unsigned char adr_slave, unsigned char adr_byte, unsigned char data_byte)
{
    twi(TWI_START);                                            //формируем сигнал START
    TWDR=adr_slave;                                            //загружаем адрес slave на запись
    twi(TWI_TRANSMIT);                                        //передаем адрес
    TWDR=adr_byte;                                            //загружаем адрес байта
    twi(TWI_TRANSMIT);                                        //передаем
    twi(TWI_RECEIVE_ACK);                                    //получаем подтверждение от slave
    TWDR=data_byte;                                            //загружаем байт данных
    twi(TWI_TRANSMIT);                                        //передаем
    twi(TWI_RECEIVE_ACK);                                    //
    twi(TWI_STOP);                                            //формируем сигнал STOP
}

void OutBitFromByte(unsigned char out_bit_num, unsigned char input_bit_num, unsigned char input_byte)
{
    unsigned char port=PORTD;
    port&=~(1<<out_bit_num);
    if (input_byte&(1<<input_bit_num))
    port|=(1<<out_bit_num);
    PORTD=port;
}

//===========================================функция записи данных в регистр 74HC595===========================================

void HC595_write(unsigned char d0, unsigned char d1, unsigned char d2, unsigned char d3, unsigned char d4, unsigned char d5)
{
    DDRD=(1<<DS)|(1<<SH_CP)|(1<<ST_CP);
    unsigned char i,j;
    unsigned char dig[6];
    dig[0]=d0;
    dig[1]=d1;
    dig[2]=d2;
    dig[3]=d3;
    dig[4]=d4;
    dig[5]=d5;
    for(j=0;j<=5;j++)
    {
        for(i=0; i<4; i++)                                    //цикл для последовательного вывода 4 бит данных из массива
        {
            OutBitFromByte(DS,i,bin_digits[dig[j]]);
            PORTD&=~(1<<SH_CP);                                //выводим "0" в линию SH_CP
            PORTD|=(1<<SH_CP);                                //выводим "1" в линию SH_CP - считываем бит на входе регистра
        }
    }
    PORTD|=(1<<ST_CP);                                        //выводим "1" в линию ST_CP - "защелкиваем данные"
    PORTD&=~(1<<ST_CP);                                        //выводим "0" в линию ST_CP
}

int main(void)
{
    TWSR &= ~(1<<TWPS0)|(1<<TWPS1);                            //биты предделителя
    TWBR=114;                                                //Настраиваем частоту шины
                                                            //(при 8MHz F_CPU получаем 8000000/(2*(16+114)) = 32kHz)
    unsigned char h10, h1, m10, m1, s10, s1;                //объявляем переменной для хранения значений часов, минут, секунд
    unsigned char temp_byte;
            
    temp_byte=i2c_read(adr_ds1307, 0x00);
    if(temp_byte & 0b10000000)                                //проверяем 8-ой бит (если он "CH" = 1 - значит часы не запущены)
    {
        i2c_send(adr_ds1307,0x00,0b00000000);                //запускаем часы DS1307
    }
    i2c_send(adr_ds1307,0x07,0b0010000);                    //задаём частоту генерации на SQW = 1 Hz
    while(1)
    {
        //============секунды==================
        temp_byte=i2c_read(adr_ds1307, 0x00);                //считываем байт значений секунд
        s1=    (temp_byte & 0b00001111);                        //выделяем значение единиц секунд
        s10=(temp_byte & 0b11110000)>>4;                    //выделяем значение десятков секунд
        //============минуты===================
        temp_byte=i2c_read(adr_ds1307, 0x01);                //считываем байт значений минут
        m1=    (temp_byte & 0b00001111);
        m10=(temp_byte & 0b11110000)>>4;
        //============часы=====================
        temp_byte=i2c_read(adr_ds1307, 0x02);                //считываем байт значений часов
        h1=    (temp_byte & 0b00001111);
        h10=(temp_byte & 0b11110000)>>4;

        HC595_write(h10,h1,m10,m1,s10,s1);                    //записываем данные в регистры 74HC595
    }
}
Go to the top of the page
 
+Quote Post

3 страниц V   1 2 3 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 12:12
Рейтинг@Mail.ru


Страница сгенерированна за 0.0176 секунд с 7
ELECTRONIX ©2004-2016