|
Странное поведение портов!, Мега32 - что может быть??? |
|
|
|
May 16 2006, 13:34
|
Местный
  
Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526

|
Такая ситуация - Мега32, частота 16М, порт В - подключен LCD (2x16), причем по четырехпроводной схеме. Работают старшие линии РВ(7,6,5,4). При обращении к дисплею, на младшие линии выдаются нули. Обращение к дисплею происходит в основном цикле программы. Далее, к порту В также подключено устройство, имеющее 4 выходных линии, на которых присутствует поочередно "1" на каждой линии. Состояние, когда все 4 линии "0" исключено. Опрос этих линий происходит по прерыванию (1 раз в 20 мс). Программа обработки прерывания считывает состояние регистра DDRB, переводит младшие линии порта В на прием, считывает состояние порта В (PINB), возвращает DDRB в исходное состояние, и передает управление основному телу программы. И все бы ничего, если бы не ситуация - если прерывание возникает в период работы функции вывода данных на дисплей (т.е. когда на младшие линии подаются "0"), то в прерывании считываются именно "0"!!! После переключения линий порта В на прием, делаю паузу (до 10 мксек), ничего не меняется. Т.о., это не паразитные емкости. А вот если перед переключением порта на прием, выдать на младшие линии порта "1", то все становится на свои места - данные считываются нормально. Помогите разобраться в чем дело...
|
|
|
|
|
 |
Ответов
(1 - 50)
|
May 16 2006, 13:58
|
Местный
  
Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526

|
Цитата(_artem_ @ May 16 2006, 17:53)  Приведенная вами ситуация может быть когда вы читаете к примеру статус бит из ЛСД когда происходит прерывание. Нет - я вообще ничего не читаю из LCD!!! Мало того, если я отсоединяю LCD то ничего ровным счетом не меняется! Дело не в дисплее. Я выдаю на мл. линии "0", переключаю порт на прием, выжидаю паузу - и читаю. И читаю те самые нули, которые я же туда и выдал.
|
|
|
|
|
May 16 2006, 14:04
|
Местный
  
Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526

|
Цитата(WHALE @ May 16 2006, 18:01)  а читаете через PINB? Именно!, причем, после переключения порта на прием, выжидаю паузу в несколько тактов.
|
|
|
|
|
May 16 2006, 14:25
|
Местный
  
Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526

|
Цитата(_artem_ @ May 16 2006, 18:12)  Единственное не понимаю - устройство у вас которое к младшим разрядам подсоединено - с тремья состояниями ? Если нет как вы можете ставить порт на передачу (при записи в ЛСД) а потом на прием для чтения из устройства? А зачем вам всякий раз записывать нули перед переключением направления прота ? вроде бы у вас до этого и ноль должен быть. А если уsтройство отключаете как и ЛСД тоже нули читаются ? Устройство подключено через резисторы, поэтому, когда порт В работает на передачу, дисплей воспринимает то, что передает контроллер, устройство не мешает, да и интерфейс четырехпроводный, младшие биты дисплеем игнорируются. Что касается выдачи данных, то для того, чтобы передать байт в дисплей по четырехпроводному интерфейсу, нужно проделать следующее: OutPort(data & 0xf0) OutPort(data << 4) т.о. младшие биты передаются нулями. Если я отключаю устройство от порта, то я не могу различить то ли я читаю те нули, что передал сам же, то ли это те нули, которые вызваны отсутствием устройства на шине.
|
|
|
|
|
May 16 2006, 14:37
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(Sergio66 @ May 16 2006, 17:25)  Если я отключаю устройство от порта, то я не могу различить то ли я читаю те нули, что передал сам же, то ли это те нули, которые вызваны отсутствием устройства на шине. Если у вас нет внешних Pull-up резисторов, а подключенное к младшим выводам порта B устройство имеет выход с ОК, тогда ваша ситуация вполне объяснима. При записи в PortB 1 - подключается соответствующий внутренний Pull-up резистор и вы считываете из PinB - 1, если в PortB записан 0, то соответствующий внутренний Pull-up резистор отключен и вы считываете из PinB - 0. Да, вы читаете то же самое, что находится в PORTB. Простейший выход из ситуации - всегда держать Pull-up's младшей тетрады порта B подключенными: OutPort(data | 0x0f) OutPort(data << 4 | 0x0f)
|
|
|
|
|
May 16 2006, 14:44
|
Местный
  
Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526

|
Цитата(_artem_ @ May 16 2006, 18:33)  навесте пулап резисторы - 1 ком вместо устройства а затем проведите опыт с прочитыванием без устройства и без ЛСД. Доп. устройство итак подвешено через пулап резисторы в 1 К. И картина именно такая, как я обрисовал. Я выдаю в порт нули, затем переключаю порт на прием (устройство передает что-то, но т.к. оно через резисторы, то сигнал контроллера силнее) и читаю состояние порта. И вижу там нули, именно те, которые передал!, а не данные от устройства.
|
|
|
|
|
May 16 2006, 14:59
|
Местный
  
Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526

|
Цитата(defunct @ May 16 2006, 18:37)  Цитата(Sergio66 @ May 16 2006, 17:25)  Если я отключаю устройство от порта, то я не могу различить то ли я читаю те нули, что передал сам же, то ли это те нули, которые вызваны отсутствием устройства на шине.
Если у вас нет внешних Pull-up резисторов, а подключенное к младшим выводам порта B устройство имеет выход с ОК, тогда ваша ситуация вполне объяснима. При записи в PortB 1 - подключается соответствующий внутренний Pull-up резистор и вы считываете из PinB - 1, если в PortB записан 0, то соответствующий внутренний Pull-up резистор отключен и вы считываете из PinB - 0. Да, вы читаете то же самое, что находится в PORTB. Простейший выход из ситуации - всегда держать Pull-up's младшей тетрады порта B подключенными: OutPort(data | 0x0f) OutPort(data << 4 | 0x0f) Если я правильно Вас понял, то младшая тетрада порта В должна быть на прием всегда, и с подтягивающими резисторами? А я пробовал так - при переключении на прием младщей тетрады, подключаю пуллап на этих выводах. Эффект нулевой.
|
|
|
|
|
May 16 2006, 15:18
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(Sergio66 @ May 16 2006, 17:59)  Если я правильно Вас понял, то младшая тетрада порта В должна быть на прием всегда, и с подтягивающими резисторами? А я пробовал так - при переключении на прием младщей тетрады, подключаю пуллап на этих выводах. Эффект нулевой. Да, предполагается, что младшая тетрада всегда настроена на ввод с внутренними подтягивающими резисторами (без внешних). Хотя вообще-то странно. Можете более подробно обрисовать ситуацию? Если отключить LCD и код отвечающий за его работу, оставить только устройство подключенное к младшей тетраде порта B. Правильно ли считываются состояния порта? Цитата Программа обработки прерывания считывает состояние регистра DDRB, переводит младшие линии порта В на прием, считывает состояние порта В (PINB), возвращает DDRB в исходное состояние, и передает управление основному телу программы. Зачем эти телодвижения с DDRB? Не хотите ли вы сказать, что управляющие пины LCD подключены параллельно с неким устройством к младшей тетраде порта B? Обрисуйте точную схему подключения LCD (7 пин) и устройства (4 пина) к вашему МК.
|
|
|
|
|
May 16 2006, 15:34
|
Местный
  
Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526

|
Цитата(defunct @ May 16 2006, 19:18)  Цитата(Sergio66 @ May 16 2006, 17:59)  Если я правильно Вас понял, то младшая тетрада порта В должна быть на прием всегда, и с подтягивающими резисторами? А я пробовал так - при переключении на прием младщей тетрады, подключаю пуллап на этих выводах. Эффект нулевой.
Да, предполагается, что младшая тетрада всегда настроена на ввод с внутренними подтягивающими резисторами (без внешних). Хотя вообще-то странно. Можете более подробно обрисовать ситуацию? Если отключить LCD и код отвечающий за его работу, оставить только устройство подключенное к младшей тетраде порта B. Правильно ли считываются состояния порта? Если отключаем LCD, и код, его обслуживающий, то все работает правильно. Мало того, если прерывание возникает не в период обращения к дисплею, то тоже все нормально. Функция работы с LCD настраивает старшую тетраду на выход, младшая - остается на прием. Выдаются данные в порт, далее выплняются другие ф-ии, не имеющие к порту В никакого отношения. Вотом, возникает прерывание для опроса порта В. Эта ф-я настраивает младшую тетраду на прием, опрашивает порт, восстанавливает состояние DDRB, и выходит. Вот тут то вся собака и роется.
|
|
|
|
|
May 16 2006, 15:45
|
Местный
  
Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526

|
Да, есть один нюанс, я его упустил для упрощения описания ситуации - устройство сидит не на PB0 - 3, а на линиях PB0, PB1, PB3, PB4. Т.е. линия РВ4 работает и на дисплей и на доп устройство. И перенастраиваю я именно эти линии. Только, в моем понимании это мало что меняет. Я выдал в порт данные, перенастроил порт на прием, т.е., если судить по даташиту, отключил выходной каскад контроллера от пина, и читаю этот пин. На нем должно присутствовать то, что установило внешнее устройство, т.к. дисплей абсолютно пассивет, да и его может и не быть.
|
|
|
|
|
May 16 2006, 15:59
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(Sergio66 @ May 16 2006, 18:45)  Да, есть один нюанс, я его упустил для упрощения описания ситуации - устройство сидит не на PB0 - 3, а на линиях PB0, PB1, PB3, PB4. Т.е. линия РВ4 работает и на дисплей и на доп устройство. И перенастраиваю я именно эти линии. Только, в моем понимании это мало что меняет. Я выдал в порт данные, перенастроил порт на прием, т.е., если судить по даташиту, отключил выходной каскад контроллера от пина, и читаю этот пин. На нем должно присутствовать то, что установило внешнее устройство, т.к. дисплей абсолютно пассивет, да и его может и не быть. Решение с места (если точность интервала опроса не сильно важна): запрещать прерывания на входе в функцию обращения к LCD, разрешать - на выходе из этой функции. Если же точность интервала опроса важна. С учетом последнего вашего поста, было бы неплохо взглянуть на код обработчика прерывания, может быть там что-то не так...
|
|
|
|
|
May 16 2006, 18:58
|

учащийся
    
Группа: Свой
Сообщений: 1 065
Регистрация: 29-10-05
Из: города контрастов
Пользователь №: 10 249

|
Я Вас может быть неправильно понял но не могу интерпретировать эти предложения с одним смыслом :
"Нет - я вообще ничего не читаю из LCD!!! Мало того, если я отсоединяю LCD то ничего ровным счетом не меняется! Дело не в дисплее. Я выдаю на мл. линии "0", переключаю порт на прием, выжидаю паузу - и читаю. И читаю те самые нули, которые я же туда и выдал."
и вот это :
"Если отключаем LCD, и код, его обслуживающий, то все работает правильно. Мало того, если прерывание возникает не в период обращения к дисплею, то тоже все нормально. Функция работы с LCD настраивает старшую тетраду на выход, младшая - остается на прием."
--------------------
Зачем лаять на караван , когда на него можно плюнуть?
|
|
|
|
|
May 16 2006, 20:05
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(_artem_ @ May 16 2006, 21:58)  Я Вас может быть неправильно понял но не могу интерпретировать эти предложения с одним смыслом :
"Нет - я вообще ничего не читаю из LCD!!! Мало того, если я отсоединяю LCD то ничего ровным счетом не меняется! Дело не в дисплее. Я выдаю на мл. линии "0", переключаю порт на прием, выжидаю паузу - и читаю. И читаю те самые нули, которые я же туда и выдал."
и вот это :
"Если отключаем LCD, и код, его обслуживающий, то все работает правильно. Мало того, если прерывание возникает не в период обращения к дисплею, то тоже все нормально. Функция работы с LCD настраивает старшую тетраду на выход, младшая - остается на прием." Связать можно, в первом случае, я полагаю, код, обслуживающий LCD, не был отключен. А просто был отсоединен экран. Во втором случае код отключен тоже. Проблема помоему очевидна, и скрывается в коде, обслуживающем LCD. Похоже, что операция вывода байта на экран должна быть атомарной операцией (нельзя переключать порт передав только старшую тетраду данных). Как уже писал ранее, один из путей решения проблемы - запрещать прерывания, на время работы с LCD.
|
|
|
|
|
May 16 2006, 23:06
|
Участник

Группа: Новичок
Сообщений: 38
Регистрация: 12-09-05
Пользователь №: 8 464

|
[/quote] Что касается выдачи данных, то для того, чтобы передать байт в дисплей по четырехпроводному интерфейсу, нужно проделать следующее:
OutPort(data & 0xf0) OutPort(data << 4)
т.о. младшие биты передаются нулями. Если я отключаю устройство от порта, то я не могу различить то ли я читаю те нули, что передал сам же, то ли это те нули, которые вызваны отсутствием устройства на шине. [/quote]
Вообще-то если предвидится прерывание кода изменения состояния порта иной подпрограммой которая может изменять состояние того же порта то логично делать примерно так
cbr Data,0b00001111; сброс мл. части команды/данных cli; in CopyPort,Port; cbr CopyPort,0b11110000; сброс ст. части состояния порта or CopyPort,Data; получили в старшей части то что надо out Port,CopyPort; sei; и состояние мл. части порта осталось неизменным
|
|
|
|
|
May 17 2006, 05:54
|
Местный
  
Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526

|
Цитата(_artem_ @ May 16 2006, 22:58)  Я Вас может быть неправильно понял но не могу интерпретировать эти предложения с одним смыслом :
"Нет - я вообще ничего не читаю из LCD!!! Мало того, если я отсоединяю LCD то ничего ровным счетом не меняется! Дело не в дисплее. Я выдаю на мл. линии "0", переключаю порт на прием, выжидаю паузу - и читаю. И читаю те самые нули, которые я же туда и выдал."
и вот это :
"Если отключаем LCD, и код, его обслуживающий, то все работает правильно. Мало того, если прерывание возникает не в период обращения к дисплею, то тоже все нормально. Функция работы с LCD настраивает старшую тетраду на выход, младшая - остается на прием." В первом случае отключался только LCD, во втором - и код, его обслуживающий.
|
|
|
|
|
May 17 2006, 06:40
|
Местный
  
Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526

|
Цитата(_artem_ @ May 17 2006, 01:23)  Мне это так не кажется - передача тетрады для порта половина которого работает не передачу а остальная на прием как такового значение не имеет - в любом случае в PORTB регистр записывается байт. Для авр все равно и я честно говоря не видел ограничений на манипуляцию с gpio портами (было маленькое примечание о переходе с приема на передачу и наоборот и то что при чтении порт опаздывает как минимум на один машинный цикл но не 10 микросек при 16 МГц тактовой). Если предположить что нули выдаются дисплеем потому что может затягиватся сигнал Е на входе дисплея и при этом дисплей каким то макаром работает на передачу - не подтверждается так как без физически подключенного дисплея те же самые нули (если я правильно понял написанное). Без кода и схемы никак . Это код вывода байта в дисплей void LCD_Write (unsigned char CMD, char type) { char Data; CONFIG_CONTROL_PINS; /*#define CONFIG_CONTROL_PINS LCD_E_PORT_DIR |=(1<<LCD_E_PIN); LCD_RS_PORT_DIR |= (1<<LCD_RS_PIN); LCD_RW_PORT_DIR |=(1<<LCD_RW_PIN);*/ SET_DATA_LINES_OUT; /*#define SET_DATA_LINES_OUT LCD_DATA_PORT_DIR = ((1<<LCD_D4) | (1<<LCD_D5) | (1<<LCD_D6) | (1<<LCD_D7))*/ CLEAR_LCD_E; // Disable LCD if (type == DATA) SET_LCD_DATA; else SET_LCD_CMD; // Set LCD to command OUT_DATA_PORT(CMD & 0xf0); //выдаем в порт старший полубайт /* #define OUT_DATA_PORT(data) SET_LCD_READ; CLEAR_DATA_PINS; LCD_DATA_PORT |=0;/*data*/ ;SET_LCD_WRITE*/ GENERATE_E_STROB; // Write data to LCD OUT_DATA_PORT(CMD <<4); //выдаем в порт младший полубайт GENERATE_E_STROB; // Write data to LCD Short_Delay(50); } А вот так выглядит та часть обработчика прерывания, которая опрашивает доп. устройство: char PORTB_config = DDRB; DDRB &= ~((1<<PB0) | (1<<PB1) | (1<<PB3) | (1<<PB4)); __delay_cycles(10); //10 тактов генератора if ((PINB & 0x1b) ) { if (PT_status & PT_LINE_ACTIVE) PT_status |= PT_ACTIVE; else PT_status |=PT_LINE_ACTIVE; } else { if (PT_status & PT_LINE_ACTIVE) PT_status &=~PT_LINE_ACTIVE; else PT_status &= ~PT_ACTIVE; } DDRB = PORTB_config; Вот, так обстоят дела. На сегодня доподлинно мне известно, что весь бардак из-за линии РВ5 (общей у LCD и доп. устройства). Всегда читается последний записанный бит (в случае, если прерывание встряло в работу функции обмена с дисплеем), а не фактическое состояние линии доп. устройства. /* #define OUT_DATA_PORT(data) SET_LCD_READ; CLEAR_DATA_PINS; LCD_DATA_PORT |=0;/*data*/ ;SET_LCD_WRITE*/ Пардон, в этой строчке опечатка - это было сделано в проверочных целях, на самом деле все обстоит так: /* #define OUT_DATA_PORT(data) SET_LCD_READ; CLEAR_DATA_PINS; LCD_DATA_PORT |=data ;SET_LCD_WRITE*/
Эскизы прикрепленных изображений
|
|
|
|
|
May 17 2006, 10:35
|
Местный
  
Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526

|
Цитата(_artem_ @ May 17 2006, 14:06)  Можно отрассировать по выходу из обработчика прерывания содержимое стека, точнее адресс куда программа вернется после инструкции RETI когда проблема произошла? Можно прямо перед выходом из обработчика прерываний в одну переменную сохранить содержимое стека а в другую флаг присутствия проблемы установленный в : if ((PINB & 0x1b) ) { ....... } else { flag = 1; }
потом в конце вывода в дисплей проверить флаг и если он установлен вывести значение стека на дислпеы или уарт и затем сбросить флаг после . И потом конечно листинг ассемблера с С кодом вместе (как минимум куска на кторый указывает стек).
Еше один вопрос - читается ли 0 все время когда вывод на лсд или иногда ?
Можно также на время OUT_DATA_PORT запретить прерывание dlja vyvoda obeix tetrad :
__disable_interrupts(); OUT_DATA_PORT; __enable_interrupts();
и сообшить результат. При чтении порта РВ4 я вижу то, что быо выдано на эту линию в обработчике дисплея только в том случае, если прерывание возникло во время обмена с дисплеем.
|
|
|
|
|
May 17 2006, 11:54
|
Местный
  
Группа: Свой
Сообщений: 232
Регистрация: 22-02-06
Из: Воронеж
Пользователь №: 14 589

|
В общем так: Самый простой выход из ситуации это, как уже говорилось Цитата запрещать прерывания, на время работы с LCD Если это недопустимо и если точно известно, что период следования прерываний больше времени работы обслуживателя LCD, то можно сделать так: Код char flag = 0; // флаг разрешения обслуживания LCD ................. while ( flag == 0 ); // ждать, пока небыло прерывания [LCD] // процедура обслуживания LCD flag = 0; // запретить обслуживание LCD
................. // в конце обработчика прерывания if ( flag == 0 ) { flag = 1; } // если был запрет на обслуживание LCD, то разрешить его. Успехов.
--------------------
Истина рождается в спорах; но когда страсти кипят, истина испаряется.
|
|
|
|
|
May 17 2006, 15:49
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(Sergio66 @ May 17 2006, 18:35)  Я только что проделал такой эксперимент - я отключтл дисплей, отключил доп. устройство и запустил программу так, как будто все подключено. Только функция работы с дисплеем выдает все "1" во все линии порта В. В обработчике прервания я вижу PINB в "1"! Т.е. ноги висят в воздухе, я выдаю на них "1", потом переключаюсь на прием, и вижу на них те же "1"! Может быть я просто имею "битую" микросхему? Нет  микросхема не битая. Вы выводите 1 в Port, тем самым вы подключаете внутренний Pull-up резистор, и МК ведет себя совершенно адекватно считывая 1 с соответствующего PinX. Проведите пожалуйста такой эксперимент как вам посоветовал _artem: __disable_interrupts(); OUT_DATA_PORT; __enable_interrupts(); или: asm("cli"); //вывод обеих тетрад на LCD asm("sei"); Должно все работать
|
|
|
|
|
May 19 2006, 09:22
|
Местный
  
Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526

|
Цитата(defunct @ May 17 2006, 19:49)  Цитата(Sergio66 @ May 17 2006, 18:35)  Я только что проделал такой эксперимент - я отключтл дисплей, отключил доп. устройство и запустил программу так, как будто все подключено. Только функция работы с дисплеем выдает все "1" во все линии порта В. В обработчике прервания я вижу PINB в "1"! Т.е. ноги висят в воздухе, я выдаю на них "1", потом переключаюсь на прием, и вижу на них те же "1"! Может быть я просто имею "битую" микросхему?
Нет  микросхема не битая. Вы выводите 1 в Port, тем самым вы подключаете внутренний Pull-up резистор, и МК ведет себя совершенно адекватно считывая 1 с соответствующего PinX. Проведите пожалуйста такой эксперимент как вам посоветовал _artem: __disable_interrupts(); OUT_DATA_PORT; __enable_interrupts(); или: asm("cli"); //вывод обеих тетрад на LCD asm("sei"); Должно все работать Это на результат не влияет. Т.к. я уже выдал "1" на линии, запрет прерываний не имеет в данном случае ровно никакого значения, т.к. в процедуре обработки прер-я я переключаю линии на прием, и "1" после этого в них не выдаю, так, что пулл ап резисторы я не подключаю. Но читаю на пинах то ,что выдал в порт.
|
|
|
|
|
May 19 2006, 12:13
|
Местный
  
Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526

|
Цитата(_artem_ @ May 19 2006, 15:55)  Sergio66, можно ли сделать так : - прямо в ISR устройства проверить на состояние "все нули" и если да то получить содержимое памяти по адресу SP + 2 (стек), и выдать его на какое то устройство (уарт или чтото в этом вроде) - откомпилировать программу без оптимизации и получить ассеемблерный листинг вперемешку с C кодом - и все это выставить здесь (можно лишь кусок программы ) с указанием адреса откуда программа прервалась. Все это наверное можно проделать. Но хотелось бы разобраться в чем дело. Вот еще такой эксперимент - все ноги РВ притянул к массе через 5,6 К. Обставил вывод на дисплей запретами прерываний. Теперь прерывание не влезает в процесс работы с дисплеем. Передаю в дисплей только "0", при этом дополнительное устройство работает и на одной из 4 его линий постоянно присутствует "1". Линия РВ4 - общая у дисплея и доп. устр. На нее я выдаю "0". И вот, что интересно, когда в отладчике программа останавливается при чтении из порта РВ4 "0", то AVRSTUDIO мне верно показывает наличие "1" на линии РВ4. Т.е. те сигналы, которые генерит доп. устройство на линии РВ0,1,3 читаются нормально, а вот РВ4, куда я выдал "0", читается как "0", хотя доп. устройство выдало туда "1". А отладчик показывает верно - наличие "1".
|
|
|
|
|
May 19 2006, 12:46
|
Местный
  
Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526

|
Цитата(_artem_ @ May 19 2006, 15:55)  Sergio66, можно ли сделать так : - прямо в ISR устройства проверить на состояние "все нули" и если да то получить содержимое памяти по адресу SP + 2 (стек), и выдать его на какое то устройство (уарт или чтото в этом вроде) - откомпилировать программу без оптимизации и получить ассеемблерный листинг вперемешку с C кодом - и все это выставить здесь (можно лишь кусок программы ) с указанием адреса откуда программа прервалась. Кроме всего прочего, мне удалось выяснить (в отличие от того, что я писал ранее), не имеет значения где прервана программа. Я проделал со стеком то, что Вы написали, и увидел, что прерывание возникло в момент довольно длительных арифметических вычислений, абсолютно не затрагивающих работу с периферией. Т.е. не в том дело, что прерван процесс обмена с LCD, а в том, что данные выданы в линию, и остаются актуальными там несмотря на переключение порта на прием.
|
|
|
|
|
May 19 2006, 15:50
|
Участник

Группа: Новичок
Сообщений: 38
Регистрация: 12-09-05
Пользователь №: 8 464

|
Цитата(Sergio66 @ May 19 2006, 12:22)  Цитата(defunct @ May 17 2006, 19:49)  Цитата(Sergio66 @ May 17 2006, 18:35)  Я только что проделал такой эксперимент - я отключтл дисплей, отключил доп. устройство и запустил программу так, как будто все подключено. Только функция работы с дисплеем выдает все "1" во все линии порта В. В обработчике прервания я вижу PINB в "1"! Т.е. ноги висят в воздухе, я выдаю на них "1", потом переключаюсь на прием, и вижу на них те же "1"! Может быть я просто имею "битую" микросхему?
Нет :) микросхема не битая. Вы выводите 1 в Port, тем самым вы подключаете внутренний Pull-up резистор, и МК ведет себя совершенно адекватно считывая 1 с соответствующего PinX. Это на результат не влияет. Т.к. я уже выдал "1" на линии, запрет прерываний не имеет в данном случае ровно никакого значения, т.к. в процедуре обработки прер-я я переключаю линии на прием, и "1" после этого в них не выдаю, так, что пулл ап резисторы я не подключаю. Но читаю на пинах то ,что выдал в порт. Вам все толком говорят. Вы же сами выбрасываете эти 1 в порт. При переключении на вход это уже автоматом подтягивающие резисторы.
|
|
|
|
|
May 19 2006, 20:16
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(Sergio66 @ May 19 2006, 20:26)  If PORTxn is written logic one when the pin is configured as an input pin, the pull-up resistor is activated. Перевожу: Если в порт PORTxn записана "1" в то время, как этот порт (пин) настроен на прием, то pull-up резистор активизируется. В вашем переводе неточность, возьму на себя смелость ее исправить, ключевое слово выделено, лишний оборот "в то время, как" выброшен (в даташите его нет): Если в PORTX записана еденица когда этот пин сконфигурирован на ввод, пулап этого пина активизирован...Итого, еденица уже записана, неважно когда именно, в даташите это не конкретизируется. Может быть когда-то давно записана, может недавно, может в момент когда DDRX = 1, а может и в момент когда DDRX = 0. Но действовать на пулап эта (давно записанная) еденица будет только тогда, когда пин сконфигурирован на ввод (DDRX=0). И получается совсем другой смысл. Цитата Но не на оборот. Кто сказал, что не наоборот? Как только выполняется условие DDRX=0, PORTX=1, соответсвующий пулап будет действовать на PINX. Цитата Вы хотите сказать, что если последняя операция с выводом данных в порт закончилась выводом "1", то переключение порта на вход автоматом включает pull-up резисторы? Именно это и говорим. Цитата Судя по документации - это не так. В даташите нет такого утверждения, и не следует строить ложных домыслов, основанных на неверном переводе, к тому же на практике эти домыслы не подтверждаются. По сабжу: Почему-то у меня есть некоторая уверенность в том, что даже если вам удастся заставить считывать показания устройства правильно, то появится новая проблема с ошибками вывода на LCD экран (когда устройство своей "еденицей" будет давить 0 выводимый на LCD, либо наоборот нулем будет давить еденицу, недалеко так и попалить одно из двух или МК или устройство). На вашем месте, я бы давно уже подыскал любой другой свободный пин, и подключил бы к нему злополучный вывод устройства. Организовать "шару" это не такая уж простая задача как может показаться на первый взгляд.
|
|
|
|
|
May 20 2006, 00:05
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Применение развязки на резисторах мягко говоря некоректно. Видел когда-то в одном из синклеров. Правильным является применение буферного элемента (например АП5/6, ИР22/33, ТМ9, 561ЛН1 и т.д.) В крайнем случае, если хотите сэкономить примените диоды и подпорку. Хотя это и не совсем ... Далее ... при подключении двунаправленного устройства необходимо при переключении направления вывода уравнивать подпорку. Т.е. правильным является конструкция типа ... sbi portb,WR out portd,wl ; вывести wl в порт cbi portb,WR ; и подтвердить ldi wh,$0 ; на ввод out ddrd,wh ; порт ldi wh,$ff ; Порт подпереть out portd,wh данная прога при работе с FTDI245. Если последних две операции не выполнять, то возникают ошибки при чтении. Далее ... например при чтении клавиатуры или др. устр. имеющих большую ёмкость монтажа необходимо ... сначала читать потом выводить номер столбца потом пауза и цикл повторяется. При этом 200 мкс я бы оценил как малая задержка. Желательно хотябы 1мс ожидания с момента изменения на любой из линий. Учитывая Ваши резисторы 10мс. И последнее - у Вас, по моему, борьба со следствиями, а надо устранять причину. Т.е. реально любым предложенным способом разделить устройства (разные ноги, буферный элемент, диоды+подпорка) и разделить во времени программы их обслуживающие (например если имелось обращение к одному устройству, то перезапускается таймер отсчитывающий время до обращения к другому) Реализацию использования общей шины для нескольких устройств можно посмотреть в примере который выложил я - "Пульт I2C".
|
|
|
|
|
May 20 2006, 11:05
|
Местный
  
Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526

|
Цитата(_artem_ @ May 20 2006, 07:45)  атмега 32 может давать до десяти миллиампер на выходе без особо сушественного изменения напряжения , значит ток порядка 5 мА на выходе для сохранения быстродействия при чтения по входу с учетом резистора особых хлопот атмега не доставит. В данном случае 5 мА будет диктовать минимальное значение резистора - 1 кОм при 5 вольтах питания. Давайте возьмем значение резистора больше - 5 кОм. Теперь, максимальная входная емкость атмега для gpio равна 10 pF (таблица 119 стр 290). Для зашитного резистора значение которого мы предположили постоянная времени цепочки будет равна 10 пФ * 5 кОм = 50 наносекунд . Длительность такта процессора для частоты в 16 МГц равна 62.5 наносекунд . А так как 150-200 наносекунд достаточно для установления напряжения на входе атмега после переключения с режима выхода на вход и при том что Sergio ждет не менее чем 10 циклов (625 наносекунд) никаких проблем с входной емкостью по идее не должно быть..... если конечно Sergio использовал номинал резистора на основании которого построены эти предположения. Прошу поправить меня если ошибся.
Такой вопрос уважаемому Segio - сколько же все таки сопротивление резистора ?) У нас использованы резисторы 5,6 К
|
|
|
|
|
May 20 2006, 12:21
|
Местный
  
Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526

|
Цитата(_artem_ @ May 20 2006, 16:14)  Mozno postavit 1 kOm i poprobovat? Vi tak i ne soobshili o zamene porta na drugoy .
Vy oscillopgrafom na ustroystve i porte merili (pri delitele 1:10 chtob emklsot malaya byla)? Пока не сделали. Сейчас хотим подключить вообще другую плату. Паяем JTAG.
|
|
|
|
|
May 20 2006, 21:53
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Ребята, можно делать всё!!! Можно бриться кривой бритвой из-за угла!!! Но зачем??? Я видел различные нестандартные применения стандартных микрух. Но ни разу не видел, с моей точки зрения, обоснованности такого использования! Ни разу мне ни хотелось это повторить. Если это единичное изделие, тогда я ещё как-то могу понять и объяснить простой ленью.
Многолетний опыт показывает что попытка оживления и эксплуатации кривой схемы или программы обходится дороже с точки зрения времени и затрат труда. И, как правило, в конце всё таки меняешь на нормальное!!! Так зачем начинать??? Выяснил что это НЕПРАВИЛЬНО, - сел и перепаял. Отдал день. И двигайся дальше!
С уважением. Просто высказываю свою точку зрения. Мне жутко жалко своего времени. У меня его мало осталось. И мне действительно жалко Вашего, времени потраченного впустую.
|
|
|
|
|
May 20 2006, 22:24
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(_artem_ @ May 21 2006, 01:08)  Почему впустую ? Потому что "овчинка выделки не стоит". задача решается проще. Поупражняться с пользой можно было бы например так: За это время, можно было сделать то же самое устройство на двух МК, связанных по двухпроводке или по UART'у. Один МК сугубо для LCD причем с нормальной 8-битной схемой включения, а второй для всего остального. Вместо меги32 задачу можно было бы решить на двух M48, которые вместе стоят дешевле одной М32. Можно было тупо добавить шифратор, который бы кодировал 4 линии подключаемого устройства в две. В общем решений, причем в равной степени стандартных, предостаточно, надо лишь дать волю фантазии. Цитата(SasaVitebsk @ May 21 2006, 00:53)  Так зачем начинать??? Выяснил что это НЕПРАВИЛЬНО, - сел и перепаял. Отдал день. И двигайся дальше! Полностью солидарен с Вами.
|
|
|
|
|
May 21 2006, 07:49
|
Местный
  
Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526

|
Цитата(defunct @ May 21 2006, 02:24)  Цитата(_artem_ @ May 21 2006, 01:08)  Почему впустую ?
Потому что "овчинка выделки не стоит". задача решается проще. Поупражняться с пользой можно было бы например так: За это время, можно было сделать то же самое устройство на двух МК, связанных по двухпроводке или по UART'у. Один МК сугубо для LCD причем с нормальной 8-битной схемой включения, а второй для всего остального. Вместо меги32 задачу можно было бы решить на двух M48, которые вместе стоят дешевле одной М32. Можно было тупо добавить шифратор, который бы кодировал 4 линии подключаемого устройства в две. В общем решений, причем в равной степени стандартных, предостаточно, надо лишь дать волю фантазии. Цитата(SasaVitebsk @ May 21 2006, 00:53)  Так зачем начинать??? Выяснил что это НЕПРАВИЛЬНО, - сел и перепаял. Отдал день. И двигайся дальше! Полностью солидарен с Вами. Господа, дабы прекратить этот философский спор, что стоит делать, а вместо чего не плохо было бы попить пива, скажу так: есть серийное устройство, которое мы выпускаем тысячами. Хотим добавить к устройству новую функцию, подключив к нему другое устройство. Рынок очень чувствителен к стоимости изделия. Поэтому варианты с добавлением микросхем - это изменения в принципиальную схему, перенастройка производства, а производство не в России, и т.д., и т.п. очень долго и дорого. Тем более, что есть вариант простого подключения, параллельно с дисплеем. Задачка решается (с точки зрения производства) в один ход. А в моем случае - это главное. А программу переписать - в любом случае проще и быстрее. Кстати, проблема решилась сама собой - мне до сих пор не понятно, каким образом! Я исключил из программы все модули, и подключая их по одному - проверял работу портов. В конце концов - все модули подключены, программа работает корректно. Не знаю, при следующем ребилде сохранится ли работоспособность. Плохо то, что причины странного поведения портов я так и не понял. Думаю, что это вопрос корректности оптимизатора. Другого объяснения я не нахожу. Но, то, что мы неделю плющили мозги, уверяю вас, даром никому не пройдет!!! "Математика - это гимнастика ума" - помните? Всем спасибо огромное! Приятно знать, что ты не один!!!
|
|
|
|
|
Jun 2 2006, 13:15
|
Местный
  
Группа: Свой
Сообщений: 303
Регистрация: 3-03-05
Пользователь №: 3 044

|
Приветствую, Господа!
Делал я штуку, в которой LCD по 4-х проводной схеме управлялся портом B и на этих же линиях сидела клавиатура из 4-х кнопок развязанная резисторами и подающая "0" (точно как на картинке, только все 4 линии (LCD) и pullup's только от AVR . Имел точно такойже эффект.
Вскрытие показало, что сигнал на входе порта не успевает принять желаемое значение за время от переключения порта на считывание до собственно считывания этого порта в прерывании. Одновременно выяснилось, что развязывающие резисторы 5.6к многовато.
Помогло: - уменьшение резисторов до 3.6К - разнесение момента переключения и считывания порта на 100мкс (это удобная для меня дискретность, обусловленная особенностью программы).
В процессе вскрытия выяснилась еще одна интересная вещь: если у LCD отключить питание, а на AVR оставить ("завешивал" и плюс и минус по очереди) потребляемый ток остается почти такой же, как и при подключеном питании LCD - т.е он начинает кормиться со входов.
Интересно, а осцилограф включали?
Не легко бороться со схемой, когда нельзя залезть внутрь с паяльником (этоя я про LCD).
--------------------
Опыт - чудесная вещь: легко использовать, можно продать, трудно пропить.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|