Registros IIC

De Wikitronica
Revisión del 12:03 3 jul 2016 de Jesus Molina (Discusión | contribuciones)

(dif) ← Revisión anterior | Revisión actual (dif) | Revisión siguiente → (dif)
Saltar a: navegación, buscar

La dirección del IIC tiene 10-bit de direccionamiento, 0x11110, se utilizan los primeros 5 bits del primer byte de dirección. Se pueden tener varias combinaciones de leer/escribir, estos formatos son posibles con cambios en los 10-bit de direccionamiento.


Definición de Registros: Todos los registros y bits de control del IIC se especifican sólo por sus nombres, ya que Freescale proporciona una cabecera para trasladar los nombres a las apropiadas direcciones absolutas.

  • IIC Address Register (IICxA)
    IIC1A 0x0030
    IIC2A 0x1868

IICxA.png

Esta dirección de registro tiene 8 bits donde los 7 de la izquierda a la derecha es la Slave Address(Dirección del Esclavo). Esta dirección contiene la dirección del esclavo que se utiliza el modulo IIC. Este campo es usado en el esquema de dirección de siete bits, donde son los 7 bits más bajos del esquema de direcciones de 10 bits.


  • IIC Frequency Divider Register (IICxF)
    IIC1F 0x0031
    IIC2F 0x1869

IICxFreg.jpg

Esta dirección de registro tiene 8 bits, donde los bits 7 y 8 son el factor multiplicador(MULT),los 2 bits MULT se usan para definir el factor mul, este factor se utiliza junto con el SCL para generar la baud rate ó la velocidad de transmisión del IIC. Esto 2 bit MULT definen el factor mul de la siguiente manera:

00 mul = 01

01 mul = 02

10 mul = 04

11 Reserved

Los últimos cinco bits de la izquierda a la derecha de esta dirección de registro son para la velocidad del reloj (ICR), estos bits se utiliza para determinar del reloj de bus para la selección de la tasa de bits.

Los bits MULT y los bits del clock rate se usan para calcular la velocidad de transmisión, el tiempo de retención SDA, el tiempo de inicio del SCL y el tiempo de detenimiento del SCL. Cada una se puede calcular de la siguiente manera:

-IIC baud rate = bus speed (Hz)/(mul * SCL divider)

-SDA hold time = bus period (s) * mul * SDA hold value

-SCL Start hold time = bus period (s) * mul * SCL Start hold value

-SCL Stop hold time = bus period (s) * mul * SCL Stop hold value

  • IIC Control Register (IICxC1)
    IIC1C1 0x0032
    IIC2C1 0x186A

IICxC1.jpg

Este registro de control esta definido por 8 bits, el bit 7 es el de habilitación (IICEN) donde con 0 el IIC no esta habilitado y con 1 el IIC esta habilitado.

El siguiente bit "6" es el de la habilitación de interrupción(IICIE), este determina cuando una interrupción fue solicitada, con 0 no fue solicitada la habilitación y con 1 si fue solicitada la interrupción.

El 5 bit es el del modo maestro seleccionado (MST), con este bit si se cambia de de 0 a 1 cuando la señal se genera en el bus y luego se selecciona el modo maestro. Cuando este bit cambia de 1 a 0 se genera una señal de detención o STOP, y el modo de operación cambia de maestro a esclavo.

0 Slave mode.

1 Master mode.

El 4 bit es el modo de transmicion seleccionado (TX), con este bit se selecciona el modo de transferencia entre el esclavo y el maestro.En el modo maestro de este bit debe establecerse de acuerdo con el tipo de transferencia requerida. Por lo tanto, para los ciclos de direcciones, este bit siempre será alto.Cuando se establezca en modo esclavo este bit debe establecerse por el software de acuerdo con el bit de SRW en el registro de estado.

Recibe 0.

Transmite 1.

El tercer bit es el de reconocimiento de transmicion habilitada (TXAK), este bit reconoce la transmitir habilitada Este bit especifica el valor llevado a la SDA durante el reconocimiento de datos en ciclos, para tanto receptor maestro como receptor esclavo.

0 Se envia una señal de recepción al bus después de recibir un data byte.

1 Ninguna señal de reconocimiento es enviada

El segundo es el de repetir inicio(RSTA) Escribir un 1 en este bit generará una condición de START repetida siempre y cuando sea el maestro. Este bit siempre será leído como bajo. El intento que se repita en el momento equivocado resultará en la pérdida de arbitraje.

  • IIC Status Register (IICxS)
    IIC1S 0x0033
    IIC2S 0x186B

IICxS.png

Este registro tiene 8 bits donde el bit 7 se llama bandera de transferencia completa(TCF), este bit se establece en la finalizacion de la transferencia de bytes.Tenga en cuenta que este bit sólo es válida durante o inmediatamente después de una transferencia al módulo IIC o desde el modulo IIC.El bit de TCF se elimina mediante la lectura del registro IICxD en el modo receptor o escribiendo en IICxD en el modo de transmisión.

0 Transfer in progress.

1 Transfer complete.

El sexto bit es el de dirigido como un esclavo(IAAS), esté bit se establece cuando la dirección de la llamada coincide con la dirección del esclavo programado, o cuando el bit GCAEN se establece y se recibe una llamada general.Escribir el registro IICxC borra este bit.

El quinto bit es el de bus ocupado(BUSY), indica el estado del bus independientemente del esclavo o del maestro. El bit BUSY está activa cuando se detecta una señal de arranque y se apaga cuando se detecta una señal de STOP.

0 bus está inactivo.

1 bus está ocupado.

El cuarto bit es el de arbitraje perdido(ARBL), este bit es activado por hardware cuando se pierde el procedimiento de arbitraje. El bit debe ser despejado por software, escribiendo un 1 a la misma.

0 funcionamiento de bus estándar.

1 La pérdida de arbitraje.

El 2 bit es el de esclavo de lectura/escritura(SRW),cuando es llamado como un esclavo del SRW bits indica el valor del bit de comando R / W de la dirección solicitante y la envía al maestro.

0 Esclavo recibir, por escrito maestro a esclavo.

1 Esclavo de transmisión, maestra de lectura del esclavo.

El bit 1 es el de bandera de interrupcion del ICC (IICIF), se establece cuando una interrupción está pendiente. Este bit debe ser limpiado por software, escribiendo un 1 en la rutina de interrupción. Uno de los siguientes eventos pueden establecer el bit IICIF:

• Una transferencia de bytes completa • Ajuste de la dirección del esclavo a la dirección llamando • Arbitraje perdió 0 No se interrumpen en espera. 1 interrupción pendiente

el bit 0 Recibe Reconocimiento(RXAK),cuando es baja, indica una señal de confirmación se ha recibido después la realización de un byte de la transmisión de datos en el bus. Si el bit es alto RXAK significaría que no se se detecta la señal.

0 Reconocer recibido.

1 No se reconocen recibido.

  • IIC Data I/O Register (IICxD)
    IIC1D 0x0034
    IIC2D 0x186C

IICxD.png

Esta dirección de registro tiene 8 bits donde todos los bits dan la informacion de DATA, DATA en modo maestro de transmisión, hace que cuando datos son escritos en el IICxD, se inicie una transferencia de los datos, el bit más significativo se envía primero. En modo maestro de recepción, la lectura de este registro inicia la recepción del siguiente byte de datos.

Cuando se está cambiando el modo maestro de recepción, el modo de inspección debe ser cambiado antes de leer el registro IICxD para evitar una iniciación involuntaria de un maestro recibiendo la transferencia de datos.

En el modo esclavo, las mismas funciones están disponibles después de haberse producido una coincidencia de direcciones.

Tenga en cuenta que el bit TX en IICxC debe reflejar correctamente la dirección deseada de transferencia de los modos maestro y esclavo para que empiece la transmisión. Por ejemplo, si la IIC se configura para modo maestro de transmisión, pero se desea estar en modo maestro de recepción, entonces la lectura de la IICxD no iniciará la recepción.

La lectura de la IICxD devolverá el último byte recibido, mientras que la IIC está configurada tanto en modo maestro de recepción o modo esclavo de recepción. El IICxD no refleja todos los bytes que se transmite en el bus IIC, ni puede verificar el software que un byte se ha escrito para IICxD correctamente leyendo de nuevo.

En el modo maestro de transmisión, el primer byte de los datos escritos en IICxD siguiente afirmación de MST se utiliza para la transferencia de la dirección y debería formar parte de la dirección de llamada (en el bit 7 al bit 1) concatenado con el bit deseado R/W (en la posición de bit 0)

  • IIC Control Register 2 (IICxC2)
    IIC1C2 0x0035
    IIC2C2 0x186D

IICxC2.png

Esta dirección de registro tiene 8 bits, donde el bit primer bit de izquierda a derecha es el de Dirección general de llamada a activar (GCAEN), donde este bit activara o desactivara la dirección de llamada general.

El bit siguiente al bit GCAEN es el bit de Extensión de dirección (ADEXT), donde controla el numero de bits usado para la dirección del esclavo.

Y los últimos tres bits de los 8 de IICxC2 son de la dirección del esclavo (AD[10:8]).

En el esquema de direcciones de 10 bits la AD [10: 8] contiene los tres bits superiores de la dirección del esclavo. Este campo sólo es válido cuando se establece el bit ADEXT.


Ejemplo Acelerometro

En el siguiente ejemplo se muestra como se modifica el valor de los bits de PTC y PTD de los leds en la tarjeta a medida que esta detecta información de movimiento en el eje "y" mediante el Acelerometro, con el cual se comunica a través del protocolo IIC.

Ejemplo Acelerometro.gif
/////////////////////////////////////////////////////////////////////////////////////////
//
// Accelerometer Demonstration for Freescale DEMOQE Rev. C Development Board
// --------------------------------------------------------------------------------------
//
// CodeWarrior V6.0 for MCUs
//
/////////////////////////////////////////////////////////////////////////////////////////

#include <hidef.h> /* for EnableInterrupts macro */
#include "derivative.h" /* include peripheral declarations */
#include "accelerometer.h" /* include main program defines and declarations */

/////////////////////////////////////////////////////////////////////////////////////////
// ICS_FEI
// --------------------------------------------------------------------------------------
// intitializes ICS for FEI mode with DCOH
/////////////////////////////////////////////////////////////////////////////////////////
void ICS_FEI(void) {

  if (NVICSTRM != 0xFF)
    ICSTRM = NVICSTRM;                        // load trim value if NV location not blank
  else
    ICSTRM = 0xAD;                  // use a default value if NVICSTRM is blank
  ICSC1 = ICSC1_FEI;
  ICSC2 = ICSC2_FEI;
  ICSSC = ICSSC_FEI;
  while (ICSC1_CLKS != ICSSC_CLKST) {}  // wait for clk state to match clk select
} //end InitICG

/////////////////////////////////////////////////////////////////////////////////////////
// InitKBI
// --------------------------------------------------------------------------------------
// initializes 4 switches on DEMO or EVB as KBI's 
/////////////////////////////////////////////////////////////////////////////////////////
void InitKBI(void) {
// Enable KBI1P[3:2] as interrupt
  KBI1PE = KBI_SW;
  KBI1SC = 0b00000110;
/*               ||||
                 |||+---- KBIMOD = KBI detection mode: 0=edge only
                 ||+----- KBIE   = KBI int enable: 1=enabled
                 |+------ KBACK  = KBI int acknowledge: 1=clr IRQF
                 +------- KBF    = KBI flag
*/
}

/////////////////////////////////////////////////////////////////////////////////////////
// InitSCI
// --------------------------------------------------------------------------------------
// initializes SCI1 to specified baudrate 
/////////////////////////////////////////////////////////////////////////////////////////
void InitSCI(word baud) {

  SCI1BD = baud;  // set baud
} //end InitSCI
 
/////////////////////////////////////////////////////////////////////////////////////////
// RecChar & SendChar
// --------------------------------------------------------------------------------------
// receives/sends an ascii char on SCI1 at preset baudrate 
/////////////////////////////////////////////////////////////////////////////////////////
char RecChar(void) {
  byte rec_char;

  if (SCI1S1_RDRF)  // 1st half of RDRF clear procedure
    rec_char = SCI1D;  // 2nd half of RDRF clear procedure
  SCI1C2_RE = 1;    // enable Rx
  while(!SCI1S1_RDRF){  };
  rec_char = SCI1D; // get recieved character
  SendChar((char) rec_char); // echo received character
  return (char) SCI1D;
} //end RecChar 

void SendChar(char s_char) {
 
  SCI1C2 = 0x08;    // enable Tx
  while(!SCI1S1_TDRE){ }
  SCI1D = (byte) s_char;   // 2nd half of TDRE clear procedure
} //end SendChar

/////////////////////////////////////////////////////////////////////////////////////////
// SendMsg
// --------------------------------------------------------------------------------------
// sends an ascii string out SCI1 at preset baudrate 
/////////////////////////////////////////////////////////////////////////////////////////
void SendMsg(char msg[]) {
  byte i=0;
  char nxt_char;
 
  SCI1C2 = 0x08;    // enable Tx
  nxt_char = msg[i++];
  while(nxt_char != 0x00) {
    while(!SCI1S1_TDRE){}
    SCI1D = (byte) nxt_char; // 2nd half of TDRE clear procedure
    nxt_char = msg[i++];
  } //end while((SCI1D
} //end SendMsg

/////////////////////////////////////////////////////////////////////////////////////////
// hex2bcd
// --------------------------------------------------------------------------------------
// converts hexadecimal word into a binary-coded decimal word 
/////////////////////////////////////////////////////////////////////////////////////////
word hex2bcd(word hex){
  byte dec[4],i;
  word bcd;


  for (i=0;i<4;i++){
    dec[i] = (byte) (hex%10);
    hex = (word) (hex/10);
  }
 
  if (hex>0){
    bcd=0xffff;
  }else{
    bcd=(word)((word)(dec[3]<<12) + (word)(dec[2]<<8) + (dec[1]<<4) + dec[0]);
  }
  return bcd;
} //end hex2bcd
 
/////////////////////////////////////////////////////////////////////////////////////////
// asc2byte & asc2word
// --------------------------------------------------------------------------------------
// converts an ascii string of 2 or 4 numeric chars into a byte or word 
/////////////////////////////////////////////////////////////////////////////////////////
byte asc2byte(char n_asc) {
  byte n;

  n = (byte)(n_asc - 0x30);      //convert from ascii to int
  if(n > 0x09)           // if num is $a or larger...
    n -= 0x07;           // ...sub $7 to correct
  if(n > 0x0f)           // if lower case was used...
    n -= 0x20;           // ...sub $20 to correct
  if(n > 0x0f)           // if non-numeric character...
    n = 0x00;            // ...default to '0'
  return n;
} //end asc2num

word asc2word(byte n_asc[2]) {
  word n,n2;

// assumes n_asc[0] is MSB, n_asc[1] is LSB
  n = (word)(n_asc[0] - 0x30);   //convert from ascii to int
  if(n > 0x09)           // if num is $a or larger...
    n -= 0x07;           // ...sub $7 to correct
  if(n > 0x0f)           // if lower case was used...
    n -= 0x20;           // ...sub $20 to correct
  if(n > 0x0f)           // if non-numeric character...
    n = 0x00;            // ...default to '0'
  n = (word)(n<<8);              // shift into high byte
  n2 = (word)(n_asc[1] - 0x30);  //convert from ascii to int
  if(n2 > 0x09)          // if num is $a or larger...
    n2 -= 0x07;          // ...sub $7 to correct
  if(n2 > 0x0f)          // if lower case was used...
    n2 -= 0x20;          // ...sub $20 to correct
  if(n2 > 0x0f)          // if non-numeric character...
    n2 = 0x00;           // ...default to '0'
  n += n2;               //    
  return n;
} //end asc2word

/////////////////////////////////////////////////////////////////////////////////////////
// byte2asc & word2asc
// --------------------------------------------------------------------------------------
// converts a byte or word into an ascii string of 2 or 4 chars
/////////////////////////////////////////////////////////////////////////////////////////
char * byte2asc(byte num, byte base) {
  byte n;

  if (base){
    n=(byte)(hex2bcd(num));
  }else{
    n=num;
  } //end if (base)
  n_str[0] = (byte)((n>>0x04)+0x30);  // convert MSN to ascii
  if(n_str[0]>0x39)           // if MSN is $a or larger...
    n_str[0]+=0x07;           // ...add $7 to correct
  n_str[1] = (byte)((n&0x0f)+0x30);   // convert LSN to ascii
  if(n_str[1]>0x39)           // if LSN is $a or larger...
    n_str[1]+=0x07;           // ...add $7 to correct
  n_str[2] = 0x00;            // add line feed
  return  (char *) n_str;
} //end byte2asc

char * word2asc(word num, byte base) {
  word n;

  if (base){
    n=hex2bcd(num);
  }else{
    n=num;
  } //end if (base)

  n_str[0] = (byte)((n>>12)+0x30);    // convert MSN to ascii
  if(n_str[0]>0x39)           // if MSN is $a or larger...
    n_str[0]+=0x07;           // ...add $7 to correct
  n_str[1] = (byte)(((n>>8)&0x0f)+0x30);   // convert 2nd MSN to ascii
  if(n_str[1]>0x39)           // if LSN is $a or larger...
    n_str[1]+=0x07;           // ...add $7 to correct
  n_str[2] = (byte)(((n>>4)&0x0f)+0x30);   // convert 2nd MSN to ascii
  if(n_str[2]>0x39)           // if LSN is $a or larger...
    n_str[2]+=0x07;           // ...add $7 to correct
  n_str[3] = (byte)((n&0x0f)+0x30);   // convert 2nd MSN to ascii
  if(n_str[3]>0x39)           // if LSN is $a or larger...
    n_str[3]+=0x07;           // ...add $7 to correct
  n_str[4] = 0x00;    // add line feed
  return  (char *) n_str;
   
} //end word2asc

/////////////////////////////////////////////////////////////////////////////////////////
// StartTPM & StopTPM
// --------------------------------------------------------------------------------------
// Starts and stops TPM1 at busclk rate
/////////////////////////////////////////////////////////////////////////////////////////
void StartTPM(byte PS){
  TPM1SC = (byte)(0x08 | (0x07&PS));
  StartCount = TPM1CNT;
}// end StartTPM

word StopTPM(void){
  StopCount = (word)(TPM1CNT - StartCount);
  TPM1SC = 0;
  return StopCount;
}// end StopTPM

/////////////////////////////////////////////////////////////////////////////////////////
// PeriphInit
// --------------------------------------------------------------------------------------
// Initializes various registers and peripherals
/////////////////////////////////////////////////////////////////////////////////////////
void PeriphInit(void)
{ 
  // Disables COP and Enable STOP instruction and RESET and BKGD pin
  SOPT1 = 0x23;
 
  // Selects FEI mode
  // Sets trimming for fBUS about 25 MHz
  ICS_FEI();
 
  // Enable all pullups
  PTAPE = 0xFF;
  PTBPE = 0xFF;
  PTCPE = 0xFF;
  PTDPE = 0xFF;
  PTEPE = 0xFF;
  PTFPE = 0xFF;
  PTGPE = 0xFF;
  PTHPE = 0xFF;
  PTJPE = 0xFF;
  PTCDD = 0x3F;
  PTEDD = 0xC0;
  PTCD =  0x3F;
  PTED =  0xC0;
 
  /* Configures PTG[2:1] as accelerometer sensitivity
      PTG2:PTG1
        0    0  = 1.5g
        0    1  = 2.0g
        1    0  = 4.0g
        1    1  = 6.0g
  */
  PTGD = 0x00;
  PTGDD = 0x06;
   
  // Timer2 overflow about every 1ms
  TPM2MOD = 25000;
  // Stops timer2 and select 1 as prescaler divisor
  TPM2SC = 0x00;
   
  // Initializes SCI Peripheral
  InitSCI(fei_baud);
         
}

/////////////////////////////////////////////////////////////////////////////////////////
// filter_data
// --------------------------------------------------------------------------------------
// Filters the collected x,y,z data using simple IIR filter
/////////////////////////////////////////////////////////////////////////////////////////
void filter_data(void)
{
  byte i;
  dword X, Y, Z;

  X = x.reading[samp];
  Y = y.reading[samp];
  Z = z.reading[samp];
 
  for (i=samp;i>0;i--){
    X = (X + ((x.reading[i] + x.result[i-1])>>1))>>1;
    Y = (Y + ((y.reading[i] + y.result[i-1])>>1))>>1;
    Z = (Z + ((z.reading[i] + z.result[i-1])>>1))>>1;
  }
 
  x.result[samp] = (word)X;
  y.result[samp] = (word)Y;
  z.result[samp] = (word)Z;
}// end filter_data

/////////////////////////////////////////////////////////////////////////////////////////
// avg_data
// --------------------------------------------------------------------------------------
// - averages 10 collected x,y,z values
// - puts results in elements 0 of arrays
/////////////////////////////////////////////////////////////////////////////////////////
void avg_data(void)
{
  byte j;
  long x_avg=0, y_avg=0, z_avg=0;

  for (j=1;j<=samp;j++){
    x_avg += x.reading[j];
    y_avg += y.reading[j];
    z_avg += z.reading[j];
  }
  x.result[samp] = (word)(x_avg>>4);
  y.result[samp] = (word)(y_avg>>4);
  z.result[samp] = (word)(z_avg>>4);
}// end avg_data

/////////////////////////////////////////////////////////////////////////////////////////
// copy_data
// --------------------------------------------------------------------------------------
// - copies reading into result
/////////////////////////////////////////////////////////////////////////////////////////
void copy_data(void) {
 
  x.result[samp] = x.reading[samp];
  y.result[samp] = y.reading[samp];
  z.result[samp] = z.reading[samp];
}// end copy_data

/////////////////////////////////////////////////////////////////////////////////////////
// ReadAcceleration
// --------------------------------------------------------------------------------------
// Reads acceleration data on a given axis and saves it to the axis structure
/////////////////////////////////////////////////////////////////////////////////////////
void ReadAcceleration(void){
  byte i;
  signed int temp;

  for(i=0;i<3;i++){
    temp = IIC_Rec_Data[i] & 0x3F;  //Get rid of Alert bit
    if(IIC_Rec_Data[i] & 0x20){
       temp |= 0xFFC0;                                 //Sign extension
       temp += 32;
       IIC_Converted_Data[i] = temp;
    }else{  
      IIC_Converted_Data[i] = temp + 32;
    }
  }
}//end ReadAcceleration

/////////////////////////////////////////////////////////////////////////////////////////
// ShowAcceleration
// --------------------------------------------------------------------------------------
// -  Prints the accelaration data in the terminal;
/////////////////////////////////////////////////////////////////////////////////////////
void ShowAcceleration (void)
{
  word SampleCNT;
  byte j,k;  
 
  ReadAcceleration();            // Read acceleration data
  ADCSC1 = 0x01;                 // Select ADC1 (PTA1) channel
  x.reading[samp]  = (dword)( IIC_Converted_Data[0] <<8);
  ADCSC1 = 0x08;                 // Select ADC8 (PTA6) channel
  y.reading[samp]  = (dword)( IIC_Converted_Data[1] <<8);
  ADCSC1 = 0x09;                 // Select ADC9 (PTA7) channel
  z.reading[samp]  = (dword)( IIC_Converted_Data[2] <<8);
 
  StartTPM(0);   //0 = TPM prescaler = /2

  if(samp>0){
    switch (mode){
      case filter: filter_data();   break;
      case avg   : avg_data();      break;
      default    : copy_data();
    }
  } else {
    copy_data();
  }
 
  SampleCNT = StopTPM();
  if (SampleCNT<0x0100) {
    for(j=0xff;j>0;j--){
      for(k=0x10;k>0;k--){}
    }
  }

  // Display Acceleration
  SendMsg("\r\n");
  SendMsg(word2asc((word)x.result[samp],dis_base));
  SendMsg(",");
  SendMsg(word2asc((word)y.result[samp],dis_base));
  SendMsg(",");
  SendMsg(word2asc((word)z.result[samp],dis_base));
  SendMsg(",");
  SendMsg(word2asc(SampleCNT,dis_base));
 
  //145B min Y ->
  //2F00 max Y
  if (y.result[samp]>=0x2cec){
      PTCD = 0xFF;
      PTED = 0xFF;
  }
     
  else if (y.result[samp]>=0x3000){//4
      PTCD = 0xFF;
      PTED = 0xFF;
  }
  else if (y.result[samp]>=0x2700){//3
       PTCD = 0xFC;
         PTED = 0xFF;
}
  else if (y.result[samp]>=0x2500){//2
       PTCD = 0xF8;
       PTED = 0xFF;
   }
 
  else if (y.result[samp]>=0x2400){//1
       PTCD = 0x00;
       PTED = 0xFF;
   }
 
 
  else if (y.result[samp]>=0x1800){//    Todos prendidos
      PTCD = 0x00;
      PTED=0x00;
  }
      
  else if (y.result[samp]>=0x1600)//1
  {
        PTCD = 0xC3;
        PTED = 0x00;
  }
  else if (y.result[samp]>=0x1400)//2
  {
       PTCD = 0x6F;
       PTED = 0x00;
  }
  else if (y.result[samp]>=0x1359)//3
  {
       PTED = 0x00;
       PTCD = 0xFF;
  }     
  else if (y.result[samp]>=0x0fa0)//4
  {     
         PTED = 0xFF;
         PTCD = 0xFF;
  }
 
  // Shift array of results if we hit max
  if (samp >= max-1) {
    for (j=0;j<max-1;j++){
      x.result[j]  = x.result[j+1];
      x.reading[j] = x.reading[j+1];
      y.result[j]  = y.result[j+1];
      y.reading[j] = y.reading[j+1];
      z.result[j]  = z.result[j+1];
      z.reading[j] = z.reading[j+1];
    }
    samp = max-1;
  } else {
    samp++;
  } //end if (i => max)
 
 
 
}// end ShowAcceleration

/////////////////////////////////////////////////////////////////////////////////////////
//  Function used as Master
//---------------------------------------------------------------------------------------
//  Master_Read_and_Store
//  Master_Write_MMA7660_register
//  Master_Read_MMA7660_register
/////////////////////////////////////////////////////////////////////////////////////////

void Master_Read_and_Store(void) {
  IIC_Rec_Data[rec_count++] = IIC2D;
}


void Master_Write_MMA7660_register(byte transbytes) {
  last_byte = 0;                    // Initialize variables to 0
    count = 0;
  bytes_to_trans = transbytes;      
 
  if (transbytes == 0) return;
 
  IIC2C1_TX = 1;                    // Set TX bit for Address cycle
  IIC2C1_MST = 1;                   // Set Master Bit to generate a Start
 
  IIC2D = mma7660[count++];         // Send first byte (should be 7-bit address + R/W bit)   
}

void Master_Read_MMA7660_register(byte transbytes, byte recbytes) {

  rec_count = 0;                    // Initialize variables to 0
  last_byte = 0;                   
    count = 0;
    repeat_start_sent = 0;
   
  bytes_to_trans = transbytes;     
  num_to_rec = recbytes;
 
 
  if (transbytes == 0) return; 
   
  IIC2C1_TXAK = 0;
  IIC2C1_TX = 1;                    // Set TX bit for Address cycle
  IIC2C1_MST = 1;                   // Set Master Bit to generate a Start
 
  reading_mma7660_reg = 1;
  IIC2D = mma7660[count++];         // Send first byte (should be 7-bit address + R/W bit)   
}

/////////////////////////////////////////////////////////////////////////////////////////
//  MMA7660_configuration
//---------------------------------------------------------------------------------------
//  MMA7660 uses default configuration
//  120 samples/second; Disable interrupts
//  MMA7660 enter into active mode
/////////////////////////////////////////////////////////////////////////////////////////
void MMA7660_configuration(void){
 
  mma7660[0] = 0x98;
  mma7660[1] = 0x07;
  mma7660[2] = 0x01;
  Master_Write_MMA7660_register(3);
 
}
/////////////////////////////////////////////////////////////////////////////////////////
//  IIC_configuration
//---------------------------------------------------------------------------------------
//  fIIC is 25MHz/4/48 = 130KHz
//  Enable IIC module and interrupts
/////////////////////////////////////////////////////////////////////////////////////////
void IIC_configuration (void) {
 
  IIC2F = 0x90;         /* Multiply factor of 4. SCL divider of 48 */
  IIC2C1  = 0xC0;       /* Enable IIC module and interrupts */
}

/////////////////////////////////////////////////////////////////////////////////////////
// MAIN
// --------------------------------------------------------------------------------------
// Entry point
/////////////////////////////////////////////////////////////////////////////////////////
void main(void){

  PeriphInit();
  InitKBI();
  IIC_configuration();
 
  EnableInterrupts;
 
  MMA7660_configuration();
  
// Selects fBUS as timer1 clock source and start timer
  TPM1SC = 0x08;
//  SendMsg("\fX, Y, Z\r\n");
  while (!SW1){}
  for(;;){
    while(SW4){
      if(!(IIC_Rec_Data[0]&IIC_Rec_Data[1]&IIC_Rec_Data[2]&0x40)){
        ShowAcceleration();         // Show acceleration data
      }else{                        // MMA7660 updating
      }
     
      if (PTHD_PTHD7 == 1) {        //Wait for IIC bus to be free
      
        while (PTHD_PTHD7 == 0);    // Wait while pin is low
       
           while (IIC2C1_MST == 1);    // Wait untill IIC is stopped
          
           //Read Xout, Yout, Zout
           mma7660[0] = 0x98;
           mma7660[1] = 0x00;
           Master_Read_MMA7660_register(2,3);
     
      }else {
     
      }
           
    } //end while(SW4)
    while(SW3){_Stop;}
  } //end for(;;)
   
}

/////////////////////////////////////////////////////////////////////////////////////////
// KBI_ISR
// --------------------------------------------------------------------------------------
// Reads PTA[3:2] and shifts to LSBs
// Debounces switch
// Acknowledges KBF
/////////////////////////////////////////////////////////////////////////////////////////
interrupt VectorNumber_Vkeyboard void KBI_ISR(void){
  byte d,b;
 
  //capture which pin was pushed
  mode = (byte)(KBI_VAL);
  //debounce button
  for (d=0xff;d>0;d--){
    for (b=0x80;b>0;b--){}
  }
  //clear KBF
  KBI1SC_KBACK = 1;
}
   
////////////////////////////////////////////////////////////////////////////////////////
// IIC_ISR
// --------------------------------------------------------------------------------------
// IIC communication
// Master mode transmit and receive
////////////////////////////////////////////////////////////////////////////////////////

interrupt VectorNumber_Viicx void IIC_ISR(void) {

  IIC2S_IICIF = 1;              // Clear Interrupt Flag  
  if (IIC2C1_TX) {              // Transmit or Receive?                           
///////////////////// Transmit ////////////////////////////                   
    if (repeat_start_sent) {
      IIC2C1_TX = 0;                // Switch to RX mode
      if (num_to_rec == 1)
        IIC2C1_TXAK = 1;            // This sets up a NACK 
          IIC2D;                        // Dummy read from Data Register
    }
    else if ((last_byte) & (reading_mma7660_reg)) {
      IIC2C1_RSTA = 1;              //Repeat start
      IIC2D = (mma7660[0] | 0x01);  //Set Read bit
      repeat_start_sent = 1;
    }
        else if (last_byte) {           // Is the Last Byte?
            IIC2C1_MST = 0;               // Generate a Stop
        }
        else if (last_byte != 1) {
          if (IIC2S_RXAK) {             // Check for ACK
              IIC2C1_MST = 0;             // No ACk Generate a Stop
          }
          else if (!IIC2S_RXAK) {         
              IIC2D = mma7660[count++];     // Transmit Data              
              if (count == bytes_to_trans)
                last_byte = 1;                         
          }
        }
  } else {           
///////////////////// Receive ////////////////////////////       
    if ((num_to_rec - rec_count) == 2) {     
          IIC2C1_TXAK = 1;          // This sets up a NACK
          Master_Read_and_Store();          
    }
    else if ((num_to_rec - rec_count) == 1) {     
          IIC2C1_MST = 0;           // Send STOP
          Master_Read_and_Store();
        }           
        else {       
          Master_Read_and_Store();
        }
  }
}

Contributors

Anna, Jesus Molina