Tengo la placa de desarrollo explorer 16 equipada con el PIC24FJ128GA010. Escribí un código C para escribir algo en la pantalla LCD y un LED parpadeando después de eso. Escribí el mismo código en ensamblaje y ambos códigos funcionan. Noté algo después de programar la placa con el código ensamblador, es que cuando se desconecta y se vuelve a conectar la alimentación, la pantalla LCD no muestra nada, debo reprogramar el dispositivo nuevamente desde MPLAB X, pero en el código C la placa funciona correctamente.
Y alguna otra cosa extraña, en ensamblador escribí una función de retraso simple que depende de disminuir un valor y una rama si no es una instrucción cero, ¡parece que el código entra en un ciclo infinito porque el valor nunca se incrementa de alguna manera! Descubrí esto mientras estaba depurando.
#define FOSC (8000000ULL)
#define FCY (FOSC/2)
#pragma config JTAGEN=OFF, GCP=OFF,GWRP=OFF , COE=OFF , FWDTEN=OFF, ICS=PGx2
#pragma config FCKSM=CSDCMD, OSCIOFNC=OFF,POSCMOD=XT, FNOSC=PRI
#include <libpic30.h>
#include <p24FJ128GA010.h>
#include <xc.h>
#define LCD_RS PORTBbits.RB15
#define LCD_RW PORTDbits.RD5
#define LCD_E PORTDbits.RD4
void LCD_SendChar(char value)
{
PORTE = value;
LCD_RS = 1;
LCD_E = 1;
Nop();
LCD_E = 0;
__delay_ms(5);
}
void LCD_SendCmd(int cmd)
{
PORTE = cmd;
LCD_RS = 0;
LCD_E = 1;
Nop();
LCD_E = 0;
__delay_ms(5);
}
void LCD_SendString(char* value)
{
while(*value != 0)
LCD_SendChar(*value++);
}
void LCD_Init()
{
TRISE = 0x00;
TRISDbits.TRISD4 = 0;
TRISDbits.TRISD5 = 0;
TRISBbits.TRISB15 = 0;
__delay_ms(50);
// Function Set
// 0 0 1 8/4 2/1 10/7 x x | 0x20 - 0x3F
LCD_SendCmd(0x38);
// Display ON/OFF and Cursor
// 0 0 0 0 1 D U B | 0x08 - 0x0F
LCD_SendCmd(0x0E);
// Character Entry Mode
// 0 0 0 0 0 1 1/D S | 0x04 - 0x07
LCD_SendCmd(0x06);
// Clear Display
// 0 0 0 0 0 0 0 1
LCD_SendCmd(0x01);
// Display and Cursor Home
// 0 0 0 0 0 0 1 x
LCD_SendCmd(0x02);
}
int main()
{
LCD_Init();
LCD_SendCmd(0x82);
LCD_SendString("Hello World!");
TRISA = 0x00;
LATA = 0xAA;
while(1) {
LATA ^= 0xFF;
__delay_ms(500);
}
return (0);
}
;.include "p24fj128ga010.inc"
.include "xc.inc"
config __CONFIG2, POSCMOD_XT & OSCIOFNC_OFF & FCKSM_CSDCMD & FNOSC_PRI
config __CONFIG1, JTAGEN_OFF & GCP_OFF & GWRP_OFF & COE_OFF & FWDTEN_OFF & ICS_PGx2
.global _main
.text
_main:
CALL LCD_INIT
MOV #0x82, W0
CALL LCD_SendCmd
MOV #'H', W0
CALL LCD_SendChar
MOV #'E', W0
CALL LCD_SendChar
MOV #'L', W0
CALL LCD_SendChar
MOV #'L', W0
CALL LCD_SendChar
MOV #'O', W0
CALL LCD_SendChar
MOV #' ', W0
CALL LCD_SendChar
MOV #'W', W0
CALL LCD_SendChar
MOV #'O', W0
CALL LCD_SendChar
MOV #'R', W0
CALL LCD_SendChar
MOV #'L', W0
CALL LCD_SendChar
MOV #'D', W0
CALL LCD_SendChar
MOV #'!', W0
CALL LCD_SendChar
CLR TRISA
CLR LATA
COM LATA
L: GOTO L
LCD_INIT:
CLR TRISE
BCLR TRISD, #4
BCLR TRISD, #5
BCLR TRISB, #15
CALL Delay_1
;Function Set
;0 0 1 8/4 2/1 10/7 x x | 0x20 - 0x3F
MOV #0x38, W0
CALL LCD_SendCmd
;Display ON/OFF and Cursor
;0 0 0 0 1 D U B | 0x08 - 0x0F
MOV #0x0E, W0
CALL LCD_SendCmd
;Character Entry Mode
;0 0 0 0 0 1 1/D S | 0x04 - 0x07
MOV #0x06, W0
CALL LCD_SendCmd
;Clear Display
;0 0 0 0 0 0 0 1
MOV #0x01, W0
CALL LCD_SendCmd
;Display and Cursor Home
;0 0 0 0 0 0 1 x
MOV #0x02, W0
CALL LCD_SendCmd
RETURN
LCD_SendCmd:
MOV W0, PORTE
BCLR PORTB, #15
BSET PORTD, #4
NOP
BCLR PORTD, #4
CALL Delay_1
RETURN
LCD_SendChar:
MOV W0, PORTE
BSET PORTB, #15
BSET PORTD, #4
NOP
BCLR PORTD, #4
CALL Delay_1
RETURN
Delay_1:
REPEAT #0xD00
NOP
RETURN
Delay:
REPEAT #16383
NOP
RETURN
Delay_1s:
MOV #0xFFFF, W0
MOV W0, G
R1: DEC G
REPEAT #0x3D
NOP
BRA NZ, R1
RETURN
.end
ACTUALIZACIÓN: el dispositivo no lee ningún controlador LCD programado (C o ensamblaje) en el reinicio de energía, por lo tanto, no muestra nada en la pantalla LCD, pero todo lo demás funciona: \
Francamente, tu código apesta. Debe detenerse y aprender algunas técnicas de codificación antes de continuar. Cuanto más persista en hacer las cosas de esta manera, más doloroso será.
En primer lugar, no hay un solo comentario a la vista. Eso no solo es descaradamente irresponsable, lo priva de una verificación de cordura de primer paso, le generará trabajo en el futuro, sino que también es francamente grosero pedirle a otros que lo vean.
Hacer cronometraje por ocupado-esperar es otra mala técnica de programación:
Retraso_1s: MOV #0xFFFF, W0 MOV W0, G R1: DEC G REPETIR #0x3D NOP SUJETADOR NZ, R1 DEVOLVER
Los problemas con esto incluyen:
Una manera mucho mejor de hacer un retraso de 1 segundo es usar un temporizador. El valor del período del temporizador se calcularía en el momento de la construcción a partir del valor deseado y la velocidad del reloj de la instrucción. La frecuencia de reloj de la instrucción se definiría con otras constantes en un lugar central que alguien puede verificar fácilmente cuando se cambia la frecuencia de reloj o se transfiere el proyecto a un PIC diferente. Un retraso de hasta 1 s puede requerir el conteo de múltiples tics más cortos derivados de un temporizador.
La temporización puede ser necesaria en varios puntos de un proyecto, de modo que puede ser útil configurar una interrupción periódica desde un temporizador y luego hacer que la rutina de interrupción derive varios relojes o establezca indicadores utilizados por el resto del sistema. 1 ms (velocidad de 1 kHz) suele ser un período útil para esto. Para esperar 1 segundo, por ejemplo, contaría 1000 tics del reloj global de 1 ms. Es posible que la configuración del temporizador en esta rutina de interrupción deba ajustarse a medida que cambia el hardware, pero el resto del sistema se basa en los pulsos de reloj regulares de 1 ms y es completamente independiente del tiempo del ciclo de instrucción, los retrasos de interrupción, etc.
¡Su problema es que tiene un "bucle de bloqueo" en su código ASM! En su lugar, debería tener un comando final. Parece que el comando final está fuera de lugar, debería estar al final de main, NO al final de las subrutinas.
venny
venny
3bdalla
3bdalla
3bdalla
crosley
3bdalla
venny
adam lorenzo
venny
3bdalla
venny
3bdalla
venny
3bdalla
Voluntad
3bdalla