Curso de programación de PIC en PICBasic Pro

En realidad es muy sencillo y no se usa mucho código por lo mismo.
La interrupción por recepción del módulo EUSART es similar a las demás interrupciones.
Pero en éste caso el bit o bandera RCIF se pone en cero cuando se lee el buffer RCREG.

Te adjunto un ejemplo para que entiendas el proceso.
PD:
Así como no usaste resistencias para el display, también te recomiendo que en la simulación no uses el MAX232 y conectes el COMPIM directamente al PIC.
 

Adjuntos

  • 18F2550 Interrupción EUSART.rar
    47 KB · Visitas: 76
Pues hoy me toca rectificarme en el tema de controlar un led rgb con tmr0 y la lectura ir. A 8mhz conseguí justo pero si se pueden trabajar bien ambas cosas con una portadora pwm de 1khz y una definición del duty de 100. Pongamos qUE ya tengo el motor funcionando ahora solo faltan los pequeños detalles y mariconadillas para hacer un modulo algo chachi..

Los cálculos. (No suelo andar con ecuaciones complejas qUE no se manejar)
Seria esto....

tmr0 interruccion control RGB

+ 2.000.000,00000000 un cuarto osc
/ 2,00000000 tmr0 2:1 prescaler
---------------------
+ 1.000.000,00000000
/ 9,00000000 tmr0=247
---------------------
+ 111.111,11111111 frecuencia tmr0 interrupciones
/ 107,00000000 escala pwm
---------------------
+ 1.038,42159917 frecuencia final pwm


procesos ic entre interruccion tmr0

+ 9,00000000 tmr0=247
* 2,00000000 prescaler 2:1
---------------------
+ 18,00000000
* 4,00000000 un cuarto osc
---------------------
+ 72,00000000 procesos por interruccion tmr0
- 36,00000000 procesos ocupa interrupción tmr0 pwm
----------
36,0000000 procesos restantes


Conté qUE son 36 procesos la interRUPción trm0 pero realmente andarán entre 20 y 30 nunca se dan todas las decisiones al mismo tiempo lo cual sobran mas de 36 procesos para correr el programa normal....

Después si puedo o me dejan procederé a pasar el programa. Preparado para ir mejorando las costillas qUE lo Haran mas chachi. CoMo memoria de colores el control del leD blanco de iluminación por pwm interno y bueno dejando el pin gpio.2 libre o con un leD por el momento..

Un saludo

Puse un largo de duty en 107 cuando no voy a subir duty a mas de 100 para el rojo quizás 94 de máximo. Eso sera un truquito para adaPtar las corrientes de los diStintos colores al transformador qUE suele ser de 12.5v y para qUE puedan rebajar bien los cuerpos inductores qUE estabilizaran la modulación de pulsos en una corriente muy estable y poco rizado por la modulacion.

Un saludo
 
Última edición por un moderador:
Mas que hacer una pregunta, sólo diré, gracias D@rkbytes, por la ayuda de PICBasic.
Pasarlo aP[/SIZE]roton IDE no fue muy difícil, sólo tuve quehacer unos cambios, pero la interrupción serial corre muy bien.
 
Última edición por un moderador:
En realidad es muy sencillo y no se usa mucho código por lo mismo.
La interrupción por recepción del módulo EUSART es similar a las demás interrupciones.
Pero en éste caso el bit o bandera RCIF se pone en cero cuando se lee el buffer RCREG.

Te adjunto un ejemplo para que entiendas el proceso.
PD:
Así como no usaste resistencias para el display, también te recomiendo que en la simulación no uses el MAX232 y conectes el COMPIM directamente al PIC.


Muchas gracias, mi estimado, su ejemplo ha sido importante para comprender la interrupción,
pero tengo otro detalle.
Sería muy amable de su parte si me ayuda, ya que usted es un experto.

Le cuento que hago la interrupción de recepción por usart, pero no retorna al bucle donde éste empezó.
No sé qué problema puede ser. A ver si me da una mano.

Le dejo el programa de prueba.
PHP:
HIGH PORTC.2               'enable 
HIGH PORTC.4               'strobe
DAT   VAR PORTC.0          'data
CLK   VAR PORTC.1          'clook

DS1     VAR BYTE
A       VAR BYTE

RCSTA = %10010000          'Enable serial port and continuous receive, 
TXSTA = %00100000          ' Enable transmit and asynchronous mode 

INTCON = %11000000         'CONFIGURACION DE LA INTERRUPCION USART 
PIE1   = %00100000

on interrupt goto INTER


A = 63
SHIFTout DAT,CLK,1,[A]
INTERMITENTE:
read  0,a
pause 200
low 300
pause  200
high 300
pause 200
GOTO INTERMITENTE

DISABLE
INTER: 
PIR1.5 = 1                       
HSERIN [DEC1 DS1] 
eeprom 0,[0]
LOOKUP DS1,[63,6,91,79,102,109,124,7,127,103,0],A
write 0,a
read  0,a
SHIFTout DAT,CLK,1,[A]
ENABLE 
RESUME  
END
 
Última edición por un moderador:
No, muy mal.
Necesitas poner mas atención sobre las configuraciones de los registros usados en el ejemplo que subí.
De esa forma no va a funcionar tu programa.

El bit 5 (RCIF = EUSART Receive Interrupt Flag bit) del registro PIR1 es el que necesitas comprobar para verificar si existió interrupción por recepción.
La hoja de datos dijo:
1 = The EUSART receive buffer, RCREG, is full (cleared when RCREG is read)
0 = The EUSART receive buffer is empty
[/COLOR]
Ese bit se pondrá en 1 cuando contenga datos, tú no debes establecer esa condición.

Hay mas problemas en tu programa y te recomiendo que le des una buena leída a la hoja de datos.
 
Pues ya de vuelta. Voy exponer cómo quedó el programa en basic. Funciona perfectamente.

Código:
'regulador 3 pwm para led rgb con 12f683
'
'
' define osc (8)
'
' defnicion de variables y bit alias
'
' variables variadas
estado Var byte  ' bit de marcas de memoria
tiempos var estado.bit0
secuencias var estado.bit1
pulsado var estado.bit2
m2 var estado.bit3
tiempo var word
temp1 var byte
temp2 var byte
temp3 var byte
' bariables para PWM rgb
PWMrgb var byte
PWMled1 var byte
PWMled2 var byte
PWMled3 var byte
' variables de infrarrojo
contador var word ' aprovechos su alias como punto para retrasos y infrarrojos
infra var contador.byte0 ' esto permite reducir muchos la bariable 16bit
pulso var byte
boton var byte
casilla var byte
codigos var byte [14]
codigo var byte [7]
'
' alias de pin's
'
port_piloto var gpio.1 ' bit usado para el pulsador independiente 
port_ir var gpio.3 ' bit usado para el re eptor infrarrojo
port_led3 var gpio.4 ' control pwm led3
port_led2 var gpio.5 ' control pwm led2
port_led1 var gpio.0 ' control pwm led1
'
' registro configuracion inicial
' 
status=%00000000
option_reg=%00000000 ' configuracion de interruciones primarias
intcon=%00000000 ' configuracion de estatado de interrucciones primarias
pie1=%00000000 ' configuracion de interruciobes perineales
pir1=%00000000 ' estado de las interrucciones perineales
pcon=%00000001 ' configuracion del encendido
eecon1=%00000000 ' configuracion de etado de la eepron
osctune=%00001100 ' configuracion calibrado fino del oscilador
osccon=%01110000 ' configuracion del oscilador
t1con=%00100000 ' conpiguracion temporizador 1, TMR1
t2con=%00000000 ' configuracion temporizador 2, TMR2
cmcon1=%00000000 ' configuracion del comparador por TMR1
ccp1con=%00000000 ' configuracion del registro de control ccp1
cmcon0=%00000111 ' configuracion del comparador operacional
vrcon=%00000000 ' configuracion del voltage de referencia del comparadoronfiguracion del comparador operacional
adcon0=%00000000 ' configuracion de las entradas analogicas
ansel=%00000000 ' ajuste de las entradas analogicas
'
' definicion de puertos inicial
'
trisio=%001000 ' define los bit del puerto entrada o salida
gpio=%000010 ' define los bit del puerto
wpu=%000000 ' define los pull up del puerto
ioc=%000000 ' define como marca de interruccion los bit del puerto
'
' bariables iniciales
'
for temp1=0 to 9
    temp2=temp1+8
    read temp2,codigos[temp1]
next temp1
PWMled1=0
PWMled2=0
PWMled3=0
pwmrgb=108
boton=0
tmr0=247
intcon=%10100000 ' iniciamos interruciones, solo tmr0, perineales apagadas
ON INTERRUPT GOTO interrucciones ' define salto interruciones
goto programa
'
' 
' control de interrucciones
'
'  solo controlando tmr0
DISABLE
interrucciones:
tmr0=247
intcon.2=0
PWMrgb=PWMrgb-1
if pwmrgb=0 then 
    PWMrgb=107
    gpio=%000010 ' borra los 3 pines pwm de los led
endif
if PWMrgb=PWMled1 then port_led1=1 'activa pin's
if PWMrgb=PWMled2 then port_led2=1
if PWMrgb=PWMled3 then port_led3=1
pir1.7=0
resume
enable
'
' programa
'
programa:
if port_ir=0 then gosub infrarrojos ' lectura infrarrojos
if boton>0 then gosub tecla ' acciones

goto programa
'
'  lectura infrarrojos
'
infrarrojos:
contador=0
while port_ir=0 ' leemos el largo del pulso alto de inicio codigo
    contador=contador+1
wend
if contador<180 then salto_ruido ' si es menor seguro sea ruido IR
contador=0
while port_ir=1 ' leemos el largo del pulso bajo de inicio codigo
    contador=contador+1
    if contador>90 then salto_ruido ' si es mayor seguro no sera correcto
wend
pulso=0
repeat
    port_piloto=0
    infra=0
    while port_ir=0 ' cuenta el largo el pulso alto
        infra=infra+1
        if infra>34 then salto_barrido ' si desborda salimos a comprovarlo
    wend
    infra=0
    while port_ir=1 ' cuenta el largo el pulso bajo
        infra=infra+1
        if infra>48 then salto_barrido ' si desborda salimos a comprovarlo
    wend
    casilla=pulso>>3 ' divido entre 4 para encasillar en byte's
    codigo[casilla]=codigo[casilla]<<1 ' desplazo byte para ingresar nuevo bit 
    if infra>18 then codigo[casilla]=codigo[casilla]+1 ' si es un 1 lo suma
    pulso=pulso+1 ' cuenta el largo de bit serial
until pulso=48 ' limite maximo serial 48bit
salto_barrido:
if codigo[0]=codigos[0] then ' comprovamos byte de acceso bajo
    if codigo[1]=codigos[1] then ' comprovamos el byte de acceso alto
        boton=codigo[casilla] ' almaceno el ultimo byte en boton
    endif ' se puede mejorar la veracidad de los  2 
endif     ' ultimos byte's. NEC, RC5, Panasonic48bit
salto_ruido:
port_piloto=1
return
'
' accion de la tecla pulsada del pando infrarrojo
'
tecla:
select case boton ' comprovamos la accion de la tecla pulsada
    case codigos[9]' subir global
        if pwmled1<100 then ' para si un valor llega al maximo
            if pwmled2<100 then
                if pwmled3<100 then
                    if pwmled1>0 then pwmled1=pwmled1+1 ' para mantener a 0
                    if pwmled2>0 then pwmled2=pwmled2+1
                    if pwmled3>0 then pwmled3=pwmled3+1
                endif
            endif
        endif    
    case codigos[8]' bajar global
        if pwmled1>0 then pwmled1=pwmled1-1 ' hasta llegar a 0
        if pwmled2>0 then pwmled2=pwmled2-1
        if pwmled3>0 then pwmled3=pwmled3-1
    case codigos[7]' subir pwm1
        if pwmled3<100 then pwmled3=pwmled3+1
    case codigos[6]' bajar pwm1
        if pwmled3>0 then pwmled3=pwmled3-1
    case codigos[5]' subir pwm2
        if pwmled2<100 then pwmled2=pwmled2+1
    case codigos[4] ' bajar pwm2
        if pwmled2>0 then pwmled2=pwmled2-1
    case codigos[3] ' subir pwm3
        if pwmled1<100 then pwmled1=pwmled1+1
    case codigos[2] ' bajar pwm3
        if pwmled1>0 then pwmled1=pwmled1-1
end select
boton=0
return
'
'
' datos de la eepron 
' 
data @8
data $02,$FD ' 16bit de acceso ir NEC RC5
datA $DF,$5F,$CF,$9F,$7F,$0F ' las 6 telas de subir y bajar
data $4F,$87 ' las dos teclas de subir bajar global
Pongamos que es lo básico, con mi rutina de lectura de IR y solo controlar un led RGB, es lo básisico, pero lo que quiero decir con definirlo todo, es que el programa tenga-una una estructura de flujo de procesos viable, donde se puede ampliar sin problema su programa...

El que me tengo currado es lo mismo, solo que activando el pwm interno.
Los números del mando, las memorias de los colores, tecla de almacenado y otra tecla que hace la secuencias de un color a otro de la memoria, quizás una tecla para aunmentar la velocidad de las secuencias y otra que configuraré para los valores iniciales al encenderse..
(Es una rayada decidir la presencia de la comodidad para usar el chisme.)


Y bueno, lo expuse porque en parte esta idea se me ocurrió aquí peleándome con alguno..
Y que por-lo-menos tengo el trabajo con una definición del duty de 100 y a una frecuencia PWM a 1 Khz, una respuesta de un mando que es correcta su codificación serial y ocupando poco mas de 400 procesos

Un saludo.


Como no escribo correctamente, me editaron el mensaje.
 
Última edición por un moderador:
No, muy mal.
Necesitas poner mas atención sobre las configuraciones de los registros usados en el ejemplo que subí.
De esa forma no va a funcionar tu programa.

El bit 5 (RCIF = EUSART Receive Interrupt Flag bit) del registro PIR1 es el que necesitas comprobar para verificar si existió interrupción por recepción.

Ese bit se pondrá en 1 cuando contenga datos, tú no debes establecer esa condición.

Hay mas problemas en tu programa y te recomiendo que le des una buena leída a la hoja de datos.




muchas grasias dr por su correccion

tengo una duda es posible hacer inerrupciones usart con 2 o mas hserin o solo puedo usar un hserin

disable
If PIR1.5 = 1 Then ; ¿Ocurrió interrupción por recepción EUSART?
Flag_Rx = 1
hserin[dec1 a]
hserin[dec1 b]
hserin[dec1 c]
hserin[dec1 d]
hserin[dec1 e]
.
.
.
endif
resume
enable
end
 
No, porque de esa forma todas las variables contendrán lo que en el momento de la interrupción tenga el primer byte del buffer.
Lo correcto sería hacer uso de un único HSerIn, de ésta forma:
HSerIn ParityLabel, Timeout, Label, [a, b, c, d, e]
Así recibes de una sola vez cada byte del buffer en las variables.

ParityLabel, Timeout y Label, son parámetros opcionales.
La conversión con "Dec x" la puedes hacer posteriormente.
 
Hola muchachos,me preguntaba si hay una función similar en pic basic como la hay en arduino que es la funcion millis() ,en el que por comparación puedo realizar otras tareas como apagar y encender un led sin utilizar la función delay o pause.Ya que si uso la función delay detengo la ejecución del programa y no puedo realizar otras tareas segun el tiempo establecido a menos que use interrupciones.
Por ejemplo que un led parpadee y en simultaneo que pueda con un pulsador encender o apagar otro led.
Debido a mi escaso conocimiento sobre picbasic no lo se.
Muchas gracias por sus respuestas.
 
No, no la hay.,.. Como se hace es con un timer , interrupción de timer o un contador con un pauseus, y quizás con algún otro algoritmo similar.

 
Última edición:
Buenos días compañeros del grupo, estoy haciendo una comunicación usart entre un pic 16f887 y un modulo mp3 el DFPLAYER, la comunicación entre el modulo y el pic ya la tengo y viceversa, el problema esta que cuando quiero enviar una cadena con el Hserout [STR ArrayVar\n] no me envía el dato.
La verdad no entiendo muy bien la parte \n, quiero enviar un comando para especificar el volumen inicial ya que el por defecto lo carga en 30.

Código:
VOL VAR BYTE [7] ; cree la variable array
VOL[0] = $7E ; le cargo el comando a la array 
VOL[1] = $FF
VOL[2] = $06
VOL[3] = $06
VOL[4] = $00
VOL[5] = $00
VOL[6] = $A ;este bit el que le da el Volumen especifico al modulo.
VOL[7] = $EF 

;Cuando quiero enviar el comando lo hago así:
Hserout [STR VOL\8] ; Se supone que acá debería de enviarme los VOL[] cargados con los valores, eso creo ;y entido yo.

Espero me puedan colaborar.
Les agradezco de antemano.
 

Adjuntos

  • SistemadeLlamado.rar
    1.5 KB · Visitas: 34
Última edición:
HSerOut [Str ArrayVar\n] debe funcionar correctamente enviando los datos del arreglo.
\n es para especificar cuantos bytes deben ser enviados.
En tu caso, 8 bytes y como el byte cero también cuenta, la instrucción debe ser así.
HSerOut [Str VOL\7]
 
HSerOut [Str ArrayVar\n] debe funcionar correctamente enviando los datos del arreglo.
\n es para especificar cuantos bytes deben ser enviados.
En tu caso, 8 bytes y como el byte cero también cuenta, la instrucción debe ser así.
HSerOut [Str VOL\7]

Buenas tardes Dark te cuento que tampoco asi me funciono, me ha funcionado asi:

HSerOut [VOL[1], VOL[2], VOL[3], VOL[4], VOL[5], VOL[6], VOL[7], VOL[8]]

ó asi directamente

HSerOut [$7E, $FF, $06, $06, $00, $00, $0F, $EF]

pero de la otra forma no me envia los datos, de la otra forma se reduce codigo, pero bueno tocara dejarlo asi mientras veo donde esta la falla.

Cordial saludo y gracias por responder (y).
 
Pues si funciona como te mencioné, tendrías que entrar en modo de depuración para encontrar el problema.

También se puede usar un bucle for.
Por ahora estoy fuera y con el móvil, pero en cuanto llegue a casa, adjunto dentro de este mismo post, un ejemplo con Str

****Edit****

Adjunto el ejemplo.
Nota:
Si se desea usar la simulación, se debe establecer la vista del Virtual Terminal, en Hex Display Mode.
 

Adjuntos

  • 16F887 RS-232 Str ArrayVar.rar
    46.7 KB · Visitas: 67
Última edición:
Hola D@rk y compañeros

Te cuento que ya encontre el problema, era que estaba enviando mal el comando con la variable array, la estaba enviando desde [1] y no desde [0], y lo que hacia era que me envia un dato de más.
El ejemplo que montaste esta interesate y no sabia que asi tambien se podia cargar el dato, de pronto tienes ejemplos de HSEROUT, HSERIN y LCDOUT STR con sus modificadores la verdad en español es muy poca la info de estas instrucciones y las que estan en ingles no las entiendo bien y el traductor no ayuda :cry:.

Muchas gracias por la ayuda.

Cordial saludo(y)

En la instruccion LCDOUT STR no pude visualizar nada, me salian los caractres del lcd que son en japones creo.
 
Última edición:
Saludos.
Los ejemplos sobre HSerIn y HSerOut, los puedes ver por aquí:
Interfaz RS232 PIC PC (Proyecto Completo VB6)

Y para LCDOut Str, prueba con este programa:
PHP:
; Definición de pines para la pantalla.
Define LCD_DREG PORTD        ; Puerto de datos.
Define LCD_DBIT     4        ; Bit de inicio de datos.
Define LCD_RSREG PORTD        ; Puerto de RS (Register Select)
Define LCD_RSBIT    0        ; Pin para RS
Define LCD_EREG PORTD        ; Puerto de E (Enable)
Define LCD_EBIT     1        ; Pin para E

; Declaración de variables:
LCDChar Var Byte[10]        ; Arreglo para los caracteres a mostrar en la pantalla.

Inicio:
    ANSEL = 0               ; Puerto A como digital
    
    ; Cargar el arreglo con el mensaje.
    LCDChar[0] = "H"
    LCDChar[1] = "o"
    LCDChar[2] = "l"
    LCDChar[3] = "a"
    LCDChar[4] = " "
    LCDChar[5] = "M"
    LCDChar[6] = "u"
    LCDChar[7] = "n"
    LCDChar[8] = "d"
    LCDChar[9] = "o"
    LCDChar[10] = " "

    LCDOut $FE,1            ; Inicializa o borra la pantalla.
    LCDOut $FE,$80,"Ej: Str ArrayVar"
    LCDOut $FE,$C0,Str LCDChar\10

Programa:    
    While 1 = 1
       Toggle PORTA.0
       Pause 500
    Wend
    
    End
 
Y para LCDOut Str, prueba con este programa:
PHP:
    LCDOut $FE,1            ; Inicializa o borra la pantalla.
    LCDOut $FE,$80,"Ej: Str ArrayVar"
    LCDOut $FE,$C0,Str LCDChar\10

    
    End

Hola D@rk y compañeros, bueno lo que pretendia hacer con LCDOut $FE,$C0,Str LCDChar\10 era que si recibia un dato lo cargara en una variable array y visualizarlo con esa instruccion, pero me muestra caracteres del LCD, pero para mas facilidad cargue las arrays en la instruccion y funciona bn.

Tengo una duda con respecto a trabajar con las comunicaciones, cuando uso HSERIN y SERIN2 se me crea un conflicto y el puerto por el cual quiero recibir los datos de un modulo rf empieza a recibir datos sin estar enviando nada, fluctua, en este caso como debo manejar las instrucciones, en rutinas separadas o manejar el HSERIN por interrupciones, otra duda que tengo es cuando se trabaja por los modulos hardware del pic ellos trabajan en segundo plano mientras uno sigue con el codigo?.
El modulo DFPLAYER MP3 trabaja por HSERIN y el modulo RF por SERIN2.

Cordial saludo y un abrazo
 
Los módulos de R.F. tienen mucho ruido en su salida y por ese motivo se tiene que usar un protocolo de codificación y decodificación.

Mira este post, tal vez te pueda servir:
PIC12F675 y módulo de R.F, no recibe datos

Hola D@rk, se me olvidaba mencionar que el puerto oscilaba sin tener el modulo conectado al puerto, utilice varios puertos y siempre pasaba lo mismo, cuando colocaba el puente en el pin y lo tocaba en la otra punta empezaba a oscilar, ahi fuen donde descarte el modulo, yo trabaje los modulos antes y no me presentaron ningun problema, claro que los use con unos pic 16f628a y ahora lo iba a implementar en el 16f887.

Otra de las causas no se si de pronto sea la protoboard en las que monte el circuito son unas wish y no se que tal sean.

Cordial saludo
 
Coloca una resistencia pull-up de 10 kΩ en el pin Rx.
No es conveniente que el microcontrolador funcione con los periféricos desconectados.

Existen algunas Protoboards que son pésimas.
Hace poco tiré una a la basura porque medía bastante resistencia de lado a lado. (Hasta 150 Ω)
 
Última edición:
Atrás
Arriba