Diferencia entre revisiones de «Introducción IIC y sus interrupciones»

De Wikitronica
Saltar a: navegación, buscar
 
(No se muestran 5 ediciones intermedias de 2 usuarios)
Línea 67: Línea 67:
  
 
* SDA - Línea de Data Serial (Serial Data Line): Es la línea de datos serial del sistema del IIC. Es bidireccional.
 
* SDA - Línea de Data Serial (Serial Data Line): Es la línea de datos serial del sistema del IIC. Es bidireccional.
 +
 +
 +
== Interrupciones ==
 +
 +
El IIC puede generar sólo una interrupción. Para que se genere una interrupción, debe ocurrir cualquiera de los eventos de la tabla siguiente, siempre y cuando el bit IICIE esté activado:
 +
 +
{| class="wikitable"
 +
|+ Interrupciones mediante IIC
 +
! Fuente de interrupción !! Status !! Flag !! Local Enable
 +
|-
 +
| Completar la transferencia de 1 byte || TCF || IICIF || IICIE
 +
|-
 +
| Ajuste de direcciones de llamada recibidas || IAAS || IICIF || IICIE
 +
|-
 +
| Pérdida de arbitraje || ARBL || IICIF || IICIE
 +
|}
 +
 +
La interrupción es impulsada por el bit IICIF (del IIC Status Register) y es enmascarada con el bit IICIE (del IIC Control Register). El bit IICIF se puede limpiar asignándole un 1 en la rutina de interrupción. El usuario puede determinar el tipo de interrupción mediante la lectura del Status Register.
 +
 +
'''Interrupción por transferencia de byte'''
 +
 +
El bit TCF (transfer complete flag) se establece a flanco de bajada del 9th clock para indicar la completación de la transferencia del byte
 +
 +
'''Interrupción por detección de dirección'''
 +
 +
Cuando la dirección de llamadas coincide con la dirección del esclavo programado (IIC address register) o cuando el bit GCAEN está activado y una llamada general es recibida, el bit IAAS en el Status Register es activado. La CPU es interrumpida siempre y cuando se active el bit IICIE. La CPU debe revisar el bit SRW y activar su modo Tx en consecuencia.
 +
 +
'''Interrupción por pérdida de arbitraje'''
 +
 +
El IIC es un verdadero bus con múltiples maestros que permite más de un maestro para ser conectado en él. Si dos o más maestros tratan de controlar el bus al mismo tiempo, se determina la prioridad relativa de los maestros en contienda por un procedimiento de arbitraje de datos. El módulo IIC asegura esta interrupción cuando pierde el proceso de arbitraje de datos y el bit ARBL en el Status Register está activado.
 +
 +
El arbitraje se puede perder en las siguientes circunstancias:
 +
 +
* SDA probado como bajo cuando el maestro produce un alto durante un ciclo de dirección o de transmisión de datos.
 +
 +
* SDA probado como bajo cuando el maestro produce un alto durante el bit de aviso de un ciclo de recepción de datos
 +
 +
* Un ciclo de arranque se intenta cuando el bus está ocupado
 +
 +
* Un ciclo repetido de arranque es requerido en modo esclavo
 +
 +
* Se detecta una condición de parada cuando el maestro no lo solicitó
 +
 +
'''Resets'''
 +
 +
El IIC se desactiva luego de un RESET. El IIC no puede provocar un reinicio o reseteo del microcontrolador.
 +
 +
== Ejemplo - Código para el acelerómetro usando el protocolo IIC ==
 +
 +
El siguiente código, hecho en lenguaje C y compilado y quemado en el DEMOQE128 usando el software CodeWarrior 10.6, enciende los LEDS de dos en dos de acuerdo a las lecturas provistas por el acelerómetro. La comunicación es establecida utilizando el protocolo IIC.
 +
 +
<syntaxhighlight lang="c">
 +
 +
 +
#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;
 +
 +
  /* 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;
 +
 +
  // Habilitación de los LEDs y se colocan apagados por defecto
 +
    PTCDD = 0x3F;
 +
    PTEDD = 0xC0;
 +
 
 +
    PTCD = 0xFF;
 +
    PTED = 0xFF;
 +
 
 +
  // 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 - Toolkit
 +
  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));
 +
 +
 +
  //Lighting the LED module according to the "y" position, using the accelerometer
 +
 +
  if (y.result[samp]>=0x2F79){
 +
     
 +
      PTED = 0x00;
 +
      PTCD = 0x00;}
 +
 +
  if (y.result[samp]>=0x2CEC){
 +
      PTCD_PTCD0=0;
 +
      PTCD_PTCD1=0;
 +
      PTCD_PTCD2=0;
 +
      PTCD_PTCD3=0;
 +
      PTCD_PTCD4=0;
 +
      PTCD_PTCD5=0;}
 +
 +
  else if (y.result[samp]>=0x2AC9){
 +
      PTCD_PTCD0=0;
 +
      PTCD_PTCD1=0;
 +
      PTCD_PTCD2=0;
 +
      PTCD_PTCD3=0;}
 +
 +
  else if (y.result[samp]>=0x2619){
 +
      PTCD_PTCD0=0;
 +
      PTCD_PTCD1=0;}
 +
 +
  else if (y.result[samp]>=0x2169){
 +
        PTCD = 0xFF;
 +
            PTED = 0xFF;}
 +
 +
  else if (y.result[samp]>=0x1CB9)
 +
  {
 +
            PTED_PTED6=0;
 +
            PTED_PTED7=0;
 +
  }
 +
 +
  else if (y.result[samp]>=0x1809)
 +
  {
 +
      PTCD_PTCD4=0;
 +
      PTCD_PTCD5=0;
 +
      PTED_PTED6=0;
 +
      PTED_PTED7=0;
 +
   
 +
  }
 +
 +
  else if (y.result[samp]>=0x1359)
 +
  {
 +
        PTCD_PTCD2=0;
 +
        PTCD_PTCD3=0;
 +
        PTCD_PTCD4=0;
 +
        PTCD_PTCD5=0;
 +
        PTED_PTED6=0;
 +
        PTED_PTED7=0;
 +
     
 +
  }
 +
 
 +
  else if (y.result[samp]>=0x0FA0)
 +
  {   
 +
          PTED = 0x00;
 +
          PTCD = 0x00;
 +
  }
 +
 +
 +
 +
  // 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();
 +
        }
 +
  }
 +
 
 +
 +
</syntaxhighlight>
 +
 +
El vídeo del funcionamiento puede ser visto por este enlace:
 +
[https://youtu.be/0PBHEYPNn9Q Acelerómetro]

Revisión actual del 13:21 6 jul 2016

Introduccion IIC

El Inter-Integrated Circuit (IIC) provee un método de comunicación entre varios dispositivos. Está diseñado para operar hasta los 100 kbps con la máxima carga del bus y del tiempo. El dispositivo es capaz de operar a tasas de baudios altas, sin sobrecargar el bus. La longitud máxima de comunicación y el número de dispositivos que pueden ser conectados está limitado por la capacitancia del bus, la cual es de 400 pF.

Configuración del módulo:

Los pines SDA y SCL del módulo IIC1 pueden ser reposicionados por software usando el registro SOPT2[IIC1PS] tal como se muestra en la siguiente tabla. Este bit selecciona cual puerto de E/S con propósito general está asociado con la operación del IIC1.

Opciones de Posición del IIC1
SOPT2[IIC1PS] Pines para SDA Pines para SCL
0 por defecto PTA2 PTB6
1 PTA3 PTB7

Vectores de Interrupción:

Para la serie de microcontroladores MC9S08QE128, los cuales tienen dos IIC, el vector de interrupciones es compartido por ambos módulos IIC. Cuando las interrupciones son habilitadas para ambos módulos, se debe verificar el bit de IICIF (que hace referencia a la bandera de interrupciones) de los registros IIC1S y IIC2S (estos son los registros de status) para determinar cuál módulo es el causante de la interrupción.

Características:

El IIC incluye las siguientes características:

  • Compatibilidad con el bus estándar del IIC.
  • Operación con múltiples maestros.
  • Software programable para una de las 64 frecuencias diferentes del reloj serial.
  • Software que permite seleccionar el bit de reconocimiento (acknowledge bit)
  • Manejo de interrupciones mediante la transferencia de datos byte por byte.
  • Resolución de las interrupciones perdidas con un modo que hace intercambio automático de maestro a esclavo.
  • Llamado a las direcciones de identificación de las interrupciones.
  • Generación y detección de las señales START y STOP.
  • Generación repetida de la señal START.
  • Generación y detección del bit acknowledge.
  • Detección de la disponibilidad del bus.
  • Llamada general de reconocimiento.
  • Extensión de la dirección a 10 bits.

Modos de Operación:

Se presenta a continuación una breve descripción de los modos de operación del IIC:

  • Modo Corriendo o “Run”: Este es el modo de operación básico. Para conservar la energía en este modo, inhabilite el módulo.
  • Modo de espera o “Wait”: El módulo seguirá funcionando mientras que el microcontrolador esté en modo de espera y pueda proporcionar una alarma de despertador.
  • Modo detenido o “Stop”: El IIC está inactivo en el modo Stop para reducir el consumo de energía. La instrucción de Stop no afecta a los registros de estados del IIC. Esta instrucción reiniciará el contenido de los registros.

Descripción de Señales externas

Se describe a continuación las señales que son accesibles por cada usuario:

  • SCL — Línea del Reloj Serial (Serial Clock Line): Es bidireccional, y es la línea del reloj serial del sistema del IIC.
  • SDA - Línea de Data Serial (Serial Data Line): Es la línea de datos serial del sistema del IIC. Es bidireccional.


Interrupciones

El IIC puede generar sólo una interrupción. Para que se genere una interrupción, debe ocurrir cualquiera de los eventos de la tabla siguiente, siempre y cuando el bit IICIE esté activado:

Interrupciones mediante IIC
Fuente de interrupción Status Flag Local Enable
Completar la transferencia de 1 byte TCF IICIF IICIE
Ajuste de direcciones de llamada recibidas IAAS IICIF IICIE
Pérdida de arbitraje ARBL IICIF IICIE

La interrupción es impulsada por el bit IICIF (del IIC Status Register) y es enmascarada con el bit IICIE (del IIC Control Register). El bit IICIF se puede limpiar asignándole un 1 en la rutina de interrupción. El usuario puede determinar el tipo de interrupción mediante la lectura del Status Register.

Interrupción por transferencia de byte

El bit TCF (transfer complete flag) se establece a flanco de bajada del 9th clock para indicar la completación de la transferencia del byte

Interrupción por detección de dirección

Cuando la dirección de llamadas coincide con la dirección del esclavo programado (IIC address register) o cuando el bit GCAEN está activado y una llamada general es recibida, el bit IAAS en el Status Register es activado. La CPU es interrumpida siempre y cuando se active el bit IICIE. La CPU debe revisar el bit SRW y activar su modo Tx en consecuencia.

Interrupción por pérdida de arbitraje

El IIC es un verdadero bus con múltiples maestros que permite más de un maestro para ser conectado en él. Si dos o más maestros tratan de controlar el bus al mismo tiempo, se determina la prioridad relativa de los maestros en contienda por un procedimiento de arbitraje de datos. El módulo IIC asegura esta interrupción cuando pierde el proceso de arbitraje de datos y el bit ARBL en el Status Register está activado.

El arbitraje se puede perder en las siguientes circunstancias:

  • SDA probado como bajo cuando el maestro produce un alto durante un ciclo de dirección o de transmisión de datos.
  • SDA probado como bajo cuando el maestro produce un alto durante el bit de aviso de un ciclo de recepción de datos
  • Un ciclo de arranque se intenta cuando el bus está ocupado
  • Un ciclo repetido de arranque es requerido en modo esclavo
  • Se detecta una condición de parada cuando el maestro no lo solicitó

Resets

El IIC se desactiva luego de un RESET. El IIC no puede provocar un reinicio o reseteo del microcontrolador.

Ejemplo - Código para el acelerómetro usando el protocolo IIC

El siguiente código, hecho en lenguaje C y compilado y quemado en el DEMOQE128 usando el software CodeWarrior 10.6, enciende los LEDS de dos en dos de acuerdo a las lecturas provistas por el acelerómetro. La comunicación es establecida utilizando el protocolo IIC.

#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;
 
  /* 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;
 
  // Habilitación de los LEDs y se colocan apagados por defecto
    PTCDD = 0x3F;
    PTEDD = 0xC0;
   
    PTCD = 0xFF;
    PTED = 0xFF;
   
  // 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 - Toolkit
  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));
 

  //Lighting the LED module according to the "y" position, using the accelerometer
 
  if (y.result[samp]>=0x2F79){
      
      PTED = 0x00;
      PTCD = 0x00;}
 
  if (y.result[samp]>=0x2CEC){
      PTCD_PTCD0=0;
      PTCD_PTCD1=0;
      PTCD_PTCD2=0;
      PTCD_PTCD3=0;
      PTCD_PTCD4=0;
      PTCD_PTCD5=0;}
 
  else if (y.result[samp]>=0x2AC9){
      PTCD_PTCD0=0;
      PTCD_PTCD1=0;
      PTCD_PTCD2=0;
      PTCD_PTCD3=0;}
 
  else if (y.result[samp]>=0x2619){
      PTCD_PTCD0=0;
      PTCD_PTCD1=0;}
 
  else if (y.result[samp]>=0x2169){
        PTCD = 0xFF;
            PTED = 0xFF;}
 
  else if (y.result[samp]>=0x1CB9)
   {
            PTED_PTED6=0;
            PTED_PTED7=0;
   }
 
  else if (y.result[samp]>=0x1809)
   {
      PTCD_PTCD4=0;
      PTCD_PTCD5=0;
      PTED_PTED6=0;
      PTED_PTED7=0;
     
   }
 
  else if (y.result[samp]>=0x1359)
   {
        PTCD_PTCD2=0;
        PTCD_PTCD3=0;
        PTCD_PTCD4=0;
        PTCD_PTCD5=0;
        PTED_PTED6=0;
        PTED_PTED7=0;
       
   } 
   
   else if (y.result[samp]>=0x0FA0)
   {     
          PTED = 0x00;
          PTCD = 0x00;
   }
 

 
  // 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();
        }
  }

El vídeo del funcionamiento puede ser visto por este enlace: Acelerómetro

Contributors

MariaALE, YoelD