|
Хочу прерывание на Паскале от СОМ-порта, (Турбо Паскаль, не Дельфи) |
|
|
|
May 26 2009, 17:11
|
Вечный студент
   
Группа: Участник
Сообщений: 500
Регистрация: 11-09-06
Из: Питер
Пользователь №: 20 262

|
Программка (запускается под DOS, Win98): CODE Uses crt, dos;
Label Finish, ll00;
Const baud = 38400; COM=$3F8 { $2F8 }; intr=$0C { $0B };
Var stv, srv : pointer; cnt : word; b : byte; key : char; speed_fr : word;
{----------------------------------------------------------------------------------} {$F+} Procedure int_1c; interrupt; Begin inc(cnt); if cnt=18 then begin cnt:=0; write ('g') end; End; {$F-} {-----------------------------------------------------------------------------------} {$F+} Procedure int_rs; interrupt; Begin b:=port[COM]; write (b,' '); End; {$F-} {----------------------------------------------------------------------------------}
BEGIN speed_fr:=trunc(115200/baud+0.5); port[COM+3]:=$80; { ўЄ«. гбв ®ўЄ бЄ®p®бвЁ } port[COM+1]:=hi(speed_fr); port[COM+0]:=lo(speed_fr); port[COM+3]:=$00; { 5 bit, 1 stop, parity=none } port[COM+4]:=0; port[COM+2]:=$03; { FIFO on } port[COM+1]:=$01; { interrupt when rec'd data is available }
getintvec($1C,stv); getintvec(intr,srv);
cnt:=0; setintvec($1C,addr(int_1c)); setintvec(intr,addr(int_rs));
ll00 : if keypressed then begin key:=readkey; goto Finish; end;
{ b:=port[COM+5]; } { if (b and $01)<>0 then begin } { b:=port[COM]; } { write (b,' '); } { end; }
goto ll00;
Finish : setintvec($1C,stv); setintvec(intr,srv); halt; END. Процедурка int_1c - для тренировки - раз в сек пишет "g"; работает. По ее образу и подобию - int_rs - должна непечатать принятые с СОМ данные. Не работает. Что не так? Порт настраивается нормально, в этом легко убедиться раскомментировав 5 строчек выше "goto ll00;"
Причина редактирования: Оформление цитаты исходника.
|
|
|
|
|
May 26 2009, 23:06
|

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

|
Цитата(Diusha @ May 26 2009, 20:11)  Не работает. Что не так? Write() нежелательно использовать внутри прерываний насколько помню. еще, если память не изменяет надо заботиться о контроллере прерываний самостоятельно тобиш записать 20h в port 20h в конце обработчика для аппаратных прерываний: Код procedure Vector0C_Handler;interrupt; begin .... обработка порта(ов) COM1/3 asm mov al, 20h out 20h, al end end; Цитата(SysRq @ May 26 2009, 20:34)  COM+4.. Попробуйте $0B вместо 0 Это не нужно. Мы ж мышку питать не собираемся.
|
|
|
|
|
May 27 2009, 04:20
|
Вечный студент
   
Группа: Участник
Сообщений: 500
Регистрация: 11-09-06
Из: Питер
Пользователь №: 20 262

|
Цитата(defunct @ May 27 2009, 02:06)  Write() нежелательно использовать внутри прерываний насколько помню. А почему? Цитата(defunct @ May 27 2009, 02:06)  ...записать 20h в port 20h в конце обработчика До начала бы добраться...
Сообщение отредактировал Diusha - May 27 2009, 04:20
|
|
|
|
|
May 27 2009, 08:52
|
Гуру
     
Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847

|
Прерывание от COM порта еще надо разрешить в контролере прерываний (предполагаю, что оно весит на IRQ3) Код port[$21] := port[$21] and $f7; Ну и про Код port[$20] := $20; в конце тоже забывать не надо
|
|
|
|
|
May 27 2009, 14:05
|

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

|
Цитата(vvs157 @ May 27 2009, 15:46)  И еще в USART чипе разрешить прохождение прерывание на контроллер Не USART, а UART. Ну и это уже делается. В код топикстартера хоть заглядывали? Цитата Проще взять готовую библитотеку для ДОС для работы с COM. Вот чего не надо делать, так это брать готовую г...о-библиотеку.
|
|
|
|
|
May 27 2009, 17:15
|
Вечный студент
   
Группа: Участник
Сообщений: 500
Регистрация: 11-09-06
Из: Питер
Пользователь №: 20 262

|
Цитата(XVR @ May 27 2009, 11:52)  Прерывание от COM порта еще надо разрешить в контролере прерываний (предполагаю, что оно весит на IRQ3) Код port[$21] := port[$21] and $f7; Пробовал добавлять это. Также пробовал добавлять из _Pash`иной ссылки. Упрощенный вид сих магических действий Код port[$21] := port[$21] or $10; port[$21] := port[$21] and ($FF-$10); port[$20] := $64; - для IRQ4; либо для IRQ3: Код port[$21] := port[$21] or $08; port[$21] := port[$21] and ($FF-$08); port[$20] := $63; Бэзрезультатно. И смысл этой магии мне непонятен, т.к. не нашел понятного описания этих портов
|
|
|
|
|
May 27 2009, 18:42
|

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

|
Цитата(_Pasha @ May 27 2009, 17:13)  А Вы ее в сад отправляете.  К ссылке у меня не было никаких вопросов. Там все ОК ;> Смотреть - наздоровье. Пользовать-то зачем? Цитата(Diusha @ May 27 2009, 20:15)  И смысл этой магии мне непонятен, т.к. не нашел понятного описания этих портов Понятное описание этих и всех остальных портов можно найти в TechHelp который можно взять здесьВ двух словах, есть 2 класса прерываний - программные и аппаратные. Программные прерывания такие как int 10h,.. 13h,.. 16h,.. int 21h... вызываются из программы специальной командой INT xx для доступа к BIOS/DOS (каким-то иным) программным сервисам. Аппаратные прерывания (int 8, 9 ..0Fh ..) - вызываются аппаратурой (периферией). Исторически у x86 всего один вход INT для аппаратного прерывания, а периферии много: таймер, клавиатура, ком порты, и т.д. и т.п. Вопрос как это все подключить к одному входу проца? Ответ - добавить внешний контроллер прерываний, у которого будет столько входов сколько периферии, а выход на проц - один. Вот именно этот контроллер прерываний и располагается в портах 0x20, 0x21 и его надо настроить чтобы соответвующий сигнал запроса на прерывание от COM1 порта (IRQ4) - превратить в INT...
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|