Diferencia entre revisiones de «Registros IIC»

De Wikitronica
Saltar a: navegación, buscar
Línea 145: Línea 145:
  
 
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.
 
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.
 +
 +
<u>'''Ejemplo Acelerometro'''</u>
 +
 +
 +
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 la esta siente movimiento en el eje y, la informacion del movimiento la da el Acerelometro.
 +
 +
/////////////////////////////////////////////////////////////////////////////////////////
 +
//
 +
// 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();
 +
        }
 +
  }
 +
}

Revisión del 12:49 1 jul 2016

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)


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)

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)


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)

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)

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)

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 la esta siente movimiento en el eje y, la informacion del movimiento la da el Acerelometro.

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

  1. include <hidef.h> /* for EnableInterrupts macro */
  2. include "derivative.h" /* include peripheral declarations */
  3. 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