Continuaremos hoje com o tópico anterior,
tendo o todo conceito em vista, devemos avançar para a implementação, serão ao
todo seis rotinas simples (i2c_Ini(), i2c_Start(),
i2c_RepeatedStart(), i2c_Stop(), i2c_Write(BYTE), i2c_Read(ACKTYPE)) que
farão parte de nossa biblioteca i2c, com toda a inicialização, leitura e
escrita no dispositivo, segue abaixo a
implementação destas rotinas com as respectivas descrições.
Função: i2c_Ini()
Propósito: Inicializa a configuração
dos registradores do modulo I²C
Parâmetros: Nenhum
Descrição: O modulo é habilitado
setando o bit I2CEN(I2CCON<15>), então o modulo ira liberar os pinos SDA
e SCL, colocando o barramento no modo ocioso. A lógica de funcionamento para
mestre e escravo é ativada simultaneamente e irão responder ao software e
eventos no barramento. As funções mestre
irão permanecer em estado ocioso até que o software setar um bit de controle
que gere um evento mestre. Habilitamos Entrada/Saída do I²C, configuramos a interrupção
e ajustamos o baud rate para operar como mestre no barramento.
void i2c_Ini(void)
{
// Configura os
pinos SCL1/SDA1 como open-drain
//ODCGbits.ODCG2 = 1;
//ODCGbits.ODCG3 = 1;
// IFS1 - Interrupt Flag Status register 1
//
_______________________________________________________________
// Upper Byte
|U2TXIF |U2RXIF |INT2IF | T5IF
| T4IF | OC4IF | OC3IF
|DMA21IF|
//
|__15___|__14___|__13___|__12___|__11___|__10___|___9___|___8___|
//
_______________________________________________________________
// Lower Byte |
IC8IF | IC7IF | AD2IF |INT1IF | CNIF |
----- |MI2C1IF|SI2C1IF|
// |__
7___|___6___|___5___|___4___|___3___|___2___|___1___|___0___|
//
// MI2C1IF - I2C1 Master events Interrupt Flag status bit
//
// limpa o flag
de interrupcao do I²C1
IFS1bits.MI2C1IF
= 0;
// IPC4 - Interrupt Priority Control register 4
//
_______________________________________________________________
// Upper Byte |
----- | CNIP<2:0> | ----- | ----- | ----- | ----- |
//
|__15___|__14___|__13___|__12___|__11___|__10___|___9___|___8___|
//
_______________________________________________________________
// Lower Byte |
----- | MI2C1<2:0> | ----- | SI2C1<2:0> |
// |__
7___|___6___|___5___|___4___|___3___|___2___|___1___|___0___|
//
// MI2C1<2:0> - I²C Master Events Interrupt
Priority bits
// 011 = prioridade de
interrupcao eh 3
//
// IPC4bits.MI2C1IP = 3;
// IEC1 - Interrupt Enable Control register 1
//
_______________________________________________________________
// Upper Byte
|U2TXIE |U2RXIE |INT2IE | T5IE
| T4IE | OC4IE | OC3IE |DMA2IE
|
//
|__15___|__14___|__13___|__12___|__11___|__10___|___9___|___8___|
//
_______________________________________________________________
// Lower Byte |
IC8IE | IC7IE | AD2IE |INT1IE | CNIE |
----- |MI2C1IE|SI2C1IE|
// |__
7___|___6___|___5___|___4___|___3___|___2___|___1___|___0___|
//
// MI2C1IE - I2C1 Master events Interrupt Enable bit
//
// habilita a
interrupcao mestre do I²C1
// IEC1bits.MI2C1IE = 1;
// Setando o
baud rate
//
// a seguinte
equacao eh usada para calcular o valor de recarga
// do gerador
da taxa de comunicacao:
//
// /
Fcy Fcy
\.
// I2CBRG = |
------ - ----------- | - 1
// \
Fscl 1.111.111 /
//
// desejamo
comunicar a 400kHz, entaum os valores seraoh:
//
// Fcy = 40 MHz
// Fscl = 400 kHz
//
// /
40.000.000 40.000.000 \.
// I2CBRG = |
------------ - ------------ | - 1
// \ 400.000 1.111.111 /
//
// I2CBRG = (100 - 36 ) - 1
//
// I2CBRG = 63
//
I2C1BRG = 63;
//
// I2C1CON - I²C
1 CONtrol register
//
_______________________________________________________________
// Upper
Byte | I2CEN | ----- |I2CSIDL|
SCLREL| IPMIEN| A10M | DISSLW| SMEN |
//
|__15___|__14___|__13___|__12___|__11___|__10___|___9___|___8___|
//
_______________________________________________________________
// Lower
Byte | GCEN | STREN | ACKDT | ACKEN | RCEN |
PEN | RSEN |
SEN |
// |__
7___|___6___|___5___|___4___|___3___|___2___|___1___|___0___|
//
// assegura que
estah com o valores zerados
I2C1CON
= 0;
// A10M: 10-bit
Slave Address bit
// 0 = I2CxADD eh o endereco
escravo de 7-bit
//
I2C1CONbits.A10M = 0;
// SCLREL: SCLx
Release Control bit
// 1 = Libera o pulso SCLx
// 0 = Mantem pulso baixo do SCLx (esticar
pulso)
// Se STREN = 0:
// Bit eh R/S (ou seja, soh pode
escrever '1' para liberar o pulso.
// Hardware limpa no inicio da
transmissao do escravo.
//
// STREN: SCLx
Clock Stretch Enable bit
// Usado em conjuncao com o
bit SCLREL.
// 1 = Habilita o software ou esticamento
do pulso de recepcao
// 0 = Desabilita o software ou
esticamento do pulso de recepcao
//
// libera a
linha de pulso
I2C1CONbits.SCLREL = 1;
// desabilita o
o I²C para funcionar como escravo
I2C1ADD
= 0;
I2C1MSK = 0;
// I2CEN: I2Cx
Enable bit
// 1 = Habilita o modulo I²Cx
e configura os pinos SDAx e SCLx como porta seriais
//
I2C1CONbits.I2CEN = 1;
IFS1bits.MI2C1IF = 0;
}
|
Função: i2c_Start()
Propósito: Condição de inicio para usar o protocolo do
barramento I²C
Parâmetros: Nenhum
Descrição: Após o barramento
estar em estado ocioso, uma transição de alto para baixo da linha SDA, enquanto
o relógio SCL estiver alto, determina uma condição de inicio. Todos os dados
transferidos devem começar com a condição de inicio.
void
i2c_Start(void)
{
//
// I2C1CON - I²C 1 CONtrol register
//
_______________________________________________________________
// Upper Byte |
I2CEN | ----- |I2CSIDL| SCLREL| IPMIEN|
A10M | DISSLW| SMEN |
//
|__15___|__14___|__13___|__12___|__11___|__10___|___9___|___8___|
//
_______________________________________________________________
// Lower Byte |
GCEN | STREN | ACKDT | ACKEN | RCEN
| PEN | RSEN
| SEN |
// |__
7___|___6___|___5___|___4___|___3___|___2___|___1___|___0___|
//
// SEN: Start
Condition Enable bit (quando o I²C opera como mestre)
// 1 = Inicia condicao de
inicio nos pinos SDAx e SCLx.
// Hardware limpa no final da sequencia de
inicio do mestre
// 0 = Condicao de inicio nao estah em
progresso
//
// Start Condition
I2C1CONbits.SEN =
1;
// IFS1 - Interrupt Flag Status register 1
//
_______________________________________________________________
// Upper Byte
|U2TXIF |U2RXIF |INT2IF | T5IF
| T4IF | OC4IF | OC3IF
|DMA21IF|
//
|__15___|__14___|__13___|__12___|__11___|__10___|___9___|___8___|
//
_______________________________________________________________
// Lower Byte |
IC8IF | IC7IF | AD2IF |INT1IF | CNIF |
----- |MI2C1IF|SI2C1IF|
// |__
7___|___6___|___5___|___4___|___3___|___2___|___1___|___0___|
//
// MI2C1IF - I2C1 Master events Interrupt Flag status bit
//
// espera pelo
fim do START
while
(!IFS1bits.MI2C1IF);
// limpa o flag
IFS1bits.MI2C1IF = 0;
}
|
Função: i2c_RepeatedStart()
Propósito: Condição de inicio repetido para usar o
protocolo do barramento I²C
Parâmetros: Nenhum
Descrição: O Modulo joga o pino
SCL para baixo. Quando o modulo amostra o pino SCL baixo, irá liberar o pino
SDA pela contagem de um baud rate(Tbrg). Quando o gerador de baud rate esgota o
tempo, se a amostra do pino SDA for alta, o modulo libera o pino SCL. Quando o
modulo amostrar o pino SCL alto, o gerador de baud rate recarrega e inicia a
contagem. Os pinos SDA e SCL devem ser amostrados alto por um Tbgr. Esta ação é
seguida pela declaração do pino SDA para baixo por um Tbgr enquanto o pino SCL
estiver alto.
void
i2c_RepeatedStart(void)
{
//
// I2C1CON - I²C 1 CONtrol register
//
_______________________________________________________________
// Upper Byte |
I2CEN | ----- |I2CSIDL| SCLREL| IPMIEN|
A10M | DISSLW| SMEN |
//
|__15___|__14___|__13___|__12___|__11___|__10___|___9___|___8___|
//
_______________________________________________________________
// Lower Byte
| GCEN | STREN | ACKDT | ACKEN
| RCEN | PEN |
RSEN |
SEN |
// |__
7___|___6___|___5___|___4___|___3___|___2___|___1___|___0___|
//
// RSEN: Repeated
Start Condition Enable bit (quando o I²C opera como mestre)
// 1 = Inicia condicao de
inicio repetido nos pinos SDAx e SCLx.
// Hardware limpa no final da sequencia
de inicio repetido do mestre
// 0 = Condicao de inicio repetido nao
estah em progresso
//
// Start Condition
I2C1CONbits.RSEN
= 1;
// IFS1 - Interrupt Flag Status register 1
//
_______________________________________________________________
// Upper Byte
|U2TXIF |U2RXIF |INT2IF | T5IF
| T4IF | OC4IF | OC3IF
|DMA21IF|
//
|__15___|__14___|__13___|__12___|__11___|__10___|___9___|___8___|
//
_______________________________________________________________
// Lower Byte |
IC8IF | IC7IF | AD2IF |INT1IF | CNIF |
----- |MI2C1IF|SI2C1IF|
// |__
7___|___6___|___5___|___4___|___3___|___2___|___1___|___0___|
//
// MI2C1IF - I2C1 Master events Interrupt Flag status bit
//
// espera pelo
fim do REPEATED START
while
(!IFS1bits.MI2C1IF);
// limpa o flag
IFS1bits.MI2C1IF
= 0;
}
|
Função: i2c_Stop()
Propósito: Condição de parada ao
termino dos dados enviados no barramento
Parâmetros: Nenhum
Descrição: Uma transição de baixo
para alto da linha SDA enquanto a linha de relógio SCL estiver alta determina
uma condição de parada. Toda a transferência de dados deve terminar com a condição
de parada.
void
i2c_Stop(void)
{
//
// I2C1CON - I²C 1 CONtrol register
//
_______________________________________________________________
// Upper Byte |
I2CEN | ----- |I2CSIDL| SCLREL| IPMIEN|
A10M | DISSLW| SMEN |
//
|__15___|__14___|__13___|__12___|__11___|__10___|___9___|___8___|
//
_______________________________________________________________
// Lower Byte
| GCEN | STREN | ACKDT | ACKEN
| RCEN | PEN
| RSEN | SEN
|
// |__
7___|___6___|___5___|___4___|___3___|___2___|___1___|___0___|
//
//
// PEN: Stop Condition Enable bit (quando o
I²C opera como mestre)
// 1 = Inicia a condicao de parada nos
pinos SDAx e SCLx.
// Hardware limpa no final da
sequencia de parada do mestre
// 0 = Condicao de parada nao estah em
progresso
//
//
// Stop Condition
I2C1CONbits.PEN =
1;
// espera pelo fim do STOP
while (!IFS1bits.MI2C1IF);
// limpa o flag
IFS1bits.MI2C1IF = 0;
}
|
Função: i2c_Write(BYTE)
Propósito: Enviar um byte pelo barramento I²C
Parâmetros: btData - Informação a
ser transmitida pela I²C
Retorno: 1 - Recebeu confirmação
do dispositivo (ACK), 0 - O dispositivo escravo não respondeu.
Descrição: Para cada byte de dado
transmitido pelo mestre, o escravo deve confirmar cada um com o ACK.
BOOL i2c_Write(BYTE btData)
{
// IWCOL: Write Collision Detect bit
//1 = Tentativa
de escrever no registrador I2CxTRN falhou pq o modulo I²C estava ocupado.
//0 = Sem
colisao
//Hardware
setado por uma escrita em I2CxTRN enquanto ocupado(limpo por software).
//
//while
(I2C1STATbits.IWCOL);
// envia o dado
I2C1TRN = btData;
// espera pelo
fim do Operacao de escrita
while
(!IFS1bits.MI2C1IF);
// limpa o flag
IFS1bits.MI2C1IF
= 0;
// I2C1STAT - I²C1 STATus register
//
_______________________________________________________________
// Upper Byte
|ACKSTAT| TRSTAT| ----- | ----- | ----- | BCL
| GCSTAT| ADD10 |
//
|__15___|__14___|__13___|__12___|__11___|__10___|___9___|___8___|
//
_______________________________________________________________
// Lower Byte |
IWCOL | I2COV | D_A |
P | S
| R_W |
RBF | TBF
|
// |__
7___|___6___|___5___|___4___|___3___|___2___|___1___|___0___|
//
// ACKSTAT: Acknowledge Status bit
// (quando o I²C opera como mestre,
aplicavel durante a transmissao do mestre)
// 1 = recebido do escravo um NACK
// 0 = recebido do escravo um ACK
// Hardware setado ou limpo ao fim da
confirmacao do escravo.
//
// se o ACK nao
retornou, indica erro
if
(I2C1STATbits.ACKSTAT)
return FALSE;
else
return
TRUE;
}
|
Função: i2c_Read(BYTE)
Propósito: Ler o dado no
barramento I²C passado pelo dispositivo escravo.
Parâmetros: ackType - Tipo de confirmação
a ser enviado(ACK ou NACK).
Retorno: O byte lido do
dispositivo escravo
Descrição: Para cada byte que o
escravo transmitir para o mestre, deve ser confirmado com ACK, o ultimo byte
transmitido pelo escravo, o mestre deve enviar um NACK, para encerrar a transmissão.
BYTE i2c_Read(ACKTYPE ackType)
{
//
// I2C1CON - I²C 1 CONtrol register
//
_______________________________________________________________
// Upper Byte |
I2CEN | ----- |I2CSIDL| SCLREL| IPMIEN|
A10M | DISSLW| SMEN |
//
|__15___|__14___|__13___|__12___|__11___|__10___|___9___|___8___|
//
_______________________________________________________________
// Lower Byte
| GCEN | STREN | ACKDT | ACKEN
| RCEN | PEN |
RSEN |
SEN |
// |__
7___|___6___|___5___|___4___|___3___|___2___|___1___|___0___|
//
BYTE btInfo;
//RCEN: Receive
Enable bit (quando o I²C opera como mestre)
//1 = Habilita a
recepcao do I²C. Hardware limpa ao final do oitavo bit do byte recebido
I2C1CONbits.RCEN = 1;
// espera pela
indicacao de dado recebido
while
(!IFS1bits.MI2C1IF);
// limpa o flag
IFS1bits.MI2C1IF
= 0;
// recebe o
dado
btInfo = I2C1RCV;
// ACKDT: Acknowledge Data bit (quando o I²C
opera como mestre, aplicavel durante a recepcao)
// Valor que sera transmitido quando o
software inciar uma sequencia de confirmacao.
// 1 = Envia NACK durante a confirmacao
// 0 = Envia ACK durante a confirmacao
//
// seleciona a
confirmacao passada para a funcao (ACK ou NACK)
I2C1CONbits.ACKDT
= ackType;
//ACKEN:
Acknowledge Sequence Enable bit
//1 = Incia a
sequencia de confirmacao nos pinos SDAx e SCLx e transmite o bit de dados
ACKDT.
// Hardware limpa ao final da sequencia de
confirmacao do mestre.
//
// envia a
confirmacao escolhida
I2C1CONbits.ACKEN = 1;
// espera pela
transmissao da confirmacao
while
(!IFS1bits.MI2C1IF);
// limpa o flag
IFS1bits.MI2C1IF
= 0;
return btInfo;
}
|
Com isso
finalizamos a rotinas necessárias para comunicar com um dispositivo I²C, lembre-se
de incluir no arquivo de cabeçalho do projeto a seguinte declaração.
typedef enum tagACKTYPE
{
ACK,
NACK
} ACKTYPE;
void
i2c_Ini();
void
i2c_Start();
void
i2c_RepeatedStart();
void i2c_Stop();
BOOL i2c_Write(BYTE);
BYTE i2c_Read(ACKTYPE);
|
E na próxima parte iremos
comunicar o microcontrolador com outro dispositivo pela I²C.
é né publicou um artigo científico?
ResponderExcluirinventou mentiras sobre mim em f2
você pediu a professora de f2 para abrir mais vagas para você
e você ainda quer prejudicar quem quer aprender a matéria
foi hipócrita em gnosia 2
criticou tanto quem faltou uma aula e faltou todas as aulas do último bloco de gnosia 2
deu uma de malandro em tec1
pediu a monitora a rayssa arrais para fazer a prova prática com a outra turma
só para ter mais tempo para estudar
colocou em f3 e agora publicou um artigo científico
aquele laboratório de fitoquimica e farmacognosia deve ser uma porcaria para aceitar alguém como você
a Suzana deve estar muito desesperada para aceitar alguém como você como aluna de IC
também o fitofar aceitou a Ana Beatriz de Lima como aluna de IC
não dá para esperar muita coisa de um laboratório
que aceita a Ana Beatriz de Lima como aluna de IC
é por isso que eu queria ser expulso da faculdade
pelo menos se eu fosse expulso da faculdade
eu não precisaria ver alguém desonesta com você se dando bem na faculdade
enquanto eu que sou tão dedicado a faculdade nunca tive uma oportunidade de fazer ic na área de quimica
agora você está trabalhando na merck
será que o pessoal da merck sabe quem você é de verdade?
também um lugar que aceitou a Gabriela Santana Andrade como funcionaria
não deve ser um bom lugar para trabalhar
você é igualzinha a Gabriela Santana Andrade
vocês duas não prestam
o pior é que você é bonita
o que você tem de bonita
você tem de malvada