а можно ведь этот код отладить на нанке? подключать только к пинам всем, кроме 4 и 5(которые ворде как обычо с ic2?) сам щас проверить не могу, чтобы потом врем не терять
Получается я обращался не к тем пинас? Если бы захотел использовать d2 и d3, нужно было бы здесь #define I2C_in PINС ,,pin d указать? А первая строка что меняет?
Первая строка это частота процессора. От них зависят тайминги протокола. Порты и пины это разные стороны одного и того же. Взял пин от порта - обращайся к регистрам этого порта а не чужого. d2 d3 это пины PD2 PD3 порта D. Нужно использовать PIND,PORTD,DDRD.
в рекомендациях по снижению энергопотребления сказано, что нужно отключить порты, чтобы нмичего не потребляли они, ибо аже если на выводах нет ничего(ничего к нему не подкл)он все равно может потреблять так
друзья, тоска, такое дело, подключил часики я все хорошо, рабатают(огромное спасибо всем и в отдельности тем, кто кинул кодом) если часики питать напрямую от gnd и vcc, то все гуд, но если я так их буду питать, то они будут оч много кушать, поэтому мой план таков - патаю их через пин, на который перед считыванием инфы подаю 1(4,4 вольта), но это все теория, так у меня получалось, но только на нанке, при подлючении vcc часов к пину обычному и при попытке залить код, выдает ошибку при загрузке скетча
avrdude: Yikes! Invalid device signature.
Double check connections and try again, or use -F to override
this check.
Произошла ошибка при загрузке скетча
если разъединить связь между vcc часов и пином, то все норм, на тньке у меня, ксати, тоже получалось, но сначала я доставал это добро., затем, после загрузки, соединял
может где-то какой - нибудь резистр нужен? или конденсатор между ними
Нет, питание часов через 1к и обязательно за ним должна стоять емкость на 10 мкф или больше. Ни каких больше проводов кидать не надо. У вас же проблема с заливкой кода при подключенных часах? В таком варианте её не будет.
Да, все верно) а на энергопотреблении этот резюк на 1 к сказываться не будет? Или напряжение только теряться будет? Спасибо за ответы на мои, как кому-то может показаться, глупые вопросы)
Друзья, пипец, если вставить эту строчку в setup I2CInit (); 221 строчка из кода выше, то энергопотребление ниже 300 мкА не опускается...ввожу тиньку в pwr down, не понимаю, почему так, помогите разобраться, может что-то где-то подправить в коде? (Без этой строчки все зорошо) ну не считая того, что я не могу считывать время с часов)))
Эта команда переключает ноги на выход. Если что то к ним подключено и потребляет ток, то этот ток не будет зависить от спящего режима. Перед входом в спящий режим нужно ноги перевести в режим входа. После выхода из спящего режима ещё раз дать команду инициализации.
То есть на всякий случай можно все ноги перевести в режим low? Только тогда какой смысл в том, что мы что-то делаем в сетупе? Акромя сетупа вообще разве можно менять ноги - на вход или на выход они работают? Как это правильно сделать?
Или может эти пины как-то в low ставить?
Nik182, спасибо, попробую, надеюсь поможет, я тут почитал за это время, по идее я ведь могу в ноль поставить эти пины, типа диджиталврайт(сда_пин, лов) а перед запросм времени как раз таки запускать айси2клиент? Да и (как пониааю, ваш код делает примерно то же самое/)вообще в лупе можно спокойно менять пины на вход//на выход? Уточняю)
Да делают то же самое, только одной командой, digitalWrite длинно и долго.
Менять направление можно в любой момент. Часто, когда ног мало вывод и ввод делают через одну ногу. Соответственно в цикле приходится переключать неправление. Перед обменом запускать I2CInit();
Спасибо, почитаем) ваш совет помог) только я пришел к выводу, ну собственно в даташите это тоже указано, что эта собака вотчдог кушает примерно 5 микроамперы....можно может поставить внешний кварц и уменьшить это значение?
#define F_CPU 8000000UL
#define alPin PB5
#define _NOP() asm volatile("nop")
#define LOOP_CYCLES 8
#define us(num) (num/(LOOP_CYCLES*(1/(F_CPU/1000000.0))))
inline __attribute__((gnu_inline)) void asm_delay(uint16_t delay) {
uint16_t u = us(delay);
do _NOP(); while (delay--);
}
#define wdelay_us(x) asm_delay(us(x))
#define wdelay(x) delay(x)
#define I2CDelay() wdelay_us(10)
#define SDA_Pin PB2//присваиваем 2 пин в регистре в, на этот порт мы посылаем данные-пакеты
#define SCL_Pin PB1//присваиваем 1 пин в регистре в, на этот мы посылаем импульсы
#define I2C_in PINB//?
#define I2C_out PORTB//для выставления low/high пинам в регистре
#define I2C_dir DDRB//обращение к регистру для задания пинам input/output
#define SDA_In() (I2C_in & (1<<SDA_Pin))//"(1<<SDA_Pin)" пин у нас в SDA_Pin - 2, в двоичной это 0010, сдвиг делаем и получаем 0100, но для чего, не понимаю ибо зачем PINB нужен не ясно, вроде как отвечает за ответы от ведомого, получаем бит записи/чтения, получается единица будет только там, где в обоих байтах 1
#define SCL_In() (I2C_in & (1<<SCL_Pin))
#define DS3231_I2C_ADDRESS 0x68
inline void SDA_Hi() {//эта ф-я подтягивает к плюсу линию sda
I2C_out |= (1 << SDA_Pin);//SDA_Pin-0010, опять таки, зачем делаем сдвиг?
I2C_dir &= ~(1 << SDA_Pin);//vs что, каждый раз переопределяем, работает пин на вход или выход?
}
inline void SDA_Lo() {//эта ф-я подтягивает к минусу линию sda
I2C_out &= ~(1 << SDA_Pin);
I2C_dir |= (1 << SDA_Pin);
}
inline void SCL_Hi() {//эта ф-я подтягивает к плюсу линию scl
I2C_out |= (1 << SCL_Pin);
I2C_dir &= ~(1 << SCL_Pin);
}
inline void SCL_Lo() {//эта ф-я подтягивает к минусу линию scl
I2C_out &= ~(1 << SCL_Pin);
I2C_dir |= (1 << SCL_Pin);
}
void I2CInit (void)//тут мы как раз таки благодаря вышесозданным ф-ям определяем, в каком регистре и какие пины будут настороены на вход и выход и плюс будет там или сям
{
SDA_Hi();
SCL_Hi();
}
void I2CStart (void)
{
SCL_Hi();//выполняем условие старта, выводим scl в высокий уровень
//while (!SCL_In());
I2CDelay();
SDA_Lo();//опускаем в ноль sda
I2CDelay();
SCL_Lo();//ну и в ноль scl,, условия старта врод как выполнены
}
void I2CStop (void)//пссле завершения передачи пакета
{
SCL_Lo();//опускаем(ведущий)
SDA_Lo();//опускаем(ведущий)
I2CDelay();//в этот момент ведомый должен послать аск или наск, в зависимости от того, все передал или нет
SCL_Hi();//ведущий подымает импульсную линию и читает, что послал ведомый
//while(!SCL_In());
I2CDelay();
SDA_Hi();//так как у нас ф-я ля остановки, то вполняем условия стопа, линия scl уже поднята, поднимаем sda? условия стопа выполнены
I2CDelay();
}
boolean I2CWrite(byte b)//вот тут начинается аврал, эта штука принимает на вход весь бит
{
byte i = 1 << 7;//получаем из этого 10000000
boolean ack = 0;
while (i)//это опять какая-то сокращенная запись, какое тут условие, пока что? не закончатся биты из байта?
{
//I2CDelay();
if (b & i) SDA_Hi(); else SDA_Lo();//не понимаю, что тут за условие if, сокращенное
I2CDelay();
SCL_Hi();
I2CDelay();
SCL_Lo();
i >>= 1;
//как понимаю, просто генерирует 8 импульсов на линии scl? а на линию sda подтягивает к +, если бит в обрабатываемом байте равен 1
}
SDA_Hi();//посылаем последний бит, отвечающий за чтение/запись, так как хай, то чтение
I2CDelay();
SCL_Hi();//считываем последний бит
// while(!SCL_In());
if ( SDA_In() == 0 ) ack = 1;//что такое SDA_In() так же остается непонятным
I2CDelay();
SCL_Lo();
SDA_Hi();
return ack;
}
byte I2CRead(boolean ack)//принимаем на вход единицу или ноль из предыдуще ф-и
{
byte i = 8;
byte b = 0;
while (i--)//тоже сокращенное что-то, не понятно, но скорее всего пока i>=0
{
b <<= 1;//b =b<< 1;
SCL_Lo();
SDA_Hi();
I2CDelay();
SCL_Hi();
//while(!SCL_In());
if (SDA_In()) b |= 1;//какое-то непонятное условие,,и если вполняется, то из 1 получаем 11, далее 111 и тд
I2CDelay();
SCL_Lo();
}
if (ack) SDA_Lo();
else SDA_Hi();
I2CDelay();
SCL_Hi();
//while(!SCL_In());
I2CDelay();
SCL_Lo();
return (b);
}
Возьмите описание протокола i2c. Там всё расписано. Здесь реализация. К строке 34 - линию можно занимать только при передаче. Потом надо отдавать другим устройствам, их на линии может быть несколько. Делается это переводом режима ноги на вход. К строке 33 - стандартная запись установки бита. Реально сдвига нет. Бит определяется на этапе компиляции. Позволяет легко и понятно использовать стандартные определения битов.
80,108 пока переменная больше нуля.
104 ask не из предыдущей функции. Это признак последнего байта в посылке.
SDA_Hi SDL_Hi отпускание линии. Линия подтянута резисторами к +. Поэтому отпускание переводит в высокое состояию линию.
хм, вчера сидел с нанкой, выводил в мониторинг значения, вроде сдвиг был..но щас не смогу вспомнить, то есть если мы запишем вот это "I2C_out |= (1 << SDA_Pin);//SDA_Pin-0010, опять таки, зачем делаем сдвиг?"
вот так
I2C_out =I2C_out|SDA_Pin
будет то де самое?
получается нормальное бездействнное состояние у нас это когда оба провода подтянуты к +, как понял
хм, вчера сидел с нанкой, выводил в мониторинг значения, вроде сдвиг был..но щас не смогу вспомнить, то есть если мы запишем вот это "I2C_out |= (1 << SDA_Pin);//SDA_Pin-0010, опять таки, зачем делаем сдвиг?"
вот так
I2C_out =I2C_out|SDA_Pin
будет то де самое?
получается нормальное бездействнное состояние у нас это когда оба провода подтянуты к +, как понял
Посмотрите файл c:\Program Files (x86)\Arduino\hardware\tools\avr\avr\include\avr\iotnx5.h там описаны все регистры. SDA_pin объявлен как PB2. PB2 объявлен как 2. I2C_out =I2C_out| 2 не равноI2C_out |= (1 << 2);
(1 << 2) равно 4 или В00000100; 2 равно В00000010
Бездействие = единице при передаче = подтянуты к + = состояние вход пина для данной реализации i2c
Написав I2C_out |= (1 << SDA_Pin); мы не делаем сдвиг. Компилятор преобразует такую запись к виду I2C_out |= В00000100 - можно сразу так написать, но это будет ненаглядно.
Можно так. Только вывести время осталось.
что значат эти две строчки?
вот эти две отвечают за ноги мк, к которым будут подкл часы?
что значат эти две строчки?
вот эти две отвечают за ноги мк, к которым будут подкл часы?
первые две написаны неправильно, должно быть 1 и 0,
но их nik182 не использует, и тебе не нужно.
можешь убрать.
а SDA_Pin и SCL_Pin это номера ног I2C, как ты назывешь"к которым часы подлючены". В данном случае PB0 и PB2.
спасибо
а можно ведь этот код отладить на нанке? подключать только к пинам всем, кроме 4 и 5(которые ворде как обычо с ic2?) сам щас проверить не могу, чтобы потом врем не терять
что я делаю не так? часы подключены по питанию, подключены порты выводов к а1 и а2 нанки, но выдает только лиш
Хардварный I2C подключён к PC4, PC5. На Arduino NANO это А4, А5.
Хм, я думал таким Макаром получится любой пин использовать для связи по ic2...а на аттини 85 тогда куда, к 0 и к 2, как у автора изначально?
Отлаживал на нане. Все отлично отладилось.
Для наны А0 А1 должно быть
#define F_CPU 16000000UL
#define I2C_in PINС
#define I2C_out PORTС
#define I2C_dir DDRС
Использовать можно любой пин. Порты надо правильно прописывать и следить, что бы другие части программы их не задевали.
Получается я обращался не к тем пинас? Если бы захотел использовать d2 и d3, нужно было бы здесь #define I2C_in PINС ,,pin d указать? А первая строка что меняет?
Первая строка это частота процессора. От них зависят тайминги протокола. Порты и пины это разные стороны одного и того же. Взял пин от порта - обращайся к регистрам этого порта а не чужого. d2 d3 это пины PD2 PD3 порта D. Нужно использовать PIND,PORTD,DDRD.
А тайминги только на скорость выполнения влияют?
как отключить вывод портов перед переходм в спящий режим?
Что значит отключить вывод портов?
в рекомендациях по снижению энергопотребления сказано, что нужно отключить порты, чтобы нмичего не потребляли они, ибо аже если на выводах нет ничего(ничего к нему не подкл)он все равно может потреблять так
я как понял, нужно пины в low dвыставить
друзья, тоска, такое дело, подключил часики я все хорошо, рабатают(огромное спасибо всем и в отдельности тем, кто кинул кодом) если часики питать напрямую от gnd и vcc, то все гуд, но если я так их буду питать, то они будут оч много кушать, поэтому мой план таков - патаю их через пин, на который перед считыванием инфы подаю 1(4,4 вольта), но это все теория, так у меня получалось, но только на нанке, при подлючении vcc часов к пину обычному и при попытке залить код, выдает ошибку при загрузке скетча
Обычно ставят резистор 1к для развязки.
соединил пин с землей через 5,1 к резюк, та же история..
Програматор должен подключаться прямо к ноге, всё остальное через 1К. Иначе програматор должен персилить остальную перефирию при програмировании.
я уточню: то есть мне нужно от пина, с которого буду питать часы кинуть резюк именно на 1к, и от этого же пина я кидаю проводок на питание часов?
Нет, питание часов через 1к и обязательно за ним должна стоять емкость на 10 мкф или больше. Ни каких больше проводов кидать не надо. У вас же проблема с заливкой кода при подключенных часах? В таком варианте её не будет.
Да, все верно) а на энергопотреблении этот резюк на 1 к сказываться не будет? Или напряжение только теряться будет? Спасибо за ответы на мои, как кому-то может показаться, глупые вопросы)
Теряться будет около 0.1 вольта. На энергопотребление влиять не будет.
Я по всякому пробовал, в итоге остался у меня только один резюк, с ним вроде все работает, как нужно было правильно подключить конденсатор?
Между плюсом и минусом часов. Если он ещё не стоит не плате часов.
Хорошо, спасибо, поставим, а насколько рационально будет использовать какой-нибудь транзистор для замыкания цепи не на прямую?
Здесь такой же транзистор. Смысл что то дополнительного ставить? Ток часов существенно меньше максимально допустимого.
Просто тема тут была, там вовсе рекомендовали ставить стабилизатоп
Друзья, пипец, если вставить эту строчку в setup I2CInit (); 221 строчка из кода выше, то энергопотребление ниже 300 мкА не опускается...ввожу тиньку в pwr down, не понимаю, почему так, помогите разобраться, может что-то где-то подправить в коде? (Без этой строчки все зорошо) ну не считая того, что я не могу считывать время с часов)))
Эта команда переключает ноги на выход. Если что то к ним подключено и потребляет ток, то этот ток не будет зависить от спящего режима. Перед входом в спящий режим нужно ноги перевести в режим входа. После выхода из спящего режима ещё раз дать команду инициализации.
То есть на всякий случай можно все ноги перевести в режим low? Только тогда какой смысл в том, что мы что-то делаем в сетупе? Акромя сетупа вообще разве можно менять ноги - на вход или на выход они работают? Как это правильно сделать?
Или может эти пины как-то в low ставить?
Вообще I2CInit() какраз и переводит ноги на вход и включает подтягивающие резисторы. Попробуйте перед сном подтягивающие резисторы выключить командами
I2C_out &= ~(1 << SDA_Pin);
I2C_out &= ~(1 << SCL_Pin);
После сна вызвать I2CInit()
Nik182, спасибо, попробую, надеюсь поможет, я тут почитал за это время, по идее я ведь могу в ноль поставить эти пины, типа диджиталврайт(сда_пин, лов) а перед запросм времени как раз таки запускать айси2клиент? Да и (как пониааю, ваш код делает примерно то же самое/)вообще в лупе можно спокойно менять пины на вход//на выход? Уточняю)
Да делают то же самое, только одной командой, digitalWrite длинно и долго.
Менять направление можно в любой момент. Часто, когда ног мало вывод и ввод делают через одну ногу. Соответственно в цикле приходится переключать неправление. Перед обменом запускать I2CInit();
А можете вы расписать строчки кода в вашем предыдущем сообщении? Что значит каждый символ?
Есть тема, где это уже всё расписано и даже больше - разные способы записи одного и того же
http://arduino.ru/forum/programmirovanie/bitovye-operatsii
Хорошо расписано у них
https://www.arduino.cc/en/Reference/BitwiseXorNot
https://www.arduino.cc/en/Reference/BitwiseAnd
Спасибо, почитаем) ваш совет помог) только я пришел к выводу, ну собственно в даташите это тоже указано, что эта собака вотчдог кушает примерно 5 микроамперы....можно может поставить внешний кварц и уменьшить это значение?
я комменитровал как мог, помогите разобраться
Возьмите описание протокола i2c. Там всё расписано. Здесь реализация. К строке 34 - линию можно занимать только при передаче. Потом надо отдавать другим устройствам, их на линии может быть несколько. Делается это переводом режима ноги на вход. К строке 33 - стандартная запись установки бита. Реально сдвига нет. Бит определяется на этапе компиляции. Позволяет легко и понятно использовать стандартные определения битов.
80,108 пока переменная больше нуля.
104 ask не из предыдущей функции. Это признак последнего байта в посылке.
SDA_Hi SDL_Hi отпускание линии. Линия подтянута резисторами к +. Поэтому отпускание переводит в высокое состояию линию.
спасибо!)
хм, вчера сидел с нанкой, выводил в мониторинг значения, вроде сдвиг был..но щас не смогу вспомнить, то есть если мы запишем вот это "
I2C_out |= (1 << SDA_Pin);
//SDA_Pin-0010, опять таки, зачем делаем сдвиг?"
вот так
I2C_out =I2C_out|SDA_Pin
будет то де самое?
получается нормальное бездействнное состояние у нас это когда оба провода подтянуты к +, как понял
спасибо!)
хм, вчера сидел с нанкой, выводил в мониторинг значения, вроде сдвиг был..но щас не смогу вспомнить, то есть если мы запишем вот это "
I2C_out |= (1 << SDA_Pin);
//SDA_Pin-0010, опять таки, зачем делаем сдвиг?"
вот так
I2C_out =I2C_out|SDA_Pin
будет то де самое?
получается нормальное бездействнное состояние у нас это когда оба провода подтянуты к +, как понял
Посмотрите файл c:\Program Files (x86)\Arduino\hardware\tools\avr\avr\include\avr\iotnx5.h там описаны все регистры. SDA_pin объявлен как PB2. PB2 объявлен как 2. I2C_out =I2C_out| 2 не равно I2C_out |= (1 << 2);
(1 << 2) равно 4 или В00000100; 2 равно В00000010
Бездействие = единице при передаче = подтянуты к + = состояние вход пина для данной реализации i2c
Написав
I2C_out |= (1 << SDA_Pin); мы не делаем сдвиг. Компилятор преобразует такую запись к виду
I2C_out |=
В00000100 - можно сразу так написать, но это будет ненаглядно.Понял)
а ф-я для того, чтоб задать ежесекундное срабатыванеибудильника будет так выглядеть?
Похоже. Только писать надо не единицы, а 0х80 или В10000000. Почему сообразите?
Наверное потому что единицу мы должны в начало старш его полубайта записать, как понимаю можно еще сделать 1<<7
только вот почему то изначально на sqw у нас 5 в..
Осторжнее! 10000000 не равно В10000000. Очень сильно не равно. Я предпочитаю 0х80.
Может быть потому что в даташите написано активный низкий?
То есть при срабатывании будильника пин sqw будет прижат к 0?
Да.
хм, дак как тогда повесить прерыванеи на мк...инвертировать чтоли? там же вроде дуинка будится в том слуаче, если на не + подать, на ногу +
http://arduino.ru/Reference/AttachInterrupt
Здесь описание прерываний. Вaм нужна мода FALLING.
ааа) вон оно что) а это не будет расходовать лишнюю энергию, то, чтьо там почти всегда будет +
и еще такой вопрос есть, может таки моэжно сделать так, чтобы питать 3132 не от батарейки, и как-то в сон ее вгонять, чтобы работала как от батарейки?