attiny85 и последовательный порт

Unikolai
Offline
Зарегистрирован: 21.09.2016

"Я проверяю прерывания такой конструкциейЖ if ((PINB & (1 << PB3))==0) PORTB|=(1 << PB3); else PORTB &= ~(1 << PB3); "

оно находится тоже в этой ф-и? ISR (PCINT0_vect){}

только вот ntgthm? что это значит?

как понимаю я

PINB, получаем доступ к регистру из котоорго выуживаем, 1 или 0 у нас сейчас на пине

прерывания вы ловите на 3 порту, поэтому если на pb3 у нас возникает 1, то  ((PINB & (1 << PB3))==0) это условие не будет выполняться ибо битовый оператор & дает 1, если в битах и там и там 1, но если условие равно, то мы подрубаем подтягивающий резистор на 3 пине? PORTB|=(1 << PB3)(при этом используем оператор |, дабы если на других пинах есть вкл подтягивающие рехисторы, не трогать их

но если условие не выполняется, то инверируем 3 бит регистра PORTB, тем самым отключая подтягивающий резистор?

 

 

 

nik182
Offline
Зарегистрирован: 04.05.2015

Нет. На PB3 висит светодиод и при каждом срабатывании прерывания он перекидывается. Одно прерывание - загорелся, другое - погас. Если прерывания идут часто, подключаю осцилограф и вижу меандр с частотой следования прерываний. Само прерывание приходит на PB1 пин.

Да, внутри ISR. 

Unikolai
Offline
Зарегистрирован: 21.09.2016
void setup() {
  pinMode(4, OUTPUT);//будет работать на выход, на светодиод
  pinMode(3, INPUT);//будем ждать отсюда прерывание, поэтому ставми на вход
  GIMSK=1<<PCIE;
  PCMSK = 1 << PCINT3;//ждем прерывания только от 3 ноги

}

void loop() {
delay(100);//чтобы сразу не гас, избавляемся от дребезга
  digitalWrite(4, LOW); 

}
ISR (PCINT0_vect){
digitalWrite(4, HIGH); 
}

получается что-то такое?

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Unikolai пишет:


ISR (PCINT0_vect){
if (PINB&(1<<PINB3)) { return;}
  
 digitalWrite(4, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(10);                       // wait for a second
  digitalWrite(4, LOW);    // turn the LED off by making the voltage LOW
  delay(10);
}

что -то я делаю не так..

Внутри прерывания - запрещены другие прерывания, а значит delay() не работает, также как и millis().

"Время - остановилось!!!" (произносить демоническим голосом ;););)

nik182
Offline
Зарегистрирован: 04.05.2015

Последняя функция setup  должна быть sei(); - глобальное разрешение прерываний. 

nik182
Offline
Зарегистрирован: 04.05.2015

wdrakula пишет:

Unikolai пишет:


ISR (PCINT0_vect){
if (PINB&(1<<PINB3)) { return;}
  
 digitalWrite(4, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(10);                       // wait for a second
  digitalWrite(4, LOW);    // turn the LED off by making the voltage LOW
  delay(10);
}

что -то я делаю не так..

Внутри прерывания - запрещены другие прерывания, а значит delay() не работает, также как и millis().

"Время - остановилось!!!" (произносить демоническим голосом ;););)

Просто к сведению. Для 85  тиньки в ардуине есть два ядра. Одно честное,с прерываниями по таймеру. Там действительно не работают функции времени в прерывании. Второе называется NOMILLIS. В нем прерывания вообще не используются, а delay задаётся честным циклом. Поэтому delay() в прерывании работает замечательно, чем я пользуюсь при подавлении дребезга от контактов датчиков. Да и по объему второе ядро меньше. Но miilis()  в нем выдает ересь. 

Фукции delay второго ядра:

void delay(unsigned int ms)
{
  while(ms--){
    delayMicroseconds(1000);
  }
}


/* Delay for the given number of microseconds.  Assumes a 1, 8, 12, 16, 20 or 24 MHz clock. */
void delayMicroseconds(unsigned int us)
{
  // call = 4 cycles + 2 to 4 cycles to init us(2 for constant delay, 4 for variable)
  
	// calling avrlib's delay_us() function with low values (e.g. 1 or
	// 2 microseconds) gives delays longer than desired.
	//delay_us(us);
#if F_CPU >= 24000000L
	// for the 24 MHz clock for the aventurous ones, trying to overclock

	// zero delay fix
  if (!us) return; //  = 3 cycles, (4 when true)

	// the following loop takes a 1/6 of a microsecond (4 cycles)
	// per iteration, so execute it six times for each microsecond of
	// delay requested.
	us *= 6; // x6 us, = 7 cycles

	// account for the time taken in the preceeding commands.
	// we just burned 22 (24) cycles above, remove 5, (5*4=20)
  // us is at least 6 so we can substract 5
	us -= 5; //=2 cycles

#elif F_CPU >= 20000000L
	// for the 20 MHz clock on rare Arduino boards

	// for a one-microsecond delay, simply return.  the overhead
	// of the function call takes 18 (20) cycles, which is 1us
	__asm__ __volatile__ (
		"nop" "\n\t"
		"nop" "\n\t"
		"nop" "\n\t"
		"nop"); //just waiting 4 cycles
  if (us <= 1) return; //  = 3 cycles, (4 when true)

	// the following loop takes a 1/5 of a microsecond (4 cycles)
	// per iteration, so execute it five times for each microsecond of
	// delay requested.
	us = (us << 2) + us; // x5 us, = 7 cycles

	// account for the time taken in the preceeding commands.
	// we just burned 26 (28) cycles above, remove 7, (7*4=28)
  // us is at least 10 so we can substract 7
	us -= 7; // 2 cycles

#elif F_CPU >= 16000000L
	// for the 16 MHz clock on most Arduino boards

	// for a one-microsecond delay, simply return.  the overhead
	// of the function call takes 14 (16) cycles, which is 1us
	if (us <= 1) return; //  = 3 cycles, (4 when true)

	// the following loop takes 1/4 of a microsecond (4 cycles)
	// per iteration, so execute it four times for each microsecond of
	// delay requested.
	us <<= 2; // x4 us, = 4 cycles

	// account for the time taken in the preceeding commands.
	// we just burned 19 (21) cycles above, remove 5, (5*4=20)
  // us is at least 8 so we can substract 5
	us -= 5; // = 2 cycles, 

#elif F_CPU >= 12000000L
	// for the 12 MHz clock if somebody is working with USB

	// for a 1 microsecond delay, simply return.  the overhead
	// of the function call takes 14 (16) cycles, which is 1.5us
	if (us <= 1) return; //  = 3 cycles, (4 when true)

	// the following loop takes 1/3 of a microsecond (4 cycles)
	// per iteration, so execute it three times for each microsecond of
	// delay requested.
	us = (us << 1) + us; // x3 us, = 5 cycles

	// account for the time taken in the preceeding commands.
	// we just burned 20 (22) cycles above, remove 5, (5*4=20)
  // us is at least 6 so we can substract 5
	us -= 5; //2 cycles

#elif F_CPU >= 8000000L
	// for the 8 MHz internal clock

	// for a 1 and 2 microsecond delay, simply return.  the overhead
	// of the function call takes 14 (16) cycles, which is 2us
	if (us <= 2) return; //  = 3 cycles, (4 when true)

	// the following loop takes 1/2 of a microsecond (4 cycles)
	// per iteration, so execute it twice for each microsecond of
	// delay requested.
	us <<= 1; //x2 us, = 2 cycles

	// account for the time taken in the preceeding commands.
	// we just burned 17 (19) cycles above, remove 4, (4*4=16)
  // us is at least 6 so we can substract 4
	us -= 4; // = 2 cycles

#else
	// for the 1 MHz internal clock (default settings for common AVR microcontrollers)

	// the overhead of the function calls is 14 (16) cycles
	if (us <= 16) return; //= 3 cycles, (4 when true)
	if (us <= 25) return; //= 3 cycles, (4 when true), (must be at least 25 if we want to substract 22)

	// compensate for the time taken by the preceeding and next commands (about 22 cycles)
	us -= 22; // = 2 cycles
	// the following loop takes 4 microseconds (4 cycles)
	// per iteration, so execute it us/4 times
  // us is at least 4, divided by 4 gives us 1 (no zero delay bug)
	us >>= 2; // us div 4, = 4 cycles
	

#endif

	// busy wait
	__asm__ __volatile__ (
		"1: sbiw %0,1" "\n\t" // 2 cycles
		"brne 1b" : "=w" (us) : "0" (us) // 2 cycles
	);
	// return = 4 cycles
}

#if F_CPU == 20000000
  // 20 MHz / 128 ~= 125 KHz
  #define ADC_ARDUINO_PRESCALER   B111
#elif F_CPU == 18432000
  // 18.432 MHz / 128 ~= 125 KHz
  #define ADC_ARDUINO_PRESCALER   B111
#elif F_CPU == 16000000
  // 16 MHz / 128 = 125 KHz
  #define ADC_ARDUINO_PRESCALER   B111
#elif F_CPU == 12000000
  // 12 MHz / 64 ~= 125 KHz
  #define ADC_ARDUINO_PRESCALER   B110
#elif F_CPU == 8000000
  // 8 MHz / 64 = 125 KHz
  #define ADC_ARDUINO_PRESCALER   B110
#elif F_CPU == 1000000
  // 1 MHz / 8 = 125 KHz
  #define ADC_ARDUINO_PRESCALER   B011
#elif F_CPU == 128000
  // 128 kHz / 2 = 64 KHz -> This is the closest you can get, the prescaler is 2
  #define ADC_ARDUINO_PRESCALER   B000
#else
  #error Add an entry for the selected processor speed.
#endif 

 

Unikolai
Offline
Зарегистрирован: 21.09.2016


void setup() {
  pinMode(4, OUTPUT);//будет работать на выход, на светодиод
  pinMode(3, INPUT);//будем ждать отсюда прерывание, поэтому ставми на вход
  GIMSK=1<<PCIE;
  PCMSK = 1 << PCINT3;//ждем прерывания только от 3 ноги
sei(1); или единицу не нужно?

}

void loop() {
delay(100);//чтобы сразу не гас, избавляемся от дребезга
  digitalWrite(4, LOW); 

}
ISR (PCINT0_vect){
digitalWrite(4, HIGH); 
}


я как понял через сеи мы работаем с регистром sreg

nik182
Offline
Зарегистрирован: 04.05.2015

Да, Можно через регистр, но зачем если есть прямая команда?

А программа где то так, иначе включение светодиода может произойти в любой момент delay(100), даже в самом конце:

volatile bool fl;

void setup() {
  pinMode(4, OUTPUT);//будет работать на выход, на светодиод
  pinMode(3, INPUT);//будем ждать отсюда прерывание, поэтому ставми на вход
  GIMSK=1<<PCIE;
  PCMSK = 1 << PCINT3;//ждем прерывания только от 3 ноги
  sei();
}

void loop() {
  if (fl){
  digitalWrite(4, HIGH); 
  delay(100);//чтобы сразу не гас, избавляемся от дребезга
  digitalWrite(4, LOW); 
  fl=false;
  }
}
ISR (PCINT0_vect){
fl=true; 
}

 

Unikolai
Offline
Зарегистрирован: 21.09.2016

ясно, сапсибо! скоро буду пробовать, может сегодня и часы успею подцепить

в принципе думаю пока нет под рукой bycnhevtynf/. стоит уточнить

void system_sleep()
{
  cbi(ADCSRA, ADEN);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  sleep_mode();
  sleep_disable();
  sbi(ADCSRA, ADEN);
}

этой ф-ей погужаем в сон, но просыпался МК так по вотчдогу

как понимаю, чтобы тиньку усыпить достаточно вот этого

  set_sleep_mode(SLEEP_MODE_PWR_DOWN);

хотя 

sleep_enable(); и sleep_cpu(); наверное еще ужын

как я понял sbi это что-то, позволяющее менять направление порта(вход/выход)не трогая другие порты

cbi то же, только для установки пина(бита) в ноль, то бишь для работы его на вход

а вот с этими ребятами уже совсем тяжко ADCSRA, ADEN

получается ADEN это бит регистра ADCSRA, если установить его в ноль, то не работает ацп чтоли7  тпа для большего энергосбереения?

Unikolai
Offline
Зарегистрирован: 21.09.2016
volatile bool fl;

void setup() {
  pinMode(4, OUTPUT);//будет работать на выход, на светодиод
  pinMode(3, INPUT);//будем ждать отсюда прерывание, поэтому ставми на вход
  GIMSK=1<<PCIE;
  PCMSK = 1 << PCINT3;//ждем прерывания только от 3 ноги
  sei();
}

void loop() {
  if (fl){
  digitalWrite(4, HIGH); 
  delay(100);//чтобы сразу не гас, избавляемся от дребезга
  digitalWrite(4, LOW); 
  fl=false;
  }
}
ISR (PCINT0_vect){
fl=true; 
}

я как полагал, прерывание должно срабатывать при смене на пине 1 на 0, возможно это дребезг контактов, но суть в томЮ, что диод загорается при тычке + на 3 пин, и при том при сем если после поносить к нему +, то диод гореть не будет, будто нужно енкоторое время на восстановление

тинька работает на 1 мегагерце, на нем у нее всегда все хорошо

nik182
Offline
Зарегистрирован: 04.05.2015

Обратите внимание на MCUCR – MCU Control Register. Если туда ничего не записать, то прерывание будет генеритьстя постоянно при замыкании ноги на ноль-и всё это время программа не будет работать. Что бы оно генерилось при фронте 1 -> 0 в этот регистр надо записать 2 или В10.

....ADEN это бит регистра ADCSRA, если установить его в ноль, то не работает ацп чтоли7  тпа для большего энергосбереения? - Да именно так. Еще есть регистр ACSR – Analog Comparator Control and Status Register. Если записать в него ACD бит - 0х80 то выключится компаратор и энергосбережение ещё улучшится.

  

 

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

Unikolai пишет:

как я понял sbi это что-то, позволяющее менять направление порта(вход/выход)не трогая другие порты

cbi то же, только для установки пина(бита) в ноль, то бишь для работы его на вход

Это уже из ассемблера: sbi - установить бит, cbi - сбросить бит.

Хотя эта конструкция уже СИшная:
sbi(ADCSRA, ADEN);
cbi(ADCSRA, ADEN);

По идее тоже самое, что и:
ADCSRA |= (1<<ADEN);
ADCSRA &= ~(1<<ADEN);

Unikolai
Offline
Зарегистрирован: 21.09.2016

то есть просто в сетап добавить строчку 

MCUCR=В10;?

nik182
Offline
Зарегистрирован: 04.05.2015

Да :-)

Unikolai
Offline
Зарегистрирован: 21.09.2016

а что значит по фронту?

volatile bool fl;

void setup() {
  pinMode(4, OUTPUT);//будет работать на выход, на светодиод
  pinMode(3, INPUT);//будем ждать отсюда прерывание, поэтому ставми на вход
  GIMSK=1<<PCIE;
  PCMSK = 1 << PCINT3;//ждем прерывания только от 3 ноги
  MCUCR=B10;
  sei();
}

void loop() {
  if (fl){
  digitalWrite(4, HIGH); 
  delay(100);//чтобы сразу не гас, избавляемся от дребезга
  digitalWrite(4, LOW); 
  fl=false;
  }
}
ISR (PCINT0_vect){
fl=true; 
}

после загрузки этого скетча, дио сам загареется, когда он горит, если поднести к pb3 + батарейки, гореть перестает

плохо, что с тиньи ничего в порт посылать нельщя...

Если на пие pn3 постоянно дердать +,то светодиод не загорается, если убрать этот плюс, то начинается вакханалия, может ли быть такое, что на пн3 в этот момент постоянно меняется состояние? Хотя вроде как настроен он на вход и по идее там автоматом должен быть включен резистор...

pinMode(3, INPUT);//будем ждать отсюда прерывание, поэтому ставми на вход
  digitalWrite(3, HIGH);
может это прописать? но в таком случае ничего вообщше не светится...
nik182
Offline
Зарегистрирован: 04.05.2015

Фронт это момент перепада уровней. Запись HIGH в порт включает подтяжку к +. Для срабатывания прерывания нужно пин заземлить на короткое время. Что значит послать в порт? Ecли в сериал то нет никаких проблем, нужен только USB-TTL пребразователь.

Unikolai
Offline
Зарегистрирован: 21.09.2016

Папа дак разве к + все подтягивались..у нас же срабатывает прерывание как раз таки получается если плюс батарейки подрубить к плюсу устройства, а вот минус на пин подавать, я наоборот делал..я думал если мы ставим пин на вход, то он как раз таки к минусу подтягивается резистором) да, в сериал

http://ardunn.ru/goods/%D0%9F%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%... вот такакя штука есть, но как понимаю не подойдет она и нужна такая

http://ardunn.ru/goods/USB-TTL-FTDI-%D0%B0%D0%B4%D0%B0%D0%BF%D1%82%D0%B5...

?

nik182
Offline
Зарегистрирован: 04.05.2015
Unikolai
Offline
Зарегистрирован: 21.09.2016
pinMode(3, INPUT);//будем ждать отсюда прерывание, поэтому ставми на вход
  digitalWrite(3, HIGH);
прописал это в сетапе, теперь при подаче - на 3 пин происходит то, что должно происходить))
void system_sleep()
{
  cbi(ADCSRA, ADEN);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  sleep_mode();
  sleep_disable();
  sbi(ADCSRA, ADEN);
}

 

теперече мне не сно тут что, в одной функции, кторую мы вызываем, когда хотим, чобы устроцйство уснуло, мы отключаем тот же самый ацп, но в ней же его и вкючаем..как так?? или выполнение кода у нас продолжится после строчек cbi(ADCSRA, ADEN);

  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  sleep_mode();

то бишь сразу после сна и после  того, что написано в обработчике прерываний у нас выполнятся эти строчки

 sleep_disable();
  sbi(ADCSRA, ADEN);

?

nik182
Offline
Зарегистрирован: 04.05.2015

А откуда вы это кусок взяли? Я мало работал со слип модами, но помню что после входа в слип процессор засыпает и ничего не делает до прерывания. А дальше, после прерывания, сильно зевисит от логики. В тех процессорах, что я знаю, если в прерывании не выставить флаг окончания сна, то процессор снова уснёт. В вашем куске после оператора sleepmode() процессор засыпает и спит до неизвестного мне события. После просыпания выполняется sleepdisable() и программа продолжает выполнятся. Ну а то что перед засыпанием выключают АЦП это нормально для экономии энергии. Как последующее включение. Между этими событиями может произойти не один день ;-)

Unikolai
Offline
Зарегистрирован: 21.09.2016

в принипе все хорошо, но есть ньюансы...например, устанавливаю в регистр 0х1 1<<, а при чтении получается байт 10100000...про это я уже писал, что я только не делал

вот потому то я не люблю, когда в коде что-то свое, нерпоработанное, оказывается ф-я, которая читала мои регистры переводила внутри себя число из 2 в 10чную, потому такая несурахица и аходила

это ппц...если эту ф-ю поменять, то, например в секундах может появиться число более 60...

Unikolai
Offline
Зарегистрирован: 21.09.2016
void read_register(byte *r, byte adress)
{
  I2CStart();
  I2CWrite((DS3231_I2C_ADDRESS << 1));
  I2CWrite(adress);
  I2CStop ();
  I2CStart();
  I2CWrite((DS3231_I2C_ADDRESS << 1) + 1);
  *r = bcdToDec(I2CRead(0));
  I2CStop ();
}

byte I2CRead(boolean ack)
{
  byte i = 8;
  byte b = 0;
  while (i--)
  {
    b <<= 1;
    SCL_Lo();
    SDA_Hi();
    I2CDelay();
    SCL_Hi();
    //while(!SCL_In());
    if (SDA_In()) b |= 1;
    I2CDelay();
    SCL_Lo();
  }
  if (ack) SDA_Lo();
  else SDA_Hi();
  I2CDelay();
  SCL_Hi();
  //while(!SCL_In());
  I2CDelay();
  SCL_Lo();
  return (b);
}

если в 9 строке убрать ф-ю для перевода 2чного числа в 10тичное, то начинается неистовый ппц


10000000
10000000
10000000
111
1
ON1
0
1:5:81
10000000
10000000
10000000
10000000
111
0
OFF1:5:82
10000000
10000000
10000000
10000000
111
1
ON1
0
1:5:82
10000000
10000000
10000000
10000000
111
0
OFF1:5:83
10000000
10000000
10000000
10000000
111
1
ON1
0
1:5:83
10000000
10000000
10000000
10000000
111
0
OFF1:5:84
10000000
10000000
10000000
10000000
111
1
ON1
0
1:5:84
10000000
10000000
10000000
10000000
111
0
OFF1:5:85
10000000
10000000
10000000
10000000
111
1
ON1
0
1:5:85
10000000
10000000
10000000
10000000
111
0
OFF1:5:86
10000000
10000000
10000000
10000000
111
1
ON1
0
1:5:86
10000000
10000000
10000000
10000000
111
0
OFF1:5:87
10000000
10000000
10000000
10000000
111
1
ON1
0
1:5:87
10000000
10000000
10000000
10000000
111
0
OFF1:5:88
10000000
10000000
10000000
10000000
111
1
ON1
0
1:5:88
10000000
10000000
10000000
10000000
111
0
OFF1:5:89
10000000
10000000
10000000
10000000
111
1
ON1
0
1:5:89
10000000
10000000
10000000
10000000
111
0
OFF1:6:0
10000000
10000000
10000000
10000000
111
1
ON1
0
1:6:0
10000000
10000000
10000000
10000000
111
0
OFF1:6:1
10000000
10000000
10000000
10000000
111
1
ON1
0
1:6:1
10000000
10000000
10000000
10000000
111
0
OFF1:6:2
10000000
10000000
10000000
10000000
111
1
ON1
0
1:6:2
10000000
10000000
10000000
10000000
111
0
OFF1:6:3
10000000
10000000
10000000
10000000
111
1
ON1
0
1:6:3
10000000
10000000
10000000
10000000
111
0
OFF1:6:4
10000000
10000000
10000000
10000000
111
1
ON1
0
1:6:4
10000000
10000000
10000000
10000000
111
0
OFF1:6:5
10000000
10000000
10000000
10000000
111

зато регистры начинает считывать правиьно

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Unikolai, не смотря на кем-то данное название bcd to dec, никакого преобразования в "десятичное" там нет. Просто два независимых полубайта с данными склеиваются в один байт. (кстати сомнительная необходимость их склеивать, ибо разработчики часового чипа специально для удобства пользователей придумали хранить каждую цифру отдельно!) Соответссно если вы прочитали не элемент регистров времени, а байт конфигурации, то подвергать его такой перепаковке не следует.

nik182
Offline
Зарегистрирован: 04.05.2015

Именно. Эта подпрограмма из примера к библиотеке часов. Необходима для правильного заполнения регистров времни. К остальным регистрам применять не надо.

Unikolai
Offline
Зарегистрирован: 21.09.2016
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return ( (val / 10 * 16) + (val % 10) );
}

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

но все арвно, мне не понятно абсолютно, как эта ф-я работает??

если подставлять и счиатть как пример, о получается ерунда какая-то, тут наверное нематематический подход нужен

в моем понимани должен быть хотя бы цикл какой-то, где мы там дели на 2 с остатком, а тут где че...

nik182
Offline
Зарегистрирован: 04.05.2015

Каждый полубайт содержит десятичное число, например 23 часа записаны в байт как В0010 и В0011. Из них целый байт получается В00100011 - это число совсем не равно 23. Если вы считали байт из регистра времени, то его надо разделить на 2 полубайта и левый полубайт помножить на 10, т.к. это десятки. Что и делает эта подпрограмма. 

Unikolai
Offline
Зарегистрирован: 21.09.2016

ладно, это завтра на свежуюголову обмозгую, сейчас же встал nffjq вопрос, исходя из кода моего, у меня ведь прерывания только с 3 ноги могут ловиться? просто проблемы возникли...все грузанул на тиньку, все вроде хорошо, один пин тиньку у меня идет на питание часов в тот момент, вернее чуть заранее, когда нам нужно считать время ии же выставить флаг прерывания в 0, но...если с этот пин соединяю с + часов, то у меня постоянно идет прерывание именно с часов!, если + часов подключить к +батарейки, то вроде как все нормально...

Unikolai
Offline
Зарегистрирован: 21.09.2016

я все авно не пойму, как работает эта ф-я, есть у нас например то же самео число 23 и что с инм происходит? если рассуждать матиматичсски ((23/10)*16)+(23%10)) в левой скобке получается дробное число, в правой части остаток от деления, но это всю плюсуется, двоичным числом тут вроде и не пахнет

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Unikolai,   это целочисленная математика.    23/10 =2,  2*16=32.   23%10 =3    32+3 =35

Unikolai
Offline
Зарегистрирован: 21.09.2016

но ведь мы получили 10тичное число

и делим мы на 10

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Unikolai, у человека и МК разные способы восприятия данных и счёта.  Если опустить разные нюансы, то можно сказать что для контроллера не существует вообще никаких чисел кроме двоичных.

Unikolai
Offline
Зарегистрирован: 21.09.2016

это то я понимаю, но ведь это ф-я как раз таки для преобразования десятичного в двоичное, как это сделать я понимаю, но не прослеживаю той же логики в данной ф-и, я просто хочу понять, ведь она вроде как работает

 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Unikolai, я вам уже писал в #173, что название "десятичное в двоичное" имеет слишком специфический смысл, не стоит воспринимать его буквально. Изучите битовые операции как таблицу умножения учат в школе. Что б прямо от зубов отлетало. Та формула из #175 несмотря на то, что написана десятичным счётом обретает смысл только если её представлять как битовые операции сдвигов и сложения.  Это видимо такой прикол -переписать её дясятичным эквивалентом, что-б другие, типа вас смотрели и думали что это за хрень такая )

Unikolai
Offline
Зарегистрирован: 21.09.2016

вы уж меня извините, я не особо шарю) но вы сам писали "Unikolai, не смотря на кем-то данное название bcd to dec, никакого преобразования в "десятичное" там нет. Просто два независимых полубайта с данными склеиваются в один байт." разве изначально под полубайт подразумевает не двоичную систему?

"Unikolai,   это целочисленная математика.    23/10 =2,  2*16=32.   23%10 =3    32+3 =35" ведь у нас в часах один байт-регистр и нам десятичное как раз таки(по моей логике) нужно разделитьчисло и каждое поотдельности преобразовать в двоичную систему и после этого сложить(младший истраиший. сделать один)

то есть число 23,2-010,3-011, после склейки должны получить 00100011(ну или наоборот) и+ нолики по краям..наверное...то есть 0001000110, там же мы складываем десятичные числа, или же компилятор сразу их рассматривает как двоичные(имею ввиду то, что если мы пример напишем в какой-нибудь ф-b? например 2+2, то мы получим 4, а не 0100

картинка к "ноликам"по краям

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Unikolai, давайте вы будете условно считать что всё, что считает МК -это двоичная система, про другие он не знает. Как вы напишите в программе  - 10*16 или 10<<4 не важно, программа понимает всякие варианты).

Unikolai
Offline
Зарегистрирован: 21.09.2016

эта ф-я получает десятичное число, но такое, которое потом будет удолитворять условию, что переведенное  двоичную систему младший байт будет десятком, старший единицей, но я тут прошу объяснить, почему мы делим на десять(я как понимаю таким макаром мы получаем как раз таки первую часлк(десятки)и почему-то умножаем именно на 16...почему на 16? далее мы получаем вторую цифру из числа и все это складываем, это аксиома какая-то чтоли, что если мы складываем два десятичных числа(которые составляют например 23)одно из которых домножаем на 16, то мы получаем при переводе его в двоичную систему получаем, что старший байт этого байта при перевое в десятичную систему является как раз таки 2, а младший тройкой?? 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Unikolai, я вам уже сказал, что смысл этих манипуляция полностью может быть ясен тольк тому, кто дружит с двоичными операциями. Раз вам непонятно, значит вы всё ещё не понимаете двоичный язык. Тут всё просто как дважды два. /10 - взять старшую цифру. *16 -сдвинуть на 4 бита влево. %10 взять младшую цифру.

nik182
Offline
Зарегистрирован: 04.05.2015

Старший байт байта не существует. Есть старший полубайт. Верхние четыре бита MSB-BIT7...BIT4. Это определение создателей ds3231 для хранения десятков. Если вы считаете байт и захотите его вывести на индикатор то вы не будите делать поразрядовое преобразвание цифр, а сразу выводить последовательность полубайтов. Функция получает не десятичное число. Она получает закодированное десятичное число. По этой формуле происходит пререкодировка в бинарный формат, которым оперирует процессор.

16 = 0x10 = B10000= 1<<4 это сдвиг нижнего полубайта на место верхнего. Т.Е. вычисляем сначала зачение верхнего полубайта. Делим число на 10 и получаем количество десятков. Результат в нижнем полубайте - сдвигаем ему на верх. Вычисляем и прибавляем нижний полубайт. Получаем чсло для регистра ds3231. Больше ни для чего не годное.        

Unikolai
Offline
Зарегистрирован: 21.09.2016

мне уже прото стыдно и смешно, на вводе у нас десятичное число? а операции, получаются, уже в самом начале как для двоичного...я не понимаю, как МК понимает, что ту ему нужно работать с этим числом уже как с двоичныи?

я понял, вот что я и хотл услышать от вас, все дело в типе переменной с которой мы работаетм) если написать

Serial.println(2*2*3); то получим 12

а вот если сделать так

 byte g=2;
  byte i=2;
  byte q=3;
    Serial.println(q*i*q);
то получим 18, то есть когда у нас тип byte? хотя мы и вводим десятичны для нас числа, программа де изначально их рассматривает, как числа в двоичном коде, поэтому и возникла эта жуткая непонятка, вроде операции с входными десятичными, а получаем двоичное непонтнокаквышедшее)
спасио за терпение, друзья)
хотя я не понля!! ахаах
как же так, те же самые десятки, мы ведь их получаем путем деления именно изначальнодесятичного числа на 10, а потом уже работаем с ним как с байтом...
с теми же битовыми операциями я знаком и маломальски начинаю их применять потихоньку, но... тут нет ни |ни & ни ^? ничего такого
Unikolai
Offline
Зарегистрирован: 21.09.2016

если мы байты складываем, то мы просто склеиваем их? если умножаем байт на 3, например, то мы берем 3 этих байта и так же склеиваем? неее...неверно все

nik182
Offline
Зарегистрирован: 04.05.2015

А если напишем Serial.println(2*2*3,HEX); получим 0хС, а если Serial.println(2*2*3,BIN); - B01100

Процессор ничего не знает про десятичные, восьмеричные и прочие, кроме двоичных. Всё что мы видим и называем не двоичными, это наше представление числа для нашего удобства.   уже писал 16 = 0x10 = B10000= 1<<4 - это одно и то же число и процессор его всегда!!!! знает только как В10000. Всё остальное это результат преобразования. Для вашего восприятия. Мне, за много лет работы с микропроцессорами практически всё равно как записано число. У меня в голове сразу висят нолики и единички двоичного представления.

Складывая полубайты мы не склеиваем их. Мы делаем честное сложение двоичных чисел. Вот только у этих чисел на месте единичек взаимно всегда стоят нули. Поэтому перехода в следующий разряд от сложения не происходит и в результирующем числе нолики и единички стоят точно на тех же местах, что и в изначальных полубайтах.

В операциях мы множим-делим не на 10, а на В1010.  Это  тоже двоичная операция, выполняемая исключительно для получения значения  выводимого на дисплей в качестве удобной для вас цифры. Если посмотреть код числа 1000, то для ASCII представления это будет 0х31,0х30,0х30,0х30 или В00110001001100000011000000110000, в десятичном виде это будет 825241648 - совсем не 1000. 

Unikolai
Offline
Зарегистрирован: 21.09.2016
  if (f_wdt == 1)
  {

    //set_registers(B10000000, B10000000, B10000000, B10000000 , 0x7);
    
    f_wdt = 0;

    delay(500);
    set_register(B00000000, 0x0F);
    digitalWrite(4, HIGH);
    delay(50);
    digitalWrite(4, LOW);
    system_sleep();
  }

}
ISR (PCINT0_vect) {

  f_wdt = 1;
}
тут почти весь код
суть в том, что если связать проодком пин 3 на тиньке(ловит перрывания) и выход sqw часов, то возрастает потребление на 1 мА)) и даже если убрать связи между проводами  ic2, то по каким-то причинам порой начинает мигать светодиод..хотя сбрасывать флаг для этого нужно обязательно(чего происходить в принципе не мложет)мигает так он раз 15-20, а может и раза 4, по-разному, как так..

в этом вопросе к сожалению я так пока и не разобрался, но появился другой

сколько таки должны потреблять часы при питании т батарейки и вкл будульнике? у меня чего т много выходит

кстати...а что, если питаться от батарейки, то по ic2 данные тоже можно передавать?

и вот еще, всех с наступающим!!!)))

Unikolai
Offline
Зарегистрирован: 21.09.2016

странно, изложение сути вчера пчему-то не сохранилось, дак вот

есть тинька. 0 пин можно пока не трогать я его отключил(от него хотел питать часы перед снятием данных) 1и 2 - ic2, 3 пин ловит прерывания, на четвыртый пин запитан светодио для индикациивсе бы хорошо, но: при подключении пина 3 на выход sqw часов происходит резкое повышение энергопотребления, на 0,87 мА(при том при сем остальные пины часов я от мк вообще отключаю, не считая птания, запитываю батарейку) и при этом мигает этот светодиод, чего вроде как .snm не может, ибо сбрасывать флаг будильника нечему(провода сда cwk отключены...)вот такие пироги, как так?

Unikolai
Offline
Зарегистрирован: 21.09.2016

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

Unikolai
Offline
Зарегистрирован: 21.09.2016

друзья, уточните таки, точно должны прерывания от будильника работать при питании от батарейки?

nik182
Offline
Зарегистрирован: 04.05.2015

Николай. Вы предлогаете за вас изучить даташит на ds3231? Я почитал. Нигде не нашёл утверждения, что прерывания от батареи не работают. Я вижу другую проблему. Что бы случилось прерывание, нужно на ноге тиньки изменить уровень. В силу схемотехники на ноге прерывания должно присутствовать напряжение, которое будет замыкаться на массу при прерывании DS3231. Вы обеспечили на ноге INT/SQW напряжение +питания через резистор  в режиме сна?   

Unikolai
Offline
Зарегистрирован: 21.09.2016

я прсто тоже читал как мог и не нашел ничего такого..а разве с самихчасов + не хватает? ведь там даже светодиод горит..или этого недостаточно? нужно через 10к светодиод подключать?

я вообще как думал, что при срабатывании будильника и прерывания через сами часы(транзистор или что-то в этом роде) у нас идет замыкание на землю питания, после сбрасывания флага прерывания часы запитывают выход sqw от питания "+"

nik182
Offline
Зарегистрирован: 04.05.2015

Посмотрите на первой и восьмой странице даташита картинки. Особенно на восьмой. Там прямо нарисовано, что на выход INT не подаётся никакого напряжения. Это прсто вывод транзистора, второй ногой сидящий на массе. Если напряжение на этот выход не подано, то узнать сработал или нет выход не возможно. На первой странице специально нарисован внешний резистор на + для того, что выход можно было использовать. Вы же диод к плюсу прикручиваете, что бы он горел? Если его прикрутить к земле и к ноге INT он никогда не загорится.  

Unikolai
Offline
Зарегистрирован: 21.09.2016

но ведь у меня готовый модуль, как я понял там даташитовская схема и есть резистор(ибо все равботаетс основным питанием) хотелось бы найти конкретно схему готовго модуля..

не понимаю почему, но с основным питанием все хорошо, если настроить будильник так, чтобы срабатывал каждую минуту, и отключать питание основное, то на выходах sqw и "-" появляется ниспадающее почти до 0 напряжение, восновном до полного нуля всп падает  еще до срабатывания будильника...

nik182
Offline
Зарегистрирован: 04.05.2015

Резистор подключен к основному питанию. К батарее не подключен. Почему при отсуствии основного питания на выводе прерывания должно быть напряжение? Откуда? Батарея ни какого соединения с основным питанием не имеет. Кстати. Вы ни разу не выложили полную схему вашего устройства. Приходится гадать на кофейной гуще, что бы хоть что то вам ответить по существу.