Diferencia entre revisiones de «Código Acelerómetro para Codewarrior 10.6»
Línea 1: | Línea 1: | ||
+ | <div align= "rigth">[[Archivo:AcelerometroFuncionando.gif]]</div> | ||
− | + | ''Prueba de funcionamiento | |
− | + | ||
− | + | ||
− | + | ||
− | ''Prueba de funcionamiento | + | |
del acelerómetro'' | del acelerómetro'' | ||
Línea 11: | Línea 8: | ||
== Descripción de funciones == | == Descripción de funciones == | ||
+ | === Inicialización de periféricos === | ||
+ | |||
+ | ==== ICS ==== | ||
− | |||
− | |||
El módulo ICS (Internal Clock Source) maneja las diferentes opciones para la fuente de reloj. Tiene siete modos de operación: FEI, FEE, FBI, FBILP, FBE, FBELP, y stop. En este caso se trabajará con el modo por defecto FEI. | El módulo ICS (Internal Clock Source) maneja las diferentes opciones para la fuente de reloj. Tiene siete modos de operación: FEI, FEE, FBI, FBILP, FBE, FBELP, y stop. En este caso se trabajará con el modo por defecto FEI. | ||
Línea 32: | Línea 30: | ||
'''Rutina de inicialización''' | '''Rutina de inicialización''' | ||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
− | # | + | #Define ICSC1_FEI 0x04 |
− | # | + | #Define ICSC2_FEI 0x06 |
− | # | + | #Define ICSSC_FEI 0x80 |
Línea 49: | Línea 47: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
+ | ==== KBI ==== | ||
− | + | Es el módulo de interrupción por teclado. | |
− | Es el módulo de interrupción por teclado. | + | |
El registro KBIxSC es un registro de estado y control.Está compuesto por 8 bits, de los cuales, los 4 bits menos significativos tienen un significado específico y permiten habilitar y deshabilitar distintas instancias de las interrupciones y manejar el control del registro. | El registro KBIxSC es un registro de estado y control.Está compuesto por 8 bits, de los cuales, los 4 bits menos significativos tienen un significado específico y permiten habilitar y deshabilitar distintas instancias de las interrupciones y manejar el control del registro. | ||
Línea 59: | Línea 57: | ||
[[Archivo:Kbi2.jpg]] | [[Archivo:Kbi2.jpg]] | ||
− | + | <br> | |
'''Rutina de Inicialización''' | '''Rutina de Inicialización''' | ||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
− | # | + | #Define KBI_SW KBI1PE_KBIPE2_MASK | KBI1PE_KBIPE3_MASK |
Línea 80: | Línea 78: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | ====SCI==== | + | ==== SCI ==== |
+ | |||
SCI (Serial Communications Interface), permite la transmisión y recepción de datos por el puerto serial. | SCI (Serial Communications Interface), permite la transmisión y recepción de datos por el puerto serial. | ||
La configuración de este módulo es necesaria, ya que a través de su registro de datos (SCIxD) se lleva a cabo la transmisión de la data desde el acelerómetro al procesador. | La configuración de este módulo es necesaria, ya que a través de su registro de datos (SCIxD) se lleva a cabo la transmisión de la data desde el acelerómetro al procesador. | ||
Línea 92: | Línea 91: | ||
[[Archivo:SCIxBDH.png]] | [[Archivo:SCIxBDH.png]] | ||
− | |||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
Línea 100: | Línea 98: | ||
} | } | ||
− | </syntaxhighlight | + | </syntaxhighlight> |
− | ====PeriphInit==== | + | ==== PeriphInit ==== |
Es quien se encarga de desabilitar interrupciones, habilito todos los pullups (Desde PTA hasta PTJ), iniciar el módulo SCI y además configurar ciertos parámetros del acelerómetro. | Es quien se encarga de desabilitar interrupciones, habilito todos los pullups (Desde PTA hasta PTJ), iniciar el módulo SCI y además configurar ciertos parámetros del acelerómetro. | ||
Línea 145: | Línea 143: | ||
InitSCI(fei_baud); | InitSCI(fei_baud); | ||
} | } | ||
− | </syntaxhighlight | + | </syntaxhighlight> |
− | ====IIC==== | + | ==== IIC ==== |
La función '''''IIC_Configuration''''' se encarga de setear los bits de dos registros para configurar dos cosas principalmente: | La función '''''IIC_Configuration''''' se encarga de setear los bits de dos registros para configurar dos cosas principalmente: | ||
Línea 154: | Línea 152: | ||
[[Archivo:IICxFreg.jpg]] | [[Archivo:IICxFreg.jpg]] | ||
− | |||
[[Archivo:IICxF.jpg]] | [[Archivo:IICxF.jpg]] | ||
Línea 168: | Línea 165: | ||
IIC2C1 = 0xC0; | IIC2C1 = 0xC0; | ||
} | } | ||
− | </syntaxhighlight> | + | </syntaxhighlight> |
+ | |||
+ | === Funciones para la transmisión y recepción de datos === | ||
− | |||
La función RecChar obtiene uno a unos los caracteres enviados a tráves del protocolo IIC desde el registro SCI1D. De igual forma, las funciones SendChar y SendMsg utilizan este registro, descomponen en caracteres el mensaje y lo envían uno a uno. | La función RecChar obtiene uno a unos los caracteres enviados a tráves del protocolo IIC desde el registro SCI1D. De igual forma, las funciones SendChar y SendMsg utilizan este registro, descomponen en caracteres el mensaje y lo envían uno a uno. | ||
Línea 176: | Línea 174: | ||
'''SCIxC2: SCI Control Register 2''' | '''SCIxC2: SCI Control Register 2''' | ||
+ | |||
[[Archivo:SCIxC2.png]] | [[Archivo:SCIxC2.png]] | ||
+ | |||
'''SCIxS1: SCI Status Register 1'''[[Archivo:SCIxS1.png]] | '''SCIxS1: SCI Status Register 1'''[[Archivo:SCIxS1.png]] | ||
'''SCIxD: SCI Data Register''' | '''SCIxD: SCI Data Register''' | ||
+ | |||
[[Archivo:SCIxD.png]] | [[Archivo:SCIxD.png]] | ||
− | ====Recibir caracter==== | + | ==== Recibir caracter ==== |
+ | |||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
char RecChar(void) { | char RecChar(void) { | ||
Línea 197: | Línea 199: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | ====Enviar caracter==== | + | ==== Enviar caracter ==== |
+ | |||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
void SendChar(char s_char) { | void SendChar(char s_char) { | ||
Línea 207: | Línea 210: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | ====Enviar mensaje==== | + | ==== Enviar mensaje ==== |
+ | |||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
void SendMsg(char msg[]) { | void SendMsg(char msg[]) { | ||
Línea 224: | Línea 228: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | ===Conversión de datos=== | + | === Conversión de datos === |
− | ====Hexadecimal a BCD (Binary-Coded Decimal)==== | + | |
+ | ==== Hexadecimal a BCD (Binary-Coded Decimal) ==== | ||
+ | |||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
word hex2bcd(word hex){ | word hex2bcd(word hex){ | ||
Línea 245: | Línea 251: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
+ | ==== De ASCII a un byte ==== | ||
− | |||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
byte asc2byte(char n_asc) { | byte asc2byte(char n_asc) { | ||
Línea 262: | Línea 268: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | ====De ASCII a una palabra==== | + | ==== De ASCII a una palabra ==== |
+ | |||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
word asc2word(byte n_asc[2]) { | word asc2word(byte n_asc[2]) { | ||
Línea 288: | Línea 295: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | ====De byte a ASCII==== | + | ==== De byte a ASCII ==== |
+ | |||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
char * byte2asc(byte num, byte base) { | char * byte2asc(byte num, byte base) { | ||
Línea 309: | Línea 317: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | ====De palabra a ASCII==== | + | ==== De palabra a ASCII ==== |
+ | |||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
Línea 340: | Línea 349: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | ===Aceleración=== | + | === Aceleración === |
+ | |||
+ | ==== Read Acceleration ==== | ||
− | |||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
void ReadAcceleration(void){ | void ReadAcceleration(void){ | ||
Línea 361: | Línea 371: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
+ | ==== Show Acceleration ==== | ||
− | |||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
void ShowAcceleration (void) | void ShowAcceleration (void) | ||
Línea 425: | Línea 435: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | ===Funciones del Maestro=== | + | === Funciones del Maestro === |
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
Línea 439: | Línea 449: | ||
void Master_Write_MMA7660_register(byte transbytes) { | void Master_Write_MMA7660_register(byte transbytes) { | ||
last_byte = 0; // Initialize variables to 0 | last_byte = 0; // Initialize variables to 0 | ||
− | + | count = 0; | |
bytes_to_trans = transbytes; | bytes_to_trans = transbytes; | ||
Línea 457: | Línea 467: | ||
rec_count = 0; // Initialize variables to 0 | rec_count = 0; // Initialize variables to 0 | ||
last_byte = 0; | last_byte = 0; | ||
− | + | count = 0; | |
− | + | repeat_start_sent = 0; | |
− | + | ||
bytes_to_trans = transbytes; | bytes_to_trans = transbytes; | ||
num_to_rec = recbytes; | num_to_rec = recbytes; | ||
Línea 476: | Línea 486: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | ===Configuración del TMP=== | + | === Configuración del TMP === |
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
Línea 494: | Línea 504: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | ===Rutinas de Interrupción=== | + | === Rutinas de Interrupción === |
'''KBI_ISR''' | '''KBI_ISR''' | ||
Línea 501: | Línea 511: | ||
''interrupt VectorNumber_Vkeyboard '' | ''interrupt VectorNumber_Vkeyboard '' | ||
− | # | + | #Define KBI_VAL (PTAD&0x0C)>>2 |
void KBI_ISR(void){ | void KBI_ISR(void){ | ||
Línea 526: | Línea 536: | ||
IIC2S_IICIF = 1; // Clear Interrupt Flag | IIC2S_IICIF = 1; // Clear Interrupt Flag | ||
if (IIC2C1_TX) { // Transmit or Receive? | if (IIC2C1_TX) { // Transmit or Receive? | ||
− | ///////////////////// Transmit //////////////////////////// | + | ///////////////////// Transmit //////////////////////////// |
if (repeat_start_sent) { | if (repeat_start_sent) { | ||
IIC2C1_TX = 0; // Switch to RX mode | IIC2C1_TX = 0; // Switch to RX mode | ||
if (num_to_rec == 1) | if (num_to_rec == 1) | ||
IIC2C1_TXAK = 1; // This sets up a NACK | IIC2C1_TXAK = 1; // This sets up a NACK | ||
− | + | IIC2D; // Dummy read from Data Register | |
} | } | ||
else if ((last_byte) & (reading_mma7660_reg)) { | else if ((last_byte) & (reading_mma7660_reg)) { | ||
Línea 538: | Línea 548: | ||
repeat_start_sent = 1; | 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 { | + | } else { |
− | ///////////////////// Receive //////////////////////////// | + | ///////////////////// Receive //////////////////////////// |
if ((num_to_rec - rec_count) == 2) { | 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) { | else if ((num_to_rec - rec_count) == 1) { | ||
− | + | IIC2C1_MST = 0; // Send STOP | |
− | + | Master_Read_and_Store(); | |
− | + | } | |
− | + | else { | |
− | + | Master_Read_and_Store(); | |
− | + | } | |
} | } | ||
} | } | ||
Línea 569: | Línea 579: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | === Modos de Operación === | |
− | ===Modos de Operación=== | + | |
Por medio de interrupciones, se puede detectar el modo en el que el acelerómetro trabajará. Cada uno de estos modos se encarga de almacenar el valor que recibe cuando el sensor detecta un cambio en las coordenadas de X, Y, Z y puede Filtrar los datos de los valores recibidos (Función filter_data) Promedia el valor de las lecturas realizadas (Función Avg_data) o simplemente copiar los valores de la lectura de las variables (Función copy_data). | Por medio de interrupciones, se puede detectar el modo en el que el acelerómetro trabajará. Cada uno de estos modos se encarga de almacenar el valor que recibe cuando el sensor detecta un cambio en las coordenadas de X, Y, Z y puede Filtrar los datos de los valores recibidos (Función filter_data) Promedia el valor de las lecturas realizadas (Función Avg_data) o simplemente copiar los valores de la lectura de las variables (Función copy_data). | ||
− | ====Filter_data==== | + | ==== Filter_data ==== |
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
Línea 598: | Línea 607: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | ====Avg_data==== | + | ==== Avg_data ==== |
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
Línea 617: | Línea 626: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | ====Copy_data==== | + | ==== Copy_data ==== |
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
Línea 628: | Línea 637: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | ==Material de Referencia== | + | == Material de Referencia == |
Código del proyecto: | Código del proyecto: |
Revisión del 22:10 22 jun 2016
Prueba de funcionamiento del acelerómetro
Contenido
- 1 Descripción general
- 2 Descripción de funciones
- 3 Material de Referencia
Descripción general
Descripción de funciones
Inicialización de periféricos
ICS
El módulo ICS (Internal Clock Source) maneja las diferentes opciones para la fuente de reloj. Tiene siete modos de operación: FEI, FEE, FBI, FBILP, FBE, FBELP, y stop. En este caso se trabajará con el modo por defecto FEI.
Para inicilizar el ICS deben modificarse tres de sus registros:
ICSC1: ICS Control Register 1
ICSC2: ICS Control Register 2
ICSSC: ICS Status and Control
Rutina de inicialización
#Define ICSC1_FEI 0x04
#Define ICSC2_FEI 0x06
#Define ICSSC_FEI 0x80
void ICS_FEI(void) {
if (NVICSTRM != 0xFF)
ICSTRM = NVICSTRM;
else
ICSTRM = 0xAD;
ICSC1 = ICSC1_FEI;
ICSC2 = ICSC2_FEI;
ICSSC = ICSSC_FEI;
while (ICSC1_CLKS != ICSSC_CLKST) {}
}
KBI
Es el módulo de interrupción por teclado.
El registro KBIxSC es un registro de estado y control.Está compuesto por 8 bits, de los cuales, los 4 bits menos significativos tienen un significado específico y permiten habilitar y deshabilitar distintas instancias de las interrupciones y manejar el control del registro.
El registro KBIxPE es un registro que está relacionado con los pines de la tarjeta de desarrollo. Nos permite configurar cuáles pines se habilitarán para las interrupciones, los cuales posteriormente serán enlazados con algún dispositivo.
Rutina de Inicialización
#Define KBI_SW KBI1PE_KBIPE2_MASK | KBI1PE_KBIPE3_MASK
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
*/
}
SCI
SCI (Serial Communications Interface), permite la transmisión y recepción de datos por el puerto serial. La configuración de este módulo es necesaria, ya que a través de su registro de datos (SCIxD) se lleva a cabo la transmisión de la data desde el acelerómetro al procesador. En este caso, para su inicialización solo hace falta modificar dos registros:
SCIxBDL
SCIxBDH
void InitSCI(word baud) {
SCI1BD = baud; // Se configura el valor de la tasa de baudios especificada
}
PeriphInit
Es quien se encarga de desabilitar interrupciones, habilito todos los pullups (Desde PTA hasta PTJ), iniciar el módulo SCI y además configurar ciertos parámetros del acelerómetro.
void PeriphInit(void)
{
// Desabilita las instrucciones de COP y habilita las instrucciones de STOP, RESET y BKGD
SOPT1 = 0x23;
// Selecciona el modo FEI
// Seteamos el trimming del fBUS en 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;
/* Configura PTG[2:1] como la sensitividad del acelerometro
PTG2:PTG1
0 0 = 1.5g
0 1 = 2.0g
1 0 = 4.0g
1 1 = 6.0g
*/ //
PTGD = 0x00; // selecciono como salida el puerto G
PTGDD = 0x06; // selecciono sensibilidad de 1.5g
// Timer2 overflow about every 1ms
TPM2MOD = 25000; // registro que contiene el valor del contador
// Detiene el Timer2 y selecciona 1 como un divisor prescalar
TPM2SC = 0x00; //
// Initializes SCI Peripheral
InitSCI(fei_baud);
}
IIC
La función IIC_Configuration se encarga de setear los bits de dos registros para configurar dos cosas principalmente:
El Registro de Divisor de Frecuencia, para definir la taza de baudios y el tiempo de espera.
El Registro de Control del IIC, configurando La habilitación del modulo IIC, sus interrupciones y definiéndolo en modo esclavo, receptor y con una señal de acknowledge.
void IIC_configuration (void) {
IIC2F = 0x90;
IIC2C1 = 0xC0;
}
Funciones para la transmisión y recepción de datos
La función RecChar obtiene uno a unos los caracteres enviados a tráves del protocolo IIC desde el registro SCI1D. De igual forma, las funciones SendChar y SendMsg utilizan este registro, descomponen en caracteres el mensaje y lo envían uno a uno.
Los registros utilizados por estas funciones son:
SCIxC2: SCI Control Register 2
SCIxD: SCI Data Register
Recibir caracter
char RecChar(void) {
byte rec_char;
if (SCI1S1_RDRF) // Si el buffer de transmisión esta lleno
rec_char = SCI1D; // Limpio el buffer
SCI1C2_RE = 1; //Habilito la transmisión
while(!SCI1S1_RDRF){ };// Espero hasta que el buffer no esté vacío
rec_char = SCI1D; // Obtengo el caracter enviado
SendChar((char) rec_char);// Reenvío el caracter
return (char) SCI1D;
}
Enviar caracter
void SendChar(char s_char) {
SCI1C2 = 0x08; // Habilito la transmisión de datos
while(!SCI1S1_TDRE){ } //Mientras el buffer de transmisión de datos este lleno espero
SCI1D = (byte) s_char; //Escribe el caracter que será enviado
}
Enviar mensaje
void SendMsg(char msg[]) {
byte i=0;
char nxt_char;
SCI1C2 = 0x08; //Habilito la transmisión
nxt_char = msg[i++];
while(nxt_char != 0x00) { //Mientras sea diferente de NULL
while(!SCI1S1_TDRE){} //Mientras el buffer de transmsión de datos este lleno espero
SCI1D = (byte) nxt_char; // Escribo el caracter en el registro de datos
nxt_char = msg[i++]; //Leo el siguiente caracter del arreglo
}
}
Conversión de datos
Hexadecimal a BCD (Binary-Coded Decimal)
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;
}
De ASCII a un byte
byte asc2byte(char n_asc) {
byte n;
n = (byte)(n_asc - 0x30); //Conviere de ASCII a 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;
}
De ASCII a una palabra
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;
}
De byte a ASCII
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
De palabra a ASCII
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
Aceleración
Read Acceleration
void ReadAcceleration(void){
byte i;
signed int temp;
for(i=0;i<3;i++){
temp = IIC_Rec_Data[i] & 0x3F;
if(IIC_Rec_Data[i] & 0x20){
temp |= 0xFFC0;
temp += 32;
IIC_Converted_Data[i] = temp;
}else{
IIC_Converted_Data[i] = temp + 32;
}
}
}
Show Acceleration
void ShowAcceleration (void)
{
word SampleCNT;
byte j,k;
ReadAcceleration();
ADCSC1 = 0x01;
x.reading[samp] = (dword)( IIC_Converted_Data[0] <<8);
ADCSC1 = 0x08;
y.reading[samp] = (dword)( IIC_Converted_Data[1] <<8);
ADCSC1 = 0x09;
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));
// 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)
}
Funciones del Maestro
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)
}
Configuración del TMP
void StartTPM(byte PS){
TPM1SC = (byte)(0x08 | (0x07&PS));
StartCount = TPM1CNT;
}
word StopTPM(void){
StopCount = (word)(TPM1CNT - StartCount);
TPM1SC = 0;
return StopCount;
}
Rutinas de Interrupción
KBI_ISR
''interrupt VectorNumber_Vkeyboard ''
#Define KBI_VAL (PTAD&0x0C)>>2
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
''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();
}
}
}
Modos de Operación
Por medio de interrupciones, se puede detectar el modo en el que el acelerómetro trabajará. Cada uno de estos modos se encarga de almacenar el valor que recibe cuando el sensor detecta un cambio en las coordenadas de X, Y, Z y puede Filtrar los datos de los valores recibidos (Función filter_data) Promedia el valor de las lecturas realizadas (Función Avg_data) o simplemente copiar los valores de la lectura de las variables (Función copy_data).
Filter_data
void filter_data(void)
{ // guarda el valor de las coordenadas de X,Y,Z
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;
}
Avg_data
void avg_data(void)
{// promedia el valor leido por x, y, z desde j hasta samp
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);
}
Copy_data
void copy_data(void) { // copio el promedio leido en una variable resultado para x, y ,z
x.result[samp] = x.reading[samp];
y.result[samp] = y.reading[samp];
z.result[samp] = z.reading[samp];
}
Material de Referencia
Código del proyecto: