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

Приведенная вами ситуация может быть когда вы читаете к примеру статус бит из ЛСД когда происходит прерывание.
Нет - я вообще ничего не читаю из LCD!!! Мало того, если я отсоединяю LCD то ничего ровным счетом не меняется! Дело не в дисплее. Я выдаю на мл. линии "0", переключаю порт на прием, выжидаю паузу - и читаю. И читаю те самые нули, которые я же туда и выдал.
Sergio66
May 16 2006, 14:04
Цитата(WHALE @ May 16 2006, 18:01)

а читаете через PINB?
Именно!, причем, после переключения порта на прием, выжидаю паузу в несколько тактов.
_artem_
May 16 2006, 14:12
Единственное не понимаю - устройство у вас которое к младшим разрядам подсоединено - с тремья состояниями ? Если нет как вы можете ставить порт на передачу (при записи в ЛСД) а потом на прием для чтения из устройства? А зачем вам всякий раз записывать нули перед переключением направления прота ? вроде бы у вас до этого и ноль должен быть. А если уsтройство отключаете как и ЛСД тоже нули читаются ?
Sergio66
May 16 2006, 14:25
Цитата(_artem_ @ May 16 2006, 18:12)

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

навесте пулап резисторы - 1 ком вместо устройства а затем проведите опыт с прочитыванием без устройства и без ЛСД.
Доп. устройство итак подвешено через пулап резисторы в 1 К. И картина именно такая, как я обрисовал.
Я выдаю в порт нули, затем переключаю порт на прием (устройство передает что-то, но т.к. оно через резисторы, то сигнал контроллера силнее) и читаю состояние порта. И вижу там нули, именно те, которые передал!, а не данные от устройства.
Sergio66
May 16 2006, 14:59
Цитата(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)
Если я правильно Вас понял, то младшая тетрада порта В должна быть на прием всегда, и с подтягивающими резисторами? А я пробовал так - при переключении на прием младщей тетрады, подключаю пуллап на этих выводах. Эффект нулевой.
defunct
May 16 2006, 15:18
Цитата(Sergio66 @ May 16 2006, 17:59)

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

Цитата(Sergio66 @ May 16 2006, 17:59)

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

Да, есть один нюанс, я его упустил для упрощения описания ситуации - устройство сидит не на PB0 - 3, а на линиях PB0, PB1, PB3, PB4. Т.е. линия РВ4 работает и на дисплей и на доп устройство. И перенастраиваю я именно эти линии. Только, в моем понимании это мало что меняет. Я выдал в порт данные, перенастроил порт на прием, т.е., если судить по даташиту, отключил выходной каскад контроллера от пина, и читаю этот пин. На нем должно присутствовать то, что установило внешнее устройство, т.к. дисплей абсолютно пассивет, да и его может и не быть.
Решение с места (если точность интервала опроса не сильно важна): запрещать прерывания на входе в функцию обращения к LCD, разрешать - на выходе из этой функции.
Если же точность интервала опроса важна. С учетом последнего вашего поста, было бы неплохо взглянуть на код обработчика прерывания, может быть там что-то не так...
Laksus
May 16 2006, 18:06
Доп. устройство итак подвешено через пулап резисторы в 1 К.
...
___________________
Ну а если проверить нет ли там обрыва где нибудь?
Александр
2006 05 16
Насколько я помню протокол,последней операцией записи данных LCD по 4-х проводной линии должна
быть установка шины данных в 1.и ваши проблемы не совсем понятны-привели-бы кусок схемы и кода.
З.Ы. а в симуляторе пробовали смотреть?
_artem_
May 16 2006, 18:58
Я Вас может быть неправильно понял но не могу интерпретировать эти предложения с одним смыслом :
"Нет - я вообще ничего не читаю из LCD!!! Мало того, если я отсоединяю LCD то ничего ровным счетом не меняется! Дело не в дисплее. Я выдаю на мл. линии "0", переключаю порт на прием, выжидаю паузу - и читаю. И читаю те самые нули, которые я же туда и выдал."
и вот это :
"Если отключаем LCD, и код, его обслуживающий, то все работает правильно. Мало того, если прерывание возникает не в период обращения к дисплею, то тоже все нормально. Функция работы с LCD настраивает старшую тетраду на выход, младшая - остается на прием."
defunct
May 16 2006, 20:05
Цитата(_artem_ @ May 16 2006, 21:58)

Я Вас может быть неправильно понял но не могу интерпретировать эти предложения с одним смыслом :
"Нет - я вообще ничего не читаю из LCD!!! Мало того, если я отсоединяю LCD то ничего ровным счетом не меняется! Дело не в дисплее. Я выдаю на мл. линии "0", переключаю порт на прием, выжидаю паузу - и читаю. И читаю те самые нули, которые я же туда и выдал."
и вот это :
"Если отключаем LCD, и код, его обслуживающий, то все работает правильно. Мало того, если прерывание возникает не в период обращения к дисплею, то тоже все нормально. Функция работы с LCD настраивает старшую тетраду на выход, младшая - остается на прием."
Связать можно, в первом случае, я полагаю, код, обслуживающий LCD, не был отключен. А просто был отсоединен экран. Во втором случае код отключен тоже. Проблема помоему очевидна, и скрывается в коде, обслуживающем LCD. Похоже, что операция вывода байта на экран должна быть атомарной операцией (нельзя переключать порт передав только старшую тетраду данных). Как уже писал ранее, один из путей решения проблемы - запрещать прерывания, на время работы с LCD.
_artem_
May 16 2006, 21:23
Мне это так не кажется - передача тетрады для порта половина которого работает не передачу а остальная на прием как такового значение не имеет - в любом случае в PORTB регистр записывается байт. Для авр все равно и я честно говоря не видел ограничений на манипуляцию с gpio портами (было маленькое примечание о переходе с приема на передачу и наоборот и то что при чтении порт опаздывает как минимум на один машинный цикл но не 10 микросек при 16 МГц тактовой). Если предположить что нули выдаются дисплеем потому что может затягиватся сигнал Е на входе дисплея и при этом дисплей каким то макаром работает на передачу - не подтверждается так как без физически подключенного дисплея те же самые нули (если я правильно понял написанное).
Без кода и схемы никак .
OlegIvanov
May 16 2006, 23:06
[/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; и состояние мл. части порта осталось неизменным
Sergio66
May 17 2006, 05:54
Цитата(_artem_ @ May 16 2006, 22:58)

Я Вас может быть неправильно понял но не могу интерпретировать эти предложения с одним смыслом :
"Нет - я вообще ничего не читаю из LCD!!! Мало того, если я отсоединяю LCD то ничего ровным счетом не меняется! Дело не в дисплее. Я выдаю на мл. линии "0", переключаю порт на прием, выжидаю паузу - и читаю. И читаю те самые нули, которые я же туда и выдал."
и вот это :
"Если отключаем LCD, и код, его обслуживающий, то все работает правильно. Мало того, если прерывание возникает не в период обращения к дисплею, то тоже все нормально. Функция работы с LCD настраивает старшую тетраду на выход, младшая - остается на прием."
В первом случае отключался только LCD, во втором - и код, его обслуживающий.
Sergio66
May 17 2006, 06:40
Цитата(_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*/
_artem_
May 17 2006, 10:06
Можно отрассировать по выходу из обработчика прерывания содержимое стека, точнее адресс куда программа вернется после инструкции RETI когда проблема произошла? Можно прямо перед выходом из обработчика прерываний в одну переменную сохранить содержимое стека а в другую флаг присутствия проблемы установленный в :
if ((PINB & 0x1b) )
{
.......
}
else
{
flag = 1;
}
потом в конце вывода в дисплей проверить флаг и если он установлен вывести значение стека на дислпеы или уарт и затем сбросить флаг после . И потом конечно листинг ассемблера с С кодом вместе (как минимум куска на кторый указывает стек).
Еше один вопрос - читается ли 0 все время когда вывод на лсд или иногда ?
Можно также на время OUT_DATA_PORT запретить прерывание dlja vyvoda obeix tetrad :
__disable_interrupts();
OUT_DATA_PORT;
__enable_interrupts();
и сообшить результат.
Sergio66
May 17 2006, 10:35
Цитата(_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 я вижу то, что быо выдано на эту линию в обработчике дисплея только в том случае, если прерывание возникло во время обмена с дисплеем.
_artem_
May 17 2006, 11:27
Вложенные прерывания разрешены ? Конкретно знаете на какой инструкции прерывание срабатывает с проблемой?
В общем так:
Самый простой выход из ситуации это, как уже говорилось
Цитата
запрещать прерывания, на время работы с LCD
Если это недопустимо и если точно известно, что период следования прерываний больше времени работы обслуживателя LCD, то можно сделать так:
Код
char flag = 0; // флаг разрешения обслуживания LCD
.................
while ( flag == 0 ); // ждать, пока небыло прерывания
[LCD] // процедура обслуживания LCD
flag = 0; // запретить обслуживание LCD
.................
// в конце обработчика прерывания
if ( flag == 0 ) { flag = 1; } // если был запрет на обслуживание LCD, то разрешить его.
Успехов.
Sergio66
May 17 2006, 15:35
Я только что проделал такой эксперимент - я отключтл дисплей, отключил доп. устройство и запустил программу так, как будто все подключено. Только функция работы с дисплеем выдает все "1" во все линии порта В. В обработчике прервания я вижу PINB в "1"! Т.е. ноги висят в воздухе, я выдаю на них "1", потом переключаюсь на прием, и вижу на них те же "1"!
Может быть я просто имею "битую" микросхему?
defunct
May 17 2006, 15: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");
Должно все работать
Laksus
May 17 2006, 16:30
После переключения линий порта В на прием, делаю паузу (до 10 мксек), ничего не меняется. Т.о., это не паразитные емкости.
...
DDRB &= ~((1<<PB0) | (1<<PB1) | (1<<PB3) | (1<<PB4));
__delay_cycles(10); //10 тактов генератора
if ((PINB & 0x1b) )
_______________________________
Так все таки, 10мксек или 10тактов,
при 16 МГц это большая разница.
У Вас не указаны значения сопротивлений.
Но если даже предположить, что добавочные сопротивления
тоже 1кОм, то емкость для постоянной времени в 10тактов
будет примерно 300пФ.
Емкость "голого" вывода порядка 10 пФ, так что дорожки
печатной платы и провода шлейфа могут вполне достигнуть
достаточной емкости.
Так что вполне могут быть и паразитные емкости.
____________
Александр
2006 05 17
Sergio66
May 19 2006, 09:22
Цитата(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" после этого в них не выдаю, так, что пулл ап резисторы я не подключаю. Но читаю на пинах то ,что выдал в порт.
_artem_
May 19 2006, 11:55
Sergio66, можно ли сделать так :
- прямо в ISR устройства проверить на состояние "все нули" и если да то получить содержимое памяти по адресу SP + 2 (стек), и выдать его на какое то устройство (уарт или чтото в этом вроде)
- откомпилировать программу без оптимизации и получить ассеемблерный листинг вперемешку с C кодом
- и все это выставить здесь (можно лишь кусок программы ) с указанием адреса откуда программа прервалась.
Sergio66
May 19 2006, 12:13
Цитата(_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".
Sergio66
May 19 2006, 12:32
Все чудо в том, что отладчик видит "1" на линии, а программа читает "0"!!!
Sergio66
May 19 2006, 12:46
Цитата(_artem_ @ May 19 2006, 15:55)

Sergio66, можно ли сделать так :
- прямо в ISR устройства проверить на состояние "все нули" и если да то получить содержимое памяти по адресу SP + 2 (стек), и выдать его на какое то устройство (уарт или чтото в этом вроде)
- откомпилировать программу без оптимизации и получить ассеемблерный листинг вперемешку с C кодом
- и все это выставить здесь (можно лишь кусок программы ) с указанием адреса откуда программа прервалась.
Кроме всего прочего, мне удалось выяснить (в отличие от того, что я писал ранее), не имеет значения где прервана программа. Я проделал со стеком то, что Вы написали, и увидел, что прерывание возникло в момент довольно длительных арифметических вычислений, абсолютно не затрагивающих работу с периферией. Т.е. не в том дело, что прерван процесс обмена с LCD, а в том, что данные выданы в линию, и остаются актуальными там несмотря на переключение порта на прием.
Sergio66
May 19 2006, 13:20
Вот такой кусок кода -
while (1)
{
DDRB = 0xf0;
PORTB = 0;
__disable_interrupt();
DDRB &= ~((1<<PB0) | (1<<PB1) | (1<<PB3) | (1<<PB4));
__delay_cycles(100);
data = PINB;
data&= 0x1b;
if (data == 0)
{
asm("NOP");
}
при условии, что внешнее устройство обеспечивает наличие "1" на одной из линий 0,1,3,4, мы никогда не должны попасть в ветвь "if" однако, именно туда мы и попадаем, причем только в том случае, если внешнее устройство генерит 1 на РВ4. Отладчик видит эту "1" а программа - нет.
_artem_
May 19 2006, 13:34
Может у вас с портом неполадки? Можно будет вывод устройства перекинуть с PB4 на PB5 ? все остальное оставьте нетронутым а в программе анaлизируйте PB5?
OlegIvanov
May 19 2006, 15:50
Цитата(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 в порт. При переключении на вход это уже автоматом подтягивающие резисторы.
Sergio66
May 19 2006, 17:26
[/quote]
Вам все толком говорят. Вы же сами выбрасываете эти 1 в порт. При переключении на вход это уже автоматом подтягивающие резисторы.
[/quote]
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 резистор активизируется.
Но не на оборот. Вы хотите сказать, что если последняя операция с выводом данных в порт закончилась выводом "1", то переключение порта на вход автоматом включает pull-up резисторы? Судя по документации - это не так.
defunct
May 19 2006, 20:16
Цитата(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, либо наоборот нулем будет давить еденицу, недалеко так и попалить одно из двух или МК или устройство).
На вашем месте, я бы давно уже подыскал любой другой свободный пин, и подключил бы к нему злополучный вывод устройства. Организовать "шару" это не такая уж простая задача как может показаться на первый взгляд.
_artem_
May 19 2006, 22:48
Sergio66, Можно поменять пин ПБ4 на какой нибудь другой ? У меня подозрение что этот пин глючный.
SasaVitebsk
May 20 2006, 00:05
Применение развязки на резисторах мягко говоря некоректно. Видел когда-то в одном из синклеров. Правильным является применение буферного элемента (например АП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".
_artem_
May 20 2006, 03: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 - сколько же все таки сопротивление резистора ?)
Sergio66
May 20 2006, 11:05
Цитата(_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 К
_artem_
May 20 2006, 12: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)?
Sergio66
May 20 2006, 12:21
Цитата(_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.
SasaVitebsk
May 20 2006, 21:53
Ребята, можно делать всё!!! Можно бриться кривой бритвой из-за угла!!! Но зачем???
Я видел различные нестандартные применения стандартных микрух. Но ни разу не видел, с моей точки зрения, обоснованности такого использования! Ни разу мне ни хотелось это повторить. Если это единичное изделие, тогда я ещё как-то могу понять и объяснить простой ленью.
Многолетний опыт показывает что попытка оживления и эксплуатации кривой схемы или программы обходится дороже с точки зрения времени и затрат труда. И, как правило, в конце всё таки меняешь на нормальное!!! Так зачем начинать??? Выяснил что это НЕПРАВИЛЬНО, - сел и перепаял. Отдал день. И двигайся дальше!
С уважением. Просто высказываю свою точку зрения. Мне жутко жалко своего времени. У меня его мало осталось. И мне действительно жалко Вашего, времени потраченного впустую.
_artem_
May 20 2006, 22:08
Почему впустую ? Любой мысленный процесс это физкультура, каким нелепым предмет мыслительного процесса или убогими мои мозги не были бы.)
Просто мы хотим выяснить - действительно ли данное решение неправильно или что то другое. Не могу я априори сказать что это неправильно - презумпция невиновности есть).
defunct
May 20 2006, 22:24
Цитата(_artem_ @ May 21 2006, 01:08)

Почему впустую ?
Потому что "овчинка выделки не стоит".
задача решается проще.
Поупражняться с пользой можно было бы например так:
За это время, можно было сделать то же самое устройство на двух МК, связанных по двухпроводке или по UART'у. Один МК сугубо для LCD причем с нормальной 8-битной схемой включения, а второй для всего остального. Вместо меги32 задачу можно было бы решить на двух M48, которые вместе стоят дешевле одной М32.
Можно было тупо добавить шифратор, который бы кодировал 4 линии подключаемого устройства в две.
В общем решений, причем в равной степени стандартных, предостаточно, надо лишь дать волю фантазии.
Цитата(SasaVitebsk @ May 21 2006, 00:53)

Так зачем начинать??? Выяснил что это НЕПРАВИЛЬНО, - сел и перепаял. Отдал день. И двигайся дальше!
Полностью солидарен с Вами.
Sergio66
May 21 2006, 07:49
Цитата(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)

Так зачем начинать??? Выяснил что это НЕПРАВИЛЬНО, - сел и перепаял. Отдал день. И двигайся дальше!
Полностью солидарен с Вами.
Господа, дабы прекратить этот философский спор, что стоит делать, а вместо чего не плохо было бы попить пива, скажу так: есть серийное устройство, которое мы выпускаем тысячами. Хотим добавить к устройству новую функцию, подключив к нему другое устройство. Рынок очень чувствителен к стоимости изделия. Поэтому варианты с добавлением микросхем - это изменения в принципиальную схему, перенастройка производства, а производство не в России, и т.д., и т.п. очень долго и дорого. Тем более, что есть вариант простого подключения, параллельно с дисплеем. Задачка решается (с точки зрения производства) в один ход. А в моем случае - это главное. А программу переписать - в любом случае проще и быстрее.
Кстати, проблема решилась сама собой - мне до сих пор не понятно, каким образом! Я исключил из программы все модули, и подключая их по одному - проверял работу портов. В конце концов - все модули подключены, программа работает корректно. Не знаю, при следующем ребилде сохранится ли работоспособность. Плохо то, что причины странного поведения портов я так и не понял.
Думаю, что это вопрос корректности оптимизатора. Другого объяснения я не нахожу.
Но, то, что мы неделю плющили мозги, уверяю вас, даром никому не пройдет!!! "Математика - это гимнастика ума" - помните?
Всем спасибо огромное! Приятно знать, что ты не один!!!