##// END OF EJS Templates
Versión inicial de los bloques de comunicación para el módulo de procesamiento.
Versión inicial de los bloques de comunicación para el módulo de procesamiento.

File last commit:

r216:217
r219:220
Show More
powerEngine.c
286 lines | 5.4 KiB | text/x-c | CLexer
/*
* powerEngine.c
*
* Created on: Mar 23, 2015
* Author: shinobi
*/
#include "powerEngined.h"
#include "usi_i2c_slave.h"
#include <util/delay.h>
#include <avr/interrupt.h>
#define DQ_HIGH DQ_PORT |= (1<<DQ_BIT)
#define DQ_LOW DQ_PORT &= ~(1<<DQ_BIT)
#define DQ_INPUT DQ_DDR &= ~(1<<DQ_BIT)
#define DQ_OUTPUT DQ_DDR |= (1<<DQ_BIT)
#define DQ_READ ((DQ_PIN&(1<<DQ_BIT))!=0)?0x01:0x00
#define US (1000000.0/ F_CPU )
#define TM0_ON TCCR0B |=(0<<CS02)|(0<<CS01)|(1<<CS00)
#define TM0_OFF TCCR0B &= ~((1<<CS02)|(1<<CS01)|(1<<CS00))
#define TM1_ON TCCR1 |= (1<<CS13)|(1<<CS12)|(1<<CS11)|(1<<CS10)
#define TM1_OFF TCCR1 &= ~((1<<CS13)|(1<<CS12)|(1<<CS11)|(1<<CS10))
#define MAX_TM_CYCLES 15
volatile uint8_t presenced_flg = 0;
volatile uint8_t process_flg = 0;
volatile uint8_t tm_cycles = 0;
extern char* USI_Slave_register_buffer[];
/*!
* \fn write_0_signal
* \brief genera el simbolo que corresponde a '0' logico en el protocolo
* especificatdo en el datasheet del IC DS2438Z
* \see write_1_signal
* \see write_byte
*/
void write_0_signal(){
DQ_LOW;
_delay_us(65);
DQ_HIGH;
_delay_us(1);
}
/*!
* \fn write_1_signal
* \brief genera el simbolo que corresponde a '1' logico en el protocolo
* especificatdo en el datasheet del IC DS2438Z
* \see write_0_signal
* \see write_byte
*/
void write_1_signal(){
DQ_LOW;
_delay_us(10);
DQ_HIGH;
_delay_us(56);
}
/*!
* \fn write_byte
* \brief Escribe un byte por el puerto DQ
* \param byte El byte a escribir
* \see write_0_signal
* \see write_1_signal
*/
void write_byte(uint8_t byte){
uint8_t mask = 0x00;
while(mask!=0){
if((byte&mask)!=0){
write_1_signal();
}else{
write_0_signal();
}
mask = (uint8_t)(mask << 1);
}
}
/*!
* \fn write_bytes
* \brief Escribe "len" bytes por el puerto DQ
* \param pbytes Puntero a inicio de buffer que contiene los bytes
* \param len >Numero de bytes a escribir
* \see write_byte
*/
void write_bytes(uint8_t* pbytes,uint8_t len){
do{
len-=1;
write_byte(pbytes[len]);
}while(len>0);
}
/*!
* \fn read_signal
* \brief Lee un bit del puerto DQ
* \return '1' o '0'.
* \see read_byte
*/
uint8_t read_signal(){
uint8_t bit = 0;
DQ_LOW;
_delay_us(2);
DQ_HIGH;
DQ_INPUT;
_delay_us(8);
bit = DQ_READ;
_delay_us(55);
DQ_OUTPUT;
DQ_HIGH;
_delay_us(1);
return bit;
}
/*!
* \fn read_byte
* \brief Lee un byte de el puerto DQ
* \see read_signal
* \see read_bytes
*/
uint8_t read_byte(){
uint8_t shift = 0x00;
uint8_t byte = 0x00;
uint8_t bit= 0;
while(shift< 8){
bit = read_signal();
byte |= (bit<<shift);
shift++;
}
return byte;
}
/*!
* \fn read_bytes
* \brief Lee "len" bytes de el puerto DQ
* \param pbytes puntero a buffer, contendra los bytes leidos.
* \param len Numero de bytes a leer.
* \see read_byte
*/
void read_bytes(uint8_t* pbytes, uint8_t len){
do{
len-=1;
pbytes[len] = read_byte();
}while(len>0);
}
/*!
* \fn initialization
* \brief Inicia o reinicia al IC DS2438Z
*/
void initialization(){
TCNT0 = 0x0000;
presenced_flg = 0;
DQ_LOW;
_delay_us(490);
TM0_ON;
DQ_HIGH;
while(presenced_flg != 1){}
}
/*!
* \fn memory_read
* \brief Realiza la lectura de toda la memoria del IC DS2438Z
*/
void memory_read(uint8_t* pbytes, uint8_t page_addr){
uint8_t crc;
initialization();
write_byte(SKIP_ROM);
write_byte(READ_SP);
write_byte(page_addr);
read_bytes(pbytes,8);
crc = read_byte();
initialization();
}
/*!
* \fn convert
* \brief Inicia la conversion ADC de los parametros desados
* \param cmd CONVERT_T para iniciar la conversion de temperatura. CONVERT_V
* para iniciar la conversion de voltaje.
*/
void convert(uint8_t cmd){
uint8_t bit = 0;
initialization();
write_byte(SKIP_ROM);
write_byte(cmd);
do{
bit = read_signal();
}while(bit != 1);
initialization();
}
/*!
* \fn void send_data
* \brief Envia data al sistema enbebido por puerto twi
* \param pbytes Puntero a buffer de bytes a enviar.
* \param len Numero de bytes a enviar. Debe ser menor o igual a USI_SLAVE_REGISTER_COUNT.
*/
void send_data(uint8_t* pbytes, uint8_t len){
int i;
for(i=0;i<USI_SLAVE_REGISTER_COUNT;i++){
if(i<len){
USI_Slave_register_buffer[i]=(char)(pbytes[i]);
}else{
USI_Slave_register_buffer[i]='\0';
}
}
}
//usado para cronometrar la lectura del presence pulse
ISR(TIM0_COMPA_vect ){
TM0_OFF;
}
//detecta el nivel bajo. usado para detectar el presence pulse
ISR(PCINT0_vect){
uint16_t cnt;
if((PINB&(1<<PINB3))==0x00){
if((cnt>=60*US)&&(cnt<=240*US)){
presenced_flg=1;
}
}
}
ISR(TIM1_COMPB_vect){
tm_cycles++; // cuenta de 60 segundos
if(tm_cycles>=MAX_TM_CYCLES){
process_flg = 1;
tm_cycles=0;
}
}
int main(){
uint8_t pbytes[8];
// inicializa
USI_I2C_Init(I2C_SLAVE_ADDR);
cli();
// interrupcion externa
GIMSK |= _BV(PCIE); // Turn on Pin Change interrupt
PCMSK |= _BV(PCINT3); // Which pins are affected by the interrupt
// timer0 CTC con OCRA como top. Debe interrumpir en 250us luego de
// TM0_ON
TCCR0A = (1<<COM0A1)|(1<<COM0A0)|(1<<WGM01)|(0<<WGM00);
TCCR0B = (0<<WGM02);
TM0_OFF;
OCR0A = (uint8_t)(250*US);
// timer1 CTC TOP : OCR1C ; pre-scaler 16384
TCCR1 = (1<<COM1A1)|(1<<COM1A0);
TM1_OFF;
OCR1A = (uint8_t)(244*US);// x 15 ciclo x 16384 (pre-scaler)
//Activa interrupciones de timers
TIMSK |= (1<<OCIE1A)|(1<<OCIE0A);
presenced_flg=0;
sei();
do{
process_flg = 0;
convert(CONV_T);
convert(CONV_V);
memory_read(pbytes,PAGE_0);
send_data(pbytes,8);
while(!(process_flg==1)){};
}while(1==1);
return 0;
}