¡Hola!
Estoy intentando sacar lo que me llega por la UART por el módulo LCD usando la función Lcd_Chr_CP(). El primer problema con el que me encontré es que mikroC parece trabajar bien sólo con módulos de 40 caracteres de ancho. Digo esto porque después de escribir 24 caracteres tengo que escribir 16 más (que no se muestran) para que salte de línea. Esto lo he solventado llevando manualmente la posición del cursor.
He descubierto que tengo un problema. Después de encender el montaje, cuando mando un array de bytes al PIC, sólo recibe los tres primeros, independientemente de cuantos mande. Cuando vuelvo a mandar datos ya los recibe todos. Sé que es un problema de la recepción en la UART y no a la hora de mostrarlo en el LCD porque llevo la cuenta de caracteres recibidos.
Un ejemplo. Pongamos que mando "xxxx" (sin '\n' al final). El LCD muestra "xxx". A continuación mando "xxxxxx" y el LCD muestra "xxxxxxxxx". Con el código modificado que adjunto a continuación, que muestra la cuenta de caracteres recibidos, mandando lo mismo se mostraría "123" y "123456789". Con lo que claramente hay un byte sin recibir. Lo curioso es que no me pasa sólo tras inicializar la UART, sino también al cambiar de línea en el display con Lcd_Cmd(_LCD_SECOND_ROW).
#define NROWS 2
#define NCOLS 24
sbit LCD_RS at RB0_bit;
sbit LCD_EN at RB1_bit;
sbit LCD_D4 at RA0_bit;
sbit LCD_D5 at RA1_bit;
sbit LCD_D6 at RA2_bit;
sbit LCD_D7 at RA3_bit;
sbit LCD_RS_Direction at TRISB0_bit;
sbit LCD_EN_Direction at TRISB1_bit;
sbit LCD_D4_Direction at TRISA0_bit;
sbit LCD_D5_Direction at TRISA1_bit;
sbit LCD_D6_Direction at TRISA2_bit;
sbit LCD_D7_Direction at TRISA3_bit;
void main() {
char character;
unsigned char col=0;
unsigned char row=0;
unsigned char recibidos=0;
OSCCON=0x7E;
ANSEL=0;
TRISA=0;
UART1_Init(9600);
Lcd_Init();
Lcd_Cmd(_LCD_CURSOR_OFF);
Lcd_Cmd(_LCD_CLEAR);
while(1) {
if(UART1_Data_Ready()) {
character = UART1_Read();
if (0xFE !=character) {
if('\n'!=character) {
recibidos++;
if(0==col) {
if(0==row) {
Lcd_Cmd(_LCD_CLEAR);
}
else
Lcd_Cmd(_LCD_SECOND_ROW);
}
Lcd_Chr_CP(recibidos+48);
}
else
col=NCOLS-1;
col++;
if(NCOLS==col) {
col=0;
row++;
if(NROWS==row)
row=0;
}
}
else {
while(!UART1_Data_Ready());
character = UART1_Read();
switch (character) {
case 1: Lcd_Cmd(_LCD_CLEAR); row=0; col=0; break;
case 2: Lcd_Cmd(_LCD_RETURN_HOME); break;
case 12: Lcd_Cmd(_LCD_CURSOR_OFF); break;
case 13: Lcd_Cmd(_LCD_BLINK_CURSOR_ON); break;
case 14: Lcd_Cmd(_LCD_UNDERLINE_ON); break;
case 16: Lcd_Cmd(_LCD_MOVE_CURSOR_LEFT);
col--;
if(NCOLS<col) {
col=NCOLS-1;
row--;
if(NROWS<row)
row=0;
}
break;
case 20: Lcd_Cmd(_LCD_MOVE_CURSOR_RIGHT);
col++;
if(NCOLS==col) {
col=0;
row++;
if(NROWS==row)
row=0;
}
break;
case 24: Lcd_Cmd(_LCD_SHIFT_LEFT); break;
case 28: Lcd_Cmd(_LCD_SHIFT_RIGHT); break;
case 192: Lcd_Cmd(_LCD_SECOND_ROW); row=1; col=0; break;
}
}
}
}
}
En un primer momento pensé que fuera que el buffer de recepción de la UART desbordara, pero no se explica que lo de recibir sólo tres bytes sea sólo en la primera transmisión y no en las demás.
Por si sirve de algo, así es como mando los datos:
echo -n xxxx >/dev/ttyS1
echo -n xxxxxx >/dev/ttyS1
Y esta es la configuración de la UART de mi PC según stty:
$ stty -F /dev/ttyS1
speed 9600 baud; line = 0;
min = 1; time = 0;
-brkint -icrnl ixoff -imaxbel
-opost -onlcr
-isig -icanon -iexten -echo -echoe
Ya sé que igual usando interrupciones en vez de polling me quitaría de problemas, pero quisiera saber por qué ocurre esto.