#define TMR_10us 65535 - 32 // Valor a cargar en el TMR para 10 useg
#define TMR_1ms 65535 - 6000 // Valor a cargar en el TMR para 1 mseg
#define TMR_9ms 65535 - 53930 // Valor a cargar en el TMR para 9 mseg
// Variables globales.
uint8_t cont_int = 0;
uint8_t dutys_buff[100]; //Buffer donde se almacenan cuando deben ir a off las salidas
uint8_t dutys[8]; //Duty cicle de cada salida PWM
// FUNCION DE INTERRUPCION
void interrupt ISR(void) {
if(INTCONbits.TMR0IF){
uint8_t i, mask;
INTCONbits.TMR0IF = 0; // Limpiamos bandera de desborde
switch(cont_int){ // Verifico en que interrupcion estoy
case 0: // Es la primera
TMR0 = TMR_1ms; // Ajusto para que proxima int sea en 1 mseg
PORTD = 0x0F; // Pongo en 1 las 4 salidas.
mask = 1; // Preparo el buffer a usar para hacer el toggle
for(i=0;i<8;i++){ // de la salida correspondiente segun el duty elegido
dutys_buff[dutys[i]] = dutys_buff[dutys[i]] | mask;
mask = mask << 1;
}
cont_int++; // Incremento interrupcion
break;
case 101: // Si estoy en la 101
TMR0 = TMR_9ms; // Configuro para interrumpir en 9 mseg
PORTD = 0; // Serían 11 mseg desde el comienzo
cont_int++; // Pongo todos los PWM a 0
break; // Incremento interrupcion
case 102: // Si es la 102
TMR0 = TMR_9ms; // Tengo que esperar otros 9 mseg para completar
cont_int = 0; // los 20 mseg. Reseteo el contador de interrupciones
break;
default: // Si es la int 1 a 100
TMR0 = TMR_10us; // Ajusto para que proxima int sea dentro de 10 useg
PORTD ^= dutys_buff[cont_int - 1]; // Si corresponde pongo a 0 la salida
cont_int++; // Incremento el contador
break;
}
}
}
/*
* File: main.c
* Author: elgarbe
*
* Created on 25 de abril de 2014, 12:40
*/
#define _XTAL_FREQ 48000000
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <plib/usart.h>
#include "configuracion_de_fuses.h"
#include "configuracion_hard.h"
#define TMR_10us 65535 - 32 // Valor a cargar en el TMR para 10 useg
#define TMR_1ms 65535 - 6000 // Valor a cargar en el TMR para 1 mseg
#define TMR_9ms 65535 - 53930 // Valor a cargar en el TMR para 9 mseg
// Variables globales.
uint8_t cont_int = 0;
uint8_t dutys_buff[200]; //Buffer donde se almacenan cuando deben ir a off las salidas
uint8_t dutys[8]; //Duty cicle de cada salida PWM
// FUNCION DE INTERRUPCION
void interrupt ISR(void) {
if(INTCONbits.TMR0IF){
uint8_t i, mask;
INTCONbits.TMR0IF = 0; // Limpiamos bandera de desborde
switch(cont_int){ // Verifico en que interrupcion estoy
case 0: // Es la primera
TMR0 = TMR_1ms; // Ajusto para que proxima int sea en 1 mseg
PORTD = 0x0F; // Pongo en 1 las 4 salidas.
mask = 1; // Preparo el buffer a usar para hacer el toggle
for(i=0;i<8;i++){ // de la salida correspondiente segun el duty elegido
dutys_buff[dutys[i]] = dutys_buff[dutys[i]] | mask;
mask = mask << 1;
}
cont_int++; // Incremento interrupcion
break;
case 101: // Si estoy en la 101
TMR0 = TMR_9ms; // Configuro para interrumpir en 9 mseg
PORTD = 0; // Serían 11 mseg desde el comienzo
cont_int++; // Pongo todos los PWM a 0
break; // Incremento interrupcion
case 102: // Si es la 102
TMR0 = TMR_9ms; // Tengo que esperar otros 9 mseg para completar
cont_int = 0; // los 20 mseg. Reseteo el contador de interrupciones
break;
default: // Si es la int 1 a 100
TMR0 = TMR_10us; // Ajusto para que proxima int sea dentro de 10 useg
PORTD ^= dutys_buff[cont_int - 1]; // Si corresponde pongo a 0 la salida
cont_int++; // Incremento el contador
break;
}
}
}
void MyMsDelay(int ms);
void main(void) {
uint8_t i;
// unsigned char MsgFromPIC[100];
ADCON1=0x0F; //Todos entrada/salida digitales. - equivalente en binario ADCON1= 0b00001111
TRISA=0x00; //Todos como salida.
TRISB=0x00; //Todos como salida.
TRISC=0x00; //Todos como salida.
TRISD=0x80; //RC7 como entrada (RX de la usart)
TRISE=0x00; //Todos como salida. - equivalente en binario TRISE = 0b00000000
T0CON = 0; //16 bits, %2 prescaler, Timer apagado
// TMR2 = TMR_ADJ; // Ajuste para obtener 100useg por cada Interrupcion
// (frecuencia a la que trabaja el cpu/dbaudrate)/16)-1
// (48.000.000/115200)/16)-1 = 25
OpenUSART(USART_TX_INT_OFF &
USART_RX_INT_OFF & //Sin interrupciones
USART_ASYNCH_MODE & //Modo asincrono (fullduplex)
USART_EIGHT_BIT & //8 bits de datos
USART_CONT_RX & //Recepción continua
USART_BRGH_HIGH, 25); //115.2 K Baudios
INTCONbits.TMR0IF = 0;
INTCONbits.TMR0IE = 1; // Habilito int del Timer 0
INTCONbits.GIE = 1; // Habilito la int global
for(i=0;i<100;i++)
dutys_buff[i] = 0;
//Hacer funcion de asignacion de duty!!!!!!!!
dutys[0] = 0; //Pongo el duty de la salida 1 en 1 mseg
dutys[1] = 50; //Pongo el duty de la salida 2 en 1.5 mseg
dutys[2] = 100; //Pongo el duty de la salida 3 en 2 mseg
dutys[3] = 75; //Pongo el duty de la salida 4 en 1.75 mseg
MyMsDelay(500);
T0CONbits.TMR0ON = 1;
while(1){
LED4=1;
MyMsDelay(500);
LED4=0;
MyMsDelay(500);
}
}
void MyMsDelay(int ms){
while(ms--){
__delay_ms(1);
}
}
/*
* File: main.c
* Author: elgarbe
*
* Created on 25 de abril de 2014, 12:40
*/
#define _XTAL_FREQ 16000000
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <plib/usart.h>
#include "configuracion_de_fuses.h"
#include "configuracion_hard.h"
//#include <types.h>
#define RX_CHANNELS 8
/* defines */
#define RX_SUCCESS 1
#define RX_NO_PACKET 0
/****************************************************************************/
/* Private Variables */
/****************************************************************************/
static unsigned int pulses[RX_CHANNELS]; //Matriz para guardarel tiempo de cada pulso de cada canal
static char packet_available; //Bandera para indicar que ya recibimos RX_CHANNELS pulsos
void MyMsDelay(int ms);
unsigned char rx_get_packet(unsigned int packet[RX_CHANNELS]);
// Variables globales.
// FUNCION DE INTERRUPCION
void interrupt ISR(void) {
// persistent local variables
static unsigned int tmp_pulses[RX_CHANNELS];
static unsigned int prev_ticks = 0;
static unsigned int current_pulse = 0;
unsigned int curr_ticks, nanos, c; // local variables
if(PIR2bits.CCP2IF){
curr_ticks = CCPR2H; // compute delta time (each tick is 10ns)
curr_ticks <<= 8;
curr_ticks += CCPR2L;
nanos = curr_ticks - prev_ticks;
if (nanos > 12000){ //Si el tiempo del pulso supera los 3mseg
current_pulse = 0; //es que estamos en el pulso de sincronismo
}
else {
tmp_pulses[current_pulse] = nanos; // store this sample
current_pulse++; // advance to next pulse
if (current_pulse == RX_CHANNELS) { // check for end of packet
current_pulse = 0; // wrap pointer
for (c=0; c<RX_CHANNELS; c++) // copy out packet
pulses[c] = tmp_pulses[c]/4;
packet_available = 1; // signal available packet
}
}
prev_ticks = curr_ticks; // save current as previous for next event
PIR2bits.CCP2IF = 0; // Limpiamos bandera del CCP
}
}
void main(void) {
unsigned char canal, MsgFromPIC[100];
unsigned int rx_values[RX_CHANNELS];
ADCON1=0x0F; //Todos entrada/salida digitales. - equivalente en binario ADCON1= 0b00001111
TRISA=0x00; //Todos como salida- - equivalente en binario TRISA = 0b00000000
TRISB=0X00; //Todos como salida. - equivalente en binario TRISB = 0b00000000
TRISC=0X00; //Todos como salida. - equivalente en binario TRISC = 0b00000000
TRISD=0x00; //D7 a D1 como salida D0 como entrada
TRISE=0X00; //Todos como salida. - equivalente en binario TRISE = 0b00000000
LATD=0x00; //Leds apagados.-
TRISCbits.RC6 = 0; //TX pin set as output
TRISCbits.RC7 = 1; //RX pin set as input
TRISCbits.RC1 = 1; //CCP2 as Input
T3CONbits.TMR3ON = 0; //Stop de Timer
T3CONbits.RD16 = 1; //16 bits timer
T3CONbits.T3CCP2 = 1; //TMR3 is source of CCP2
T3CONbits.T3CKPS = 0; //Sin prescaler
CCP2CONbits.CCP2M = 5; //Capture mode: every rising edge
PIR2bits.CCP2IF = 0; //Cler ny pending Int
PIE2bits.CCP2IE = 1; // Habilito la int por CCP2
INTCONbits.PEIE = 1; // Habilito int de los perifericos. CCP2 es uno de ellos
INTCONbits.GIE = 1; // Habilito la int global
LED1=1;
MyMsDelay(2000);
LED1=0;
OpenUSART(USART_TX_INT_OFF &
USART_RX_INT_OFF & //Activar la interrupcion por la recepcion de dato del buffer de Rx del USART
USART_ASYNCH_MODE & //Modo asincrono (fullduplex)
USART_EIGHT_BIT & //8 bits de datos
USART_CONT_RX & //Recepción continua
USART_BRGH_HIGH, 51); //9600 Baudios
T3CONbits.TMR3ON = 1; //Strt de Timer
MyMsDelay(500);
//
while(1){
//Verifico si hay datos nuevo provenientes del Tx
canal=rx_get_packet(rx_values);
if(canal == RX_SUCCESS){
for (canal=0; canal<RX_CHANNELS; canal++){
sprintf(MsgFromPIC, "%d, ", rx_values[canal]);
putsUSART(MsgFromPIC);
}
sprintf(MsgFromPIC, "\r\n");
putsUSART(MsgFromPIC);
}
LED1=1;
MyMsDelay(10);
LED1=0;
MyMsDelay(10);
}
}
void MyMsDelay(int ms){
while(ms--){
__delay_ms(1);
}
}
// If a packet has arrived since the last call, 'packet' is filled with
// the contents of the packet and RX_SUCCESS is returned. If no packet
// is available, RX_NO_PACKET is returned.
// The size of 'packet' must be at least RX_CHANNELS.
// This is NOT thread safe.
unsigned char rx_get_packet(unsigned int packet[RX_CHANNELS]) {
char avail, ch;
// turn off timer2 capture interrupts while accessing packet_available
PIE2bits.CCP2IE = 0; // Deshabilito la int por CCP2
avail = packet_available; // grab current value
packet_available = 0; // set to zero
PIE2bits.CCP2IE = 1; // Vuelvo a encender la Interrupcion
if (avail) { // check if a packet is available
for (ch=0; ch<RX_CHANNELS; ch++) // copy packet
packet[ch] = pulses[ch];
return RX_SUCCESS; // set as success
}else{
return RX_NO_PACKET; // set as failure
}
}
/*
* ADXL345.h
*
* Created on: 04/12/2013
* Author: elgarbe
*/
#ifndef ADXL345_H_
#define ADXL345_H_
#define ADXL345_R 0xA7 //Read Address
#define ADXL345_W 0xA6 //Write
#define ADXL345_D 0x32 //Data
#define ACC_SAMP_BIASS 600 //Número de muestras para calular biass
// Definición de funciones.
void ADXL345_init();
char ADXL345ReadByte(char address);
void BMP085WriteByte(char address, char data);
void ADXL345_read_data(short* _accel_X, short* _accel_Y, short* _accel_Z);
void ADXL345_GetBiass(float* _biass_X, float* _biass_Y, float* _biass_Z);
#endif /* ADXL345_H_ */
/*
* ADXL345.c
*
* Created on: 02/04/2014
* Author: elgarbe
*/
#include "ADXL345.h"
#include <plib/i2c.h>
#include <stdio.h>
extern void MyMsDelay(int ms);
/************************************************************************
* Read initial calibration constants
************************************************************************/
char ADXL345ReadByte(char address){
// Variables locales.
signed char data=0x00;
StartI2C();
WriteI2C(ADXL345_W);
WriteI2C(address);
StartI2C();
WriteI2C(ADXL345_R);
data=ReadI2C();
StopI2C();
return(data);
}
void ADXL345WriteByte(char address, char data){
StartI2C();
WriteI2C(ADXL345_W);
WriteI2C(address);
WriteI2C(data);
StopI2C();
}
void ADXL345_init(){
ADXL345WriteByte(0x2D, 0b00000000);
MyMsDelay(10);
ADXL345WriteByte(0x31, 0b00001011); // 1XXX Full res, XX11 +-2g
MyMsDelay(10);
ADXL345WriteByte(0x2C, 0b00001010); // 100Hz Data Output Rate
MyMsDelay(10);
ADXL345WriteByte(0x2D, 0b00001000);
MyMsDelay(10);
}
void ADXL345_read_data(short* _accel_X, short* _accel_Y, short* _accel_Z){
// Variables locales.
char msb=0x00;
char lsb=0x00;
StartI2C();
IdleI2C();
WriteI2C(ADXL345_W);
IdleI2C();
WriteI2C(ADXL345_D);
IdleI2C();
RestartI2C();
IdleI2C();
WriteI2C(ADXL345_R);
IdleI2C();
lsb = ReadI2C();
IdleI2C();
AckI2C();
IdleI2C();
msb = ReadI2C();
IdleI2C();
*_accel_X = (256*msb) + lsb;
AckI2C();
lsb = ReadI2C();
IdleI2C();
AckI2C();
IdleI2C();
msb = ReadI2C();
IdleI2C();
*_accel_Y = (256*msb) + lsb;
AckI2C();
lsb = ReadI2C();
IdleI2C();
AckI2C();
IdleI2C();
msb = ReadI2C();
IdleI2C();
*_accel_Z = (256*msb) + lsb;
NotAckI2C();
IdleI2C();
StopI2C();
}
void ADXL345_GetBiass(float* _biass_X, float* _biass_Y, float* _biass_Z){
int i;
short accel_X, accel_Y, accel_Z;
for (i = 0; i < ACC_SAMP_BIASS; i += 1) {
ADXL345_read_data(&accel_X, &accel_Y, &accel_Z);
*_biass_X += accel_X;
*_biass_Y += accel_Y;
*_biass_Z += accel_Z;
MyMsDelay(1);
}
*_biass_X /= ACC_SAMP_BIASS;
*_biass_Y /= ACC_SAMP_BIASS;
*_biass_Z /= ACC_SAMP_BIASS;
*_biass_Z -= 256;
}
/*
* File: main.c
* Author: elgarbe
*
* Created on 25 de abril de 2014, 12:40
*/
#define _XTAL_FREQ 8000000
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <plib/i2c.h>
#include <plib/usart.h>
#include "ADXL345.h"
#include "configuracion_de_fuses.h"
#include "configuracion_hard.h"
#define ACEL_X_SCALE 0.0039 //Sensibilidad en cada eje
#define ACEL_Y_SCALE 0.0039 //extraÃdo del datasheet
#define ACEL_Z_SCALE 0.0039
void i2c_init(void);
void MyMsDelay(int ms);
// Variables globales.
void main(void) {
short accel_X, accel_Y, accel_Z;
float g_X, g_Y, g_Z;
unsigned char MsgFromPIC[100];
float Biass_X, Biass_Y, Biass_Z;
// cambiamos la frecuencia del oscilador interno del valor por defecto de 32khz
// a 8mhz mediante los bits del registro OSCCON
OSCCONbits.IRCF2 = 1;
OSCCONbits.IRCF1 = 1;
OSCCONbits.IRCF0 = 1;
ADCON1=0x0F; //Todos entrada/salida digitales. - equivalente en binario ADCON1= 0b00001111
TRISA=0x00; //Todos como salida- - equivalente en binario TRISA = 0b00000000
TRISB=0X00; //Todos como salida. - equivalente en binario TRISB = 0b00000000
TRISC=0X00; //Todos como salida. - equivalente en binario TRISC = 0b00000000
TRISD=0x00; //D7 a D1 como salida D0 como entrada
TRISE=0X00; //Todos como salida. - equivalente en binario TRISE = 0b00000000
LATD=0x00; //Leds apagados.-
TRISCbits.RC6 = 0; //TX pin set as output
TRISCbits.RC7 = 1; //RX pin set as input
LED1=1;
MyMsDelay(5000);
LED1=0;
OpenUSART(USART_TX_INT_OFF &
USART_RX_INT_ON & //Activar la interrupcion por la recepcion de dato del buffer de Rx del USART
USART_ASYNCH_MODE & //Modo asincrono (fullduplex)
USART_EIGHT_BIT & //8 bits de datos
USART_CONT_RX & //Recepción continua
USART_BRGH_HIGH, 51); //9600 Baudios
i2c_init();
MyMsDelay(500);
ADXL345_init();
sprintf(MsgFromPIC, "Obteniendo Offset...\r\n");
putsUSART(MsgFromPIC);
ADXL345_GetBiass(&Biass_X, &Biass_Y, &Biass_Z);
sprintf(MsgFromPIC, "Offsets: %.2f, %.2f, %.2f\r\n", Biass_X, Biass_Y, Biass_Z);
putsUSART(MsgFromPIC);
while(1){
LED4=1;
ADXL345_read_data(&accel_X, &accel_Y, &accel_Z);
g_X = (accel_X - Biass_X) * ACEL_X_SCALE;
g_Y = (accel_Y - Biass_Y) * ACEL_Y_SCALE;
g_Z = (accel_Z - Biass_Z) * ACEL_Z_SCALE;
sprintf(MsgFromPIC, "G's: %.2f, %.2f, %.2f\r\n", g_X, g_Y, g_Z);
// sprintf(MsgFromPIC, "Offsets: %d, %d, %d\r\n", accel_X, accel_Y, accel_Z);
putsUSART(MsgFromPIC);
MyMsDelay(500);
LED4=0;
MyMsDelay(500);
}
}
void i2c_init(void){
/*A veces hay que hacer el siguiente work around explicado en el errata de
microchip para asegurarse que no haya inconvenientes con el bus I2C
Work around
Before configuring the module for I2C operation:
1. Configure the SCL and SDA pins as outputs by clearing their corresponding TRIS bits.
2. Force SCL and SDA low by clearing the corresponding LAT bits.
3. While keeping the LAT bits clear, configure SCL and SDA as inputs by setting their TRIS
bits.
*/
TRISBbits.TRISB0=0; //SET PINS AS OUTPUTS
TRISBbits.TRISB1=0;
PORTBbits.RB0 = 0;
PORTBbits.RB1 = 0;
TRISBbits.TRISB0=1; //SET PINS AS INPUTS
TRISBbits.TRISB1=1;
//////////////////////////////////////////////////Fin del Work Around////////////////////////////////////////////////////////////
CloseI2C();
OpenI2C(MASTER, SLEW_OFF);
SSPADD = 19; //100KHz con Xtal de 8MHz
//I2C 400Khz Los valores qeu funcionan para 100 Khz 129, para 400 Khz el valor es 29
//La formula para el calculo es SSPADD = ((Fosc/BitRate)/4)-1
}
void MyMsDelay(int ms){
while(ms--){
__delay_ms(1);
}
}
No es un OR exclusivo ??