I've got a 16F877A reading serial data from a digital multimeter. The DMM data can be read using HyperT on the PC; the idea is to try using ucontrollers to decrease costs and try to display the available data on a 2x16 LCD. So far I've got a simulated circuit on Proteus and a physical circuit from a previous project. The current problem is this:
In the Proteus circuit, whenever I start the read, the LCD never reads the entire data being sent, just the first few characters. For example, suppose that the data has a format of +0000.32 DV. On HyperT the data is fully shown, but the LCD will only display '+00', then hangs.
Here's my code:
I'm using the examples provided by Microchip, using MPLAB 8.xx. Here's the other files:
This is the header where the baud rate and oscillator clocks are defined:
I once tried changing the code a bit so that it reads and echoes keyboard chars, and the LCD works. If I press the keys one by one, it displays just fine. However, when I press the keys really fast, the LCD freezes again. I suspect the PIC didn't have enough time to read each cahracter being sent and this freezes up the PIC. Might be wrong though. I attached the Proteus circuit for reference.
In the Proteus circuit, whenever I start the read, the LCD never reads the entire data being sent, just the first few characters. For example, suppose that the data has a format of +0000.32 DV. On HyperT the data is fully shown, but the LCD will only display '+00', then hangs.
Here's my code:
Code:
#include <stdio.h>
#include <htc.h>
#include "usart.h"
#ifndef _XTAL_FREQ
// Unless specified elsewhere, 4MHz system frequency is assumed
#define _XTAL_FREQ 20000000
#endif
#define rs RB4 //RS pin of the LCD display
#define e RB5 //E pin of the LCD display
#define lcd_data PORTD //LCD 8-bit data PORT
void delay(unsigned long data);
void send_config(unsigned char data);
void send_char(unsigned char data);
void lcd_goto(unsigned char data);
void lcd_clr(void);
void send_string(const char *s);
void init_all(void);
void displaylcdchar(int line, unsigned short text);
void displaylcdint(int line, int text);
int i;
void main(void)
{
unsigned char input;
INTCON=0; // purpose of disabling the interrupts.
init_comms(); // set up the USART - settings defined in usart.h
init_all();
i =0;
// Output a message to prompt the user for a keypress
printf("\rPress a key and I will echo it back:\n");
lcd_goto(0);
send_string("Press a key and");
__delay_ms(500);
__delay_ms(500);
while(1)
{
if(i==16)
{
//printf("\n");
i=0;
}
input = getch();
lcd_goto(i);
send_char(input);
printf("\rI detected [%c]",input);
i++;
}
}
void init_all(void) // initialise all values and variables
{
TRISA = 0b00001111;
//PORTA = 0xFF;
TRISB = 0x00; // port B as output
PORTB = 0xFF; //clear portB
//TRISC = 0x00; // port C as output
//PORTC = 0x00; //clear portC
TRISD = 0b00000000; //port d as input
PORTD = 0x00;
TRISE = 0b00000000; //all outputs
//LCD initialise
send_config(0b00000001); //clear display at lcd
send_config(0b00000010); //lcd return to home
send_config(0b00000110); //entry mode-cursor increase 1
send_config(0b00001100); //display on, cursor off and cursor blink off
send_config(0b00111000); //function set
ADCON1 = 0x06; //sets the PORTA to be all digital I/Os
}
void delay(unsigned long data) //delay function, the delay time
{ //depend on the given value
for( ;data>0;data--);
}
void send_config(unsigned char data) //send lcd configuration
{
rs=0; //set lcd to configuration mode
lcd_data=data; //lcd data port = data
e=1; //pulse e to confirm the data
delay(50);
e=0;
delay(50);
}
void send_char(unsigned char data) //send lcd character
{
rs=1; //set lcd to display mode
lcd_data=data; //lcd data port = data
e=1; //pulse e to confirm the data
delay(10);
e=0;
delay(10);
}
void lcd_goto(unsigned char data) //set the location of the lcd cursor
{ //if the given value is (0-15) the
if(data<16) //cursor will be at the upper line
{ //if the given value is (20-35) the
send_config(0x80+data); //cursor will be at the lower line
} //location of the lcd cursor(2X16):
else // -----------------------------------------------------
{ // | |00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15| |
data=data-20; // | |20|21|22|23|24|25|26|27|28|29|30|31|32|33|34|35| |
send_config(0xc0+data); // -----------------------------------------------------
}
}
void lcd_clr(void) //clear the lcd
{
send_config(0x01);
delay(600);
}
void send_string(const char *s) //send a string to display in the lcd
{
while (s && *s)send_char (*s++);
}
void uart_send(unsigned char data)
{
while(TXIF==0); //only send the new data after
TXREG=data; //the previous data finish sent
}
I'm using the examples provided by Microchip, using MPLAB 8.xx. Here's the other files:
Code:
#include <htc.h>
#include <stdio.h>
#include "usart.h"
void
putch(unsigned char byte)
{
/* output one byte */
while(!TXIF) /* set when register is empty */
continue;
TXREG = byte;
}
unsigned char
getch() {
/* retrieve one byte */
while(!RCIF) /* set when register is not empty */
continue;
return RCREG;
}
unsigned char
getche(void)
{
unsigned char c;
putch(c = getch());
return c;
}
This is the header where the baud rate and oscillator clocks are defined:
Code:
#ifndef _SERIAL_H_
#define _SERIAL_H_
#define BAUD 9600
#define FOSC 20000000L
#define NINE 0 /* Use 9bit communication? FALSE=8bit */
#define DIVIDER ((int)(FOSC/(16UL * BAUD) -1))
#define HIGH_SPEED 1
#if NINE == 1
#define NINE_BITS 0x40
#else
#define NINE_BITS 0
#endif
#if HIGH_SPEED == 1
#define SPEED 0x4
#else
#define SPEED 0
#endif
#if defined(_16F87) || defined(_16F88)
#define RX_PIN TRISB2
#define TX_PIN TRISB5
#else
#define RX_PIN TRISC7
#define TX_PIN TRISC6
#endif
/* Serial initialization */
#define init_comms()\
RX_PIN = 1; \
TX_PIN = 1; \
SPBRG = DIVIDER; \
RCSTA = (NINE_BITS|0x90); \
TXSTA = (SPEED|NINE_BITS|0x20)
void putch(unsigned char);
unsigned char getch(void);
unsigned char getche(void);
#endif
I once tried changing the code a bit so that it reads and echoes keyboard chars, and the LCD works. If I press the keys one by one, it displays just fine. However, when I press the keys really fast, the LCD freezes again. I suspect the PIC didn't have enough time to read each cahracter being sent and this freezes up the PIC. Might be wrong though. I attached the Proteus circuit for reference.