|
|
View previous topic :: View next topic |
Author |
Message |
petur
Joined: 26 Mar 2010 Posts: 5
|
PIC16F628A with PICDEM4 LCD problem - help needed |
Posted: Mon Apr 12, 2010 10:39 am |
|
|
Hy everybody,
I need your help. I'm a newbie in programming microcontrollers.
I am using PICDEM 4 DEMO Board with a PIC16F628A mCtrl.
I want to display something on the LCD and to send the message through RS232 .. but it's not working, and I don't know why. Only the led on PIN_A0 is shining ... that's all
-- I'm not using the right pins, fuses ... or what is the problem ? Please help me.
Here is my code
Code: |
#include "only_lcd.h"
#define LCD_ENABLE_PIN PIN_B4
#define LCD_RS_PIN PIN_B6
#define LCD_RW_PIN PIN_B5
#define LCD_TYPE 2
#include <lcd.c>
void main()
{
output_high(PIN_A0);
lcd_init();
lcd_putc("\fReady...\n");
lcd_putc('a');
// TODO: USER CODE!!
}
|
The content of lcd.h
Code: |
#include <16F628A.h>
#FUSES NOWDT //No Watch Dog Timer
#FUSES INTRC //Internal RC Osc
#FUSES PUT //Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOMCLR //Master Clear pin used for I/O
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#use delay(clock=2000000)
#use rs232(baud=9600,parity=N,xmit=PIN_B5,rcv=PIN_B2,bits=8)
|
The LCD.C provided by CCS
Code: |
///////////////////////////////////////////////////////////////////////////
//// LCDD.C ////
//// Driver for common LCD modules ////
//// ////
//// lcd_init() Must be called before any other function. ////
//// ////
//// lcd_putc(c) Will display c on the next position of the LCD. ////
//// The following have special meaning: ////
//// \f Clear display ////
//// \n Go to start of second line ////
//// \b Move back one position ////
//// ////
//// lcd_gotoxy(x,y) Set write position on LCD (upper left is 1,1) ////
//// ////
//// lcd_getc(x,y) Returns character at position x,y on LCD ////
//// ////
///////////////////////////////////////////////////////////////////////////
//// (C) Copyright 1996,2003 Custom Computer Services ////
//// This source code may only be used by licensed users of the CCS C ////
//// compiler. This source code may only be distributed to other ////
//// licensed users of the CCS C compiler. No other use, reproduction ////
//// or distribution is permitted without written permission. ////
//// Derivative programs created using this software in object code ////
//// form are not restricted in any way. ////
///////////////////////////////////////////////////////////////////////////
// As defined in the following structure the pin connection is as follows:
// D0 enable
// D1 rs
// D2 rw
// D4 D4
// D5 D5
// D6 D6
// D7 D7
//
// LCD pins D0-D3 are not used and PIC D3 is not used.
// Un-comment the following define to use port B
struct lcd_pin_map { // This structure is overlayed
BOOLEAN enable; // on to an I/O port to gain
BOOLEAN rs; // access to the LCD pins.
BOOLEAN rw; // The bits are allocated from
BOOLEAN unused; // low order up. ENABLE will
int data : 4; // be pin B0.
} lcd;
#define use_portb_lcd TRUE
#if defined use_portb_lcd
#locate lcd = getenv("sfr:PORTB") // This puts the entire structure over the port
#define set_tris_lcd(x) set_tris_b(x)
#else
#locate lcd = getenv("sfr:PORTD") // This puts the entire structure over the port
#define set_tris_lcd(x) set_tris_d(x)
#endif
#define lcd_type 2 // 0=5x7, 1=5x10, 2=2 lines
#define lcd_line_two 0x40 // LCD RAM address for the second line
BYTE const LCD_INIT_STRING[4] = {0x20 | (lcd_type << 2), 0xc, 1, 6};
// These bytes need to be sent to the LCD
// to start it up.
// The following are used for setting
// the I/O port direction register.
struct lcd_pin_map const LCD_WRITE = {0,0,0,0,0}; // For write mode all pins are out
struct lcd_pin_map const LCD_READ = {0,0,0,0,15}; // For read mode data pins are in
BYTE lcd_read_byte() {
BYTE low,high;
set_tris_lcd(LCD_READ);
lcd.rw = 1;
delay_cycles(1);
lcd.enable = 1;
delay_cycles(1);
high = lcd.data;
lcd.enable = 0;
delay_cycles(1);
lcd.enable = 1;
delay_us(1);
low = lcd.data;
lcd.enable = 0;
set_tris_lcd(LCD_WRITE);
return( (high<<4) | low);
}
void lcd_send_nibble( BYTE n ) {
lcd.data = n;
delay_cycles(1);
lcd.enable = 1;
delay_us(2);
lcd.enable = 0;
}
void lcd_send_byte( BYTE address, BYTE n ) {
lcd.rs = 0;
while ( bit_test(lcd_read_byte(),7) ) ;
lcd.rs = address;
delay_cycles(1);
lcd.rw = 0;
delay_cycles(1);
lcd.enable = 0;
lcd_send_nibble(n >> 4);
lcd_send_nibble(n & 0xf);
}
void lcd_init() {
BYTE i;
set_tris_lcd(LCD_WRITE);
lcd.rs = 0;
lcd.rw = 0;
lcd.enable = 0;
delay_ms(15);
for(i=1;i<=3;++i) {
lcd_send_nibble(3);
delay_ms(5);
}
lcd_send_nibble(2);
for(i=0;i<=3;++i)
lcd_send_byte(0,LCD_INIT_STRING[i]);
}
void lcd_gotoxy( BYTE x, BYTE y) {
BYTE address;
if(y!=1)
address=lcd_line_two;
else
address=0;
address+=x-1;
lcd_send_byte(0,0x80|address);
}
void lcd_putc( char c) {
switch (c) {
case '\f' : lcd_send_byte(0,1);
delay_ms(2);
break;
case '\n' : lcd_gotoxy(1,2); break;
case '\b' : lcd_send_byte(0,0x10); break;
default : lcd_send_byte(1,c); break;
}
}
char lcd_getc( BYTE x, BYTE y) {
char value;
lcd_gotoxy(x,y);
while ( bit_test(lcd_read_byte(),7) ); // wait until busy flag is low
lcd.rs=1;
value = lcd_read_byte();
lcd.rs=0;
return(value);
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Apr 12, 2010 11:44 am |
|
|
Quote: |
#include <16F628A.h>
#FUSES NOWDT //No Watch Dog Timer
#FUSES INTRC //Internal RC Osc
#FUSES PUT //Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOMCLR //Master Clear pin used for I/O
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#use delay(clock=2000000)
#use rs232(baud=9600,parity=N,xmit=PIN_B5,rcv=PIN_B2,bits=8) |
In your code above, you are attempting to configure the program
to run with a 2 MHz internal oscillator.
Download the 16F628A data sheet:
http://ww1.microchip.com/downloads/en/DeviceDoc/40044G.pdf
Look in the "Special Features" section of the data sheet. It explains
the internal oscillator options. It runs at 4 MHz, not 2 MHz:
Quote: |
14.2.4 PRECISION INTERNAL 4 MHZ OSCILLATOR
|
Also, I downloaded the PicDem4 User's guide:
http://ww1.microchip.com/downloads/en/DeviceDoc/51337b.pdf
The LCD on this board is not connected directly to the PIC. It goes
through an "i/o expander" chip. This means that all the normal LCD
drivers (including the one from CCS) won't work on this board.
Quote: |
A.14 LCD DISPLAY
The LCD display has two lines with 16 characters per line. It is connected
to the I/O expander (U3) which can be driven by all three device sockets.
|
To make the LCD on this board work with CCS, you would have to
download the "PICDEMâ„¢ 4 Software and Demo Files" from this page:
http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en010054
Inside the Zip file, there is an ASM source file called 16IoExpLcd.asm.
It shows how to talk to the I/O Expander chip. This ASM code would
have to be translated to CCS. Or at least, the protocol would have to
be analyzed and understood. Then a CCS program could be written that
would let you use the LCD. |
|
|
petur
Joined: 26 Mar 2010 Posts: 5
|
|
Posted: Mon Apr 12, 2010 4:35 pm |
|
|
Thanks for the reply ... I've just modified the address of the lines based on the ASM examples, but I don't think is enough. Can you help me with an example ? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Apr 12, 2010 4:50 pm |
|
|
Just changing the address somewhere won't do anything.
If you take the time to look at the ASM source files in this Zip file
from the Microchip page that I linked earlier,
Quote: | PICDEMâ„¢ 4 Software and Demo Files |
you will see that the Microchip PicDem 4 LCD driver is built around this low level routine:
Quote: |
; Function: SPImbbWrite1Byte
;
; PreCondition: SPImbbInit must have already been invoked.
;
; Overview:
; This routine is used to transmit 1 byte through SPI,
; Bit-Banged Mode
|
It's in this file in the Zip package:
Quote: | \picdem 4 demo code\picdem 4 16f demo\16spimb.asm |
All the routines in all the LCD files would have to be translated to CCS.
The whole job must be done. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Apr 18, 2010 4:17 pm |
|
|
Here is a test program and an LCD driver for the PicDem 4 board.
I don't have a PicDem 4 board to test this code on. But I compiled
their MPASM firmware and programmed it into a 16F628, and then
I looked at the I/O Expander signals with a logic analyzer. The
signals produced by the code below look very similar to the Microchip
firmware. So I think it has a good chance to work. I did this with
vs. 4.106 of the CCS compiler.
Many of the delays used in the LCD driver are very long. I think
they are much longer than is really needed. But, the Microchip
firmware has these long delays in it, so I kept them the same
in the code below. Also, I kept the init values exactly the same.
Here's the test program. It should be saved as "PicDem4_Test.c".
It's the main source program for the project.
Code: |
#include <16F628.h>
#fuses INTRC_IO, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock = 4000000)
// We can't use the hardware UART at the same time as the LCD
// because they share pin B1.
//#use rs232(baud=9600, xmit=PIN_B2, rcv=PIN_B1, ERRORS)
#include "PicDem4_lcd.c" // This is the PicDem 4 LCD driver
#define PICDEM4_PERIPH_CS PIN_B3
// The RS-232 level converter chips, LIN bus transceiver,
// and Motor Driver chip on the PicDem4 board are all
// enabled or disabled by one PIC pin (Pin B3).
#define disable_peripherals() output_low(PICDEM4_PERIPH_CS)
#define enable_peripherals() output_high(PICDEM4_PERIPH_CS)
//==========================
void main()
{
disable_peripherals();
delay_ms(1000); // Start-up delay for i/o expander
lcd_init(); // Always call this first.
printf(lcd_putc,"Hello World\n");
printf(lcd_putc,"This is line 2");
delay_ms(2000);
printf(lcd_putc,"\fHi There\n");
printf(lcd_putc,"PicDem4 LCD");
while(1);
}
|
This is the LCD driver. It should be saved as "PicDem4_lcd.c".
Code: |
// This is a PicDem4 LCD driver for the CCS compiler.
// This driver writes to the LCD by writing to the
// I/O Expander on the PicdDem4 board, using SPI.
// The LCD is connected to the I/O Expander.
#define SDO PIN_B1 // SPI data
#define SCK PIN_B4 // SPI clock
#define LCD_E_BITMASK 0x10
#define LCD_RS_BITMASK 0x40
#define LCD_LINE2_ADDRESS 0x40
// The value is transmitted MSB first, in SPI Mode 2,
// to the I/O Expander chip on the PicDem4 board.
void spi_write_byte(int8 value)
{
int8 i;
for(i = 0; i < 8; i++)
{
output_low(SDO);
output_high(SCK);
if(bit_test(value, 7))
output_high(SDO);
else
output_low(SDO);
value <<= 1;
delay_us(4);
output_low(SCK);
delay_us(6);
}
output_low(SDO);
}
//----------------------------------------------
void lcd_send_nibble(int8 address, int8 value)
{
value &= 0x0F;
if(address)
{
value |= LCD_RS_BITMASK;
}
SPI_write_byte(value);
delay_us(5);
SPI_write_byte(value | LCD_E_BITMASK);
delay_us(5);
SPI_write_byte(value);
delay_us(5);
}
//----------------------------------------------
// Send one byte to the LCD via the I/O expander.
void lcd_send_byte(int8 address, int8 value)
{
delay_ms(40); // Possibly this delay can be reduced
lcd_send_nibble(address, value >> 4); // Send high nibble first
lcd_send_nibble(address, value & 0x0F);
}
//--------------------------------
void lcd_init(void)
{
output_low(SCK);
output_low(SDO);
delay_ms(1);
spi_write_byte(0x00); // Init I/O Expander
delay_ms(150);
lcd_send_nibble(0, 3);
delay_ms(40);
lcd_send_nibble(0, 3);
delay_ms(1);
lcd_send_nibble(0, 3);
delay_ms(1);
lcd_send_nibble(0, 2);
delay_ms(40);
lcd_send_byte(0, 0x28); // Function set
lcd_send_byte(0, 0x0D); // Display = ON
lcd_send_byte(0, 0x01); // Display clear
lcd_send_byte(0, 0x06); // Entry Mode
lcd_send_byte(0, 0x80); // DDRAM address 0
}
//----------------------------
void lcd_gotoxy(int8 x, int8 y)
{
int8 address;
if(y != 1)
address = LCD_LINE2_ADDRESS;
else
address=0;
address += x-1;
lcd_send_byte(0, 0x80 | address);
}
//----------------------------------------
void lcd_putc(char c)
{
switch(c)
{
case '\f':
lcd_send_byte(0,1);
delay_ms(2);
break;
case '\n':
lcd_gotoxy(1,2);
break;
case '\b':
lcd_send_byte(0,0x10);
break;
default:
lcd_send_byte(1,c);
break;
}
}
|
|
|
|
bmmribeiro
Joined: 12 May 2012 Posts: 5
|
|
Posted: Sat May 12, 2012 5:01 pm |
|
|
That code really works?
I want to program PICDEM4 in C (obviously sending messages to the LCD display) but using HI-TECH PICC instead CCS compiler.
Anybody can help me?... |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
bmmribeiro
Joined: 12 May 2012 Posts: 5
|
|
Posted: Sat May 12, 2012 5:25 pm |
|
|
Thanks for your reply.
However, is there any feedback about the correct functionality of your code above in CCS?
If it works, I can try to translate the code to be understandable for other compiler... |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat May 12, 2012 5:54 pm |
|
|
If there was feedback, it would be posted in this thread. |
|
|
bmmribeiro
Joined: 12 May 2012 Posts: 5
|
|
Posted: Sun May 13, 2012 4:10 am |
|
|
You are right.
I'm using PIC18f1320 (18pin). I don't understand how my PIC can comunicate with the PIC16F72 (20pin-QFN) embedded in I/O expander block, so that to send messages to LCD display.
Sorry my english (I'm portuguese) and forgive my insistence but I really need some help...
Thanks in advance. |
|
|
dyeatman
Joined: 06 Sep 2003 Posts: 1934 Location: Norman, OK
|
|
Posted: Sun May 13, 2012 5:24 am |
|
|
As was stated earlier, go to the Hi-Tech forum. If you can't get the kind of
help available here then maybe you shouldn't be using Hi-tech. This
forum is one of the advantages of using CCS C. However. we are not a
beginner's teaching forum either and won't write your code or test it for you.
That's your job. The moderator needs to lock this thread. _________________ Google and Forum Search are some of your best tools!!!! |
|
|
bmmribeiro
Joined: 12 May 2012 Posts: 5
|
|
Posted: Sun May 13, 2012 8:00 am |
|
|
Please forget HI-TECH.
I saw the code above and I would to know if is possible to explain it better.
Programming it's not the problem, the problem is to understand the logic about the communication between 16F628 (or 18F1320) and I/O expander block.
Sorry any inconvenience... |
|
|
dyeatman
Joined: 06 Sep 2003 Posts: 1934 Location: Norman, OK
|
|
Posted: Sun May 13, 2012 9:35 am |
|
|
OK, forget about Hitech.
PCM did not post the code two years ago to have someone question his
work. He is one of the top programmers on this forum and you can be
assured what he wrote is good code.
Instead of a blanket "explain your code". Ask specific questions about
certain lines and you might get an answer from someone here.
If you don't know the CCS compiler you need to learn the fundamentals of
that first before you start asking questions about how CCS code works. If
you don't know the compiler how can you understand CCS code? _________________ Google and Forum Search are some of your best tools!!!! |
|
|
bmmribeiro
Joined: 12 May 2012 Posts: 5
|
|
Posted: Tue May 15, 2012 2:01 pm |
|
|
Code: | #define SDO PIN_B1 // SPI data
#define SCK PIN_B4 // SPI clock |
PIN_B1 means RB1 and PIN_B4 means RB4? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|