Hardware Access/pt: what changed
Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.
Title: Hardware Access/pt
| Old | New | Line | |
|---|---|---|---|
| 1 | + | ## Visão Geral | |
| 2 | + | ||
| 3 | + | Está página é o inicio de um tutorial sobre acesso a dispositivos de hardware no Lazarus. Estes dispositivos incluem, mas não se limitam a: Placas ISA e PCI, as portas paralela e serial e USB. | |
| 4 | + | ||
| 5 | + | Acessar o hardware de uma maneira completamente multi-plataforma não é implementada pela biblioteca RunTime do Free Pascal ou pela LCL, assim este tutorial cobre métodos diferentes para diferentes plataformas. O código pode ser compilado em ambientes diferentes utilizando compilação condicional. Abaixo segue um exemplo disso: | |
| 6 | + | ||
| 7 | + | ``` pascal | |
| 8 | + | uses | |
| 9 | + | Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, ExtCtrls, | |
| 10 | + | {$IFDEF WIN32} | |
| 11 | + | Windows; | |
| 12 | + | {$ENDIF} | |
| 13 | + | {$IFDEF Linux} | |
| 14 | + | ports; | |
| 15 | + | {$ENDIF} | |
| 16 | + | ``` | |
| 17 | + | ||
| 18 | + | Não se sabe ainda, até esse momento, se Mac OS x/x86 permitirá acesso HW. Ele pode não permitir isso, embora eu assuma neste caso , em tempo, que drivers como io.dll aparecerão. | |
| 19 | + | ||
| 20 | + | ## Comparação entre Paralelo e Serial | |
| 21 | + | ||
| 22 | + | Placas ISA, Placas PCI e a Porta Paralela comunicam-se com o computador utilizando um protocolo de comunição **paralela**. A Porta Serial e dispositivos USB trabalham com um protocolo **serial**. Como o processando e, consequentemente, as linguagens de programação trabalham com uma abordagem paralela aos dados, esse tipo de acesso é mais fácil de ser implementado no lado do software. Ao acessar uma variável do tipo inteiro, por exemplo, você pode acessar seu conteúdo inteiro com um único comando. Com o protocolo serial apenas um bit é enviado de cada vez e é preciso juntá-los para depois poder compreender os dados. | |
| 23 | + | ||
| 24 | + | A Comunicação serial é difícil de ser implementada diretamente, mas pode ser muito fácil se utilizarmos um componente pronto. Ela também é mais difícil no lado do hardware, logo muitos dispositivos utilizam Circuitos Integrados especialmente desenvolvidos ou até microcontroladores para implementar o protocolo serial. | |
| 25 | + | ||
| 26 | + | Agora uma breve comparação dos protocolos de comunicação: | |
| 27 | + | ||
| 28 | + | | | Velocidade | Dificuldade de implementação do hardware | | |
| 29 | + | |----|----|----| | |
| 30 | + | | Porta Serial | Muito lenta (\< E5 bit/s) | Média | | |
| 31 | + | | Porta Paralela | Lenta (~ E6 bit/s) | Fácil | | |
| 32 | + | | Placa ISA | Média (~ E7 bit/s) | Média | | |
| 33 | + | | USB | Média (~ E7 bit/s) | Difícil | | |
| 34 | + | | Placa PCI | Muito Rápida (\> E9 bit/s) | Muito difícil | | |
| 35 | + | ||
| 36 | + | ## Comunicação Paralela | |
| 37 | + | ||
| 38 | + | ### Utilizando a inpout32.dll para Windows | |
| 39 | + | ||
| 40 | + | O Windows tem diferentes formas para acessar dispositivos de hardware na série 9x e na série NT. A série 9x (95, 98, Me) os programas podem acessar as portas diretamente, da mesma maneira que era feito no DOS. A série NT, porém, não permite isto e todos acesso as portas devem ser feitos através de Dispositivos Drivers. Isto é um mecanismo de segurança, mas pode complicar o desenvolvimento de aplicativos pequenos que apenas precisam acessar uma determinada porta. | |
| 41 | + | ||
| 42 | + | Felizmente existe uma biblioteca que carrega dentro de si um driver. Quando ela é chamada para acessar uma determinada porta ela detecta se o Windows em operação é da série NT e, em caso afirmativo, descomprime o driver Hwinterface.sys e o instala no kernel. Se a série 9x for detectada ele simplesmente utiliza instruções de assembler para acessar o hardware. | |
| 43 | + | ||
| 44 | + | Mas como utilizar a biblioteca? Simples! Ela possuí apenas duas funções, Inp32 e Out32, e seu uso é bastante intuitivo. | |
| 45 | + | ||
| 46 | + | Nós estaremos carregando a biblioteca dinamicamente, então é bom definir as funções antes: | |
| 47 | + | ||
| 48 | + | ``` pascal | |
| 49 | + | type | |
| 50 | + | TInp32 = function(Address: ShortInt): ShortInt; stdcall; | |
| 51 | + | TOut32 = procedure(Address: ShortInt; Data: ShortInt); stdcall; | |
| 52 | + | ``` | |
| 53 | + | ||
| 54 | + | - Address representa o endereço da porta a ser acessada. | |
| 55 | + | - Out32 envida Dados para a porta. | |
| 56 | + | - Inp32 returna um byte da porta no Address. | |
| 57 | + | ||
| 58 | + | Agora podemos carregar a biblioteca. Isto pode ser implementado num lugar como o evento OnCreate do seu formulário principal: | |
| 59 | + | ||
| 60 | + | ``` pascal | |
| 61 | + | type | |
| 62 | + | TMyForm = class(TForm) | |
| 63 | + | ......... | |
| 64 | + | private | |
| 65 | + | { private declarations } | |
| 66 | + | Inpout32: THandle; | |
| 67 | + | Inp32: TInp32; | |
| 68 | + | Out32: TOut32; | |
| 69 | + | ......... | |
| 70 | + | implementation | |
| 71 | + | ......... | |
| 72 | + | procedure TMyForm.FormCreate(Sender: TObject); | |
| 73 | + | begin | |
| 74 | + | {$IFDEF WIN32} | |
| 75 | + | Inpout32 := LoadLibrary('inpout32.dll'); | |
| 76 | + | if (Inpout32 <> 0) then | |
| 77 | + | begin | |
| 78 | + | @Inp32 := GetProcAddress(Inpout32, 'Inp32'); | |
| 79 | + | if (@Inp32 = nil) then Caption := 'Error'; | |
| 80 | + | @Out32 := GetProcAddress(Inpout32, 'Out32'); | |
| 81 | + | if (@Out32 = nil) then Caption := 'Error'; | |
| 82 | + | end | |
| 83 | + | else Caption := 'Error'; | |
| 84 | + | {$ENDIF} | |
| 85 | + | end; | |
| 86 | + | ``` | |
| 87 | + | ||
| 88 | + | Se você carregar a biblioteca no evento OnCreate não esqueça de descarrega-la no evento OnDestroy: | |
| 89 | + | ||
| 90 | + | ``` pascal | |
| 91 | + | procedure TMyForm.FormDestroy(Sender: TObject); | |
| 92 | + | begin | |
| 93 | + | {$IFDEF WIN32} | |
| 94 | + | FreeLibrary(Inpout32); | |
| 95 | + | {$ENDIF} | |
| 96 | + | end; | |
| 97 | + | ``` | |
| 98 | + | ||
| 99 | + | Aqui está um exemplo de uso da função Inp32: | |
| 100 | + | ||
| 101 | + | ``` pascal | |
| 102 | + | {$IFDEF WIN32} | |
| 103 | + | myLabel.Caption := IntToStr(Inp32($0220)); | |
| 104 | + | {$ENDIF} | |
| 105 | + | ``` | |
| 106 | + | ||
| 107 | + | Este código foi testado com uma placa ISA própria na porta\$0220, utilizando o Lazarus 0.9.10 no Windows XP. Obviamente é necessário possuir a unidade Windows na cláusula "uses" para que este código possa funcionar. Para distribuir um aplicativo que utilize a biblioteca você precisa apenas incluir a "inpout32.dll" no mesmo diretório do executável. | |
| 108 | + | ||
| 109 | + | Está é a página principal da biblioteca: [www.logix4u.net/inpout32.htm](http://www.logix4u.net/inpout32.htm) | |
| 110 | + | ||
| 111 | + | ### Usando assembler no Windows 9x | |
| 112 | + | ||
| 113 | + | No Windows 9x você pode também utilizar código assembler. Supondo que você deseja escrever em \$CC para a portal \$320. O seguinte código fará isso: | |
| 114 | + | ||
| 115 | + | ``` pascal | |
| 116 | + | {$ASMMODE ATT} | |
| 117 | + | ... | |
| 118 | + | asm | |
| 119 | + | movl $0x320, %edx | |
| 120 | + | movb $0xCC, %al | |
| 121 | + | outb %al, %dx | |
| 122 | + | end ['EAX','EDX']; | |
| 123 | + | ``` | |
| 124 | + | ||
| 125 | + | ### Troubleshooting no Windows | |
| 126 | + | ||
| 127 | + | Uma possível fonte de confusão usando hardware paralelo que não suporta Plug and Play no Windows é que o Windows pode associar a porta utilizada pelo seu hardware para outro dispositivo. Você pode procurar instruções na URL a seguir sobre como falar para o Windows não associar o endereço de seu dispositivo para dispositivos Plug And Play: | |
| 128 | + | ||
| 129 | + | <http://support.microsoft.com/kb/135168> | |
| 130 | + | ||
| 131 | + | ### Utilizando ioperm para acessar portas no Linux | |
| 132 | + | ||
| 133 | + | A melhor maneira de acessar dispositivos de hardware no Linux é através de drivers, mas, devido a complexidade envolvida na criação de um, às vezes um método mais simples é muito útil. | |
| 134 | + | ||
| 135 | + | Para utilizar a unidade "[[doc:rtl/ports|ports]]" no Linux, seu programa deve ser executado como super-usuário (ex: root) e a função IOPerm deve ser chamada para definir as permissões de acesso as portas. Você pode encontrar documentação sobre a unidade "[[doc:rtl/ports|ports]]" [aqui](http://www.freepascal.org/docs-html/rtl/ports/index.html). | |
| 136 | + | ||
| 137 | + | A primeira coisa a ser feita é estabelecer um vínculo com o (g)libc e chamar a função IOPerm. Uma unidade que estabelece vínculos para todo o (g)libc existe no Free Pascal, mas ela causa problemas quando é utilizada diretamente pela aplicação e vinculação estática, além do que não é uma boa idéia porque ela mudança frequentemente entre versões em uma incompatível maneira. Funções como ioperm, entretanto, são improváveis de serem modificadas. | |
| 138 | + | ||
| 139 | + | ``` pascal | |
| 140 | + | {$IFDEF Linux} | |
| 141 | + | function ioperm(from: Cardinal; num: Cardinal; turn_on: Integer): Integer; cdecl; external 'libc'; | |
| 142 | + | {$ENDIF} | |
| 143 | + | ``` | |
| 144 | + | ||
| 145 | + | - "from" representa a primeira porta a ser acessada. | |
| 146 | + | - "num" é o número de portas após a primeira a serem acessadas, assim ioperm(\$220, 8, 1) dará ao programa acesso a todos portas entre e incluindo \$220 e \$227. | |
| 147 | + | ||
| 148 | + | Após vincular OIPerm você pode utilizar port\[\<Endereço\>\] para acessar as portas. | |
| 149 | + | ||
| 150 | + | ``` pascal | |
| 151 | + | {$IFDEF Linux} | |
| 152 | + | i := ioperm($220, 8, 1); | |
| 153 | + | port[$220] := $00; | |
| 154 | + | myLabel.Caption := 'ioperm: ' + IntToStr(i); | |
| 155 | + | i := Integer(port[$220]); | |
| 156 | + | myOtherLabel.Caption := 'resposta: ' + IntToStr(i); | |
| 157 | + | {$ENDIF} | |
| 158 | + | ``` | |
| 159 | + | ||
| 160 | + | Este código for testado com uma placa ISA própria na porta \$0220, utilizando o Lazarus 0.9.10 no Mandriva Linux 2005 e no Damn Small Linux 1.5. | |
| 161 | + | ||
| 162 | + | ### Acesso geral ao Hardware UNIX | |
| 163 | + | ||
| 164 | + | ``` pascal | |
| 165 | + | {$IFDEF Unix} | |
| 166 | + | Uses Clib; // recupera o nome da biblioteca libc. | |
| 167 | + | {$ENDIF} | |
| 168 | + | ||
| 169 | + | {$IFDEF Unix} | |
| 170 | + | function ioperm(from: Cardinal; num: Cardinal; turn_on: Integer): Integer; cdecl; external clib; | |
| 171 | + | {$ENDIF} | |
| 172 | + | ``` | |
| 173 | + | ||
| 174 | + | **Nota** Note que o FPC fornece uma abstração para ioperm chamada "fpioperm" na [[doc:rtl/x86/index.html|unit x86]], e também define funções out e inport. Essas funções atualmente são implementadas por Linux/x86 e FreeBSD/x86. | |
| 175 | + | ||
| 176 | + | Não é recomendado vincular libc a menos que seja absolutamente necessário para possibilitar o desenvolvimento e portabilidades das funções. Também a vinculação manual da libc (declarando importações pontuais libc para funções que estão disponíveis noutros países) como feito anteriormente não é recomendado (ex: a importação libc na linha acima irá falhar se, desnecessariamente, o padrão lib C não é chamado libc, como por exemplo libroot no BeOS, ou em plataformas com simbolos não-padrão C estragados). | |
| 177 | + | ||
| 178 | + | **Nota 2** Usar _unit_ libc não é recomendado sob quaisquer outras cirscunstâncias do que a compatibilidade com Kylix. Isso porque a unit é relativamente não-portável (garanta a exposição das estruturas e outros símbolos privados) e deve ser modificada tão pouco quanto possível fora das questões de compatibilidades com Kylix. | |
| 179 | + | ||
| 180 | + | ## Comunicação Serial | |
| 181 | + | ||
| 182 | + | A seção de [[Hardware Access/pt|Links Externos]] tem tutoriais de portas seriais UNIX e Windows. | |
| 183 | + | ||
| 184 | + | ## USB | |
| 185 | + | ||
| 186 | + | ### libusb | |
| 187 | + | ||
| 188 | + | Uma possibilidade multi-plataforma para Linux, BSDs e Mac OS X é a [libusb](http://libusb.sourceforge.net/). | |
| 189 | + | ||
| 190 | + | Os cabeçalhos estão listado em <http://www.freepascal.org/contrib/db.php3?category=Miscellaneous>: | |
| 191 | + | ||
| 192 | + | | nome | autor | versão | data | link | comentários | | |
| 193 | + | |----|----|----|----|----|----| | |
| 194 | + | | libusb.pp | nowrap \| Uwe Zimmermann | 0.1.12 | nowrap \| 2006-06-29 | <http://www.sciencetronics.com/download/fpc_libusb.tgz> | | | |
| 195 | + | | libusb.pas | Johann Glaser | | nowrap \| 2005-01-14 | <http://www.johann-glaser.at/projects/libusb.pas> | | | |
| 196 | + | | fpcusb | Joe Jared | 0.11-14 | nowrap \| 2006-02-02 | <http://relays.osirusoft.com/fpcusb.tgz> | nowrap \| link download quebrado | | |
| 197 | + | ||
| 198 | + | ### FTDI | |
| 199 | + | ||
| 200 | + | Se você usa um dos chips da [FTDI](http://www.ftdichip.com/), você pode os cabeçalhos pascal da sua interface de dll para o chip. | |
| 201 | + | ||
| 202 | + | ## Links Externos | |
| 203 | + | ||
| 204 | + | Comparação de velocidade de Protocolos de Comunicação | |
| 205 | + | ||
| 206 | + | 1. <http://en.wikipedia.org/wiki/Serial_port#Speed> | |
| 207 | + | 2. <http://www.lvr.com/jansfaq.htm> - Jan Axelson's Parallel Port FAQ | |
| 208 | + | 3. <http://en.wikipedia.org/wiki/USB#Transfer_Speed> | |
| 209 | + | 4. <http://en.wikipedia.org/wiki/PCI#Conventional_PCI_bus_specifications> | |
| 210 | + | ||
| 211 | + | Links de Comunicação Serial: | |
| 212 | + | ||
| 213 | + | 1. Em UNIX: [1](http://www.easysw.com/~mike/serial/serial.html) | |
| 214 | + | 2. Em Windows: <http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnfiles/html/msdn_serial.asp> | |
| 215 | + | 3. Componente Synaser: <http://synapse.ararat.cz/> | |
| 216 | + | 4. Pacote Delphi Comport: <http://sourceforge.net/projects/comport/> | |
| 217 | + | ||
| 218 | + | ISA Digital Oscilloscope - Um exemplo de acesso ao hardware com fonte completo incluso: | |
| 219 | + | ||
| 220 | + | [2](http://eletronicalivre.incubadora.fapesp.br/portal/english/oscilloscope/) | |
| 221 | + | ||
| 222 | + | --- | |
| 223 | + | *From the Free Pascal wiki, page "Hardware Access/pt", as it stood on 2020-02-16 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).* |
