Created
November 28, 2013 02:58
-
-
Save pleonex/7686642 to your computer and use it in GitHub Desktop.
Ejercicio 6.3 de práctica 6 de la asignatura "Sistemas Electrónicos Digitales".
Ejemplo de uso de microcontrolador PIC con periféricos usando I2C y RS232.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/**************************************************** | |
** Ejercicio 6.3 - Práctica 6 - SED * | |
** * | |
** Programado por Benito Palacios Sánchez - 2013 * | |
****************************************************/ | |
#include "../../lib/18F4520.h" | |
#device ADC=16 | |
#fuses HS, WDT2048 | |
#use delay(clock=8MHZ, restart_wdt) | |
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, bits=8) | |
#include <ctype.h> | |
#include "../../lib/PCF8583.c" | |
#include "../../lib/2432.c" | |
#include "../../lib/FLOATEE.C" | |
#include "../../lib/LCDEasy.c" | |
#use fast_io(b) | |
#define LCD_COMMAND 0 | |
#define LCD_CLEAR 1 | |
#define LCD_HOME 2 | |
#define ADC_MAX 65535 | |
#define VOL_MAX 5 | |
#define EEPROM_LENGTH 0x0FFF | |
#define BLOCK_LENGTH 0x000F | |
#define N_BLOCKS EEPROM_LENGTH / BLOCK_LENGTH | |
void procesa_comando(); | |
void muestra_bytes_pos(); | |
void muestra_bytes_long(); | |
void muestra_byte(int16 dir); | |
void muestra_bloques_hora(); | |
void muestra_bloques_fecha(); | |
void muestra_bloques(); | |
void muestra_datos_pos(); | |
void muestra_datos_long(); | |
void muestra_dato(int16 dir); | |
void muestra_media_poten(); | |
void muestra_comandos(); | |
int8 hex2int8(char c); | |
int16 hex2int16(char* hex); | |
// Variables de comando | |
char Comando[5]; | |
char Argumentos[2][9]; | |
int8 Idx_args = 0; | |
int8 Idx_escri = 0; | |
// Para saber si en esa posición hay datos o no. | |
int16 ultima_eepos = 0; | |
/* | |
Mediante el uso de interrupciones se puede despertar al PIC de su modo de bajo | |
consumo de forma que se puede obtener información en cualquier momento y no | |
hay que esperar a que el WDT lo despierte. | |
*/ | |
#INT_RDA | |
void en_caracter_recibido() { | |
char c = getc(); | |
if (c == '-') { | |
// Inicio del comando. Inicializa | |
memset(Comando, '\0', 5); | |
memset(Argumentos[0], '\0', 9); | |
memset(Argumentos[1], '\0', 9); | |
Idx_args = 0; | |
Idx_escri = 0; | |
} else if (c == ' ') { | |
// Argumento siguiente | |
Idx_escri = 0; | |
Idx_args++; | |
} else if (c == '\r') { | |
// Ejecuta el comando | |
procesa_comando(); | |
} else if (c == '\n') { | |
// No hace nada, pues se envía junto a \r que ya se procesó | |
} else if (Idx_args == 0) { | |
// Escribiendo comando... | |
Comando[Idx_escri++] = c; | |
} else if (Idx_args == 1 || Idx_args == 2) { | |
// Escribiendo argumento... | |
Argumentos[Idx_args - 1][Idx_escri++] = c; | |
} | |
} | |
void procesa_comando() { | |
printf("Comando: %s | Arg0: %s | Arg1: %s\r\n", Comando, Argumentos[0], | |
Argumentos[1]); | |
switch (Comando) { | |
case "h": muestra_comandos(); break; | |
case "rsb": muestra_bloques(); break; | |
case "rsd": muestra_bytes_long(); break; | |
case "rsdi": muestra_datos_long(); break; | |
case "rsp": muestra_bytes_pos(); break; | |
case "rspi": muestra_datos_pos(); break; | |
case "rh": muestra_bloques_hora(); break; | |
case "rf": muestra_bloques_fecha(); break; | |
case "gmp": muestra_media_poten(); break; | |
default: printf("Comando no reconocido.\r\n"); | |
} | |
} | |
void muestra_bytes_pos() { | |
int16 pos1 = hex2int16(Argumentos[0]); | |
int16 pos2 = hex2int16(Argumentos[1]); | |
for ( ; pos1 <= pos2 && pos1 < ultima_eepos; pos1++) | |
muestra_byte(pos1); | |
} | |
void muestra_bytes_long() { | |
int16 dir = hex2int16(Argumentos[0]); | |
int16 len = hex2int16(Argumentos[1]); | |
int16 i; | |
for (i = 0; i < len && dir + i < ultima_eepos; i++) | |
muestra_byte(dir + i); | |
} | |
void muestra_byte(int16 dir) { | |
printf("%4X: %2X\r\n", dir, read_ext_eeprom(dir)); | |
} | |
void muestra_bloques_hora() { | |
int8 hora1 = (Argumentos[0][0] - '0') * 10 + (Argumentos[0][1] - '0'); | |
int8 min1 = (Argumentos[0][3] - '0') * 10 + (Argumentos[0][4] - '0'); | |
int8 seg1 = (Argumentos[0][6] - '0') * 10 + (Argumentos[0][7] - '0'); | |
int8 hora2 = (Argumentos[1][0] - '0') * 10 + (Argumentos[1][1] - '0'); | |
int8 min2 = (Argumentos[1][3] - '0') * 10 + (Argumentos[1][4] - '0'); | |
int8 seg2 = (Argumentos[1][6] - '0') * 10 + (Argumentos[1][7] - '0'); | |
int8 horat, mint, segt; | |
int16 pos, i; | |
for (pos = 11; pos < ultima_eepos; pos += BLOCK_LENGTH) { | |
horat = read_ext_eeprom(pos); | |
mint = read_ext_eeprom(pos + 1); | |
segt = read_ext_eeprom(pos + 2); | |
if ((hora1 < horat) || ((hora1 == horat) && (min1 < mint)) || | |
((hora1 == horat) && (min1 == mint) && (seg1 <= segt))) { | |
break; | |
} | |
} | |
for ( ; pos < ultima_eepos; pos += BLOCK_LENGTH) { | |
for (i = pos - 11; i < pos - 11 + BLOCK_LENGTH && i < ultima_eepos; i++) | |
muestra_dato(i); | |
horat = read_ext_eeprom(pos); | |
mint = read_ext_eeprom(pos + 1); | |
segt = read_ext_eeprom(pos + 2); | |
if ((hora2 < horat) || ((hora2 == horat) && (min2 < mint)) || | |
((hora2 == horat) && (min2 == mint) && (seg2 <= segt))) { | |
break; | |
} | |
} | |
} | |
void muestra_bloques_fecha() { | |
int8 dia1 = (Argumentos[0][0] - '0') * 10 + (Argumentos[0][1] - '0'); | |
int8 mes1 = (Argumentos[0][3] - '0') * 10 + (Argumentos[0][4] - '0'); | |
int8 anio1 = (Argumentos[0][6] - '0') * 10 + (Argumentos[0][7] - '0'); | |
int8 dia2 = (Argumentos[1][0] - '0') * 10 + (Argumentos[1][1] - '0'); | |
int8 mes2 = (Argumentos[1][3] - '0') * 10 + (Argumentos[1][4] - '0'); | |
int8 anio2 = (Argumentos[1][6] - '0') * 10 + (Argumentos[1][7] - '0'); | |
int8 diat, mest, aniot; | |
int16 pos, i; | |
for (pos = 8; pos < ultima_eepos; pos += BLOCK_LENGTH) { | |
aniot = read_ext_eeprom(pos); | |
mest = read_ext_eeprom(pos + 1); | |
diat = read_ext_eeprom(pos + 2); | |
if ((anio1 < aniot) || ((anio1 == aniot) && (mes1 < mest)) || | |
((anio1 == aniot) && (mes1 == mest) && (dia1 <= diat))) { | |
break; | |
} | |
} | |
for ( ; pos < ultima_eepos; pos += BLOCK_LENGTH) { | |
for (i = pos - 8; i < pos - 8 + BLOCK_LENGTH && i < ultima_eepos; i++) | |
muestra_dato(i); | |
aniot = read_ext_eeprom(pos); | |
mest = read_ext_eeprom(pos + 1); | |
diat = read_ext_eeprom(pos + 2); | |
if ((anio2 < aniot) || ((anio2 == aniot) && (mes2 < mest)) || | |
((anio2 == aniot) && (mes2 == mest) && (dia2 <= diat))) { | |
break; | |
} | |
} | |
} | |
void muestra_bloques() { | |
int16 pos1 = hex2int16(Argumentos[0]) * BLOCK_LENGTH; | |
int16 pos2 = hex2int16(Argumentos[1]) * BLOCK_LENGTH + BLOCK_LENGTH; | |
for ( ; pos1 < pos2 && pos1 < ultima_eepos; pos1++) | |
muestra_dato(pos1); | |
} | |
void muestra_datos_pos() { | |
int16 pos1 = hex2int16(Argumentos[0]); | |
int16 pos2 = hex2int16(Argumentos[1]); | |
for ( ; pos1 <= pos2 && pos1 < ultima_eepos; pos1++) | |
muestra_dato(pos1); | |
} | |
void muestra_datos_long() { | |
int16 dir = hex2int16(Argumentos[0]); | |
int16 len = hex2int16(Argumentos[1]); | |
int16 i; | |
for (i = 0; i < len && dir + i < ultima_eepos; i++) | |
muestra_dato(dir + i); | |
} | |
void muestra_dato(int16 dir) { | |
int8 b_pos = dir % BLOCK_LENGTH; | |
switch (b_pos) { | |
case 0: | |
printf("%4X: Voltaje 1 -> %.2f\r\n", dir, read_float_ext_eeprom(dir)); | |
break; | |
case 1: | |
case 2: | |
case 3: | |
break; // Si no es desde la posición 0, no tienen sentido | |
case 4: | |
printf("%4X: Voltaje 2 -> %.2f\r\n", dir, read_float_ext_eeprom(dir)); | |
break; | |
case 5: | |
case 6: | |
case 7: | |
break; // Si no es desde la posición 4, no tienen sentido | |
case 8: | |
printf("%4X: Anio 20%u\r\n", dir, read_ext_eeprom(dir)); | |
break; | |
case 9: | |
printf("%4X: Mes %u\r\n", dir, read_ext_eeprom(dir)); | |
break; | |
case 10: | |
printf("%4X: Dia %u\r\n", dir, read_ext_eeprom(dir)); | |
break; | |
case 11: | |
printf("%4X: Hora %u\r\n", dir, read_ext_eeprom(dir)); | |
break; | |
case 12: | |
printf("%4X: Minutos %u\r\n", dir, read_ext_eeprom(dir)); | |
break; | |
case 13: | |
printf("%4X: Segundos %u\r\n", dir, read_ext_eeprom(dir)); | |
break; | |
case 14: | |
printf("%4X: Dia de la semana %s\r\n", dir, | |
weekday_names[read_ext_eeprom(dir)]); | |
break; | |
} | |
} | |
void muestra_media_poten() { | |
int8 ult_bloque = ultima_eepos / BLOCK_LENGTH; | |
int16 i; | |
float suma1 = 0; | |
float suma2 = 0; | |
for (i = 0; i < ult_bloque; i++) { | |
suma1 += read_float_ext_eeprom(i * BLOCK_LENGTH); | |
suma2 += read_float_ext_eeprom(i * BLOCK_LENGTH + 4); | |
} | |
printf("Media voltaje 1: %.2f\r\n", suma1 / ult_bloque); | |
printf("Media voltaje 2: %.2f\r\n", suma2 / ult_bloque); | |
} | |
void muestra_comandos() { | |
printf("| Comandos |: \r\n"); | |
printf(" -h Muestra comandos disponibles. \r\n"); | |
printf(" -rsb ni n Lee secuencialmente 'n' bloques de\r\n"); | |
printf(" datos partiendo del bloque 'ni'. \r\n"); | |
printf(" -rsd p l Lee secuencialmente 'l' bytes de \r\n"); | |
printf(" datos partiendo de 'p'. \r\n"); | |
printf(" -rsdi p l Igual que '-rsd' pero interpreta \r\n"); | |
printf(" (si es posible) los datos. \r\n"); | |
printf(" -rsp p1 p2 Lee secuencialmente todos los \r\n"); | |
printf(" datos entre 'p1' y 'p2' (p2 > p1).\r\n"); | |
printf(" -rspi p1 p2 Igual que '-rsp' pero interpreta \r\n"); | |
printf(" (si es posible) los datos. \r\n"); | |
printf(" -rh h1 h2 Lee bloques entre las horas 'h1' y\r\n"); | |
printf(" 'h2' (h2 > h1). Formato hh:mm:ss \r\n"); | |
printf(" -rf f1 f2 Lee bloques entre las fechas 'f1' \r\n"); | |
printf(" y 'f2' (f2 > f1). Formato dd/mm/aa\r\n"); | |
printf(" -gmp Visualiza la media de todos los \r\n"); | |
printf(" valores de potenciometro. \r\n"); | |
printf("NOTA: Para 'rsb', 'rsd', 'rsdi', 'rsp' y 'rspi';\r\n"); | |
printf("el formato de sus argumentos es XXXX (hex). \r\n"); | |
} | |
void main() { | |
char weekday[10]; | |
date_time_t dt; | |
int16 lectura; | |
float volt1_out; | |
float volt2_out; | |
int16 ee_pos = 0; | |
// Configuración del módulo reloj | |
PCF8583_init(); | |
// Establece la hora actual | |
dt.year = 13; | |
dt.month = 11; | |
dt.day = 28; | |
dt.hours = 03; | |
dt.minutes = 15; | |
dt.seconds = 43; | |
dt.weekday = 4; | |
PCF8583_set_datetime(&dt); | |
// Configuración de conversor A-DC | |
setup_adc_ports(AN0_TO_AN3); | |
setup_adc(ADC_CLOCK_DIV_8); | |
// Configuración de interrupción | |
enable_interrupts(INT_RDA); | |
enable_interrupts(GLOBAL); | |
// Configuración de pantalla LCD | |
lcd_init(); | |
lcd_send_byte(LCD_COMMAND, LCD_CLEAR); | |
// Mensaje inicial de bienvenida | |
printf(" Bienvenido al ejercicio 6.3 \r\n"); | |
printf("Cada 8 seg. obtendra la hora en la pantalla LCD \r\n"); | |
printf("junto al valor de los potenciometros. Ademas, \r\n"); | |
printf("dispone de comandos extras para recibir mediante\r\n"); | |
printf("RS232 informacion guardada en la EEPROM externa.\r\n"); | |
muestra_comandos(); | |
while (true) { | |
setup_wdt(WDT_ON); | |
sleep(); | |
setup_wdt(WDT_OFF); | |
lcd_send_byte(LCD_COMMAND, LCD_CLEAR); | |
// Lee y muestra la fecha y hora | |
PCF8583_read_datetime(&dt); | |
strcpy(weekday, weekday_names[dt.weekday]); | |
printf(lcd_putc, "%s, %2u/%2u/%2u \nHora: %u:%2u:%2u ", | |
weekday, dt.day, dt.month, dt.year, | |
dt.hours, dt.minutes, dt.seconds); | |
delay_ms(1000); | |
// Obtiene y muestra el valor de los potenciómetros | |
set_adc_channel(2); | |
delay_us(10); | |
lectura = read_adc(); | |
volt1_out = (float)lectura / ADC_MAX * VOL_MAX; | |
set_adc_channel(3); | |
delay_us(10); | |
lectura = read_adc(); | |
volt2_out = (float)lectura / ADC_MAX * VOL_MAX; | |
lcd_send_byte(LCD_COMMAND, LCD_CLEAR); | |
printf(lcd_putc, "VOLT1: %.2f\nVOLT2: %.2f", volt1_out, volt2_out); | |
// Los guarda en la EEPROM en bloque consecutivo. De esta forma dada una | |
// dirección de memoria se puede saber qué tipo de dato hay grabado. | |
if (ee_pos + BLOCK_LENGTH > EEPROM_LENGTH) | |
ee_pos = 0; | |
write_float_ext_eeprom(ee_pos, volt1_out); | |
ee_pos += 4; | |
write_float_ext_eeprom(ee_pos, volt2_out); | |
ee_pos += 4; | |
write_ext_eeprom(ee_pos++, dt.year); | |
write_ext_eeprom(ee_pos++, dt.month); | |
write_ext_eeprom(ee_pos++, dt.day); | |
write_ext_eeprom(ee_pos++, dt.hours); | |
write_ext_eeprom(ee_pos++, dt.minutes); | |
write_ext_eeprom(ee_pos++, dt.seconds); | |
write_ext_eeprom(ee_pos++, dt.weekday); | |
// Actualiza la variable que contiene la última posición escrita. | |
if (ee_pos > ultima_eepos) | |
ultima_eepos = ee_pos; | |
} | |
} | |
int16 hex2int16(char* hex) { | |
int16 valor = 0; | |
int8 i = 0; | |
int8 j = 12; | |
while (hex[i] != '\0') { | |
valor |= (int16)hex2int8(hex[i]) << j; | |
i++; | |
j -= 4; | |
} | |
return valor; | |
} | |
int8 hex2int8(char hex) { | |
hex = toupper(hex); | |
if (hex >= '0' && hex <= '9') | |
return hex - '0'; | |
else if (hex >= 'A' && hex <= 'F') | |
return hex - 'A' + 10; | |
else | |
return 0xFF; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment