Hola a todos chicos.
Cuando uso el programa de ejemplo que trae JAL, la conexión anda muy bien. Incluso si la modifico y le voy agregando algunas tareas, la comunicación anda muy bien también. Pero cuando necesito agregarle más trabajo, la PC deja de reconocerme al PIC. Me he dado cuenta de que es por culpa de la función usb_serial_flush(). Si la llamo seguido, no tengo problema; pero si por algún problema el PIC se demora más de lo habitual para llamar a la función antes mencionada, la comunicación falla.
Para ello decidí usar la interrupción por TMR0 usando la librería, pero no he tenido buenos resultados. A fin de evitar problemas, decidí hacer mi propia configuración del TMR0; haciendo una interrupción cada 15useg (emulado en el MPLAB). Adivinen, no funcionó.
Sinceramente, ya no se porqué es la falla. Desde que retomé con este proyecto, me he estado volviendo loco. A continuación, pego el código completo para ver si ustedes ven mi error:
-- ------------------------------------------------------------------------------------------------
--
-- Este programa ha sido generado por jallib.py
-- Plataforma Invernadero.
--
-- ------------------------------------------------------------------------------------------------
-- INICIO DEL PROGRAMA.
-- --------------------
include 18f4550 -- Incluímos la librería para controlar nuestro PIC.
-- Aunque el cristal externo es 20 MHz, la configuración es tal que el reloj de la CPU
-- se deriva de reloj PLL 96 Mhz (div2),
-- por lo tanto, establecer la frecuencia de destino para 20 MHz
pragma target clock 20_000_000
-- FUSIBLES:
-- ---------
pragma target PLLDIV P5 -- divide by 5 - 20MHZ_INPUT
pragma target CPUDIV P1 -- [primary oscillator src: /1][96 mhz pll src: /2]
pragma target USBPLL F48MHZ -- CLOCK_SRC_FROM_96MHZ_PLL_2
pragma target OSC HS_PLL
pragma target FCMEN DISABLED
pragma target IESO DISABLED
pragma target PWRTE DISABLED -- power up timer
pragma target VREGEN ENABLED -- USB voltage regulator
pragma target VOLTAGE MINIMUM -- brown out voltage
pragma target BROWNOUT DISABLED -- no brownout detection
pragma target WDTPS P32K -- watch dog saler setting
pragma target WDT CONTROL -- no watchdog
pragma target CCP2MUX ENABLED -- CCP2 pin C1
pragma target PBADEN DIGITAL -- digital input port<0..4>
pragma target LPT1OSC LOW_POWER -- low power timer 1
pragma target MCLR EXTERNAL -- master reset on RE3
pragma target STVR DISABLED -- reset on stack over/under flow
pragma target LVP DISABLED -- no low-voltage programming
pragma target XINST ENABLED -- extended instruction set
pragma target DEBUG DISABLED -- background debugging
pragma target CP0 DISABLED -- code block 0 not protected
pragma target CP1 DISABLED -- code block 1 not protected
pragma target CP2 DISABLED -- code block 2 not protected
pragma target CP3 DISABLED -- code block 3 not protected
pragma target CPB DISABLED -- bootblock code not write protected
pragma target CPD DISABLED -- eeprom code not write protected
pragma target WRT0 DISABLED -- table writeblock 0 not protected
pragma target WRT1 DISABLED -- table write block 1 not protected
pragma target WRT2 DISABLED -- table write block 2 not protected
pragma target WRT3 DISABLED -- table write block 3 not protected
pragma target WRTB DISABLED -- bootblock not write protected
pragma target WRTD DISABLED -- eeprom not write protected
pragma target WRTC DISABLED -- config not write protected
pragma target EBTR0 DISABLED -- table read block 0 not protected
pragma target EBTR1 DISABLED -- table read block 1 not protected
pragma target EBTR2 DISABLED -- table read block 2 not protected
pragma target EBTR3 DISABLED -- table read block 3 not protected
pragma target EBTRB DISABLED -- boot block not protected
-- ------------------------------------------------------------------------------------------------
-- INCLUIMOS LIBRERÍAS:
-- --------------------
include usb_serial -- Incluímos la librería para emular el puerto serial por USB.
include delay -- Incluímos la librería para las demoras.
-- ------------------------------------------------------------------------------------------------
-- CONFIGURACIÓN GENERAL DEL PIC:
-- ------------------------------
enable_digital_io() -- Por seguridad, configuraremos a los pines análogos
-- como digitales. Luego, cuando inicializemos el ADC,
-- se autoconfigurará analógicas las entradas a utilizar.
INTCON_GIE = false -- Deshabilitamos las interrupciones. Las habilitaremos
-- mas adelante.
portb_direction = output -- Todo el puerto B como salida.
portc_direction = output -- Todo el puerto C como salida.
portd_direction = output -- Todo el puerto D como salida.
pin_a4_direction = output -- Solo el RA4 como salida.
-- ------------------------------------------------------------------------------------------------
-- CONFIGURACIÓN DEL TMR0:
-- -----------------------
var byte tempori = 200
T0CON = 0b11000000 -- Habilitamos el TMR0, 8 Bit, Reloj del PIC; Prescaler 1:2
TMR0L = tempori -- A 48Mhz 15useg
INTCON_TMR0IF = 0 -- Por seguridad, limpiamos la bandera.
INTCON_TMR0IE = 1 -- Habilitamos individualmente la interrupción de TMR0
-- INTCON_GIE = 1 -- Habilitamos las interrupciones.
---------------------------------------------------------------------------------------------------
-- CONFIGURACIÓN DEL ADC:
-------------------------
;const bit ADC_HIGH_RESOLUTION = false
-- we said we want 1 analog channel...
;const byte ADC_NCHANNEL = 1
-- and no voltage reference
;const byte ADC_NVREF = 0
-- now we can include the library
-- note it's now named "adc", not "adc_hardware" anymore
;include adc
-- and run the initialization step
;adc_init()
-- ------------------------------------------------------------------------------------------------
-- VARIABLES:
-- -----------
var byte ch
var byte temp_hongo_1
var byte hum_hongo_1
var byte temp_hongo_2
var byte hum_hongo_2
var byte temp_hongo_3
var byte hum_hongo_3
var byte temp_hongo_4
var byte hum_hongo_4
var byte canal
var byte temperatura
var byte humedad
var word temp
var dword hum
-- ------------------------------------------------------------------------------------------------
-- setup the USB serial library
usb_serial_init()
INTCON_GIE = 1 -- Habilitamos las interrupciones.
-- ------------------------------------------------------------------------------------------------
-- TRATAMIENTO DE LAS INTERRUPCIONES:
-- ----------------------------------
procedure temporizador0() is
pragma interrupt NORMAL
if INTCON_TMR0IF == 1 then
usb_serial_flush()
end if
TMR0L = tempori
INTCON_TMR0IF = 0
end procedure
-- ----------------------------------------------------------------------------
-- PROCEDIMIENTOS Y FUNCIONES TOTALES.
-- -----------------------------------
-- ----------------------------------------------------------------------------
-- PROCEDIMIENTOS PARA EL CAD:
-- ---------------------------
function leer_cad(byte in canal)return byte is
var byte resultado_cad
ADCON0_CHS = canal
ADCON0_ADON = 1
_usec_delay(4) -- 20uS
ADCON0_GO = 1
while ADCON0_GO loop end loop -- Esperamos hasta que la conversión finalice.
resultado_cad = ADRESH
ADCON0_ADON = 0
return resultado_cad
end function
procedure sensar_temperatura() is
temp = BYTE(leer_cad(canal)) -- Iniciamos la conversión
temp = temp * 195 -- Multiplicamos por 195 para pasarlo a tensión
temp = temp / 100 -- Dividimos por 100 para quedarnos con la parte entera. Tamaño máximo 8 bit.
temperatura = BYTE(temp) -- El resultado de 8 bit, lo pasamos a otra variable de tamaño de 8 bit
end procedure
;
;**********************************************************************
;MEDIMOS LA HUMEDAD.
;------------------
;PASOS A SEGUIR.
;
;1- CONFIGURAR EL CANAL A SENSAR.
;2- MEDIR EL ADC DE LA HUMEDAD Y GUARDAMOS EL VALOR EN RAM
; TENEMOS QUE APLICAR LA FÓRMULA SIGUIENTE PARA OBTENER LA HUMEDAD HR = (Vout - 0,8) / 0,031
;3- PARA ELLO, DEVEMOS MULTIPLICAR EL ADC POR 196 PARA PASARLO A TENSIÓN (EN REALIDAD DEBERÍA SER 195 PERO CON ESTE, EL ERROR ES MAS GRANDE).
;4- LUEGO LO VOLVEMOS A MULTIPLICAR POR 1.000 PARA TRABAJAR CON LA SIGUIENTE FÓRMULA HR = (Vout - 800) / 31
;5- APLICAMOS LA FORMULA HR = (Vout - 800) / 31,
;5- EL RESULTADO LO DIVIDIMOS POR 10.000 PARA OBETENER LA HUMEDAD RELATIVA EN 2 DÍGITOS (O 1.000 PARA OBTENER 3 DÍGITOS, ANALIZAMOS MAS ADELANTE ESTO)
;6- LO GUARDAMOS EN LA RAM
;7- TOMAMOS 42 MUESTRAS
;8- HACEMOS EL PROMEDIO, PARA ELLO SUMAMOS LAS 42 MUESTRAS ENTRE SI Y LUEGO LA DIVIDIMOS POR 42
;9- EL RESULTADO DEL PROMEDIO LO GUARDAMOS EN LA RAM humedad
;10- SENSAMOS EL VIENTO.
;**********************************************************************
procedure sensar_humedad() is
hum = BYTE(leer_cad(canal)) -- Iniciamos la conversión
hum = hum * 196 -- Lo pasamos a tensión
hum = hum * 1000 -- Lo multiplicamos por 1000
hum = hum - 800 -- Le restamos 800
hum = hum / 31 -- Lo dividimos por 31
hum = hum / 10000 -- Lo dividimos por 10000 para obtener 3 dígitos
humedad = BYTE(hum) -- El resultado de 8 bit, lo pasamos a otra variable de tamaño de 8 bit
end procedure
-- main loop
forever loop
;
canal = 0 -- Temperatura hongo 1 (AN0).
sensar_temperatura()
-- usb_serial_flush()
temp_hongo_1 = temperatura -- Recuperamos el valor de la temperatura sensado.
-- usb_serial_flush()
;
canal = 1 -- Humedad hongo 1 (AN1).
sensar_humedad()
-- usb_serial_flush()
hum_hongo_1 = humedad -- Recuperasmos el valor de la humedad sensada.
-- usb_serial_flush()
;
canal = 2 -- Temperatura hongo 2 (AN2).
sensar_temperatura()
-- usb_serial_flush()
temp_hongo_2 = temperatura -- Recuperamos el valor de la temperatura sensado.
-- usb_serial_flush()
;
canal = 3 -- Humedad hongo 2 (AN3).
sensar_humedad()
-- usb_serial_flush()
hum_hongo_2 = humedad -- Recuperasmos el valor de la humedad sensada.
-- usb_serial_flush()
;
canal = 4 -- Temperatura hongo 3 (AN4).
sensar_temperatura()
-- usb_serial_flush()
temp_hongo_3 = temperatura -- Recuperamos el valor de la temperatura sensado.
-- usb_serial_flush()
;
canal = 5 -- Humedad hongo 3 (AN5).
sensar_humedad()
-- usb_serial_flush()
hum_hongo_3 = humedad -- Recuperasmos el valor de la humedad sensada.
-- usb_serial_flush()
;
canal = 6 -- Temperatura hongo 4 (AN6).
sensar_temperatura()
-- usb_serial_flush()
temp_hongo_4 = temperatura -- Recuperamos el valor de la temperatura sensado.
-- usb_serial_flush()
;
canal = 7 -- Humedad hongo 4 (AN7).
sensar_humedad()
-- usb_serial_flush()
hum_hongo_4 = humedad -- Recuperasmos el valor de la humedad sensada.
-- usb_serial_flush()
if ( usb_cdc_line_status() != 0x00 ) then
ch = 0
if usb_serial_read(ch) then -- leo el puerto usb
-- usb_serial_flush() -- mantengo viva la conexion usb
case ch of -- manipulación de salidas digitales
"A": pin_b7 = on -- Ventilador encendido
"B": pin_b7 = off -- Ventilador apagado
"C": pin_b6 = on -- Calefación encendido
"D": pin_b6 = off -- Calefacción apagado
"E": pin_b5 = on -- Refrigeración encendido
"F": pin_b5 = off -- Refrigeración apagado
"G": pin_b4 = on -- Luz encendido
"H": pin_b4 = off -- Luz apagado
"I": pin_b3 = on -- Humificador encendido
"J": pin_b3 = off -- Humificador apagado
;
"0": usb_serial_write(temp_hongo_1) -- Mostrar el valor de la tempereatura actual.
"1": usb_serial_write(hum_hongo_1) -- Mostrar el valor de la humedad actual.
"2": usb_serial_write(pin_b7) -- Mostrar el estado del ventilador.
"3": usb_serial_write(pin_b6) -- Mostrar el estado del calefacción.
"4": usb_serial_write(pin_b5) -- Mostrar el estado de la refrigeración.
"5": usb_serial_write(pin_b4) -- Mostrar el estado de la luz.
"6": usb_serial_write(pin_b3) -- Mostrar el estado del humificador.
;
"K": pin_b2 = on -- Vantilador 2 encendido
"L": pin_b2 = off -- Ventilador 2 apagado
"M": pin_d7 = on -- Calefacción 2 encendido
"N": pin_d7 = off -- Calefacción 2 apagado
"O": pin_d6 = on -- Refrigeración 2 encendido
"P": pin_d6 = off -- Refrigeración 2 apagado
"Q": pin_d5 = on -- Luz 2 ecendido
"R": pin_d5 = off -- Luz 2 apagado
"S": pin_d4 = on -- Humificador 2 encendido
"T": pin_d4 = off -- Humificador 2 apagado
;
"7": usb_serial_write(temp_hongo_2) -- Muestra la temperatura del hongo 2
"8": usb_serial_write(hum_hongo_2) -- Muestra la humedad del hongo 2
"9": usb_serial_write(pin_b2) -- Muestra el estado del ventilador 2
":": usb_serial_write(pin_d7) -- Muestra el estado de la calefacción 2
";": usb_serial_write(pin_d6) -- Muestra el estado de la refrigeración 2
"<": usb_serial_write(pin_d5) -- Muestra el estado de la luz 2
"=": usb_serial_write(pin_d4) -- Muestra el estado del humuficador 2
;
"a": pin_c7 = on -- Ventilador 3 encendido
"b": pin_c7 = off -- Ventilador 3 apagado
"c": pin_c6 = on -- Calefacción 3 encendido
"d": pin_c6 = off -- Calefacción 3 apagado
"e": pin_d3 = on -- Refrigeración 3 encendido
"f": pin_d3 = off -- Refrigeración 3 apagado
"g": pin_d2 = on -- Luz 3 encendido
"h": pin_d2 = off -- Luz 3 apagado
"i": pin_c0 = on -- Humificador 3 encendido
"j": pin_c0 = off -- Humificador 3 apagado
;
">": usb_serial_write(temp_hongo_3) -- Muestra la temperatura del hongo 3
"?": usb_serial_write(hum_hongo_3) -- Muestra la humedad del hongo 3
"@": usb_serial_write(pin_c7) -- Muestra el estado del ventilador 3
"(": usb_serial_write(pin_c6) -- Muestra el estado de la calefacción 3
")": usb_serial_write(pin_d3) -- Muestra el estado de la refrigeración 3
"+": usb_serial_write(pin_d2) -- Muestra el estado de la luz 3
"^": usb_serial_write(pin_c0) -- Muestra el estado del humificador 3
;
"k": pin_c1 = on -- Ventilador 4 encendido
"l": pin_c1 = off -- Ventilador 4 apagado
"m": pin_c2 = on -- Calefacción 4 encendido
"n": pin_c2 = off -- Calefacción 4 apagado
"o": pin_d0 = on -- Refrigeración 4 encendido
"p": pin_d0 = off -- Refrigeración 4 apagado
"q": pin_d1 = on -- Luz 4 encendido
"r": pin_d1 = off -- Luz 4 apagado
"s": pin_a4 = on -- Humificador 4 encendido
"t": pin_a4 = off -- Humificador 4 apagado
;
"_": usb_serial_write(temp_hongo_4) -- Muestra la temperatura del hongo 4
"!": usb_serial_write(hum_hongo_4) -- Muestra la humedad del hongo 4
" ": usb_serial_write(pin_c1) -- Muesttra el estado del ventilador 4
"#": usb_serial_write(pin_c2) -- Muestra el estado de la calefacción 4
"$": usb_serial_write(pin_d0) -- Muestra el estado de la refrigeración 4
"%": usb_serial_write(pin_d1) -- Muestra el estado de la luz 4
"&": usb_serial_write(pin_a4) -- Muestra el estado del humificador 4
;
end case
end if
end if
end loop
Como notarán, es una máquina de estado. Aún falta terminar ya que faltan funciones, que no las quiero agregar hasta tanto solucione este problema de comunicación.
Notarán que hay muchas llamadas de la función usb_serial_flush() pero que están comentada (con --) para ver si logro funcionar con la interrupción por TMR0.
Hasta tomé la precaución de activar la interrupción después de inicializar el puerto USB, para que usb_serial_flush() no sea llamado primero.
Desde ya, cualquier ayuda se los agradeceré muchísimo.
Por cierto, he probado con 2mseg y con 6mseg y nada.
Hola David, no conozco el lenguaje Jal pero tratare de ayudar si puedo, te pregunto
cual es la función de la función usb_serial_flush().
Esta función, mantiene viva la conexión entre el PIC y el USB.
Si el puerto USB se mantiene inactivo por un cierto tiempo (hasta donde se de unos 10ms), el host (la PC, en mi caso) corta la conexión.
La opcion del timer me parece acertada, seguis haciendo pruebas.
En el foro de Ucontrol, un usuario llamado nestoriano, me dio un programa que funciona y utiliza la interrupción para poder mantener viva la comunicación.
Este es el código
--;@main
include 18f4550
-- even though the external crystal is 20 MHz, the configuration is such that
-- the CPU clock is derived from the 96 Mhz PLL clock (div2), therefore set
-- target frequency to 48 MHz
pragma target clock 48_000_000
-- FUSIBLES:
-- ---------
pragma target PLLDIV P5 -- divide by 5 - 20MHZ_INPUT
pragma target CPUDIV P1 -- [primary oscillator src: /1][96 mhz pll src: /2]
pragma target USBPLL F48MHZ -- CLOCK_SRC_FROM_96MHZ_PLL_2
pragma target OSC HS_PLL
pragma target FCMEN DISABLED
pragma target IESO DISABLED
pragma target PWRTE DISABLED -- power up timer
pragma target VREGEN ENABLED -- USB voltage regulator
pragma target VOLTAGE MINIMUM -- brown out voltage
pragma target BROWNOUT DISABLED -- no brownout detection
pragma target WDTPS P32K -- watch dog saler setting
pragma target WDT CONTROL -- no watchdog
pragma target CCP2MUX ENABLED -- CCP2 pin C1
pragma target PBADEN DIGITAL -- digital input port<0..4>
pragma target LPT1OSC LOW_POWER -- low power timer 1
pragma target MCLR EXTERNAL -- master reset on RE3
pragma target STVR DISABLED -- reset on stack over/under flow
pragma target LVP DISABLED -- no low-voltage programming
pragma target XINST ENABLED -- extended instruction set
pragma target DEBUG DISABLED -- background debugging
pragma target CP0 DISABLED -- code block 0 not protected
pragma target CP1 DISABLED -- code block 1 not protected
pragma target CP2 DISABLED -- code block 2 not protected
pragma target CP3 DISABLED -- code block 3 not protected
pragma target CPB DISABLED -- bootblock code not write protected
pragma target CPD DISABLED -- eeprom code not write protected
pragma target WRT0 DISABLED -- table writeblock 0 not protected
pragma target WRT1 DISABLED -- table write block 1 not protected
pragma target WRT2 DISABLED -- table write block 2 not protected
pragma target WRT3 DISABLED -- table write block 3 not protected
pragma target WRTB DISABLED -- bootblock not write protected
pragma target WRTD DISABLED -- eeprom not write protected
pragma target WRTC DISABLED -- config not write protected
pragma target EBTR0 DISABLED -- table read block 0 not protected
pragma target EBTR1 DISABLED -- table read block 1 not protected
pragma target EBTR2 DISABLED -- table read block 2 not protected
pragma target EBTR3 DISABLED -- table read block 3 not protected
pragma target EBTRB DISABLED -- boot block not protected
include delay
include usb_serial
include print
include random
var word dato
const byte str_welcome[] = "JALLIB USB Serial Demo app\n"
-- -----------------------------------------------------------------------------
-- -----------------------------------------------------------------------------
procedure interrupcion() is
pragma interrupt
if (INTCON_TMR0IF) then
usb_serial_flush()
tmr0=64000
INTCON_TMR0IF=0
end if
if (PIR1_TMR1IF==1) then
tmr1=3038
dato=random_word
PIR1_TMR1IF=0
end if
end procedure
-- -----------------------------------------------------------------------------
-- -----------------------------------------------------------------------------
--TMR0
INTCON=0b10100000
T0CON=0b10000000
tmr0=64000
--TMR1
PIR1_TMR1IF=0
INTCON_PEIE=1
T1CON=0b11000001
usb_serial_init()
forever loop
print_string(usb_serial_data,str_welcome)
print_word_dec(usb_serial_data,dato)
print_crlf(usb_serial_data)
delay_1ms(1000)
end loop
El utilizó el PIC 18F2550. Yo solo respeté los fuses de mi pic, el resto es obra de él.
Ahora tenemos un punto de donde salir.
Nestoriano cree que alguna librería no está tratando bien la interrupción, mas precisamente en el tratamiento de la del bit GIE.
Ahora veremos si puedo adaptarlo a mis necesidades.
He creado una mejora del programa para no ejecutar la función USB_SERIAL_FUSH() mientras se mantenía una comunicación al enviar un dato. Esto es para no generar procedimiento recursivo.
Intenté con el chequeo del bit ACTVIF del registro UIR pero no funcionó. Para ello, cree una propia bandera llamado usb_en_uso donde 1 indica que está en uso, y 0 indica que no se está transmitiendo ningún dato. El programa funciona muy bien. Lo copio y pego:
--;@main
include 18f4550
-- even though the external crystal is 20 MHz, the configuration is such that
-- the CPU clock is derived from the 96 Mhz PLL clock (div2), therefore set
-- target frequency to 48 MHz
pragma target clock 48_000_000
-- FUSIBLES:
-- ---------
pragma target PLLDIV P5 -- divide by 5 - 20MHZ_INPUT
pragma target CPUDIV P1 -- [primary oscillator src: /1][96 mhz pll src: /2]
pragma target USBPLL F48MHZ -- CLOCK_SRC_FROM_96MHZ_PLL_2
pragma target OSC HS_PLL
pragma target FCMEN DISABLED
pragma target IESO DISABLED
pragma target PWRTE DISABLED -- power up timer
pragma target VREGEN ENABLED -- USB voltage regulator
pragma target VOLTAGE MINIMUM -- brown out voltage
pragma target BROWNOUT DISABLED -- no brownout detection
pragma target WDTPS P32K -- watch dog saler setting
pragma target WDT CONTROL -- no watchdog
pragma target CCP2MUX ENABLED -- CCP2 pin C1
pragma target PBADEN DIGITAL -- digital input port<0..4>
pragma target LPT1OSC LOW_POWER -- low power timer 1
pragma target MCLR EXTERNAL -- master reset on RE3
pragma target STVR DISABLED -- reset on stack over/under flow
pragma target LVP DISABLED -- no low-voltage programming
pragma target XINST ENABLED -- extended instruction set
pragma target DEBUG DISABLED -- background debugging
pragma target CP0 DISABLED -- code block 0 not protected
pragma target CP1 DISABLED -- code block 1 not protected
pragma target CP2 DISABLED -- code block 2 not protected
pragma target CP3 DISABLED -- code block 3 not protected
pragma target CPB DISABLED -- bootblock code not write protected
pragma target CPD DISABLED -- eeprom code not write protected
pragma target WRT0 DISABLED -- table writeblock 0 not protected
pragma target WRT1 DISABLED -- table write block 1 not protected
pragma target WRT2 DISABLED -- table write block 2 not protected
pragma target WRT3 DISABLED -- table write block 3 not protected
pragma target WRTB DISABLED -- bootblock not write protected
pragma target WRTD DISABLED -- eeprom not write protected
pragma target WRTC DISABLED -- config not write protected
pragma target EBTR0 DISABLED -- table read block 0 not protected
pragma target EBTR1 DISABLED -- table read block 1 not protected
pragma target EBTR2 DISABLED -- table read block 2 not protected
pragma target EBTR3 DISABLED -- table read block 3 not protected
pragma target EBTRB DISABLED -- boot block not protected
var volatile bit usb_en_uso
include delay
include usb_serial
include print
include random
var word dato
const byte str_welcome[] = "JALLIB USB Serial Demo app\n"
-- -----------------------------------------------------------------------------
-- -----------------------------------------------------------------------------
procedure interrupcion() is
pragma interrupt
if (INTCON_TMR0IF) then
if usb_en_uso == 0 then
usb_serial_flush()
end if
tmr0=64000
INTCON_TMR0IF=0
end if
if (PIR1_TMR1IF==1) then
tmr1=3038
dato=random_word
PIR1_TMR1IF=0
end if
end procedure
-- -----------------------------------------------------------------------------
-- -----------------------------------------------------------------------------
--TMR0
INTCON=0b10100000
T0CON=0b10000000
tmr0=64000
--TMR1
PIR1_TMR1IF=0
INTCON_PEIE=1
T1CON=0b11000001
usb_serial_init()
forever loop
usb_en_uso = 1
print_string(usb_serial_data,str_welcome)
print_word_dec(usb_serial_data,dato)
print_crlf(usb_serial_data)
usb_en_uso = 0
delay_1ms(1000)
end loop
De todas maneras está en prueba. Por ahora lleva funcionando por más de 15 minutos sin ningún problema.
He estado haciendo algunas pruebas de poder leer al puerto USB. Por supuesto que las primeras pruebas fueron fallidas; pero no me llevó mucho tiempo descubrir que la función usb_serial_read([byte]) no mantiene vivo la comunicación. Esto es muy importante saberlo porque es uno de los problemas que hace que nuestro dispositivo no sea reconocido.
Pongo el siguiente programa que funciona:
-- ------------------------------------------------------------------------------------------------
--
-- Este programa ha sido generado por jallib.py
--;@main
include 18f4550
-- even though the external crystal is 20 MHz, the configuration is such that
-- the CPU clock is derived from the 96 Mhz PLL clock (div2), therefore set
-- target frequency to 48 MHz
pragma target clock 48_000_000
-- FUSIBLES:
-- ---------
pragma target PLLDIV P5 -- divide by 5 - 20MHZ_INPUT
pragma target CPUDIV P1 -- [primary oscillator src: /1][96 mhz pll src: /2]
pragma target USBPLL F48MHZ -- CLOCK_SRC_FROM_96MHZ_PLL_2
pragma target OSC HS_PLL
pragma target FCMEN DISABLED
pragma target IESO DISABLED
pragma target PWRTE DISABLED -- power up timer
pragma target VREGEN ENABLED -- USB voltage regulator
pragma target VOLTAGE MINIMUM -- brown out voltage
pragma target BROWNOUT DISABLED -- no brownout detection
pragma target WDTPS P32K -- watch dog saler setting
pragma target WDT CONTROL -- no watchdog
pragma target CCP2MUX ENABLED -- CCP2 pin C1
pragma target PBADEN DIGITAL -- digital input port<0..4>
pragma target LPT1OSC LOW_POWER -- low power timer 1
pragma target MCLR EXTERNAL -- master reset on RE3
pragma target STVR DISABLED -- reset on stack over/under flow
pragma target LVP DISABLED -- no low-voltage programming
pragma target XINST ENABLED -- extended instruction set
pragma target DEBUG DISABLED -- background debugging
pragma target CP0 DISABLED -- code block 0 not protected
pragma target CP1 DISABLED -- code block 1 not protected
pragma target CP2 DISABLED -- code block 2 not protected
pragma target CP3 DISABLED -- code block 3 not protected
pragma target CPB DISABLED -- bootblock code not write protected
pragma target CPD DISABLED -- eeprom code not write protected
pragma target WRT0 DISABLED -- table writeblock 0 not protected
pragma target WRT1 DISABLED -- table write block 1 not protected
pragma target WRT2 DISABLED -- table write block 2 not protected
pragma target WRT3 DISABLED -- table write block 3 not protected
pragma target WRTB DISABLED -- bootblock not write protected
pragma target WRTD DISABLED -- eeprom not write protected
pragma target WRTC DISABLED -- config not write protected
pragma target EBTR0 DISABLED -- table read block 0 not protected
pragma target EBTR1 DISABLED -- table read block 1 not protected
pragma target EBTR2 DISABLED -- table read block 2 not protected
pragma target EBTR3 DISABLED -- table read block 3 not protected
pragma target EBTRB DISABLED -- boot block not protected
var volatile bit usb_en_uso
include delay
include usb_serial
include print
include random
var word dato
const byte str_welcome[] = "Prueba comunicación PIC-PC por USB.\n"
const byte mensaje1[] = "Ingrese un dato\n"
const byte mensaje2[] = "Ahora tiene que esperar\n"
-- -----------------------------------------------------------------------------
-- -----------------------------------------------------------------------------
procedure interrupcion() is
pragma interrupt
if (INTCON_TMR0IF) then
if usb_en_uso == 0 then
usb_serial_flush()
end if
tmr0=64000
INTCON_TMR0IF=0
end if
if (PIR1_TMR1IF==1) then
tmr1=3038
dato=random_word
PIR1_TMR1IF=0
end if
end procedure
-- -----------------------------------------------------------------------------
-- -----------------------------------------------------------------------------
--TMR0
INTCON=0b10100000
T0CON=0b10000000
--TMR1
PIR1_TMR1IF=0
INTCON_PEIE=1
T1CON=0b11000001
usb_serial_init()
tmr0=4000
var byte ch
forever loop
usb_en_uso = 0
ch = 0
print_string(usb_serial_data,mensaje1)
for 783647 loop
if usb_serial_read(ch) then -- leo el puerto usb
print_byte_dec(usb_serial_data,ch)
end if
end loop
usb_en_uso = 1
print_crlf(usb_serial_data)
print_string(usb_serial_data,mensaje2)
print_crlf(usb_serial_data)
print_string(usb_serial_data,str_welcome)
print_word_dec(usb_serial_data,dato)
print_crlf(usb_serial_data)
usb_en_uso = 0
delay_1ms(1000)
end loop
El for 783647 loop está creado para que me de 3 segundos, aproximadamente, para ingresar datos por el teclado de la PC.
Noten que, al momento de leer al puerto USB, es necesario mantener viva la comunicación por medio de la función que está en la interrupción.
Lamento ir colocando los avances por cuenta gotas, pero me sirve para saber hasta donde llegué; si por algún motivo tengo que dejarlo y luego retomar otro día.
Logré escribir un programa que lee y escribe por USB y no se corta. Hace más de una hora que lo tengo funcionando sin problema.
Me parece que es una excelente base como guía para cualquier proyecto USB-SERIAL.
Más adelante, trataré de escribir una librería para no tener dolores de cabeza. Les agradezco a todos por la ayuda, en especial de nestoriano y rubial69 (de Ucontrol) que hicieron que se llegara a buen puerto.
-- ------------------------------------------------------------------------------------------------
--
-- Este programa ha sido generado por jallib.py
--;@main
include 18f4550
-- even though the external crystal is 20 MHz, the configuration is such that
-- the CPU clock is derived from the 96 Mhz PLL clock (div2), therefore set
-- target frequency to 48 MHz
pragma target clock 48_000_000
-- FUSIBLES:
-- ---------
pragma target PLLDIV P5 -- divide by 5 - 20MHZ_INPUT
pragma target CPUDIV P1 -- [primary oscillator src: /1][96 mhz pll src: /2]
pragma target USBPLL F48MHZ -- CLOCK_SRC_FROM_96MHZ_PLL_2
pragma target OSC HS_PLL
pragma target FCMEN DISABLED
pragma target IESO DISABLED
pragma target PWRTE DISABLED -- power up timer
pragma target VREGEN ENABLED -- USB voltage regulator
pragma target VOLTAGE MINIMUM -- brown out voltage
pragma target BROWNOUT DISABLED -- no brownout detection
pragma target WDTPS P32K -- watch dog saler setting
pragma target WDT CONTROL -- no watchdog
pragma target CCP2MUX ENABLED -- CCP2 pin C1
pragma target PBADEN DIGITAL -- digital input port<0..4>
pragma target LPT1OSC LOW_POWER -- low power timer 1
pragma target MCLR EXTERNAL -- master reset on RE3
pragma target STVR DISABLED -- reset on stack over/under flow
pragma target LVP DISABLED -- no low-voltage programming
pragma target XINST ENABLED -- extended instruction set
pragma target DEBUG DISABLED -- background debugging
pragma target CP0 DISABLED -- code block 0 not protected
pragma target CP1 DISABLED -- code block 1 not protected
pragma target CP2 DISABLED -- code block 2 not protected
pragma target CP3 DISABLED -- code block 3 not protected
pragma target CPB DISABLED -- bootblock code not write protected
pragma target CPD DISABLED -- eeprom code not write protected
pragma target WRT0 DISABLED -- table writeblock 0 not protected
pragma target WRT1 DISABLED -- table write block 1 not protected
pragma target WRT2 DISABLED -- table write block 2 not protected
pragma target WRT3 DISABLED -- table write block 3 not protected
pragma target WRTB DISABLED -- bootblock not write protected
pragma target WRTD DISABLED -- eeprom not write protected
pragma target WRTC DISABLED -- config not write protected
pragma target EBTR0 DISABLED -- table read block 0 not protected
pragma target EBTR1 DISABLED -- table read block 1 not protected
pragma target EBTR2 DISABLED -- table read block 2 not protected
pragma target EBTR3 DISABLED -- table read block 3 not protected
pragma target EBTRB DISABLED -- boot block not protected
var volatile bit usb_en_uso
include delay
include usb_serial
include print
include random
var word dato
const byte str_welcome[] = "Prueba comunicación PIC-PC por USB.\n"
const byte mensaje1[] = "Ingrese un dato\a" --\a emite un tono de alerta a la PC para ser
-- reproducido por los parlantes.
const byte mensaje2[] = "Ahora tiene que esperar\n"
const byte mensaje3[] = "Usted presionó la tecla A\n"
const byte mensaje4[] = "Usted presionó la tecla B\n"
const byte mensaje5[] = "Usted presionó la tecla C\n"
const byte mensaje6[] = "Usted presionó la tecla D\n"
const byte mensaje7[] = "Usted presionó la tecla E\n"
const byte mensaje8[] = "Usted presionó la tecla F\n"
const byte mensaje9[] = "Usted presionó la tecla G\n"
const byte mensaje10[] = "Usted presionó la tecla H\n"
const byte mensaje11[] = "Usted presionó la tecla I\n"
const byte mensaje12[] = "Usted presionó la tecla J\n"
const byte mensaje13[] = "Buscando un número aleatorio. Por favor espere.\n"
const byte mensaje14[] = "Imprimiento número aleatorio: "
-- -----------------------------------------------------------------------------
-- -----------------------------------------------------------------------------
procedure interrupcion() is
pragma interrupt
if (INTCON_TMR0IF) then
if usb_en_uso == 0 then
usb_serial_flush()
end if
tmr0=64000
INTCON_TMR0IF=0
end if
if (PIR1_TMR1IF==1) then
tmr1=3038
dato=random_word
PIR1_TMR1IF=0
end if
end procedure
-- -----------------------------------------------------------------------------
-- -----------------------------------------------------------------------------
--TMR0
INTCON=0b10100000
T0CON=0b10000000
--TMR1
PIR1_TMR1IF=0
INTCON_PEIE=1
T1CON=0b11000001
usb_serial_init()
tmr0=4000
var byte ch
forever loop
ch = 0 -- Borro la variable CH
usb_en_uso = 1 -- Indico que voy a transmitir. No es necesario ejecutar la función
-- para mantener viva la comunicación USB.
print_string(usb_serial_data,mensaje1) -- Imprimo mensaje número 1. El mismo envía un tono de alerta por parlantes.
print_crlf(usb_serial_data) -- Borro una línea. Esto deja un espacio entre texto y texto.
usb_en_uso = 0 -- Indico que no voy a transmitir. Es necesario ejecutar la función
-- que mantiene viva la comunicación USB.
for 783647 loop -- Con dicho valor, voy a repetir el for por 3 segundos aproximadamente.
if usb_serial_read(ch) then -- Leo el puerto usb y lo guardo en CH
usb_en_uso = 1 -- Indico que voy a transmitir.
case ch of -- Según tecla presionada, imprimo el mensaje correspondiente.
"A": print_string(usb_serial_data,mensaje3) -- Imprime mensaje número 3 si la tecla es A
"B": print_string(usb_serial_data,mensaje4) -- Imprime mensaje número 3 si la tecla es B
"C": print_string(usb_serial_data,mensaje5) -- Imprime mensaje número 3 si la tecla es C
"D": print_string(usb_serial_data,mensaje6) -- Imprime mensaje número 3 si la tecla es D
"E": print_string(usb_serial_data,mensaje7) -- Imprime mensaje número 3 si la tecla es E
"F": print_string(usb_serial_data,mensaje8) -- Imprime mensaje número 3 si la tecla es F
"G": print_string(usb_serial_data,mensaje9) -- Imprime mensaje número 3 si la tecla es G
"H": print_string(usb_serial_data,mensaje10)-- Imprime mensaje número 3 si la tecla es H
"I": print_string(usb_serial_data,mensaje11) -- Imprime mensaje número 3 si la tecla es I
"J": print_string(usb_serial_data,mensaje12) -- Imprime mensaje número 3 si la tecla es J
end case
print_crlf(usb_serial_data) -- Borro una línea.
usb_en_uso = 0 -- Indico que no voy a transmitir por USB
end if
end loop
usb_en_uso = 1 -- Indico que voy a transmitir.
print_crlf(usb_serial_data) -- Borro una línea
print_string(usb_serial_data,mensaje2) -- Imprimo mensaje 2
print_crlf(usb_serial_data) -- Borro una línea.
print_string(usb_serial_data,str_welcome) -- Imprimo mensaje de "prueba de comunicación PIC-PC por USB.
print_crlf(usb_serial_data) -- Borro una línea.
print_string(usb_serial_data,mensaje13) -- Imprimo mensaje 13
print_crlf(usb_serial_data) -- Borro una línea.
usb_en_uso = 0 -- Indico que no voy a transmitir por USB.
delay_1ms(1000) -- Realizo un tiempo de 1s para hacerlo más realista (leer mensaje número 13)
usb_en_uso = 1 -- Indico que voy a transmitir.
print_string(usb_serial_data,mensaje14) -- Imprimo mensaje número 14.
print_word_dec(usb_serial_data,dato) -- Imprimo el número aleatorio.
print_crlf(usb_serial_data) -- Borro una línea.
usb_en_uso = 0 -- Indico que no voy a transmitir,
delay_1ms(1000) -- Espero 1 segundo y vuelvo a comenzar todo de nuevo.
end loop
Cualquier cosa pregunten.
PD: De tanto en probar, el pic dejó de ser reconocido. Lo solucioné borrando por completo al PIC y luego regrabarlo. No se si será casualidad, pero es bueno tenerlo presente.
Que buena noticia. ok! :borrachos!
Hola muchachos!!
Recien me conecto y veo que David volvió a practicar con Jal
Si mal no recuerdo, ¿no te habias comunicado antes por el puerto serie con el simulador 232 / USB y tenias el mismo problema?, según recuerdo ya lo tenias resuelto la vez pasada cuando publicaste los videos
O esto es otra cosa o recuerdo mal? dudo:
Ya había tenido problema y no lo había logrado solucionar. Luego tuve que dejarlo y quedó toda en la nada.
Anoche, luego de varios intentos fracasados, pude hacer andar la máquina de estado que estaba desarrollando para un invernadero en que estoy trabajando.
Resulta que, después de haber logrado (con personas que me ayudaron) que el PIC se mantuviera en actividad por medio de la interrupción, volví a lo mismo. La pc no me reconocía al dispositivo.
Resultó que el problema era culpa de una función llamada usb_serial_write(dato_a_enviar) Cambié esta función por la de print_byte_dec(usb_serial_data,dato_a_enviar) y salió andando de maravillas.