Программный I2C

Поклонники продукции Microchip Technology Inc тусуются тут.
Ответить
Родился
Аватара пользователя
Сообщения: 8
Зарегистрирован: Пт апр 25, 2014 10:21:54

Сообщение Demetros »

Доброго времени суток!
Столкнулся с проблемой при реализации программного I2C. Суть такова: микроконтроллер PIC16F876A работает в паре с DS1307. Это нечто вроде будильника. Я задаю время(в программе это 00:00:00), часы тикают и при достижении заданного времени (5 секунд) зажигается, например, светодиод (на самом деле проект куда более серьезный, данный пример лишь упрощение). I2C повесил на RC6 и RC7. Все работает стабильно, прием и передача идет, но проблема в том, что на порт С больше ничего повесить нельзя. После того как зажигается светодиод, сбивается прием/передача. Перепроверял много раз, нигде в коде весь порт не участвует, оперирую только отдельными пинами. Помогите, пожалуйста, найти ошибку и освободить оставшиеся пины порта С. Программу на си и проект в Proteus 7.10 SP0 прилагаю.
Заранее благодарен.
Вложения
DS1307.rar
(164.03 КБ) 372 скачивания
Реклама
Держит паяльник хвостом
Сообщения: 903
Зарегистрирован: Сб сен 11, 2010 17:32:42

Сообщение cahek80 »

можно вопрос? а зачем скобки в (RC2=1) в строке if (sec==5) (RC2=1);
Не нужно дергать спящего тигра за усы! Не высыпается 3-ий день!
Реклама
Родился
Аватара пользователя
Сообщения: 8
Зарегистрирован: Пт апр 25, 2014 10:21:54

Сообщение Demetros »

В принципе они там действительно не нужны, это наверно моя привычка с QBasica и Pascal'а брать все в операторные скобки.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18785
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

не может это быть связано с тем, что для вывода сигналов и2ц вы пишите в регистр TRISC, а светодиод зажигаете совсем не так?

P.S. как все эти нестандартные возможности "якобы Си" затрудняют понимание программы!
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Держит паяльник хвостом
Сообщения: 903
Зарегистрирован: Сб сен 11, 2010 17:32:42

Сообщение cahek80 »

Demetros писал(а):В принципе они там действительно не нужны, это наверно моя привычка с QBasica и Pascal'а брать все в операторные скобки.
немного оффтоп, но как-то впервые встречаю подобные скобки еще с кубасика и паскалей... ))

и еще немного неясно, пока не на чем прошагать - SDA_IN Вы нигде в 0 не выставляете?
Не нужно дергать спящего тигра за усы! Не высыпается 3-ий день!
Реклама
Родился
Аватара пользователя
Сообщения: 8
Зарегистрирован: Пт апр 25, 2014 10:21:54

Сообщение Demetros »

ARV: По всем симптомам так и есть, будто в какой-то момент программы происходит управление всем портом, но в программе я оперирую TRISC6 и TRISC7 (направлением 6 и 7-й ножки), по идее остальные ноги остаются работать "на выход".

cahek80: В паскале вместо "()" используется "Begin End". Прошу прощения за кривой код, на скорую руку урезал ненужные части программы. На самом деле там стояла не одна функция "RC2=1", а несколько других, они и были объединены скобками.
По поводу SDA_IN, я вроде единожды выставляю в 0 при инициализации и больше не трогаю SDA_IN. Дальнейшее "общение" идет за счет изменения направления работы ножки и подтягивающих резисторов (если я конечно не ошибаюсь).
Реклама
Держит паяльник хвостом
Сообщения: 903
Зарегистрирован: Сб сен 11, 2010 17:32:42

Сообщение cahek80 »

begin end, хм тогда уж {}, а не () :)
про TRIS* и SDA_IN да, я понял, сам когда-то так рулил тоже. Но работало без сбоев. хз.
Не нужно дергать спящего тигра за усы! Не высыпается 3-ий день!
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

но в программе я оперирую TRISC6 и TRISC7 (направлением 6 и 7-й ножки)
А как Вы думаете, после перенаправления бита порта, что будет находится в защёлке ? Откуда такая уверенность, что там будет то, что у Вас на уме ? :)


ЗЫ: Курим -
http://www.microchip.ru/files/d-sheets-rus/pic16_9.pdf
http://www.microchip.ru/lit/?mid=1x0
Друг Кота
Сообщения: 4583
Зарегистрирован: Вс дек 05, 2010 06:10:34
Откуда: ЮВ

Сообщение HHIMERA »

Demetros писал(а): I2C повесил на RC6 и RC7. Все работает стабильно, прием и передача идет, но проблема в том, что на порт С больше ничего повесить нельзя. После того как зажигается светодиод, сбивается прием/передача. Перепроверял много раз, нигде в коде весь порт не участвует, оперирую только отдельными пинами.
Смотрите в сторону RMW... "оперирую только отдельными пинами" в этих ПИКах на самом деле является операцией с портом...
В последующих ПИках поэтому и ввели регистры LATx... У Микрочипа есть апнота на эту тему...
"Я не даю готовых решений, я заставляю думать!"(С)
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1262
Зарегистрирован: Пн дек 08, 2008 10:58:48
Откуда: Винница

Сообщение urry »

ну да, согласен с Химерой - RMW.
Я уже всегда в мк, в которых нет LAT, выделяю регистр, обзываю его LATX и меняю битики в нем, а его уже - целиком выдаю в порт.
Да, дольше, зато спишь спокойно.
Контактная информация:
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18785
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

urry писал(а):Я уже всегда в мк, в которых нет LAT, выделяю регистр, обзываю его LATX и меняю битики в нем, а его уже - целиком выдаю в порт.
я так понимаю, если бы было написано традиционно PORTC |= 1<<PC7; то никаких проблем не возникло бы? я с PIC-ами никогда в жизни дел не имел
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Друг Кота
Сообщения: 4583
Зарегистрирован: Вс дек 05, 2010 06:10:34
Откуда: ЮВ

Сообщение HHIMERA »

ARV писал(а):если бы было написано традиционно PORTC |= 1<<PC7; то никаких проблем не возникло бы?
Это и есть Read-Modify-Write...
Как сказал уже Юрий... лучше юзать "фантомный регистр" и через XOR...
"Я не даю готовых решений, я заставляю думать!"(С)
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18785
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

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

что написал я, так это то же самое! это сокращенная запись PORTC = PORTC | (1<<PB7); то есть в промежуточную переменную (ее компилятор должен создать сам - автоматические переменные обычно бывают как раз регистровыми) считывается порт, над ним выполняется операция модификации, а затем результат записывается обратно в порт.

что не так?
Последний раз редактировалось AlekseyEnergo Вс май 04, 2014 20:02:39, всего редактировалось 1 раз.
Причина: Нарушение пункта 2.7 правил форума. Подредактировал. Предупрежден!
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

ARV писал(а):PORTC = PORTC | (1<<PB7); то есть в промежуточную переменную (ее компилятор должен создать сам - автоматические переменные обычно бывают как раз регистровыми) считывается порт, над ним выполняется операция модификации, а затем результат записывается обратно в порт.
что не так?
Оптимизатор убьёт эти все предположения и вставит единственную команду bsf (установка бита в регистре).
У ТС'а проблема в другом. Я уже пытался ему намекнуть, ссылочку кинул, чтобы он почитал хоть немного и покумекал. Но тут некоторые не выдержали и открыли тайну напрямую :)
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18785
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

Аlex писал(а):Оптимизатор убьёт эти все предположения и вставит единственную команду bsf (установка бита в регистре).
если PORTC определен, как volatile-переменная, оптимизатор не имеет на это права. но если это так - я пас, к PIC-ам ни рукой ни ногой :)))
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Друг Кота
Сообщения: 4583
Зарегистрирован: Вс дек 05, 2010 06:10:34
Откуда: ЮВ

Сообщение HHIMERA »

Угу... "Гложут меня смутные сомнения!"(С)
AVR Studio 4.18... Mega16A...

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

23:       asm("nop");
+000000CE:   0000        NOP                      No operation
25:       PORTC = PORTC | (1<<PB7); 
+000000CF:   9AAF        SBI       0x15,7         Set bit in I/O register
27:       asm("nop");
+000000D0:   0000        NOP                      No operation
29:       PORTC |= (1<<PB7); 
+000000D1:   9AAF        SBI       0x15,7         Set bit in I/O register
Последний раз редактировалось HHIMERA Пт апр 25, 2014 22:03:55, всего редактировалось 1 раз.
"Я не даю готовых решений, я заставляю думать!"(С)
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

ARV писал(а):не имеет на это права
Мне кажется, Вы заблуждаетесь.
volatile тут совсем не причём. Ну не убьёт компилятор совсем эту строку, если посчитает нужным, но никак не будет создавать ещё переменную. С какой радости ? :)

ЗЫ: Не путайте с языком java. Там строки, типа a=a+1; и a+=1; не эквивалентны. Для Си - это одно и тоже...
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18785
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

Аlex писал(а):Мне кажется, Вы заблуждаетесь.
volatile тут совсем не причём. Ну не убьёт компилятор совсем эту строку, если посчитает нужным, но никак не будет создавать ещё переменную. С какой радости ? :)

ЗЫ: Не путайте с языком java. Там строки, типа a=a+1; и a++; не эквивалентны. Для Си - это одно и тоже...
а мне кажется - вы заблуждаетесь :) что касается java - то я знаю ее (или его?) на уровне "смотрю в книгу - вижу фигу".

если переменная объявлена как volatile, то компилятор не имеет права выкинуть любое обращение к ней.

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

int var; 
volatile int vol;

var;
vol;
здесь обращение к var компилятор имеет право выкинуть, а обращение на чтение к vol - не имеет. соответственно в операторе vol |= 1; произойдет обязательное считывание содержимого переменной в промежуточную переменну, а затем модифицированный результат промежуточной переменной запишется обратно. более того, если написать var = vol + vol + vol; то компилятор не будет иметь права заменить это на var = vol * 3; - он так и будет трижды считывать vol!!!

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

Мой уютный бложик... заходите!
Контактная информация:
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

Ну я даже и не знаю что сказать...

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

int main(int argc, char **argv) {
int a;
volatile int b;

while(1){

	a = a | (1<<7);
	a |= (1<<7);

	b = b | (1<<7);
	b |= (1<<7);
}
}

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

29        	a = a | (1<<7);
080002f6:   ldr r3, [r7, #12]
080002f8:   orr.w r3, r3, #128      ; 0x80
080002fc:   str r3, [r7, #12]
30        	a |= (1<<7);
080002fe:   ldr r3, [r7, #12]
08000300:   orr.w r3, r3, #128      ; 0x80
08000304:   str r3, [r7, #12]
32        	b = b | (1<<7);
08000306:   ldr r3, [r7, #8]
08000308:   orr.w r3, r3, #128      ; 0x80
0800030c:   str r3, [r7, #8]
33        	b |= (1<<7);
0800030e:   ldr r3, [r7, #8]
08000310:   orr.w r3, r3, #128      ; 0x80
08000314:   str r3, [r7, #8]
IDE - CooCox. компилятор, как я понял, - arm-none-eabi.
:dont_know:
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18785
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

пока и я не вижу, что вы хотели сказать :)

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

а вот вам примерчик для AVR:

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

   PORTB = var + var + var;
  7c:	90 91 61 00 	lds	r25, 0x0061
  80:	89 2f       	mov	r24, r25
  82:	88 0f       	add	r24, r24
  84:	89 0f       	add	r24, r25
  86:	88 bb       	out	0x18, r24	; 24
   PORTB = vol + vol + vol;
  88:	20 91 60 00 	lds	r18, 0x0060
  8c:	80 91 60 00 	lds	r24, 0x0060
  90:	90 91 60 00 	lds	r25, 0x0060
  94:	82 0f       	add	r24, r18
  96:	89 0f       	add	r24, r25
  98:	88 bb       	out	0x18, r24	; 24
как видите, в первом случае считывание в регистр было 1 раз, а потом этот регистр плюсовался к исходному, а во втором случае считывание переменной сделано трижды :)))
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Ответить

Вернуться в «PIC»