| |
PROYECTOS
: Analizador Lógico
|
|
|
|
Analizador Lógico de 3 canales con un PIC
18F4550 (RRLogicalAnalyzer)
|
|
|
|
(Ver el Histórico de
realización) donde detallo, día a día, lo que voy realizando con este
proyecto ... |
|
|
Descripción:
|
|
La conclusión de este proyecto
(siempre provisional) ya está disponible. Insisto en recomendar ver el
Histórico de realización
ya que es en él donde podéis ver todo lo realizado y cómo se ha llegado
hasta este estado final. |
|
|
|
 |
El Firmware del PIC 18F4550 y el Software del PC hablan el mismo idioma
...
El PIC dispone de una recepción de comandos de dos tipos:
1.- Comandos destinados a volcar información a un Monitor RS232 Así
puedo analizar los datos numéricamente si necesidad de Soft alguno (mas
allá de un Siow, Hyperterminal o similar) Este grupo de comandos dispara
el envío de la información de forma "amigable", tabulada y con cabeceras
de explicación de qué es lo que está enviado. Le llamo "friendly_trans"
2.- Comandos destinados a enviar la información "formateada" al Soft del
PC en la que se define una trama con: inicio de transmisión, datos
encapsulados con inicio y fin de cada "churrete" y fin de transmisión.
Este grupo de comandos dispara el envío de la información de forma
sistemática con una estructura definida, fácil de procesar por el Soft del
PC. Le llamo "hardy_trans".
Ejemplo de recepción de los mismos datos en formatos "amigable" y "duro"
...
Con el Monitor Siow de CCS C:
Y con el RRLOGICANALYZER.EXE del PC que ya recibe correctamente los datos
recopilados por el PIC y es capaz de mostrármelos ... listos para dibujarlos. |
1º Lista de comandos PC -> PIC
COMMAND_RESET = 'R';
COMMAND_FIRMWARE = 'W';
COMMAND_DATA = 'X';
COMMAND_CONFIG = 'C';
COMMAND_CONFIG1 = '1';
COMMAND_CONFIG2 = '2';
COMMAND_CONFIG3 = '3';
2º Comando de ACK (Acknowledge Receipt of a Packet) PIC -> PC
char const RESPONSE_ACK = '^';
printf("^\r\n");
3º Estructura de transmisión datos PIC -> PC
CI (Carácter de Inicio) = '{'
CF (Carácer de Finalizacion) = '}'
Estructura de envío : n * (CI + m * (data) + CF + '\r\n') + ACK
4º Estructura de datos de configuración, 1 byte:
Codificacion en Delphi:
c.Compreso := 0;
if c.Active then c.Compreso := c.Compreso + 128;
if c.Raising then c.Compreso := c.Compreso + 64;
if c.Falling then c.Compreso := c.Compreso + 32;
if c.Trigger then c.Compreso := c.Compreso + 16;
if c.Invert then c.Compreso := c.Compreso + 8;
Decodificacion en CSS C por Bit
// Habilito Canal 1
if(bit_test(C1_SETTINGS,7)==1){
enable_interrupts(int_ext);
}
...
// Configuro Channel1 Flanco inicial
if(bit_test(C1_SETTINGS,7)==1){
if(bit_test(C1_SETTINGS,5)==1){
fedge1=0;
ext_int_edge(0,H_TO_L);
}
if(bit_test(C1_SETTINGS,6)==1){
fedge1=1;
ext_int_edge(0,L_TO_H);
}
}
y 5º Estructura de datos de muestreo
CI + NumPulso + Canal + nRTCC raise + Timer raise + nRTCC fall + Timer
fall + CF + "\r\n"
Emisión en CSS C:
for(i=0;i<NMUESTRAS;i++){
printf("{ %3u %1u %5lu %5lu %1u %5lu %5lu }\r\n",i+1,tUpC[ i ],tUpI[ i ],tUpT[
i ],tDownC[ i ],tDownI[ i ],tDownT[ i ]);
}
delay_ms(10);
ack_trans();
===========================================================
E j e m p l o s
Ejemplo: Orden de "envíame" la versión del firmware actual.
Al recibir el PIC el comando 'W' envía el string "{1.2.0}[13][10]^\r\n"
Ejemplo : Conversación completa PC <-> PIC comentada
Transmit: W Receive: {1.2.0}[13][10]^[13][10] Pregunta firmare y recibe
firmware
Transmit: C Receive: { 177 209 209 }[13][10]^[13][10] Pregunta
configuración y recibe settings de los tres canales
Transmit: 1 Receive: ^[13][10] Envía "prepárate para recibir
configuración
canal 1" recibe ACK
Transmit: [177] Receive: ^[13][10] Envía "configuración canal 1" recibe
ACK
Transmit: 2 Receive: ^[13][10] Envía "prepárate para recibir
configuración
canal 2" recibe ACK
Transmit: [177] Receive: ^[13][10] Envía "configuración canal 2" recibe
ACK
Transmit: 3 Receive: ^[13][10] Envía "prepárate para recibir
configuración
canal 2" recibe ACK
Transmit: [177] Receive: ^[13][10] Envía "configuración canal 3" recibe
ACK
Transmit: R Receive: ^[13][10] Envía "reseteate, limpia muestreos
anteriores y reconfigúrate" recibe ACK
Transmit: C Receive: { 177 177 177 }[13][10]^[13][10] Envía "dame
configuraciones" recibe configuraciones de los tres canales y ACK
Transmit: X
Receive: { 1 1 11 32930 1 0 8 }[13][10] Envía "dame muestreos" y recibe
tabla de datos
{ 2 1 46 52262 1 37 43339 }[13][10]
{ 3 0 0 0 0 0 0 }[13][10]
{ 4 0 0 0 0 0 0 }[13][10]
{ 5 0 0 0 0 0 0 }[13][10]
...
{ 65 0 0 0 0 0 0 }[13][10]
^[13][10]
Nota 1: Todo el código completo al final de este proyecto.
Nota 2: Todo este control desarrollado para comunicar con un Soft
específico que dibuje los pulsos en pantalla está disponible en el
Firmware del 18F4550 para ser accedido numéricamente desde un simple
terminal serie (Siow, Hyperterminal ... etc) estilo Telnet.
|
|
|
|
 |
| |
Recursos:
|
|
Descargar Firmware para el
18F4550 y Software para el PC del RRLogicalAnalyzer (ZIP 667 Kbytes) |
|
|
|
|
|
|
|
|
| |
Firmware para el 18F4550 |
|
| |
// RR Logical
Analyzer v.1.2.2d
#include <18f4550.h>
#fuses HS,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOPBADEN
#use delay(clock=20000000)
#use rs232(baud=19200, xmit=PIN_C6, rcv=PIN_C7)
int const NMUESTRAS=192;
char const SOFT_COMMAND_RESET = 'r';
char const SOFT_COMMAND_FIRMWARE = 'w';
char const SOFT_COMMAND_DATA = 'x';
char const SOFT_COMMAND_CONFIG = 'c';
char const SOFT_COMMAND_EEPROM = 'e';
char const HARD_COMMAND_RESET = 'R';
char const HARD_COMMAND_FIRMWARE = 'W';
char const HARD_COMMAND_DATA = 'X';
char const HARD_COMMAND_CONFIG = 'C';
char const HARD_COMMAND_CONFIG1 = '1';
char const HARD_COMMAND_CONFIG2 = '2';
char const HARD_COMMAND_CONFIG3 = '3';
char const RESPONSE_ACK = '^';
int const DIR_C1_SETTINGS = 0;
int const DIR_C2_SETTINGS = 1;
int const DIR_C3_SETTINGS = 2;
// Variables en RAM /////////////////////////////////////////////////
char Version[]="1.2.2d\0";
char CharRcv=0;
char Command=0;
int i=0x00;
int uTimeUp=0;
int uTimeDown=0;
int nTintext=0;
int tUpC[NMUESTRAS];
long tUpT[NMUESTRAS];
long tUpI[NMUESTRAS];
int tDownC[NMUESTRAS];
long tDownT[NMUESTRAS];
long tDownI[NMUESTRAS];
long nTimer1Overflow;
int1 fedge1=0;
int1 fedge2=0;
int1 fedge3=0;
int1 flag_recibe_config1=0;
int1 flag_recibe_config2=0;
int1 flag_recibe_config3=0;
// Settings x CANAL /////////////////////////////////////////////////
int C1_Settings= 0;
int1 C1_Active = 0;
int1 C1_Raising = 0;
int1 C1_Falling = 0;
int1 C1_Trigger = 0;
int1 C1_Invert = 0;
int C2_Settings= 0;
int1 C2_Active = 0;
int1 C2_Raising = 0;
int1 C2_Falling = 0;
int1 C2_Trigger = 0;
int1 C2_Invert = 0;
int C3_Settings= 0;
int1 C3_Active = 0;
int1 C3_Raising = 0;
int1 C3_Falling = 0;
int1 C3_Trigger = 0;
int1 C3_Invert = 0;
// Definicion de funciones //////////////////////////////////////////
void menu_trans(void);
void friendly_eeprom_trans(void);
void friendly_firmware_trans(void);
void hardy_firmware_trans(void);
void friendly_data_trans(void);
void hardy_data_trans(void);
void friendly_config_trans(void);
void hardy_config_trans(void);
void on_reset(int1 verbose);
void ack_trans(void);
void set_channel1(void);
void set_channel2(void);
void set_channel3(void);
void config_channels(int1 verbose);
#int_rda
void rda_handler() {
CharRcv=0;
if(kbhit()){
CharRcv=getc();
if(CharRcv!=0){
Command=CharRcv;
}
}
}
#int_ext
ext_handler() {
long t;
long n;
disable_interrupts(int_timer1);
disable_interrupts(int_ext1);
disable_interrupts(int_ext2);
++nTintext;
if(nTintext==1){
set_timer1(0);
nTimer1Overflow=0;
}
n=nTimer1Overflow;
t=get_timer1();
if(fedge1==0){
ext_int_edge(0,L_TO_H);
tDownI[uTimeDown]=n;
tDownT[uTimeDown]=t;
tDownC[uTimeDown]=1;
++uTimeDown;
}else
{
ext_int_edge(0,H_TO_L);
tUpI[uTimeUp]=n;
tUpT[uTimeUp]=t;
tUpC[uTimeUp]=1;
++uTimeUp;
}
++fedge1;
if(bit_test(C2_SETTINGS,7)==1){
enable_interrupts(int_ext1);
}
if(bit_test(C3_SETTINGS,7)==1){
enable_interrupts(int_ext2);
}
enable_interrupts(int_timer1);
}
#int_ext1
ext1_handler() {
long t;
long n;
disable_interrupts(int_timer1);
disable_interrupts(int_ext);
disable_interrupts(int_ext2);
++nTintext;
if(nTintext==1){
set_timer1(0);
nTimer1Overflow=0;
}
n=nTimer1Overflow;
t=get_timer1();
if(fedge2==0){
ext_int_edge(1,L_TO_H);
tDownI[uTimeDown]=n;
tDownT[uTimeDown]=t;
tDownC[uTimeDown]=2;
++uTimeDown;
}else
{
ext_int_edge(1,H_TO_L);
tUpI[uTimeUp]=n;
tUpT[uTimeUp]=t;
tUpC[uTimeUp]=2;
++uTimeUp;
}
++fedge2;
if(bit_test(C1_SETTINGS,7)==1){
enable_interrupts(int_ext);
}
if(bit_test(C3_SETTINGS,7)==1){
enable_interrupts(int_ext2);
}
enable_interrupts(int_timer1);
}
#int_ext2
ext2_handler() {
long t;
long n;
disable_interrupts(int_timer1);
disable_interrupts(int_ext);
disable_interrupts(int_ext1);
++nTintext;
if(nTintext==1){
set_timer1(0);
nTimer1Overflow=0;
}
n=nTimer1Overflow;
t=get_timer1();
if(fedge3==0){
ext_int_edge(2,L_TO_H);
tDownI[uTimeDown]=n;
tDownT[uTimeDown]=t;
tDownC[uTimeDown]=3;
++uTimeDown;
}else
{
ext_int_edge(2,H_TO_L);
tUpI[uTimeUp]=n;
tUpT[uTimeUp]=t;
tUpC[uTimeUp]=3;
++uTimeUp;
}
++fedge3;
if(bit_test(C1_SETTINGS,7)==1){
enable_interrupts(int_ext);
}
if(bit_test(C2_SETTINGS,7)==1){
enable_interrupts(int_ext1);
}
enable_interrupts(int_timer1);
}
#int_timer1
timer1_handler(){
++nTimer1Overflow;
}
// ON_RESET /////////////////////////////////////////////////////////
void on_reset(int1 verbose){
disable_interrupts(global);
disable_interrupts(int_timer1);
disable_interrupts(int_rda);
disable_interrupts(int_ext);
disable_interrupts(int_ext1);
disable_interrupts(int_ext2);
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_spi(FALSE);
setup_psp(PSP_DISABLED);
setup_counters(RTCC_INTERNAL,RTCC_DIV_2);
setup_timer_0(RTCC_OFF);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
setup_timer_2(T2_DISABLED,0,1);
setup_timer_3(T3_DISABLED);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
port_b_pullups(FALSE);
set_tris_b(0b00000111);
for(i=0;i<NMUESTRAS;i++){ tUpT[i]=0; tUpI[i]=0; tUpC[i]=0; tDownT[i]=0;
tDownI[i]=0; tDownC[i]=0;}
nTintext=0;
uTimeUp=0;
uTimeDown=0;
flag_recibe_config1=0;
flag_recibe_config2=0;
flag_recibe_config3=0;
config_channels(verbose);
delay_ms(100);
// Habilito Canal 1
if(bit_test(C1_SETTINGS,7)==1){
enable_interrupts(int_ext);
if(verbose){ printf("\r\nint_ext enabled\r\n");}
}
// Habilito Canal 2
if(bit_test(C2_SETTINGS,7)==1){
enable_interrupts(int_ext1);
if(verbose){ printf("\r\nint_ext1 enabled\r\n");}
}
// Habilito Canal 3
if(bit_test(C3_SETTINGS,7)==1){
enable_interrupts(int_ext2);
if(verbose){ printf("\r\nint_ext2 enabled\r\n");}
}
// Habilito Recepción RS232
enable_interrupts(int_rda);
// Habilito Interrupciones Global
enable_interrupts(global);
}
// MAIN //////////////////////////////////////////////////////////////////
void main() {
on_reset(0);
do{
if(Command!=0){
// Accepta byte de configuracion para Channel 1
if(flag_recibe_config1==1){
set_channel1();
}
// Accepta byte de configuracion para Channel 2
if(flag_recibe_config2==1){
set_channel2();
}
// Accepta byte de configuracion para Channel 3
if(flag_recibe_config3==1){
set_channel3();
}
// Procesa cxommandos
switch(Command){
// Commands Telnet - SOFT COMMANDS ---------------------
case '?': menu_trans();
break;
case SOFT_COMMAND_RESET :
on_reset(1); // Reset
break;
case SOFT_COMMAND_FIRMWARE:
friendly_firmware_trans(); // Send Firmaware
break;
case SOFT_COMMAND_DATA :
friendly_data_trans(); // Send Data
break;
case SOFT_COMMAND_CONFIG :
friendly_config_trans(); // Send Config
break;
case SOFT_COMMAND_EEPROM :
friendly_eeprom_trans(); // Send EEPROM
break;
// Commands Soft PC - HARD COMMANDS ---------------------
case HARD_COMMAND_RESET :
on_reset(0); // Reset
ack_trans();
break;
case HARD_COMMAND_FIRMWARE:
hardy_firmware_trans(); // Send Firmaware
break;
case HARD_COMMAND_DATA :
hardy_data_trans(); // Send Data
break;
case HARD_COMMAND_CONFIG :
hardy_config_trans(); // Send Config
break;
case HARD_COMMAND_CONFIG1 : // Atento : siguiente recepción de Cfg Channel 1
flag_recibe_config1=1;
ack_trans();
break;
case HARD_COMMAND_CONFIG2 : // Atento : siguiente recepción de Cfg Channel 2
flag_recibe_config2=1;
ack_trans();
break;
case HARD_COMMAND_CONFIG3 : // Atento : siguiente recepción de Cfg Channel 3
flag_recibe_config3=1;
ack_trans();
break;
}
Command=0;
}
} while (TRUE);
}
// menu_trans ///////////////////////////////////////////////////////
void menu_trans(void){
friendly_firmware_trans();
printf("Telnet format:\r\n\n");
printf(" %c reset tables\r\n", SOFT_COMMAND_RESET);
printf(" %c version firmware\r\n", SOFT_COMMAND_FIRMWARE);
printf(" %c config transmit\r\n", SOFT_COMMAND_CONFIG);
printf(" %c data transmit\r\n", SOFT_COMMAND_DATA);
printf(" %c eeprom transmit\r\n", SOFT_COMMAND_EEPROM);
printf("\r\n");
printf("Hardware format:\r\n\n");
printf(" %c reset tables\r\n", HARD_COMMAND_RESET);
printf(" %c version firmware\r\n", HARD_COMMAND_FIRMWARE);
printf(" %c data transmit\r\n", HARD_COMMAND_DATA);
printf(" %c config transmit\r\n", HARD_COMMAND_CONFIG);
printf(" %cb config Channel1\r\n", HARD_COMMAND_CONFIG1);
printf(" %cb config Channel2\r\n", HARD_COMMAND_CONFIG2);
printf(" %cb config Channel3\r\n", HARD_COMMAND_CONFIG3);
printf("\r\n");
}
// Set Canal ////////////////////////////////////////////////////////
void set_channel1(void){
flag_recibe_config1=0;
C1_Settings=Command;
Command=0;
write_eeprom(DIR_C1_SETTINGS,C1_SETTINGS);
delay_ms(10);
ack_trans();
}
void set_channel2(void){
flag_recibe_config2=0;
C2_Settings=Command;
Command=0;
write_eeprom(DIR_C2_SETTINGS,C2_SETTINGS);
delay_ms(10);
ack_trans();
}
void set_channel3(void){
flag_recibe_config3=0;
C3_Settings=Command;
Command=0;
write_eeprom(DIR_C3_SETTINGS,C3_SETTINGS);
delay_ms(10);
ack_trans();
}
void config_channels(int1 verbose){
// Recupero configuracion desde la EEPROM
C1_SETTINGS = read_eeprom(DIR_C1_SETTINGS);
C2_SETTINGS = read_eeprom(DIR_C2_SETTINGS);
C3_SETTINGS = read_eeprom(DIR_C3_SETTINGS);
if(verbose){ printf("\r\Config 1=%u 2=%u 3=%u\r\n",C1_SETTINGS,C2_SETTINGS,C3_SETTINGS);}
// Configuro Channel1 Flanco inicial
if(bit_test(C1_SETTINGS,7)==1){
if(bit_test(C1_SETTINGS,5)==1){
fedge1=0;
ext_int_edge(0,H_TO_L);
if(verbose){ printf("\r\nint_ext 0 H_to_L\r\n");}
}
if(bit_test(C1_SETTINGS,6)==1){
fedge1=1;
ext_int_edge(0,L_TO_H);
if(verbose){ printf("\r\nint_ext 1 L_to_H\r\n");}
}
}
// Configuro Channel2 Flanco inicial
if(bit_test(C2_SETTINGS,7)==1){
if(bit_test(C2_SETTINGS,5)==1){
fedge2=0;
ext_int_edge(1,H_TO_L);
if(verbose){ printf("\r\nint_ext1 0 H_to_L\r\n");}
}
if(bit_test(C2_SETTINGS,6)==1){
fedge2=1;
ext_int_edge(1,L_TO_H);
if(verbose){ printf("\r\nint_ext1 1 L_to_H\r\n");}
}
}
// Configuro Channel3 Flanco inicial
if(bit_test(C3_SETTINGS,7)==1){
if(bit_test(C3_SETTINGS,5)==1){
fedge3=0;
ext_int_edge(2,H_TO_L);
if(verbose){ printf("\r\nint_ext2 0 H_to_L\r\n");}
}
if(bit_test(C3_SETTINGS,6)==1){
fedge3=1;
ext_int_edge(2,L_TO_H);
if(verbose){ printf("\r\nint_ext2 1 L_to_H\r\n");}
}
}
}
// ack_trans ////////////////////////////////////////////////////////
void ack_trans(void){
printf("%c\r\n",RESPONSE_ACK);
}
// eeprom_trans /////////////////////////////////////////////////////
void friendly_eeprom_trans(void){
int i,j,u;
printf("\r\n");
for(i=0;i<16;i++) printf("%X ",i);
printf("\r\n");
for(i=0;i<16;i++) printf("== ");
printf("\r\n");
j=0;
for(i=0;i<255;i++){
u=read_eeprom(i);
printf("%X ",u);
if(++j>15){
j=0;
printf("\r\n");
}
}
u=read_eeprom(255);
printf("%X ",u);
printf("\r\n\r\n");
}
// firmware_trans ///////////////////////////////////////////////////
void friendly_firmware_trans(void){
printf("\r\nLogical Analyzer v.%s by Redpic\r\n\n",Version);
}
void hardy_firmware_trans(void){
printf("{%s}\r\n",Version);
delay_ms(10);
ack_trans();
}
// data_trans ///////////////////////////////////////////////////////
void friendly_data_trans(void){
disable_interrupts(int_timer1);
printf("\r\nResults Table:\r\n\n");
printf("Total INT_EXT detected %2u\r\n",nTintext);
printf("\r\nFalling edges Table\r\n\n");
printf("Nº C Overflows Timer\r\n");
printf("=======================\r\n");
for(i=0;i<NMUESTRAS;i++){
printf("%2u %1u %5lu %5lu\r\n",i,tDownC[i],tDownI[i],tDownT[i]);
}
printf("\r\n\nRising edges Table\r\n\n");
printf("Nº C Overflows Timer\r\n");
printf("=======================\r\n");
for(i=0;i<NMUESTRAS;i++){
printf("%2u %1u %5lu %5lu\r\n",i,tUpC[i],tUpI[i],tUpT[i]);
}
}
void hardy_data_trans(void){
disable_interrupts(int_timer1);
for(i=0;i<NMUESTRAS;i++){
printf("{ %3u %1u %5lu %5lu %1u %5lu %5lu }\r\n",i+1,tUpC[i],tUpI[i],tUpT[i],tDownC[i],tDownI[i],tDownT[i]);
}
delay_ms(10);
ack_trans();
}
// config_trans /////////////////////////////////////////////////////
void friendly_config_trans(void){
disable_interrupts(int_timer1);
printf("\r\nConfig Channels :\r\n\n");
printf("Channel 1 = %2u\r\n\n",C1_Settings);
printf("Channel 2 = %2u\r\n\n",C2_Settings);
printf("Channel 3 = %2u\r\n\n",C3_Settings);
}
void hardy_config_trans(void){
disable_interrupts(int_timer1);
printf("{ %3u %3u %3u }\r\n",C1_Settings,C2_Settings,C3_Settings);
delay_ms(10);
ack_trans();
}
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
| |
|
|
Esta página se modificó el
27/12/2008
|