Problem med flyttning av program i C *LÖST*

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
SeniorLemuren
Inlägg: 8407
Blev medlem: 26 maj 2009, 12:20:37
Ort: Kristinehamn

Problem med flyttning av program i C *LÖST*

Inlägg av SeniorLemuren »

Har ett program för att skriva till en 16 x 2 LCD som är gjort för PIC16F877A.
Har nu försökt att få det att fungera i en PIC16F628A med en 16 x 1 LCD.
LCD´n visar endast 8 fyrkantiga rutor direkt när den ansluts till spänning.

Det som skiljer är att jag använder de 4 höga bitarna RB4-RB7 som databitar i stället för RD0-RD4 i originalprogrammet.

Jag använder RA1 till RS och RA0 till E. RW är kopplad låg på kortet.

Har missat något men hittar inte vad.

En annan sak som jag har problem med är att det inte går att sätta breakpoint på vissa ställen. Jag får meddelandet: one or more breakpoints could not be resolved.
Ex. på rad som inte går att sätta breakpoint på:

Kod: Markera allt

void
lcd_putch(char c)
{
	LCD_RS = 1;	// write characters
	lcd_write( c );
}
Här är originalprogrammet som funkar på PIC16F877A

Kod: Markera allt

/*
 *	LCD interface to PIC16F877A
 *	Uses routines from delay.c
 *	This code will interface to a standard LCD controller
 *	like the Hitachi HD44780. It uses it in 4 bit mode, with
 *	the hardware connected as follows :
 *	
 *	PORTD bits 0-3 are connected to the LCD data bits 4-7 (high nibble)
 *	PORTB bit 4 is connected to the LCD RS input (register select)
 *	PORTB bit 6 is connected to the LCD R/W bit (READ WRITE)
 *	PORTB bit 7 is connected to the LCD E bit (ENABLE)
 *	To use these routines, set up the port I/O (TRISB, TRISD) then
 *	call lcd_init(), then other routines as required.
 *	
 */

#ifndef _XTAL_FREQ
 // Unless specified elsewhere, 4MHz system frequency is assumed
#define _XTAL_FREQ 4000000
#endif


#include	<htc.h>
#include	"lcd.h"

#define	LCD_RS RB4
#define	LCD_RW RB6
#define LCD_EN RB7

#define LCD_DATA	PORTD
#define	LCD_STROBE()	((LCD_EN = 1),(LCD_EN=0))

//Teckentabell med 8 byte för varje tecken. totalt 4 tecken å,Å,;Ä,Ö med adress 0x40 till 0x5f	
unsigned char char_table[32]={0x04,0x0e,0x11,0x11,0x1f,0x11,0x11,0x00,0x11,0x0e,0x11,0x11,0x1f,0x11,0x11,0x00,0x11,0x0e,0x11,0x11,0x11,0x11,0x0e,0x00,0x04,0x00,0x0e,0x01,0x0f,0x11,0x0f,0x00};

/* write a byte to the LCD in 4 bit mode */

void
lcd_write(unsigned char c)
{
	if (c == 'Å') c = 0x00; // Å
	if (c == 'Ä') c = 0x01; // Ä
	if (c == 'Ö') c = 0x02; // Ö
	if (c == 'å') c = 0x03; // å
	if (c == 'ä') c = 0xe1; // ä
	if (c == 'ö') c = 0xef; // ö
	__delay_us(40);
	LCD_DATA = ( ( c >> 4 ) & 0x0F );
	LCD_STROBE();
	LCD_DATA = ( c & 0x0F );
	LCD_STROBE();
}

/*
 * 	Clear and home the LCD
 */

void
lcd_clear(void)
{
	LCD_RS = 0;
	lcd_write(0x1);
	__delay_ms(2);
}
void
lcd_right(void)
{
	LCD_RS = 0;
	lcd_write(0x14);
	__delay_ms(2);
}

void
lcd_left(void)
{
	LCD_RS = 0;
	lcd_write(0x10);
	__delay_ms(2);
}
void
lcd_cur_off(void)
{
	LCD_RS = 0;
	lcd_write(0xC);
	__delay_ms(2);
}

/* write a string of chars to the LCD */

void
lcd_puts(const char * s)
{
	LCD_RS = 1;	// write characters
	while(*s)
		lcd_write(*s++);
}

/* write one character to the LCD */

void
lcd_putch(char c)
{
	LCD_RS = 1;	// write characters
	lcd_write( c );
}


/*
 * Go to the specified position
 */

void
lcd_goto(unsigned char pos)
{
	LCD_RS = 0;
	lcd_write(0x80+pos);
}


	
/* initialise the LCD - put into 4 bit mode */
void
lcd_init()
{
	char init_value;

	//ADCON1 = 0x06;	// Disable analog pins on PORTA

	init_value = 0x3;
	TRISB=0;
	//ANSELH = 0b00000000; //(FÖR 16F997)
	TRISD=0;
	LCD_RS = 0;
	LCD_EN = 0;
	LCD_RW = 0;
	
	__delay_ms(50);	// wait 15mSec after power applied,
	LCD_DATA	 = init_value;
	LCD_STROBE();
	__delay_ms(5);
	LCD_STROBE();
	__delay_us(200);
	LCD_STROBE();
	__delay_us(200);
	LCD_DATA = 2;	// Four bit mode
	LCD_STROBE();

	lcd_write(0x28); // Set interface length
	lcd_write(0xF); // Display On, Cursor On, Cursor Blink
	lcd_clear();	// Clear screen
	lcd_write(0x6); // Set entry Mode
// ladda ner svenska tecken	
int i=0;
for(i = 0; i < 32; i++){
	LCD_RS = 0;
	lcd_write(0x40+i); //CG-RAM-adress
	__delay_us(50);
	LCD_RS = 1;
	lcd_write(char_table[i]); //CG-RAM-data	
	__delay_us(50);

}
	
}
Här är programmet till PIC16F628A som inte funkar. (Jag har satt cdit en LED som jag låter blinka för att kolla att PICén är igång)

Kod: Markera allt

/*
 *	LCD interface to PIC16F628A
 *	like the Hitachi HD44780. It uses it in 4 bit mode, with
 *	the hardware connected as follows :
 *	
 *	PORTB bits 4-7 are connected to the LCD data bits 4-7 (high nibble)
 *	PORTA bit 1 is connected to the LCD RS input (register select)
 *	LCD R/W bit is connected to ground
 *	PORTA bit 0 is connected to the LCD E bit (ENABLE)
 */

unsigned int var_c =0;

#ifndef _XTAL_FREQ
 // Unless specified elsewhere, 4MHz system frequency is assumed
#define _XTAL_FREQ 4000000
#endif


#include	<htc.h>
#include	"lcd.h"

#define	LCD_RS RA1
//#define	LCD_RW RB6
#define LCD_EN RA0



#define LCD_DATA	PORTB
#define	LCD_STROBE()	((LCD_EN = 1),(LCD_EN=0))


/* write a byte to the LCD in 4 bit mode */

void
lcd_write(unsigned char c){
	__delay_us(40);
	var_c = c;			//****** användes för kontroll vid debugg ********	
	//LCD_DATA = ( ( c >> 4 ) & 0b11110000 ); // gamla prog. där port B0-B3 anv till data
	LCD_DATA = ( c & 0b11110000 );	
	LCD_STROBE();
	LCD_DATA = ( ( c << 4 ) & 0b11110000 );
	//LCD_DATA = ( c & 0x0F ); // gamla prog. där port B0-B3 anv till data
	LCD_STROBE();
}

/*
 * 	Clear and home the LCD
 */

void
lcd_clear(void)
{
	LCD_RS = 0;
	lcd_write(0x1);
	__delay_ms(2);
}
void
lcd_right(void)
{
	LCD_RS = 0;
	lcd_write(0x14);
	__delay_ms(2);
}

void
lcd_left(void)
{
	LCD_RS = 0;
	lcd_write(0x10);
	__delay_ms(2);
}
void
lcd_cur_off(void)
{
	LCD_RS = 0;
	lcd_write(0xC);
	__delay_ms(2);
}

/* write a string of chars to the LCD */

void
lcd_puts(const char * s)
{
	LCD_RS = 1;	// write characters
	while(*s)
		lcd_write(*s++);
}

/* write one character to the LCD */

void
lcd_putch(char c)
{
	LCD_RS = 1;	// write characters
	lcd_write( c );
}


/*
 * Go to the specified position
 */

void
lcd_goto(unsigned char pos)
{
	LCD_RS = 0;
	lcd_write(0x80+pos);
}


	
/* initialise the LCD - put into 4 bit mode */
void
lcd_init()
{
	char init_value;

	//ADCON1 = 0x06;	// Disable analog pins on PORTA		
	TRISB = 0b00000000;
	CMCON = 0b00000111;	//Comparators Off
	TRISA = 0b00000000;
	LCD_RS = 0;
	LCD_EN = 0;
	//LCD_RW = 0;// ****** satt till jord *******
	
	init_value = 0x30; // ****** 2 lägsta bitarna i höga nibbles 
	__delay_ms(50);	// wait 15mSec after power applied,
	LCD_DATA	 = init_value;
	LCD_STROBE();
	__delay_ms(5);
	LCD_STROBE();
	__delay_us(200);
	LCD_STROBE();
	__delay_us(200);
	LCD_DATA = 0x20;	// Four bit mode
	LCD_STROBE();

	lcd_write(0x28); // Set interface length
	lcd_write(0xF); // Display On, Cursor On, Cursor Blink
	lcd_clear();	// Clear screen
	lcd_write(0x6); // Set entry Mode

	
}
Här är anropet till rutinen:

Kod: Markera allt

//* LCD mainroutine Ver 1.0
//*	LCD interface to PIC16F628A
//*lcd.c Ver 1.0 is included
//*lcd.h is included
#include <htc.h>
#include "lcd.h"
#define _XTAL_FREQ 4000000
#define	DelayS(T){unsigned char i;for (i=0; i<T*10; i++)__delay_ms(100);}
#define LED_1 RA2
	


void main()
{

	lcd_init();
	lcd_goto(0);	// select first line
	lcd_puts("Hello World");


	for(;;){
	LED_1 = 1;// kontroll att PICén funkar. blinkar en led 1 gång /sek.
	DelayS(1);
	LED_1 = 0;
	DelayS(1);	
	}
} 
Senast redigerad av SeniorLemuren 19 september 2012, 15:03:53, redigerad totalt 2 gånger.
Användarvisningsbild
Icecap
Inlägg: 26632
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Problem med flyttning av program i C

Inlägg av Icecap »

Den "inbyggda" LCD-rutin förväntar sig sannolikt att använda bit 4-7 om du inte kan förklara för programmet att det faktisk är de låga bit som gäller.

Detta är en av de problem jag ser med dessa "smarta" rutiner som är färdiga. Du får läsa igenom dokumentationen för att se om du kan ange att den ska använda bit 0-3 istället.
Användarvisningsbild
SeniorLemuren
Inlägg: 8407
Blev medlem: 26 maj 2009, 12:20:37
Ort: Kristinehamn

Re: Problem med flyttning av program i C

Inlägg av SeniorLemuren »

Det är tvärsom. Den gamla rutinen använder de 4 låga bitarna på port D,
Jag använder de 4 höga bitarna på port B

Jah har ändrat här och "remmat" ut de tidigare raderna. Om jag kollar i debug så verkar det stämma. De 4 höga bitarna skickas först till LCD´n, sedan de 4 låga.

Kod: Markera allt

void
lcd_write(unsigned char c){
	__delay_us(40);
	var_c = c;			//****** användes för kontroll vid debugg ********	
	//LCD_DATA = ( ( c >> 4 ) & 0b11110000 ); // gamla prog. där port D0-D3 anv till data. 
	LCD_DATA = ( c & 0b11110000 );	//Nya prog. 
	LCD_STROBE();
	LCD_DATA = ( ( c << 4 ) & 0b11110000 );Nya prog. 
	//LCD_DATA = ( c & 0x0F ); // gamla prog. där port D0-D3 anv till data
	LCD_STROBE();
}
Användarvisningsbild
Icecap
Inlägg: 26632
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Problem med flyttning av program i C

Inlägg av Icecap »

Det ska väl ändå vara:

Kod: Markera allt

void lcd_write(unsigned char c)
  {
  __delay_us(40);
  var_c = c;         //****** användes för kontroll vid debugg ********   
#if 0
  // Use high bits on LCD_DATA port
  LCD_DATA = (c & 0b11110000);   //Nya prog.
  LCD_STROBE();
  LCD_DATA = ( ( c << 4 ) & 0b11110000 );Nya prog.
  LCD_STROBE();
#else
  // Use low bits on LCD_DATA port
  LCD_DATA = ((c  >>  4) & 0x0F); // gamla prog. där port D0-D3 anv. till data.
  LCD_STROBE();
  LCD_DATA = (c & 0x0F); // gamla prog. där port D0-D3 anv till data
  LCD_STROBE();
#endif
  }
Men denna rutin kräver att inget annat är kopplat till LCD_DATA-porten! Behöver du de andra bits till annat måste man skriva såhär:

Kod: Markera allt

void lcd_write(unsigned char c)
  {
  __delay_us(40);
  var_c = c;         //****** användes för kontroll vid debugg ********   
#if 0
  // Use high bits on LCD_DATA port
  LCD_DATA = (c & 0xF0) | (LCD_DATA & 0x0F);
  LCD_STROBE();
  LCD_DATA = ((c << 4) & 0xF0) | (LCD_DATA & 0x0F);
  LCD_STROBE();
#else
  // Use low bits on LCD_DATA port
  LCD_DATA = ((c >> 4) & 0x0F) | (LCD_DATA & 0xF0);
  LCD_STROBE();
  LCD_DATA = (c & 0x0F) | (LCD_DATA & 0xF0);
  LCD_STROBE();
#endif
  }
Användarvisningsbild
SeniorLemuren
Inlägg: 8407
Blev medlem: 26 maj 2009, 12:20:37
Ort: Kristinehamn

Re: Problem med flyttning av program i C

Inlägg av SeniorLemuren »

Det är bara aktuellt att använda dom höga bitarna på porten så koden:

Kod: Markera allt

// Use high bits on LCD_DATA port
  LCD_DATA = (c & 0b11110000);   //Nya prog.
  LCD_STROBE();
  LCD_DATA = ( ( c << 4 ) & 0b11110000 );Nya prog.
  LCD_STROBE();
Är den enda som behövs. Den andra lät jag ligga kvar utkommenterad,för att visa vad jag ändrat. Felet verkar vara någon annan stans i koden.

Jag har stirrar mig lite blind på den just nu, men jag hittar säkert felet till slut. Tänkte bara om någon skarpögd person på forumet kunde se det direkt.
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: Problem med flyttning av program i C

Inlägg av jesse »

Det verkar ju som om du får alla databitarna rätt. Är det samma fabrikat, dvs. samma initieringskoder till den nya displayen? Eller andra drivspänningar, t.ex. negativ spänning till LCDn? Eller bara något kopplingsfel?
bearing
Inlägg: 11675
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: Problem med flyttning av program i C

Inlägg av bearing »

Har du stängt av de analoga funktionerna på PORTA0-1?
Användarvisningsbild
Icecap
Inlägg: 26632
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Problem med flyttning av program i C

Inlägg av Icecap »

Det som är problemet är initieringen. Just detta med hälften på och den andra hälft av visar detta.
Användarvisningsbild
SeniorLemuren
Inlägg: 8407
Blev medlem: 26 maj 2009, 12:20:37
Ort: Kristinehamn

Re: Problem med flyttning av program i C

Inlägg av SeniorLemuren »

Dom Här?
CMCON = 0b00000111; //Comparators Off

Disply typ RT1601 Problemet är att jag inte hittar vilken driver som gäller men jag antog att det är standard HD44780 som gäller.

Edit. Annonsrubriken säger ju faktiskt så.
Användarvisningsbild
Icecap
Inlägg: 26632
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Problem med flyttning av program i C

Inlägg av Icecap »

Dags med funktionstest!
Lägg in en programsnudd som räknar upp LCD_DATA, inget annat. Då kan du med oscilloskopet se om frekvensen på de 4 pinnar faller med ökande bitnummer och se att de faktisk "rör på sig".

Sedan gör du samma sak med Strobe och Enable.
H.O
Inlägg: 5913
Blev medlem: 19 mars 2007, 10:11:27
Ort: Ronneby

Re: Problem med flyttning av program i C

Inlägg av H.O »

Något det skulle kunna vara (jag låter de som kan C analysera själva koden) är att kontrollern på den nya displayen behöver lite längre tid att utföra initieringskommandona, jag har varit med om att det har diffat nämnvärt mellan olika "HD44780-kompatibla" kontrollers.

Sen har jag för mig att 1X16 internt "egentligen" brukar vara 2X8 och måste således konfigureras som 2-radig men har du inre ändrat DET från vad som fungerar med 2X16 så är det nog inte problemet. Du kanske kan prova din 1X16 på din 877 med koden som du vet fungerar?
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 46933
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: Problem med flyttning av program i C

Inlägg av TomasL »

En iofs onödig fråga, kanske, men du använder rätt pinnar på LCD'n?
Användarvisningsbild
SeniorLemuren
Inlägg: 8407
Blev medlem: 26 maj 2009, 12:20:37
Ort: Kristinehamn

Re: Problem med flyttning av program i C

Inlägg av SeniorLemuren »

Dubbeldubbelkollat med ohmbrygga. :humm:
Användarvisningsbild
SeniorLemuren
Inlägg: 8407
Blev medlem: 26 maj 2009, 12:20:37
Ort: Kristinehamn

Re: Problem med flyttning av program i C

Inlägg av SeniorLemuren »

H.O skrev:Något det skulle kunna vara (jag låter de som kan C analysera själva koden) är att kontrollern på den nya displayen behöver lite längre tid att utföra initieringskommandona, jag har varit med om att det har diffat nämnvärt mellan olika "HD44780-kompatibla" kontrollers.

Sen har jag för mig att 1X16 internt "egentligen" brukar vara 2X8 och måste således konfigureras som 2-radig men har du inre ändrat DET från vad som fungerar med 2X16 så är det nog inte problemet. Du kanske kan prova din 1X16 på din 877 med koden som du vet fungerar?
Hade ändrat till 1 rad, men såg i en annan länk att det skall vara 2 rader som du säger, så jag har ändrat. Ingen funktion trots.
bearing
Inlägg: 11675
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: Problem med flyttning av program i C

Inlägg av bearing »

Fick du rutor över hela displayen med initiering för 2 rader?
Eller påverkas inte displayen alls av programmet?
Skriv svar