Apontamentos Teoricos e Praticos de TAC - 2009 - 2010V7
Apontamentos Teoricos e Praticos de TAC - 2009 - 2010V7
Apontamentos Teoricos e Praticos de TAC - 2009 - 2010V7
Objectivos:
- Compreensão da arquitectura interna dos µControladores;
- Introdução à programação dos µC , em “Assembler”;
- Utilização do ambiente integrado de desenvolvimento de programas – MPLAB;
- Aprender a transferir para a memória flash do µC esse programa;
- Utilização das entradas e saídas digitais dos µC.
Material a utilizar:
Software: MPLAB (IDE), MPASM Toolsuite (assembler, Linker, Librarian).
Hardware: Placa branca de montagem, µC, Regulador de tensão, 2 leds, 2 resistências de 4k7.
Data de entrega:
O programa do µC deve ser enviado por correio electrónico até às 24h de 12 Novembro.
Pretende-se ligar a electroválvula de entrada sempre que o reservatório atinja o nível N2. A
electroválvula de entrada deve permanecer ligada até que a água no reservatório atinja o nível N3.
A electroválvula de saída deve estar ligada sempre que o nível de água seja superior ao nível N1.
Os microControladores surgiram pela mão da General Instruments, nos anos 70, e tinham a
designação de “Peripheral Intelligent Computer - PIC”. Estes PICs tinham por objectivo libertar
os microprocessadores, usados nos computadores, do processamento e tratamento de entradas e
saídas digitais dos dispositivos periféricos.
Mais tarde, a General Instruments vendeu a sua divisão de semicondutores à Microchip
Technology o que potenciou o desenvolvimento dos microcontroladores.
Actualmente, os PIC são verdadeiros computadores num só chip, possuem Arithmetic Logic Unit -
ALU, Random Acess Memory - RAM, Electric Erasable Programmable ROM - EEPROM,
conversores A/D, interfaces de comunicação e são usados em quase tudo, desde em telemóveis,
DVDs , cameras, carros, frigoríficos, brinquedos, fotocopiadores, impressoras, domótica, e em
muitos outros equipamentos.
Existem também diferenças entre os dois, os PLCs foram concebidos para funcionar em ambientes
industriais e possuem por isso protecções mecânicas e eléctricas que os µC não possuem. Além
disso os µC s geram tensões iguais ou inferiores a 5v e apenas podem debitar intensidades de
corrente reduzidas.
Os µC possuem uma memória para os programas e outra memória para os dados. As duas podem
ser acedidas simultaneamente pela unidade central de processamento “Central Processing Unit -
CPU”, pois existem dois barramentos independentes, um para os dados e outro para as instruções.
Esta arquitectura é conhecida por “arquitectura de Harvard”. Os µC possuem também diversas
entradas e saídas, digitais e analógicas, e também interfaces de comunicação (Figura 1.3).
a) Pinos externos
Cada pino de um µC pode ter diversas funcionalidades, pode por exemplo: actuar como uma
saída digital de 5V, como uma entrada digital, ou como uma saída analógica (0 a5v). É este o
caso do pino nº1 do µC que vamos utilizar neste trabalho. Tal como a Figura 1.4 ilustra, o pino
nº1 deste µC pode actuar como uma entrada ou saída digital (RA2), como uma entrada
analógica (AN2) ou como uma saída analógica (Vref). Para que isto seja possível, é necessário
que cada pino externo possa ser ligado, de forma selectiva e programável, a um dos vários
circuitos internos do µC. Isto é conseguido se o nosso programa, ao ser executado pelo µC,
escrever nalguns bits de memória do µC o valor “0” ou valor “1”. O valor destes bits activam
b) Memória de dados
O PIC16F628A tem 224 bytes de memória de dados e
cada byte tem, naturalmente, oito bits.
Algumas destas posições de memória contêm os bits
especiais referidos na alínea anterior e podem ser usados
pelo programador para configurar alguns pinos externos
como entradas ou saídas, para activar ou desactivar
temporizadores internos, configurar interfaces de
comunicação Rs232, etc.
Outras posições de memória estão livres e podem ser
utilizadas livremente pelo programador, como variáveis
para armazenar números, caracteres, etc “General
Purpose Register”. Esta memória é uma memória RAM,
e perde os seus dados quando se desliga o µC (memória
volátil). Figura 1.5: Memória de dados
Os µC possuem também uma memória interna para armazenar os programas. O µC que vamos
utilizar neste trabalho possui uma memória Flash de 2048 posições. Sendo uma memória Flash
o programa não se perde mesmo quando se desliga o µC e este tipo de memória pode ser
reprogramado inúmeras vezes.
Os bits de configuração
_BOREN_ON _BOREN_OFF
_CP_ON _CP_OFF
_DATA_CP_ON _DATA_CP_OFF
_PWRTE_OFF _PWRTE_ON
_WDT_ON _WDT_OFF
_LVP_ON _LVP_OFF
_MCLRE_ON _MCLRE_OFF
_RC_OSC_CLKOUT
_RC_OSC_NOCLKOUT
_HS_OSC
_XT_OSC
_LP_OSC
Como resultado da compilação obtemos um novo ficheiro em disco, contendo código máquina,
que é necessário transferir posteriormente do computador para a memória do µC.
Podemos transferir esse código para o µC através de um programador. Existem diversos tipos de
programadores, por essa razão temos de indicar ao MPLAB qual dos programadores existentes
está disponível no laboratório. Como o programador disponível é o In Circuit Debugger - ICD2,
deverá seccionar a opção “Programmer Select Programmer MPLAB ICD2”
Utilizando o programador ICD2 transfira o programa para o µC. Ligue o ICD2 ao computador
através de uma ligação USB ou Rs232 (Figura 1.9).
Depois de transferir o programa para o µC, não se esqueça de fazer “Release” do pino “Master
Clear- MCLR” no ambiente integrado MPLAB. Só dessa forma o programa do µC poderá começar
a ser executado.
Neste exemplo pretende-se que o programa do µC active a saída digital RB0. Os 5 volt que serão
disponibilizados pelo µC, no pino RB0, serão usados para alimentar um led.
L7805
Na montagem da Figura 1.11 não será utilizado um cristal externo, mas sim o oscilador interno de
4Mhz que este µC possui.
a) Dimensione o valor da resistência que deve colocar em série com o Led para impedir uma
corrente excessiva que danifique o led ou o µC.
R = _____ Ω
SaidaDigital.asm
As opções de configuração “__CONFIG” permitem que o
list p=p16f628A programa gerado, quando for transferido para o µC , configure
#include <p16f628A.inc> os recursos internos do µC .
goto:
bcf:
bsf:
banksel:
Neste exemplo pretende-se adquirir o valor de uma entrada digital, mais exactamente da entrada
RA2 e em função do valor da entrada RA2 pretende-se também activar ou desactivar a saída RB0
(Figura 1.14).
O pino RA2 será utilizado como uma entrada digital. A saída digital continua a ser utilizada para
activar um led como no exemplo anterior. Nesta montagem vamos utilizar um cristal externo de
20Mhz para gerar o sinal eléctrico de relógio.
1 – Para que um dos pinos do µControlador possa actuar como uma entrada digital é necessário
escrever o valor um (1 - Input) num dos bits dos registos TRISA ou TRISB. Cada um destes
registos possui oito bits RA0:RA7 e RB0:RB7, respectivamente.
Neste exemplo vamos configurar o pino RA2 para actuar como uma entrada digital, capaz de
detectar se externamente lhe foi aplicada uma tensão de 5 ou 0 volt.
É necessário que o bit RA2 do registo TRISA seja colocado a “1” – Input para que o pino RA2 do
µControlador possa actuar como uma entrada digital.
2 – O µControlador fará com que o bit RA2 do registo PORTA assuma o valor “1”, se
externamente for aplicada uma tensão de 5v a este pino. O programa do µControlador deverá ler o
valor de RB1 e processá-lo em conformidade.
3- Como sabem, devido ao reduzido número de pinos cada um deles pode assumir diferentes
papéis. Os pinos RA0/AN0, RA1/AN1, RA2/AN2 e RA3/AN3 por exemplo, podem ser usados
como entradas analógicas ou como entradas/saídas digitais. Quando o µC é ligado estes quatro bits
valem “0” pelo que todos os pinos acima referidos actuam como entradas analógicas.
O programa do µC tem de escrever nos bits CM2, CM1, e CM0 do registo CMCON diferentes
combinações de “1” e “0” para alterar a forma como cada um destes pinos deve actuar (Tabela 1).
Por exemplo, para configurarmos estes quatro pinos para actuarem como entradas/saídas digitais
devemos usar as seguintes instruções: BANKSEL CMCON ; Selecção do Banco 0
MOVLW 0X07 ; 0x07 = B’00000111’
MOVWF CMCON ; RA1 passa a ser digital em vez de analógico
Este programa permite ler uma entrada digital e activar uma saída em conformidade.
EntradaDigital.asm
iniciar
banksel TRISB ; Selecção do banco 1
bsf TRISA,1 ; RA1 input Btfsc:
bcf TRISB,0 ; RB0 output
banksel PORTB ; Selecção do banco 0
MOVLW 0X07
MOVWF CMCON ; RA1 passa a ser digital em vez de analógico Movlw
main
BTFSC botao ; Testa o bit RA1. IF RA1 <> 0
goto ligasaida ; THEN goto ligasaida
goto desligasaida ; ELSE goto desligasaida
ligasaida Movwf
bsf led ; RB0=1
goto main
desligasaida
bcf led ; RB0=0
goto main
end
Figura 1.15: Programa 1 – Leitura de uma entrada digital
btfss:
movlw:
movwf:
Material a utilizar:
Motor de corrente contínua, Ponte H, microControlador, 1 potenciómetro, 2 interruptores.
Data de entrega:
O programa do µC deve ser enviado por correio electrónico até às 24h de 19 Novembro.
Como sabe a velocidade de rotação de um motor de corrente contínua CC, de íman permanente, é
directamente proporcional à tensão aplicada aos seus terminais e o seu sentido de rotação depende
da polaridade da tensão que lhe é aplicada (Figura 2.2).
Rpm = V / K Ф
Rpm Rotações por minuto
V Tensão aplicada ao motor (Volt)
K Valor numérico constante.
Ф Fluxo magnético (Webber)
T=KIФ
T Binário no veio do motor (Nm)
K Valor numérico constante.
I Intensidade da corrente (ampere)
Ф Fluxo magnético (Webber)
BC547 – NPN
Se aumentar o “duty cycle” do sinal aplicado à base do transístor e dessa forma aumentar o tempo
em que o transístor está à saturação, relativamente ao tempo em que está ao corte (Pulse Wide
Modulation), o motor atinge velocidades de rotação mais elevadas.
Se mantiver o “duty cycle” constante e aumentar a frequência da tensão aplicada à base do
transístor, as rpm do motor aumentam, diminuem, ou mantêm-se?
2.2.1 Conceitos
Para ser possível converter uma grandeza física num número digital, proporcional a essa grandeza,
várias etapas são necessárias (Figura 2.5):
Em primeiro lugar, é necessário recorrer a um sensor que permita converter uma grandeza física
num sinal eléctrico (Sensor). Este sinal eléctrico, eventualmente analógico, pode necessitar de ser
amplificado, filtrado, etc (condicionamento do sinal). Mesmo depois de termos um sinal eléctrico
devidamente tratado é necessário capturar (amostrar), quantificar esse sinal analógico e codificá-lo
num valor digital (conversão A/D).
Amostragem
Por amostragem entende-se a medição do valor que um sinal possui num determinado instante.
A Figura 2.6 apresenta uma forma de amostrar o sinal e de manter o seu valor constante durante o
processo posterior de conversão A/D.
Va(t) é o sinal que se pretende amostrar e VSH (t) é o sinal amostrado que será posteriormente
quantificado.
Intervalo de amostragem
Como a grandeza real que se pretende amostrar varia de amplitude em cada instante, é conveniente
que o intervalo de tempo entre amostragens seja o menor possível. O mesmo é dizer que a
frequência de amostragem deve ser a maior possível.
Teorema de Nyquist
De acordo com o teorema de Nyquist a frequência de amostragem de um sinal deve ser no mínimo
o dobro da frequência máxima que o sinal pode ter.
Quantificação
Por quantificação entende-se a conversão de uma grandeza analógica num valor discreto.
Através da comparação do valor amostrado com um conjunto finito de níveis, previamente
definidos, é possível determinar o nível no qual o valor amostrado se situa. O número destes níveis
é finito e quanto maior for o seu número, maior é a resolução da medição. Contudo, quanto maior
for o número de níveis também maior é o numero de bits necessários para os numerar.
A Figura 2.7 apresenta um exemplo com oito níveis de quantificação. Neste exemplo, cada nível
representa 5/7 de volt. Se a tensão amostrada possuir um valor inferior a 5/7 v a quantificação em 8
níveis representa-a como valendo 1. Se a tensão amostrada for igual ou superior a 5/8 e inferior a
10/8 de volt a quantificação em 8 níveis representa-a como valendo 2 e assim sucessivamente.
Como resultado da quantificação podemos obter oito valores inteiros, entre 0 e 7. Para representar
estes valores numa codificação binária podemos usar três bits.
Conversão A/D por seguimento é uma forma de realizar a conversão. Neste tipo de conversão o
comparador analisa se o sinal externo tem uma amplitude superior ou inferior a um sinal interno.
Este sinal interno é gerado por uma conversão digital/analógica DAC a partir de um valor digital,
valor esse que pode ser incrementado ou decrementado. Se o sinal interno for inferior ao sinal
externo o número digital é incrementado (Figura 2.8).
O PIC16F877 possui 8 pinos que podem ser usados como entradas analógicas (AN0 .. AN7).
ADCON1 (Banco 1)
Este µC só possui um circuito interno de conversão analógica/digital “ADC”, por isso é necessário
definir qual das várias entradas analógicas previamente definidas deve ser “amostrada” e
“quantificada” para gerar o resultado digital (ADRESL, ADRESH). Para seleccionar qual dos pinos
externos previamente configurados como analógicos deve ser “amostrado”, deverá configurar os
bits CHS2:CHS0 do registo ADCON0 (Figura 2.13).
Para ligar o circuito interno de conversão A/D deve activar o bit ADON. Não confundir este bit
com o bit de início de conversão GO/DONE.
Para iniciar o processo de conversão A/D o programa deverá activar o bit GO/DONE. Este bit será
posto a zero pelo hardware, automaticamente, quando a conversão estiver concluída.
ADCON0 (Banco 0)
1. Configurar o registo ADCON1 para definir quais os pinos externos que actuam como
entradas analógicas. (Bits PCFG3,2,1 e 0)
2. Configurar o registo TRISA para definir que o pino respectivo actua como uma entrada.
3. Configurar o registo ADCON0 para,
- definir a frequência do relógio (clock); (Bits ADCS1,0)
- definir qual das entradas analógicas deve ser amostrada (só pode ser amostrada
uma entrada analógica de cada vez); (Bits CHS2,1 e 0)
- alimentar o circuito interno de conversão.
4. Dar ordem de início de conversão activando o bit GO = 1 do registo ADCON0.
Por exemplo, se quisermos que o µC adquira valores de um sinal analógico no pino AN0 e o
resultado da conversão seja guardado nos 10 bits mais significativos de ADRESH+ADRESL
O programa deve configurar os bits que a seguir se definem
EntradaAnalog.asm
list p=pic16f877
#include <p16f877.inc>
__CONFIG _HS_OSC & _CP_OFF & _WDT_OFF
; Start at the reset vector
Org 0x00
goto iniciar
iniciar
banksel TRISB
CLRF TRISB ; Os RB0:7 são todos saídas
bsf TRISA,0
; Os 8bits mais significativos da conversão
Ficam em ADRESH, os 2 bits menos significativos ficam
em ADRESL
bcf ADCON1,7
; Apenas AN0 é uma entrada analógica
bsf ADCON1,3
bsf ADCON1,2
bsf ADCON1,1
bcf ADCON1,0
banksel PORTB
bsf ADCON0,7 ; Fosc/32
bcf ADCON0,6
bcf ADCON0,5 ;Canal AN0
bcf ADCON0,4
bcf ADCON0,3
bsf ADCON0,0 ; A/D enabled
Ciclo
bsf ADCON0,2 ; início da conversão
espera
btfsc ADCON0,2
goto espera
;conversão completa
movfw ADRESH
movwf PORTB
goto Ciclo
Figura 2.14: Entrada analógica
end
Recorda-se que PWM significa Pulse Wide Modulation, ou seja modulação da largura do pulso.
Um sinal eléctrico PWM observado num osciloscópio tem a forma de uma onda quadrada, com
uma tensão nula durante um tempo “t1” e com uma tensão diferente de zero durante um tempo
“t2”.
Através de uma saída digital do µC é possível gerar uma onda quadrada, que durante um tempo t1
valha zero volt e durante um tempo t2 valha 5 volt.
As saídas digitais já foram estudadas no trabalho anterior, falta apenas aprender a utilizar os
temporizadores internos do µC para dessa forma controlar o tempo que uma saída digital vale zero
volt “t1” e o tempo em que a saída vale 5 volt “t2”. Controlando t1 e t2 e controlamos a largura do
pulso “Off” e do pulso “On” dessa onda quadrada.
Monte os componentes
A saída digital continua a ser utilizada para activar um led como no exemplo anterior. Nesta
montagem vamos utilizar o cristal externo de 4 Mhz (Figura 2.15).
O exemplo seguinte pretende explicar como configurar e utilizar o temporizador “TMR0”, do µC.
O “TMR0” não é mais que uma posição da memória de dados, de 8 bits, que tem a particularidade
do seu valor poder ser incrementado automaticamente pelo hardware. Esta posição de memória
pode ser incrementada a partir do sinal de relógio “clock” do próprio µC, ou a partir de uma tensão
externa aplicada a um pino específico do µC. Sempre que ocorrer uma transição do sinal de
“clock” ou do sinal externo aplicado a esse pino, o valor do “Timer0”é automaticamente
incrementado. Quando, e se, esta posição de memória exceder o valor 255 = 28 diz-se que houve
um “estouro do Timer”. Esta ocorrência pode activar um bit da memória de dados, conhecido por
“TMR0 Interrupt Flag - T0IF” e pode gerar uma interrupção “interrupt”.
Este programa permite configurar e activar o temporizador “TMR0” fazendo com que a saída
digital RB0 se altere sempre que o TMR0 estourar (Figura 2.16).
list p=pic16f877
#include <p16f877.inc>
__CONFIG _INTRC_OSC_CLKOUT & _CP_OFF & _PWRTE_OFF & _WDT_OFF & _LVP_OFF
; Start at the reset vector
Reset_Vector code 0x000
goto iniciar
iniciar
banksel TRISB
clrf TRISB
bcf OPTION_REG,T0CS ; TOCS = 0 O sinal de Clock incrementa o Timer0
bcf OPTION_REG, T0SE ; TOSE = 0 A transição do sinal de 0 para 1 incrementa o Timer0
bsf OPTION_REG, PS2 ; PS2 = 1 256 transições do sinal produz um incremento de Timer0
bsf OPTION_REG,PS1 ; PS1 = 1
bsf OPTION_REG, PS0 ; PS0 = 1
banksel PORTB
end
Determine de quanto em quanto tempo a saída RB7 se altera. Considere que está a utilizar o
relógio interno do P16F628A (4 Mhz) ?
O temporizador TMR1 tem 16 bits, mais exactamente, o TMR1 corresponde fisicamente a duas
posições da memória de dados, de 8 bits cada, conhecidas pelas designações TMR1L e TMR1H.
Monte os componentes
Timer1.asm
list p=pic16f877
#include <p16f877.inc>
__CONFIG _HS_OSC & _CP_OFF & _PWRTE_OFF & _WDT_OFF & _LVP_OFF
; Start at the reset vector
org 0x00
goto iniciar
iniciar
banksel TRISB
clrf TRISB ; Todos os pinos de RB passam a ser saídas
banksel PORTB
bsf T1CON,5 ; prescaler /8
bsf T1CON,4 ; prescaler
bsf T1CON,3 ; osc enabled
bcf T1CON,1 ; internal clock
bsf T1CON,0 ; enables timer1
end
O programa “PWM.asm” activa uma saída digital durante 0,25s e desactiva-a durante 0,5s,
sucessivamente. Desta forma vamos gerar um sinal PWM com um período de 0,75s e um “duty
cycle” de 33% (Figura 2.20).
PWM.asm
list p=pic16f877
#include <p16f877.inc>
__CONFIG _HS_OSC & _CP_OFF & _PWRTE_OFF & _WDT_OFF & _LVP_OFF
iniciar
banksel TRISB
clrf TRISB
banksel PORTB
bsf T1CON,5 ; prescaler
bsf T1CON,4 ; prescaler
bsf T1CON,3 ; osc enabled
bcf T1CON,1 ; internal clock
bsf T1CON,0 ; enables timer1
Ciclo
movlw 0x80 ; TMR1 = 0x8000 = 65536/2 = 32678 dec
movwf TMR1H
T0_espera
btfss PIR1,TMR1IF
goto T0_espera
bcf PIR1,TMR1IF ; limpa a flag
bcf PORTB,0
movlw 0x00
movwf TMR1H
T1_espera
btfss PIR1,TMR1IF
goto T1_espera
bcf PIR1,TMR1IF ; limpa a flag
bsf PORTB,0
goto Ciclo
end
A saída digital continua a ser utilizada para activar um led como no exemplo anterior. Nesta
montagem vamos continuar a utilizar o cristal externo de 4 Mhz.
c) Altere o programa para activar a saída digital durante 0,1s e desactivá-la durante 0,2s.
EntradaAnalogPWM.asm
iniciar
banksel TRISB
clrf TRISB ; PORTB output
bsf TRISA,0 ; RA0 input
bcf ADCON1,7
; O resultado da conversão fica em ADRESH,
; apenas 2 bits da conversão ficam em ADRESL
bsf ADCON1,3 ; AN0
bsf ADCON1,2 ; "
bsf ADCON1,1 ; "
bcf ADCON1,0 ; "
banksel PORTB
bsf ADCON0,7 ; Fosc/32
bcf ADCON0,6 ; "
bcf ADCON0,5 ;Canal AN0
bcf ADCON0,4 ; "
bcf ADCON0,3 ; "
bsf ADCON0,0 ; A/D enabled
Conv_espera
btfsc ADCON0,2
goto Conv_espera
; conversão completa,
; valor guardado em ADRESH
L293D
[Johnson’00]
[Iovine’00]
[Iovine’00]
Ciclo
Conv_espera
btfsc ADCON0,2
goto Conv_espera
; conversão completa,
; valor guardado em ADRESH
list p=pic16f877
#include <p16f877.inc> ; ------ GERA um periodo PWM
; TMR1= 0xFD70 até 0xFFFF demora 0,01seg
__CONFIG _HS_OSC & _CP_OFF & _WDT_OFF movlw 0xFF
; Start at the reset vector movwf TMR1H
org 0x00 movfw ADRESH ;TMR1 = 0xFF + ADRESH
goto iniciar movwf TMR1L
bsf PORTB,2 ; liga a saída de 0 a 2 ms
iniciar T0_espera
banksel TRISB btfss PIR1,TMR1IF
clrf TRISB ; PORTB output goto T0_espera
bcf PIR1,TMR1IF ; limpa a flag
bcf ADCON1,7 ; O resultado da conversão fica em
ADRESH, apenas 2 bits da conversão fica em movlw 0xB3
ADRESL movwf TMR1L
bsf ADCON1,3 ; AN0 movlw 0xF7
bsf ADCON1,2 ; " movwf TMR1H ; Desliga a saída 17ms
bsf ADCON1,1 ; " bcf PORTB,2
bcf ADCON1,0 ; " T1_espera
btfss PIR1,TMR1IF
banksel PORTB goto T1_espera
bsf ADCON0,7 ; Fosc/32 bcf PIR1,TMR1IF ; limpa a flag
bcf ADCON0,6 ; " ; Fim PWM
bcf ADCON0,5 ;Canal AN0
bcf ADCON0,4 ; " goto Ciclo
bcf ADCON0,3 ; " end
bsf ADCON0,0 ; A/D enabled
[Rizzoni 2007] Rizzoni, G. (2007). Principles and Applications of Electrical Engineering. 5th, McGraw Hill
International. Capítulo 17.
[Paul 1992] Paul, C.R., Nasar, S.A., Unnewehr, L.E., (1992). IntrodµC tion to Electrical Engineering. 2th,
McGraw Hill. Capítulo 13
[Souza 2006] Souza, D.J. (200?). Desbravando o PIC. 8º Edição, Editora Érica. S.Paulo.
[Johnson’00] Johnson L. (2000). Experimenting With the Picbasic Pro Compiler. 1ºEd. Rosetta Technologies.
Crownhill Associates Ltd.
[Sanchez’07] Sanchez, J., Canton M. (2007). Microcontroller Programming The Microchip PIC. Taylor & Francis.
CRC Press.
Objectivos:
Compreensão do funcionamento dos motores de passo.
Utilização das saídas digitais do µC para comandar de um motor de passo.
Material a utilizar:
µC, Motor de passo, interruptores e potenciómetro.
Data de entrega:
O programa do µC deve ser enviado por correio electrónico até às 24h de 26 de Novembro.
Conforme pode observar na figura, os enrolamentos destes motores situam-se no estator e o rotor
pode ser constituído por um íman permanente, ou por um material metálico de baixa relutância
magnética (ferromagnético). O rotor, seja ele de íman permanente ou de material ferro magnético,
alinha-se com o campo magnético criado pelo(s) enrolamento(s) do estator.
A velocidade de rotação de um motor deste tipo depende da cadência com que os seus
enrolamentos são, sequencialmente, alimentados. Como o rotor se alinha como o campo magnético
criado pelo estator, quanto mais depressa alimentar o enrolamento seguinte, do estator, maior será
a velocidade de rotação do rotor.
Existe contudo um limite para a velocidade máxima de rotação do motor. Devido à indutância dos
enrolamentos do estator, tanto a corrente que percorre cada enrolamento como o campo magnético
por si criado, demoram algum tempo a atingir o seu valor máximo. Se um enrolamento estiver
ligado pouco tempo, para seja possível ligar rapidamente o enrolamento seguinte e dessa forma
tentar aumentar as rpm do motor, pode acontecer que o binário produzido por esse enrolamento
não chegue a ser suficiente para o rotor rodar. Podemos por isso dizer que o aumento da rotação de
um motor deste tipo tem como consequência a diminuição do seu binário. Pelo contrário, quando
um motor deste tipo está ligado mas parado tem binário e o seu valor é máximo (Figura 3.3).
Unipolares
Quando os enrolamentos de um motor forem sempre alimentados com a mesma polaridade e a
corrente que os percorrer tiver sempre o mesmo sentido, designam-se por motores unipolares.
a) De acordo com o exemplo da figura 3.5 e da sequência de activação dos enrolamentos nela
descrita, diga se o rotor do motor de passo bipolar roda no sentido horário ou anti-horário?
b) Qual é o passo deste motor, em graus?
Motores mistos
Os motores mistos possuem um rotor de íman permanente mas com a mesma geometria dos
rotores de relutância variável.
Figura 3.8: Circuito de controlo de motores de passo de íman permanente bipolares [AN907]
Tecnologias e Accionamento e Comando 2009/2010, Trabalho Nº 3 44
3.1.2 Circuitos de controlo
[AN907]
[Rizzoni, 2007]
Figura 3.10: Circuito de controlo de motores unipolares de íman permanente
list p=pic16f877
#include <p16f877.inc>
local tempo
__CONFIG _HS_OSC & _CP_OFF & _WDT_OFF & _LVP_OFF clrf PORTB
bsf PORTB,0 ; Activa RB0
ORG 0X00 clrf TMR1L
goto iniciar movf tempo
movwf TMR1H
iniciar T1_espera ; Espera 0 a 1 seg
banksel TRISB btfss PIR1,TMR1IF
clrf TRISB ; PORTB output goto T1_espera
;bcf ADCON1,7 ; O resultado da conversão fica em bcf PIR1,TMR1IF
;ADRESH, apenas 2 bits da
;conversão fica em ADRESL
;bsf ADCON1,3 ; AN0 clrf PORTB
;bsf ADCON1,2 ; " bsf PORTB,1 ; Activa RB1
;bsf ADCON1,1 ; " clrf TMR1L
;bcf ADCON1,0 ; " movf tempo
movlw B'00001110' movwf TMR1H
movwf ADCON1 T2_espera ; Espera 0 a 1 seg
Btfss PIR1,TMR1IF
banksel PORTB GOTO T2_espera
;bsf ADCON0,7 ; Fosc/32 BCF PIR1,TMR1IF
;bcf ADCON0,6 ; "
;bcf ADCON0,5 ;Canal AN0 clrf PORTB
;bcf ADCON0,4 ; " bsf PORTB,2 ; Activa RB2
;bcf ADCON0,3 ; " clrf TMR1L
;bsf ADCON0,0 ; A/D enabled movf w tempo
Movlw B'10000001' movwf TMR1H
movwf ADCON0 T3_espera ; Espera 0 a 1 seg
btfss PIR1,TMR1IF
;bsf T1CON,5 ; prescaler timer1 goto T3_espera
;bsf T1CON,4 ; prescaler " bcf PIR1,TMR1IF
;bsf T1CON,3 ; osc enabled
;bcf T1CON,1 ; internal clock
;bsf T1CON,0 ; enables timer1 clrf PORTB
movlw B'00111001' bsf PORTB,3 ; Activa RB3
movwf T1CON clrf TMR1L
movf tempo
Ciclo movwf TMR1H
T4_espera ; Espera 0 a 1 seg
; ----- Conversão A/D btfss PIR1,TMR1IF
bsf ADCON0,2 ; inicio da conversão goto T4_espera
Conv_espera bcf PIR1,TMR1IF
btfsc ADCON0,2
GOTO Conv_espera
; conversão completa, goto Ciclo
; valor guardado em ADRESH end
movfw ADRESH
movwf tempo
[Rizzoni 2007] Rizzoni, G. (2007). Principles and Applications of Electrical Engineering. 5th, McGraw Hill
International. Capítulo 18.
[AN822] Padmaraja Y. et. Al., Stepper Motor Microstepping with PIC18C452, Microchip, 2002.
[AN907] Reston C., et. Al., Stepping Motors Fundamentals, Microchip, 2004.
Objectivos:
Pretende-se utilizar a interface de comunicação USART / Rs232 do µC.
Material a utilizar:
µC, Conversor MAX232, cabo Rs232, um computador com o Hyperterminal.
Data de entrega:
O programa do µC deve ser enviado por correio electrónico até às 24h de 3 de Dezembro.
As redes industriais permitem controlar e monitorizar as actividades produtivas com maior rapidez
e menores custos, por essas razões as redes de comunicação de dados são cada vez mais utilizadas
na indústria.
Neste trabalho vamos utilizar o protocolo de comunicação Rs232. Utilize o programa
“Hyperterminal”, disponível no computador, para receber os dados vindos do µC.
Desenvolva um programa em assembler que faça o µC enviar, de meio em meio segundo, o estado
das suas entradas e saídas. Mais exactamente, o µC deve enviar o valor das saídas digitais (RB0 e
RB1), da entrada digital (RA1) e também o valor da entrada analógica (AN0).
Pretende-se que comunicação tenha os seguintes parâmetros: 2400 bits/segundo, 8 bits dados, sem
bit de paridade e 1 stop bit.
Para os equipamentos poderem comunicar entre si têm de respeitar um conjunto de regras comuns.
A esse conjunto de regras de comunicação chama-se protocolo de comunicação.
A Recomendação para Standard 232 – RS232 tinha por objectivo permitir a ligação de
equipamentos digitais a redes públicas analógicas, por exemplo, a ligação de terminais e
computadores à rede telefónica usando para o efeito modems. Convém lembrar que na época a
única rede de comunicação mundial era a rede telefónica, analógica, concebida para transmitir a
voz humana.
Este protocolo foi aprovado pela Electronic Industries Association -EIA, sob a designação
EIA232C. A norma EIA-232 tem tido várias evoluções, desde a primeira versão elaborada em
1960, até à versão EIA-232F.
Topologia
Neste contexto, por topologia entende-se a forma geométrica como os equipamentos se encontram
fisicamente ligados entre si. Existem várias topologias possíveis, a saber: barramento, anel, árvore,
estrela e topologia mista/híbrida
No caso do protocolo Rs232, está prevista a ligação entre dois equipamentos apenas, não se trata
por isso de uma verdadeira rede, mas sim uma ligação ponto a ponto, entre dois equipamentos.
Meio comunicação
Os fios de cobre, os cabos coaxiais, a fibra óptica e mesmo o ar, são alguns exemplos de meios de
comunicação que podem ser usados para transmitir dados entre equipamentos.
No caso vertente, o protocolo Rs232 preconiza a utilização do fio de cobre para interligar os dois
equipamentos.
Sinais eléctricos
Tx
-V
+V
Rx
-V Neutro
Blindagem do cabo
Este protocolo define também o tempo que o emissor deve manter a tensão constante, positiva ou
negativa, por cada bit enviado (bit time). Quanto menor for este tempo, maior é o número de bits
que o emissor pode enviar por segundo. Várias taxas de transferência (baudrate) estão previstas
neste protocolo: 150, 300, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200 bits/s.
A Figura 4.3 ilustra as tensões e a frequência do sinal eléctrico aplicados num fio de cobre durante
uma transmissão de vários bits, com uma taxa de 9600 bits/s. Pode observar-se que é aplicada uma
tensão negativa de – 5 volt, durante 1/9600 seg (bit time) para transmitir um bit com o valor lógico
“1”.
Taxa Distância
transferência aprox.(m)
110 850
300 800
600 700
1200 500
2400 200
4800 100
9600 70
19200 50
115 000 20
- O “start bit” corresponde a uma tensão positiva aplicada durante um “bit time”;
- Podem ser enviados 7 ou 8 bits de dados em cada palavra série;
- O bit de paridade é opcional, pode ou não ser utilizado. No caso de ser utilizada a paridade
par, este bit assume o valor “1” ou “0” por forma ao número de bits a “1” enviados na
palavra série seja sempre um número par.
- O “stop bit” corresponde a uma tensão negativa aplicada no fio de cobre durante 1, 1½, ou 2
“bit time”.
Tipo de diálogo
Quando apenas um dos equipamentos pode enviar dados e outro se limita a receber, diz-se que têm
um diálogo do tipo “simplex”.
Quando os dois equipamentos podem receber e enviar dados, mas não em simultâneo, diz-se que
têm um diálogo do tipo “half duplex”.
Quando os dois equipamentos podem enviar e receber dados em simultâneo, têm um diálogo do
tipo “full duplex”.
Numa comunicação Rs232 existem dois fios de cobre distintos para a transmissão de dados, um
em cada sentido, por essa razão os dois equipamentos podem receber e enviar dados em
simultâneo. Diz-se por isso que estamos na presença de um diálogo do tipo “Full duplex”.
O protocolo Rs232 prevê duas formas do equipamento receptor pedir ao emissor para suspender
por momentos o envio de dados. Na terminologia inglesa, controlo de fluxo designa-se por
“Handshake”.
Uma das formas de controlar o fluxo de informação entre os equipamentos, consiste no envio do
receptor para o emissor de uma palavra série especial (Xoff- 0x13 = 00010011 bin = 19 dec ).
Quando emissor recebe a palavra Xoff suspende o envio de novos dados até que o receptor lhe
envie a palavra Xon (Controlo de fluxo por Xon-Xoff).
A segunda forma de controlar o fluxo de informação entre o emissor e o receptor, consiste na
utilização de fios de cobre adicionais a ligar as portas Rs232 dos dois equipamentos. Mais
exactamente, fios de cobre adicionais a ligar o pino Request to Send - RTS ao Clear To Send –
CTS . Quando emissor pretender enviar dados activa o pino RTS e o receptor pode activar o seu
pino CTS para indicar que aceita receber dados (Controlo de fluxo por hardware).
Cabos Rs232
Nalgumas fichas, o pino Tx corresponde ao pino número 2, noutros casos ao número 3. Mas,
independentemente da ficha ser macho ou fêmea, independentemente do equipamento ser um
computador (DTE – Data Terminal Equipment) ou um modem (DCE – Data Communication
Equipment), o pino de transmissão Tx de um equipamento liga sempre ao pino Rx do outro
equipamento. Nalgumas fichas o pino “terra” corresponde ao pino 5, noutras corresponde ao pino
7. Em todo o caso, os pinos “terra” das duas fichas devem ser ligados.
O cabo descrito no lado esquerdo da Figura 4.6 permite uma comunicação Rs232, contudo este
cabo não permite um controlo de fluxo por hardware. Já o cabo do meio permite o controlo de
fluxo entre equipamentos através dos pinos Clear To Send - CTS e Request To Send – RTS.
Para o µC enviar para outros equipamentos uma palavra série, com 8 bits de dados, através de uma
ligação Rs232, o programa do µC deve escrever esses 8bits na posição da memória de dados
conhecida por, registo TXREG e esses bits serão automaticamente enviados. Por exemplo, se
pretender enviar o valor B’00010001’ para o computador, deve fazer:
Para configurar a interface Rs232 do uC, deve activar ou desactivar alguns bits dos registos
RXSTAT e TXSTAT. Cada uma destas posições de memória têm 8 bits, no entanto, neste caso,
apenas é necessário configurar 3 destes bits.
Os 3 bits anteriores valem “0” por defeito, por isso basta alterar/activar um bit, o bit SPEN.
TXSTAT RCSTAT
Por exemplo, se o cristal utilizado for de 4 Mhz e se pretender uma taxa de transferência de:
Em resumo, o código necessário para activar a interface Rs232 do uC, com 4800 bit/s, sem bit de
paridade e com 1 stop bit, resume-se a 3 instruções:
Para enviar uma palavra série com o número 00110000 deve escrever esse número no registo
TXREG.
movlw B’00110000’
movwf TXREG ; Envia uma palavra série com 8 bits de dados
Nos exemplos anteriores, a fórmula de cálculo utilizada permitiu determinar o valor a atribuir ao
registo SPBRG, como o bit BRGH valia zero por defeito e a fórmula era:
SPBRG = Fosc/TaxaTransf/64 -1
Por exemplo, se o cristal utilizado for de 4 Mhz e se pretender uma taxa de transferência de:
Com este programa, o µC envia uma palavra série para o equipamento remoto (ex. Computador).
list p=p16f877A
#include <p16f877A.inc>
__CONFIG _XT_OSC & _CP_OFF & _PWRTE_OFF & _WDT_OFF & _BODEN_OFF
; Start at the reset vector
org 0x00
goto iniciar
org 0x04
retfie
iniciar
; ---- Configuração da USART = Rs232: 4800,8,n,1
banksel TRISB
bsf TRISC,6 ; Activa o pino TX (corresponde RC6)
bcf TXSTA,4 ; SYNC = 0 (comunicação assíncrona)
bsf TXSTA,5 ; TXEN = 1 ( autoriza envio )
movlw .12 ; Baudrate = 4800
movwf SPBRG
banksel RCSTA
bsf RCSTA,7 ; SPEN = 1 (Activa a porta série)
; ------- fim da configuração da USART
main
movlw A'1' ; Na tabela ASCII, caracter '1'
; corresponde ao número 49 = 110001 = 0x31
movwf TXREG ; Envia um byte para o equip remoto
end
Este programa permite ao µC receber palavras série, e com base nos bytes recebidos activar as
saídas RB0:RB7
list p=p16f877A
#include <p16f877A.inc>
__CONFIG _HS_OSC & _CP_OFF & _PWRTE_OFF & _WDT_OFF & _LVP_OFF
org 0x00
goto configura
; ------ Rotina de serviço ao Interrupt
org 0x04
retfie
configura
; ------------- Configura a Porta Rs2321
banksel TRISB ; Selecciona banco 1
clrf TRISB ; Activa todos os pinos RB como saída
bsf TRISC,7 ; Activa o pino RC7/RX
bcf TXSTA,4 ; SYNC = 0 Activa comunicação assíncrona
movlw .12 ; Define o baudrate = 4800
movwf SPBRG
banksel RCSTA ; Selecciona o banco 0
bsf RCSTA,7 ; SPEN Serial port enable
bsf RCSTA,4 ; CREN Continuos reception enable
; ------------------------------------
main
btfss PIR1,RCIF ; IF Verifica se chegou nova palavra série
goto main ; ELSE ainda não chegou -> goto main
movfw RCREG ; THEN lê o byte recebido da porta Rs232 - Rx
movwf PORTB ; Activa as saídas RB com o bits do Byte recebido
goto main
end
Este programa permite ao µC receber palavras série, e com base nos bytes recebidos activar as
saídas RB0:RB7 como no exemplo anterior, mas além disso, todos os bytes recebidos na porta
série do µC são reenviados para o emissor. O programa configura a interface Rs232 com uma taxa
de transferência de 9600bits/s, 1 stop bit, e sem bit de paridade.
list p=p16f877A
#include <p16f877A.inc>
__CONFIG _HS_OSC & _CP_OFF & _PWRTE_OFF & _WDT_OFF & _LVP_OFF
org 0x00
goto configura
org 0x04
retfie
configura
; ------------- Configura a Porta Rs2321
banksel TRISB
bsf TRISC,7 ; Activa o pino RC7/RX
bsf TRISC,6 ; Activa o pino RC6/TX
bcf TXSTA,4 ; SYNC = 0 Activa comunicação assíncrona
bsf TXSTA,5 ; Activa TXEN=1
bsf TXSTA,2 ; BRGH = 1
movlw .25 ; Define o baudrate 9600
movwf SPBRG
main
btfss PIR1,RCIF
goto main
movfw RCREG ; Lê o byte recebido da porta Rs232 - Rx
movwf TXREG ; reenvia o byte recebido para o equipamento remoto
goto main
end
4.6 Bibliografia
[Rizzoni 2007] Rizzoni, G. (2007). Principles and Applications of Electrical Engineering. 5th, McGraw Hill
International. Capítulo 18.
[AN822] Padmaraja Y. et. Al., Stepper Motor Microstepping with PIC18C452, Microchip, 2002.
[AN907] Reston C., et. Al., Stepping Motors Fundamentals, Microchip, 2004.
[Sanchez’07] Sanchez, J., Canton M. (2007). Microcontroller Programming The Microchip PIC. Taylor & Francis.
CRC Press.
Objectivos:
Compreensão e utilização das interrupções.
Directivas do compilador
Material a utilizar:
µC, “encoder” incremental, motor de passo
Data de entrega:
O programa do µC deve ser enviado por correio electrónico até às 24h de 10 de Dezembro.
Vectores de interrupção
“Goto” - Quando o programador usar uma instrução de salto que faça com que a próxima
instrução a executar não se encontre na posição de memória consecutiva, mas sim na posição
indicada pela instrução de salto.
“Call” - Quando o programador usar uma instrução que chame uma subrotina e faça o µC
saltar para o conjunto de instruções dessa subrotina, localizada algures na sua memória e
depois regresse automaticamente à sequência inicial.
“Interrupt” - A terceira situação que pode interromper uma execução sequencial é gerada pelo
próprio hardware, de forma aleatória, assíncrona e independente da instrução que esteja a ser
executada na altura pelo µC. Este tipo de interrupção permite que a execução do programa
também salte para uma nova zona do programa, execute um conjunto de instruções e depois
regresse ao ponto em que o programa estava antes da interrupção. Esta situação parece-se com
a anterior, “Call”, mas é diferente porque agora quem define o instante em que a interrupção
ocorre é o hardware. O programador apenas define as instruções que devem ser executadas
quando a interrupção ocorrer. Ao conjunto de instruções que serão executadas quando uma
interrupção deste tipo ocorrer chama-se “rotina de serviço à interrupção - RSI” . A posição de
memória onde fica guardada a localização dessa RSI é conhecida por “vector de interrupção” e
no caso do µC que vamos utilizar este vector de interrupção corresponde ao endereço 4 da
memória dos programas.
“Interrupt flags”
Neste µC, sempre que ocorre uma interrupção, seja qual for a sua causa, é executada a mesma
rotina de serviço à interrupção RSI. Compete ao nosso programa, mais exactamente à nossa
RSI, determinar qual foi a causa da interrupção e processá-la de forma adequada. Felizmente o
hardware do µC, além de gerar uma interrupção, activa uma de várias “Flags”, aquela que
corresponder ao tipo de ocorrência que gerou o “Interrupt”.
Em assembler não existem IF, FOR, WHILE, funções ou procedimentos que também
permitiriam controlar a sequência com que as instruções são executadas.
Para trabalhar com interrupções é necessário que o programa active previamente alguns bits do
tipo Interrupt Enable – IE, presentes na sua memória de dados (Figura 5.1).
General Interrupt Enable – GIE : Este bit tem de ser activado pelo programa, seja qual for a
interrupção que se queira autorizar e processar.
PEriferal Interrupt Enable - PEIE : Este bit tem de ser activado pelo programa, quando se quer
gerar e processar interrupções do tipo externo, por exemplo
interrupções geradas por terem sido aplicadas tensões
externas aos pinos RB0, RB4 a RB7 ou mesmo
interrupções geradas pelo conversor A/D
Timer0 Interrupt Enable – T0IE : Este bit tem de ser activado pelo programa, quando se quer
gerar e processar interrupções devido ao “estouro” do
TMR0. Lembra-se que o TMR0 pode ser incrementado
pelo relógio “clock” ou por uma tensão externa aplicada ao
pino RA4 (transição).
Interrupt Enable - INTE : Este bit tem de ser activado pelo programa, quando se quer
gerar uma interrupção sempre que for aplicada uma tensão
externa ao pino RB0/INT.
RB Interrupt Enable - RBIE : Este bit tem de ser activado pelo programa, quando se quer
gerar uma interrupção quando um dos pinos, RB7 a RB4,
variar de tensão.
Analog Digital Interrupt Enable - ADIE : Este bit tem de ser activado pelo programa, para ser
gerada uma interrupção quando uma conversão A/D
terminar.
Receiver Interrupt Enable - RCIE : Este bit tem de ser activado pelo programa, para ser gerada
uma interrupção quando chegar uma palavra série Rs232 ao
µC.
Transmit Interrupt Enable - TXIE : Este bit tem de ser activado pelo programa, para ser gerada
uma interrupção sempre que for enviada uma palavra série
Rs232, por exemplo, para o computador.
Os bits do tipo Interrupt Flag – IF são activados pelo hardware quando ocorrer uma interrupção e
são limpos pelo programa/programador. A saber:
Este programa permite activar e processar as interrupções geradas pela recepção de palavras série
Rs232. Ou seja, este programa tira partido da Rotina de Serviço à Interrupção - RSI.
O µC é configurado para gerar uma interrupção sempre que receber uma palavra série e a RSI é
gravada no endereço 0x04 e posições consecutivas. A RSI definida neste programa copia o byte
recebido em RCREG para o registo TXREG, fazendo dessa forma com que ele seja reenviado para
o equipamento emissor. A RSI começa por verificar se o bit RCIF é igual a “1”, nesse caso foi
recebida uma palavra série e os 8 bits de dados estão disponíveis no registo RCREG.
A instrução RETFIE permite terminar a RSI e a execução do programa retorna ao ponto onde
estava antes da RSI ter sido chamada.
Para activar as interrupções os bits GIE, PEIE, RCIE têm de ser iguais a “1”.
Grande parte deste programa já foi estudada no trabalho anterior, as diferenças encontram-se
escritas a negrito.
list p=p16f877A
#include <p16f877A.inc>
__CONFIG _HS_OSC & _CP_OFF & _PWRTE_OFF & _WDT_OFF & _LVP_OFF
org 0x00
goto configura
configura
Este programa permite activar e processar as interrupções geradas pelo “estouro” do TMR1.
O temporizador TMR1 do µC já foi utilizado num exemplo anterior, e os bits seguintes já foram
utilizados (Figura 5.3).
iniciar
banksel TRISB
clrf TRISB ; PORTB output
; ------ Configura e activa o TMR1
banksel T1CON ; banco 0
bsf T1CON,5 ; prescaler timer1 /8
bsf T1CON,4 ; prescaler "
bsf T1CON,3 ; osc enabled
bcf T1CON,1 ; internal clock
bsf T1CON,0 ; enables timer1
clrf TMR1H ; inicializa timer1 a zero
Ciclo
goto Ciclo
end
Este programa permite activar e processar as interrupções geradas quando uma conversão
Analógico-Digital A/D termina e um valor binário de 10 bits, proporcional à tensão externa, está
disponível em ADRESL e ADRESH.
O circuito de conversão A/D do µC já foi utilizado num exemplo anterior, e os bits seguintes já
foram utilizados (Figura 5.5).
Neste exemplo, além dos bits anteriores, serão também inicializados 3 bits adicionais para
autorizar o circuito A/D a gerar interrupções sempre que uma conversão termine, a saber:
GIE, PEIE e ADIE (Figura 5.6).
Depois de ocorrer a interrupção, dentro da rotina de serviço à interrupção - RSI, é necessário pôr o
bit/”flag” ADIF a zero. Caso contrário, será gerada uma nova interrupção logo que a primeira
termine.
list p=pic16f877
#include <p16f877.inc>
__CONFIG _HS_OSC & _CP_OFF & _WDT_OFF & _LVP_OFF
org 0x00
goto iniciar
iniciar
banksel TRISB
clrf TRISB
Este programa permite activar e processar as interrupções geradas pelo pino RB0/INT. Quando a
tensão externa aplicada ao pino RB0/INT variar de 0 para 5 volt, ou vice-versa, pode ser gerada
uma interrupção. Para isso acontecer é necessário activar os bits GIE, PEIE e INTE (Figura 5.7).
Depois de ocorrer a interrupção, dentro da rotina de serviço à interrupção - RSI, é necessário pôr o
bit/”flag” INTF a zero. Caso contrário, será gerada uma nova interrupção logo que a primeira
termine
list p=pic16f877a
#include <p16f877a.inc>
iniciar
banksel TRISB
clrf TRISB ; PORTB output
bsf TRISB,0 ; PORTB.RB0 input
banksel PORTB ; banco 0
; ----- Activa interrupções
bsf INTCON, GIE ; autoriza interrupções
bsf INTCON, PEIE ; autoriza interrupções de periféricos
bsf INTCON, INTE ; autoriza interrupção gerada por RB0
Ciclo
goto Ciclo
end
As directivas são instruções para o compilador, aparecem no código, mas não são convertidas
directamente em código máquina “opcodes”. De facto, as directivas são primeiro convertidas em
várias instruções elementares de assembler e só depois são convertidas em código máquina.
Directiva “CBLOCK”
Quando o programador cria uma variável, seja em “C”, “Fortran”, “Pascal”, “Assembler” ou em
qualquer outra linguagem, o que acontece de facto é que o compilador reserva uma ou várias
posições de memória da RAM do Computador, do PLC, ou do uC, para armazenar os valores que
essa variável poderá assumir durante a execução do programa.
Em assembler podemos criar uma sequência de variáveis e simultaneamente definir os endereços
que cada uma delas ocupará na RAM, através da directiva CBLOCK.
CBLOCK 0x20
Var1 ; A variável VAR1 corresponde à posição de memória 0x20 do uC
Var2 ; A variável VAR2 corresponde à posição de memória 0x21 do Uc
Var3:2 ; A variável VAR2 corresponde às posições 0x22 e 0x23
ENDC
Movlw B’00010001’
Movwf Var1
Directiva “WHILE”
Em vez do programador repetir as instruções de cada ciclo, esta directiva leva o compilador a gerar
o código correspondente a todas as iterações do ciclo.
IF condição
Instrução i ; se a condição for VERDADEIRA executa esta instrução
………. “
Instrução i+n ; se a condição for VERDADEIRA executa esta instrução
ELSE
Instrução j ; se a condição for FALSA executa esta instrução
……….. “
Instrução j+n ; se a condição for FALSA executa estas instruções
ENDIF
Binário B'00111001'
Octal O'777'
Decimal D'100' ou em alternativa .100
Hexadecimal H'9f' ou em alternativa 0x9f
Caracter ASCII A'C' ou em alternativa 'C'
6 PROGRAMAÇÃO em “C”
Objectivos:
Introdução à linguagem “C”
- conversão analógico-digital
- temporizadores de 1ms e 1seg
- comunicação Rs232
Material a utilizar:
Placa PICDEM 2 plus, 1 cabo Rs232.
Data de entrega:
O programa do µC deve ser enviado por correio electrónico até às 24h de 17 de Dezembro.
Desenvolva as funções em “C” com “in-line assembler” e interrupções que lhe permita controlar a
conversão analógico-digital, os temporizadores e a comunicação Rs232.
ADC_Conf();
ADC_Start();
ADC_Done();
Delay_ms();
Delay_seg();
Rs232Conf();
Rs232Tx();
Rs232Rx();
Instalação do compilador
Vamos utilizar o compilador “Hi-TECH Universal ToolSuite” da Microchip. Para instalar o
compilador deve aceder ao sítio da Microchip:
http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en542849
Da mesma forma que o “Assembler” converte um ficheiro de texto, escrito em assembler, num
ficheiro com código máquina (*.o), o compilador de “C” converte um ficheiro de texto, escrito em
“C”, num ficheiro também com código máquina (*.o).
Podem existir vários ficheiros com código máquina, alguns escritos e compilados pelo utilizador,
outros já compilados por outros programadores ou pela Microchip (*.lib). Se quiser reutilizar esse
código máquina nos seus programas tem de o juntar ao seu próprio código através do “Linker”.
Após o “linker”, obtemos um ficheiro (*.hex) com todo código máquina que é necessário enviar
para o µC, mais exactamente para a sua memória de programas.
Figura 6.1: Conversão de um ficheiro de código “C” num ficheiro com código máquina [Wilmshurst’07]
Criação de um projecto em C
Depois de instalado, este compilador pode ser utilizado a partir do MPLAB IDE. Pode criar um
novo projecto, como fazia para criar projectos em assembler, através da opção “Project Wizard”,
mas agora, em vez de seleccionar a opção “MPASM toolsuite”, passa a seleccionar a opção “HI-
TECH Universal Toolsuite” (Figura 6.2).
Este programa permite activar a saída digital RB2. Todos os programas em “C” têm uma função
“main”. Esta função é a primeira a ser chamada e todo o código contido entre as chavetas da
função “{ }”, será executado.
Em “C”, todas as instruções terminam com um ponto e vírgula “;”. Os comentários começam por
“//” e prolongam-se até ao final dessa linha ou os comentários são escritos entre /* */ e podem
ocupar várias linhas.
#include <htc.h>
void main(void){
TRISB = 0x00; // número Hexadecimal
PORTB = 0b00000100; // número binário
}
Para o compilador conseguir processar palavras como “TRISB” e “PORTB” é necessário incluir
previamente o ficheiro com o seu significado, por exemplo o ficheiro “# include PIC16F887.h”.
Em alternativa podemos incluir o ficheiro “htc.h”.
Como já deve calcular, as palavras TRISB e PORTB correspondem às posições de memória de
dados do µC com mesmo nome.
Em “C”, o utilizador tem a liberdade de escrever os números em várias bases numéricas: Decimal,
Octal, Hexadecimal, Binário e também texto em ASCII, mas tem de indicar ao compilador em qual
das bases escreve um determinado valor. Para isso pode colocar um prefixo antes do número.
Este programa faz exactamente o mesmo que o anterior, mas permite dar um exemplo de como é
declarada e usada uma função. Neste exemplo a função tem o nome “activaRB2”.
Apesar da função “activaRB2()” ser a primeira função declarada neste exemplo, ela é chamada
depois e a partir da função principal “main()”. Neste exemplo a função não recebe nem retorna
valores “void”.
#include <htc.h>
void activaRB2(void){
TRISB = 0X00; // número Hexadecimal
PORTB = 0b00000100; // número binário
}
void main(void){
activaRB2();
}
Funções e procedimentos
Existe uma diferença entre funções e procedimentos. As duas permitem “agrupar” código,
tornando mais fácil a sua reutilização e repetição ao longo do programa, mas só as funções podem
retornar valores.
Dentro de um ficheiro de código “C” é possível inserir instruções em assembler, desde que se
encontrem escritas entre as directivas #asm e #endasm. Desta forma, o compilador de “C” sabe que
deve compilar essas instruções como instruções de assembler.
#asm
Instrução em assembler 1
Instrução em assembler 2
…….
Instrução em assembler n
#endasm
O Programa seguinte permite limpar a posição 0x20 da memória de dados do µC através de uma
instrução de assembler inserida num ficheiro com código “C”.
#include <htc.h>
void main(void){
#asm
clrf 0x20
#endasm
}
Se o programador quiser escrever apenas uma instrução em assembler tem a possibilidade de usar
a função asm(“ ”). Neste caso o programa anterior poderia ser escrito da seguinte maneira:
#include <htc.h>
void main(void){
asm(“clrf 0x20”);
}
Quando o compilador HI-Tech encontra a directiva “#asm”, num ficheiro com código “C”, utiliza
o seu próprio compilador de assembler e não o “MPASM toolsuite” que utilizámos nos trabalhos
anteriores. Por essa razão, o código “in-line assembler” tem algumas diferenças:
O µC pode gerar uma interrupção quando a tensão externa aplicada ao pino RB0 variar de 0 para
5v ou vice-versa. Para autorizar este tipo de interrupção é necessário activar três bits específicos da
memória de dados do µC, a saber: GIE, PEIE e INTE. Estes três bits são activados na função main
deste exemplo.
O nome da rotina de serviço à interrupção - RSI pode ser escolhido livremente pelo programador,
mas o seu nome tem de ser precedido pela palavra reservada “interrupt”.
#include <htc.h>
void main(void){
TRISB=0X01; // RB0 passa a ser entrada digital
INTE=1; // Autoriza a interrupção gerada por RB0/INT
INTEDG=0; // Transição high to low, do sinal RB0, activa interrupt
PEIE=1; // Autoriza interrupções de periféricos
GIE=1; // Autoriza interrupções
while(1){ // Enquanto for verdadeiro mantém ciclo
}
}
Dentro da RSI o programador tem de limpar o bit INTF, sob pena de quando a RSI terminar voltar
a ser imediatamente chamada mesmo sem ter ocorrido uma verdadeira interrupção.
Este programa permite demonstrar como se declaram variáveis em “C”, como se usam algumas
instruções e operadores.
Variáveis
Em “C”, o programador tem vários tipos de variáveis à disposição, dependendo do tipo de valores
que pretender guardar pode usar variáveis do tipo “char”,”int” e “float”.
Uma variável do tipo “char” ocupa 8 bits na memória do µC. Por isso, estas variáveis podem
conter números positivos de 0 a 255 “unsigned char” ou, números negativos e positivos de -128 a
127 “char”.
Uma variável do tipo “int” ocupa 16 bits na memória do µC. Por isso pode conter números
positivos de 0 a 65535 “unsigned int” ou, números negativos e positivos de -32768 a 32767 “int”.
As variáveis do tipo ”long int “ e “float“ ocupam 32 bits em memória.
O bit mais significativo das variáveis pode ser usado para representar o sinal (-). Quando este bit
vale “1” o número é negativo. Quando as variáveis são do tipo “unsigned”, sem sinal, todos os bits,
mesmo o mais significativo é usado para representar um número positivo.
Quando uma variável é declarada dentro de uma função, tem um âmbito local, pois apenas é
reconhecida dentro dessa função e só existe enquanto a sua função estiver a ser executada
(Variável Local). Se quiser que a variável local mantenha o seu valor, entre chamadas à função
onde foi declarada, pode sempre declará-la como sendo do tipo “static”. Por exemplo: static int i;
Variáveis absolutas
Em “C” é possível associar uma variável a um registo específico do µC. O exemplo seguinte
permite associar a variável “Portvar” ao endereço de memória 0x06 do µC, que no caso do
PIC16F877 corresponde ao registo PORTB.
#include <htc.h>
// Variáveis globais
char cc[2][2]= {{1,2},{3,4}};
char nome[]= {'j','o','a','o'};
void main(void){
TRISB=0X00;
PORTB = cc[1][0] ; // cc[1][0]= 3 = 0b00000011
while(1){}
}
void main(void){ *k = i + j;
int x = 2; }
int y = 2;
TRISB = 0x00;
soma(x, y, &z);
PORTB = z;
while(1){}
}
Ponteiros
Um ponteiro em “C”, corresponde a uma posição de memória, tal como uma variável. No entanto,
um ponteiro contém apenas endereços “&” de outras posições de memória, nomeadamente
endereços de posições de memória que correspondem às variáveis do nosso programa. Por isso
podemos dizer que um ponteiro aponta para uma posição de memória, para uma variável, mas de
facto contém o seu endereço.
Desenvolva o código necessário para que o µC possa ler o valor da temperatura adquirida pelo
sensor TC74 ou que, em alternativa possa ler os valores da memória SD. Em qualquer dos casos
envie os valores lidos para o computador, através da interface Rs232.
O protocolo Serial Periferal Interface SPI foi proposto pela Motorola e tinha por objectivo
permitir a comunicação entre processadores da Motorola e os seus periféricos.
Este protocolo permite que dois equipamentos troquem dados entre si, através de dois fios, ou
através de duas pistas de circuito impresso (Figura 7.1). O pino Serial Out, de um dispositivo, liga
ao pino Serial In do outro e vice-versa. Os sinais eléctricos enviados e recebidos são digitais, têm
uma tensão nula ou positiva. Este protocolo prevê também a existência de um terceiro condutor,
onde um sinal digital (sinal de relógio - Clock) com uma frequência conhecida, permite aos dois
dispositivos sincronizar o instante de tempo em que o emissor aplica uma tensão no condutor e o
instante de tempo em que o receptor deve amostrar esse sinal digital. Diz-se por isso que este tipo
de comunicação é síncrono.
7.1.2 Topologia
Numa comunicação SPI, apenas um dispositivo gera o sinal de relógio e controla os instantes de
tempo em que o relógio está ligado ou desligado. Esse dispositivo assume o papel de “Master”
controlando dessa forma o fluxo de informação e o tipo de diálogo entre ambos “Master-Slave”.
O outro dispositivo é conhecido por “Slave” e apenas pode receber ou enviar dados, se, e enquanto,
o Master activar o sinal de relógio. Pode dar-se o caso do Master enviar bits nulos para o Slave,
apenas para dar ao Slave a possibilidade de enviar dados para o Master. Por cada bit enviado para
o Slave, o Slave envia outro para o Master, no mesmo instante, em sincronismo. Trata-se por isso
de um diálogo do tipo “full-duplex”.
Cada palavra SPI é composta por 8 bits [Figura 7.3]. Por cada palavra enviada pelo “Master”, o
“Slave” tem de responder com um bit de Ack.
Neste exemplo são transmitidas duas palavras SPI, dois bytes: “11010101” e “00101010”.
A Figura 7.4 permite visualizar as tensões dos sinais eléctricos utilizados numa comunicação SPI.
Cada divisão principal do osciloscópio corresponde a 10 µs. O período do sinal de relógio é de 4µs
(Fosc= 4Mhz a dividir por 16). Neste exemplo, quando não há transmissão de dados, a tensão do
sinal de “Clock” mantém-se positiva e igual a 5v. No entanto, enquanto não há transmissão de
dados, a tensão aplicada no pino de Clock – Clk também pode ser de 0 v, depende da configuração
previamente escolhida.
O µC dispõe de um circuito interno dedicado a comunicações série deste tipo. Tal como a Figura
7.5 ilustra, o µC dispõem de um pino Serial Data Input - SDI para recepção de dados. Um pino
Serial Data Output – SDO para envio de dados. Um pino Serial Clock - SCK para sincronizar o
envio e a recepção de dados do µC com um ou mais dispositivos externos.
Este circuito dispõe de um ShiftRegister - SR de 8 bits (SSPSR Reg). Por cada bit enviado, deste
SR para o SR do dispositivo remoto, também é enviado um bit do SR remoto para este. Por outras
palavras, enquanto o sinal de Clk estiver activo, os 16 bits trocam ciclicamente de lugar, de SR
para SR. Mas bastam apenas 8 períodos de relógio para que 8 bits troquem de SR, os 8 bits do
primeiro SR passam para o segundo e os 8 bits do segundo passam para o primeiro.
Para o µC poder enviar para outros equipamentos uma palavra série SPI é necessário configurar
previamente um conjunto de bits da sua memória de dados.
Com o bit Clock Polarity - CKP = 0, o sinal de “Clock” mantém uma tensão de 0 v enquanto a
comunicação estiver inactiva “idle”. Com CKP = 1, o sinal de “Clock” mantém uma tensão de 5
volt enquanto a comunicação permanecer inactiva (Figura 7.6).
Com o bit Clock Edge - CKE = 0, cada um dos 8 bits de dados é enviado no instante em que o sinal
de “Clock” transita da tensão de inactividade (0 ou 5v) para a tensão de “Clock” activo (5 ou 0v).
Meio período depois de ter iniciado o envio de um bit, através do pino SDO, o µC faz uma
amostragem da tensão externa aplicada ao seu pino de recepção SDI. Também é possível
configurar o µC para fazer essa amostragem só quando terminar de enviar um bit no pino SDO e
não a meio. Para isso o bit Sample bit - SMP, do µC, deve ser igual a “1”.
Com o bit CKE = 1, cada bit de dados é enviado quando o sinal de “Clock” transita do nível de
tensão de activo para inactivo (idle).
Este programa permite configurar a interface de comunicação SPI, do uC, e enviar dois bytes,
ciclicamente [Wilmshurst’07, pp 273].
O exemplo seguinte configura o µC como “Master” e envia dois bytes para o dispositivo remoto,
recebendo também dois bytes vindos do dispositivo remoto [Bates’06, pp210].
Este exemplo tira partido do bit SSPIF. Quando o hardware activa este bit significa que chegaram
8 bits de dados e podem ser lidos no registo SSPBUF. Significa também que 8 bits foram
transmitidos para o dispositivo remoto em simultâneo.
O protocolo “Inter Integrated Circuit - I2C” foi proposto pela Philips Electronics para permitir a
troca de dados entre os circuitos integrados “Integrated Circuits - IC” que utilizava nos seus
equipamentos.
Actualmente, inúmeros ICs utilizam este protocolo de comunicação, nomeadamente: EEPROMs,
sensores de temperatura, LCD, µC, módulos GSM, GPS e muitos outros.
7.3.2 Topologia
Topologia em barramento.
Na figura seguinte podemos observar no osciloscópio as tensões que são aplicadas nas linhas de
dados e de relógio durante uma comunicação I2C.
Neste exemplo, o “Master” transmite os bytes 10100100 e 00110111, e o “Slave” após a recepção
de cada sequência de 8 bits força a linha de dados a zero “ACK”, confirmando dessa forma que
está activo e que recebeu os 8 bits.
Figura 7.9: Sinais eléctricos de uma transmissão I2C (osciloscópio) [Wilmshurst’07, pp292]
Pelo contrário, a mudança da tensão na linha de dados SDA para 5v, enquanto o sinal de relógio
tiver uma tensão positiva, identifica que a menagem terminou “Stop”.
1 - É necessário configurar a porta MSSP para actuar como uma interface I2C- Master, para isso é necessário fazer os
bits Syncronous Serial Port Mode - SSPM3 a SSPM0, do registo SSPCON, iguais a 1000.
2- É necessário activar os pinos SCL e SDA e os circuitos internos, fazendo o bit Synchronous Serial Port Enable –
SSPEN igual a 1.
3- Configure os bits SMP=0 e CKE = 0;
4- Defina a taxa de transferência escrevendo no registo SSPADD um valor adequado, neste caso SSPADD= 24
permite uma sinal de relógio/taxa de 100Kbps.
SSPADD= Fosc/[4* BaudRate] - 1
1- Gerar na linha de dados, SDA, uma transição de início de mensagem “Start”. Para isso deve fazer o
bit SEN do registo SSPCON2 igual a 1.
SEN=1
2- Deve enviar os 7 bits de endereço I2C do Slave “Address”, mais o 8º bit “WR”. Se o 8º bit for 0-
Write, se for 1-Read. Neste caso “0”.
SSPBUF = …
Btfss PIR1, SSPIF //confirmação local de que o envio está concluído
3- Deve esperar pelo Ack enviado pelo Slave, analisando o bit ACKSTAT do registo SSPCON2.
Btfsc SSPCON2, ACKSTAT //confirmação remota de que o Slave recebeu
5- Deve esperar pelo Ack enviado pelo Slave, analisando o bit ACKSTAT do registo SSPCON2.
6 – Deve enviar os 8 bits de dados “Data” que serão gravados na memória do Slave.
SSPBUF = …
Btfss PIR1, SSPIF //confirmação local de que o envio está concluído
7- Deve esperar pelo Ack enviado pelo Slave, analisando o bit ACKSTAT do registo SSPCON2.
Btfsc SSPCON2,ACKSTAT
8- Deve gerar na linha de dados a transição que permita identificar o fim de mensagem, para isso deve
activar o bit stoP condition ENble bit - PEN, do registo SSPCON2.
PEN= 1
2- Enviar 7 bits do endereço do Slave “Address”, mais o oitavo bit “WR”. O oitavo bit a 0 significa
uma mensagem de escrita “write”.
SSPBUF = …
Btfss PIR1, SSPIF //confirmação local de que o envio está concluído
3- Deve esperar pelo Ack enviado pelo Slave, analisando o bit ACKSTAT do registo SSPCON2.
Btfsc SSPCON2,ACKSTAT
4- Enviar o endereço da posição de memória que se quer ler e esperar pela conclusão do envio.
SSPBU= …
Btfss PIR1, SSPIF //confirmação local de que o envio está concluído
5- Deve esperar pelo Ack enviado pelo Slave, analisando o bit ACKSTAT do registo SSPCON2.
Btfsc SSPCON2,ACKSTAT
8- Deve esperar pelo Ack enviado pelo Slave, analisando o bit ACKSTAT do registo SSPCON2.
Btfsc SSPCON2,ACKSTAT
Este dispositivo tem apenas duas posições de memória: uma contém o valor
da temperatura amostrada TEMP e a outra possui bits de configuração
CONFIG, mais exactamente dois bits de configuração, um deles permite
colocar o dispositivo em “Standby” e o outro bit indica se o valor da
temperatura amostrada está pronto para ser lido “DataReady”. Nesse caso, o
valor da posição de memória TEMP pode ser lido.
CONFIG
Standby: 1 – inactivo DataReady 1 – ready
0 – activo 0 – not ready
TEMP
Para ler uma posição de memória do TC74, neste caso o endereço 0, é suficiente que µC envie o
endereço do TC74, mais o 8º bit - RD a “1”, para que o TC74 responda com um bit de confirmação
Ack e oito bits de dados Data.
2- Deve enviar os 7 bits de endereço I2C do Slave “Address”, mais o 8º bit “RD”. Se o 8º bit for 0-
Write, se for 1-Read. Neste caso “1”.
SSPBUF = …
Btfss PIR1, SSPIF //confirmação local de que o envio está concluído
3- Deve esperar pelo Ack enviado pelo Slave, analisando o bit ACKSTAT do registo SSPCON2.
Btfsc SSPCON2, ACKSTAT //confirmação remota de que o Slave recebeu
banksel _SSPCON
movlw 00101000B // SSPEN=1 CKP=0 (Clk inactivo=5 volt) SSPM3:0=1000 (Master I2C)
movwf _SSPCON
banksel _SSPSTAT
bsf _SSPSTAT,7 // SMP = 1 A amostragem do sinal recebido é feito no final do bit time
movlw 5
movwf _SSPADD // Baudrate : SSPADD= Fosc/[4* BaudRate] - 1= 4000000/[4*166666]-1= 5
// ----- Envio de uma mensagem, para o Slave com endereço 1001101, a pedir o valor da temperatura (1 Byte)
//1 ---- Start
banksel _SSPCON2 // write to TC74
bsf _SSPCON2,0 // SEN
btfsc _SSPCON2,0 // SEN
goto $-1
goto fim
fim
// --------------------------------------------------------------------------------------
O integrado 24L256 é uma EEPROM de 32K posições de memória e com 8 bits de dados por
posição. O µC pode ler ou escrever nesta memória através de uma interface I2C. Esta memória
pode ser alimentada com tensões desde os 1,8v até 5,5 v. Se aplicar uma tensão externa de 5v ao
pino Write Protected - WR não poderá escrever novos valores na EEPROM.
O endereço I2C deste dispositivo pode ser configurado aplicando tensões positivas ou nulas aos
pinos A0, A1 e A2. Desta forma o seu endereço pode assumir valores desde 0 a 7. A EEPROM
existente na placa PICDEM2 plus disponível na bancada tem o endereço zero.
24LC256
Para que o uC possa comunicar com esta EEPROM, é necessário configurar a Master Sincronous Serial Port – MSSP
// ----- Configuração da interface MSSP
banksel _TRISC // inicializa a interface MSSP
bsf _TRISC,3 // O pino de SCL passa a estar activo
bsf _TRISC,4 // O pino DAS passa a estar activo
banksel _SSPCON
movlw 00101000B // SSPEN=1 CKP=0 (Clk inactivo=5 volt) SSPM3:0=1000 (Master I2C)
movwf _SSPCON
banksel _SSPSTAT
bsf _SSPSTAT,7 // SMP = 1 A amostragem do sinal recebido é feito no final do bit time
movlw 5
movwf _SSPADD // Baudrate : SSPADD= Fosc/[4* BaudRate] - 1= 4000000/[4*166666]-1= 5
//3 ------ Espera pelo Ack que o Slave (EEPROM) há-de enviar
banksel SSPCON2
btfsc SSPCON2,ACKSTAT //ack?
goto $-1
return
;------------------------ IDLE MODULE -------------------------------------
ssprw ;check for idle SSP module
movlw 0x00
banksel SSPCON2
andwf SSPCON2,w
sublw 0x00
btfss STATUS,Z
goto $-4
btfsc SSPSTAT,R_W
goto $-1
return
;---------------------------------------------------------------------------
end