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

Еще раз про DS1307

Добавлено: Пн фев 11, 2013 20:14:15
Aselicon
Добрый вечер!
Проблема известная, DS1307 кидает цифру 165 вместо того или иного параметра. Интернеты курил,дш тоже. Ни одно из найденных мной решений, не подошло. Рullup менял от 1,5к до 5к. Питание жестко 5в, не проседает.
Отладку провожу при выводе секунд на сегментник.
Был сначала такой момент: подключал TWI к ножкам тактирования МК (кстати Мк attiny2313a), запускался от внутреннего 8мгц. Ничего не увидел такого чтоб можно было сказать работает или нет прыгали значения 165 85 и тд.
решил сделать по другому: Сегменты подключил на эти пины, а сам TWI, как по ДШ тиньки к PB7,PB5.
Делаю опрос часов около 2раз в сек. Через раз приходит 165, но часы тикают, настоящие значения приходят также.
Под спойлером исходник, схема стандартная.
Спойлер#define digit4 PORTD.0
#define digit1 PORTD.4
#define digit2 PORTD.5
#define digit3 PORTD.6
#define BUZZ PORTD.1 //Нагрузка
#define butt PIND.3 //Кнопоньки
#define CYCLE_PRESS 15
#define BUZZ_TIME 4

#include <tiny2313a.h>
#include <i2c.h>
#include <ds1307.h>
unsigned char BitPoint[]={0,0,0,0}; //Управление точками
unsigned char digit_out[4],cur_dig; //переменные для работы с 7LED
unsigned int indication; //переменная для хранения дисплейных чисел
unsigned char s,m,h; // Сек мин час
unsigned char i,j;
unsigned char SET;
bit BUT1,BUT2,BUT3,blink,set_but_bit;

flash char digits[] = { //создаём массив с цифрами
0b00000011, //0
0b10011111, //1
0b00100101, //2
0b00001101, //3
0b10011001, //4 01011111
0b01001001, //5
0b01000001, //6
0b00011111, //7
0b00000001, //8
0b00001001, //9
0b11111101, //-(minus) 10
0b11111111 // ничего не горит 11
};
void recoding(void) //функция для перекодировки в dec
{ digit_out[3]=indication%10; //Делим на 10 целое число в масив 4-разряд
indication=indication/10; //Оставляем 2 разряда
digit_out[1]=indication%10; //Делим на 10 целое число в масив 3-разряд
indication=indication/10; //Оставляем 2 разряда
digit_out[0]=indication%10; //Делим на 10 остаток в масив 2-разряд
if (indication/10!=0){digit_out[2]=indication/10;} else {digit_out[2]=11;} //тысячи

}


interrupt [TIM0_OVF] void timer0_ovf_isr(void) //ПРЕРЫВАНИЕт1 перебор разрядов
{
PORTB=0xFF; //чтобы предотвратить эффект “тени” на соседних индикаторах
PORTA=0xFF;
switch (cur_dig)
{

case 3:{BUT3=!butt; digit4=0; digit3=1; break;}; //подаём питание на разряд
case 2:{BUT1=!butt; digit3=0; digit1=1; break;}; //подаём питание на разряд
case 1:{BUT2=!butt; digit1=0; digit2=1; break;}; //подаём питание на разряд
case 0:{ digit2=0; digit4=1; break;}; //подаём питание на разряд
}


PORTB=digits[digit_out[cur_dig]] ^ (BitPoint[cur_dig]); //выводим с каждым срабатыванием таймера число из

PORTA.0=((digits[digit_out[cur_dig]])&(0b00100000))>>5;
PORTA.1= (digits[digit_out[cur_dig]])>>7;


cur_dig++; //И прикручиваем точки чтобы с ними работать потом
if(cur_dig>=4) cur_dig=0;

}

interrupt [TIM1_COMPA] void timer1_compa_isr(void) //ПРЕРЫВАНИЕт1 перебор разрядов 1/10 sek
{
//s++;
blink++;
rtc_get_time(&h,&m,&s);

TCNT1H=0x00;
TCNT1L=0x00;
}
void main(void)
{
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

PORTB=0xFF;
DDRB=0xFF;

PORTA=0xFF;
DDRA=0xFF;

DDRD=0x73;

TCCR0B=0x03; //04
TCCR1B=0x0C;
OCR1AH=0x1A; // 7A
OCR1AL=0x12; // 12

TIMSK=0x42;



i2c_init();
rtc_init(0,1,0);
rtc_write(0,0);

#asm("sei")

while (1)
{
indication=s;
recoding();
}
}

Re: Еще раз про DS1307

Добавлено: Пн фев 11, 2013 22:27:20
Soir
MeSSiR писал(а):Проблема известная, DS1307 кидает цифру 165 вместо того или иного параметра. Интернеты курил,дш тоже. Ни одно из найденных мной решений, не подошло...
Что-то у Вас накручено с переключением портов при смене индикации. Толком не понял, как Вы боретесь с "эффектом тени" и т.п. Поэтому переиначил выводы и вывод. В Proteus начало симулировать почти правильно (сыпятся предупреждения, но я в них не вникал, проект Вы не выложили, я создал свой в CVAVR на скорую руку. Что-то неправильно сконфигурировано...).

Re: Еще раз про DS1307

Добавлено: Вт фев 12, 2013 10:56:22
Aselicon
Извиняюсь за упущение. Борьба с эфф. тени - между переключениями разрядов во весь порт закачиваем едилицу. Вот полный проект, такой как он сейчас, со всеми непричесанностями и излишествами.
Поправил Ваш файл шпротеуса под свой проект. Сегменты А и С не горят почему-то.. в железе все горит как надо. Если немного пофантазировать представляя несуществующие сегменты(чтоб было проще можно побаловать себя валерьянкой) то можно заметить то, о чем я говорил, приходят и секунды и 165. значит однозначно код косячный.

Уважаемый Soir! Ваш код красив, и как говорится fully work! В железе также охотно работает. Пытаюсь понять what's difference.

"Что-то у Вас накручено с переключением портов при смене индикации." В точку, этот кусок кода дает такой негативный эффект.

Re: Еще раз про DS1307

Добавлено: Вт фев 12, 2013 16:01:02
Aselicon
Я, как ток, иду по пути наименьшего сопротивления.
На рабочий скелет накидываю свое мясо. Чтото я уже сам запрограммировался, не пойму как прикрутить мои кнопки. В битовые переменные BUT должна записаться "1" чтоб сказать - кнопка нажата. А антиТень не дает этого сделать.

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

#define butt PIND.3 //Кнопоньки
interrupt [TIM0_OVF] void timer0_ovf_isr(void) //ПРЕРЫВАНИЕт1 перебор разрядов
 {
  digit1 = 1;
  digit2 = 1;
  digit3 = 1;
  digit4 = 1; 
get_dig ( digit_out[cur_dig]);

 switch (cur_dig)
 { 
 case 3: BUT3=!butt; digit4=0;break; //подаём питание на разряд 
 case 2: BUT1=!butt; digit3=0; break; //подаём питание на разряд 
 case 1: BUT2=!butt; digit2=0; break; //подаём питание на разряд 
 case 0:                     digit1=0; break; //подаём питание на разряд 
 } 

 cur_dig++; 
 if(cur_dig>=4) cur_dig=0; 
}

Re: Еще раз про DS1307

Добавлено: Вт фев 12, 2013 16:04:05
Soir
MeSSiR писал(а):Пытаюсь понять what's difference.
"Что-то у Вас накручено с переключением портов при смене индикации." В точку, этот кусок кода дает такой негативный эффект.
В прерывании TIM0_OVF сначала Вы гасите сегменты:
PORTB=0xFF; //чтобы предотвратить эффект “тени” на соседних индикаторах
PORTA=0xFF;
В бою с тенью Вы забыли, что PORTB еще и для DS1307.
После выбора разряда на PORTB выводите код символа:
PORTB=digits[digit_out[cur_dig]] ^ (BitPoint[cur_dig]);
При этом снова забыли про DS1307.
---
Лучше сначала погасить разряды, а затем уже издеваться над PORTB и PORTA, вывести на них символ. При этом помнить о неприкасаемости выводов предназначенных для работы с DS1307. А затем включить нужный разряд.

Re: Еще раз про DS1307

Добавлено: Вт фев 12, 2013 16:57:20
Aselicon
Вчера, в программном угаре, в итоге я заметил что дергаю TWI, но потом, когда начал устанавливать каждый бит отдельно, не заметил что одну ножку я снова дергаю, опечатался. А вот сейчас присмотрелся.. Спасибо Soir! Как тут тебе плюс влепить?
З.Ы. DS1307 отличная микросхема, особенно если выпрямить свои руки, и код...

18.31: Отключил программатор(был постоянно подключен по SPI) начали снова приходить ошибки! А если руками взяться за провода интерфейса, то все снова хорошо. Поставил резистор 5к между линиями данными TWI, ошибки пропали. Считаю что проблемы в монтаже, платку для модуля с DS1307 еще не травил, сейчас торчит в макетке.

Итого:

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

interrupt [TIM0_OVF] void timer0_ovf_isr(void)      //ПРЕРЫВАНИЕт1 перебор разрядов
 {  
      PORTB.0=1;
      PORTB.1=1;
      PORTB.2=1;
      PORTB.3=1;
      PORTB.4=1;
      PORTB.6=1;
      PORTA=0xFF;

      switch (cur_dig)
      { 
         case 3:{BUT3=!butt; digit4=0;  digit3=1;  break;};  //подаём питание на разряд 
         case 2:{BUT1=!butt; digit3=0;  digit1=1;  break;};  //подаём питание на разряд 
         case 1:{BUT2=!butt; digit1=0;  digit2=1;  break;};  //подаём питание на разряд 
         case 0:{            digit2=0;  digit4=1;  break;};  //подаём питание на разряд  
      }    
      
     PORTB.0=((digits[digit_out[cur_dig]])&(0b00000001))>>0;
     PORTB.1=((digits[digit_out[cur_dig]])&(0b00000010))>>1;
     PORTB.2=((digits[digit_out[cur_dig]])&(0b00000100))>>2;
     PORTB.3=((digits[digit_out[cur_dig]])&(0b00001000))>>3;
     PORTB.4=((digits[digit_out[cur_dig]])&(0b00010000))>>4;
     PORTB.6=((digits[digit_out[cur_dig]])&(0b01000000))>>6;
    
     PORTA.0=((digits[digit_out[cur_dig]])&(0b00100000))>>5;
     PORTA.1= (digits[digit_out[cur_dig]])>>7;  

   cur_dig++;                                                            
   if(cur_dig>=4) cur_dig=0;                             
                                    
}