From: Robert B. <ro...@pe...> - 2007-07-23 20:20:40
|
Hello, I have recently moved to SDCC and even more recently started using PIC18*,= =20 more specifically 18f2550. I have two problems that I can=E4t seem to figur= e=20 out; 1. Whenever power is applied, the device seems to start up in a random=20 state and doesn't seem to start running the program. Programming the=20 device seems so make the device do *something*, but that seems quite=20 random as well, at different times, flashing the device with the exacttly= =20 same hef file seems to do different things each time. I program the device while it is in the circuit, the ICSP lines are=20 dedicated to programming, and a standard ASCII LCD is attatched in 4-bit=20 mode. I build the hex file using this Makefile: CC=3D/usr/local/bin/sdcc CFLAGS=3D -mpic16 -p18f2550 --pstack-model=3Dlarge all: main.hex main.dos.hex: main.hex #-unix2dos -n main.hex main.hex.dos main.hex: main.c lcd.o $(CC) $(CFLAGS) main.c lcd.o lcd.o: lcd.c $(CC) $(CFLAGS) -c lcd.c clean: -rm *.asm *.cod *.hex *.lst *.o The relevant parts of the main.c is #include <pic18fregs.h> #include <delay.h> #include "lcd.h" #include "main.h" typedef unsigned int config; code char at __CONFIG1L _config0 =3D 0x20; //0b00100000 code char at __CONFIG1H _config1 =3D 0x08; //0b00001000 code char at __CONFIG2L _config2 =3D 0x18; //0b00011000 code char at __CONFIG2H _config3 =3D 0x00; //0b00000000 code char at __CONFIG3H _config4 =3D 0x00; //0b00000000 code char at __CONFIG4L _config5 =3D 0xc0; //0b11000000 code char at __CONFIG5L _config6 =3D 0x0f; //0b00001111 code char at __CONFIG5H _config7 =3D 0xc0; //0b11000000 code char at __CONFIG6L _config8 =3D 0x0f; //0b00001111 code char at __CONFIG6H _config9 =3D 0xe0; //b11100000 code char at __CONFIG7L _config10 =3D 0x0f; //0b00001111 code char at __CONFIG7H _config11 =3D 0x40; //0b01000000 void init(void) { CVRCON=3D0x00; //0b00000000 OSCCON=3D0xf7; //0b11110111 CCP1CON=3D0x00; //0b00000000 CCP2CON=3D0x00; //0b00000000 UCFG=3D0x00; //0b00000000 ADCON0=3D0x00; //0b00000000 ADCON1=3D0x0f; //0b00001111 CMCON=3D0x07; //0b00000000 TRISA=3D0x00; //0b00000000 TRISB=3D0xff; //0b11111111 TRISC=3D0xfe; //0b11111110 } // Snipped the "boring" parts void main(void) { init(); delay100ktcy(9); LCDinit(); delay100ktcy(9); LCDconfig(); while(1) { LCDputc(0x41);=09//This is just an example of a function in lcd.c } } and then in lcd.c, the relevant function would be: void LCDputc(unsigned char c) { RS=3D1; RW=3D0; EN=3D1; delay1ktcy(9); LATAbits.LATA0=3D(c>>7)&0x01; LATAbits.LATA1=3D(c>>6)&0x01; LATAbits.LATA2=3D(c>>5)&0x01; LATAbits.LATA3=3D(c>>4)&0x01; delay1ktcy(9); EN=3D0; delay1ktcy(9); EN=3D1; delay1ktcy(9); LATAbits.LATA0=3D(c>>3)&0x01; LATAbits.LATA1=3D(c>>2)&0x01; LATAbits.LATA2=3D(c>>1)&0x01; LATAbits.LATA3=3Dc&0x01; delay1ktcy(9); EN=3D0; delay1ktcy(9); LATA=3DPORTA&0xf0; } =2E..which brings me to problem nr... 2. When I call LCDputc(somechar);, the "somechar" never seems to reach the= =20 function, the unsigned char c won't be what it is supposed to be.=20 Apparently I have missed something here... I have spent a lot of time=20 trying to figure this out, but I have been totally stuck... SDCC : mcs51/gbz80/z80/avr/ds390/pic16/pic14/TININative/xa51/ds400/hc08 2.7= =2E2=20 #4886 (Jul 23 2007) (UNIX), running on amd64/linux. Thank you, ro...@pe... Manah Manah! |
From: John J. M. <wb...@ar...> - 2007-07-25 11:21:53
|
----- Original Message ----- From: "Robert Bergfors" <ro...@pe...> Sent: Monday, July 23, 2007 4:14 PM Subject: [Sdcc-user] Passing data with function calls > 1. Whenever power is applied, the device seems to start up in a random > state and doesn't seem to start running the program. Programming the > device seems so make the device do *something*, but that seems quite > random as well, at different times, flashing the device with the exacttly > same hef file seems to do different things each time. > I program the device while it is in the circuit, the ICSP lines are > dedicated to programming, and a standard ASCII LCD is attatched in 4-bit > mode. Take a closer look at your LCDputc() routine. You appear to raise LCD Enable -before- you put the data on the lines. You want to put the data on the lines, raise LCD Enable, wait 450ns, then drop LCD Enable. Then move on to the next nybble. If you raise LCD Enable before putting the data on the lines the result will be more or less random. Also, I'm not sure what delay1ktcy() exactly results in, but you need a substantial wait after sending the byte. I don't recall exactly what it needs to be but it seems like it is on the order of 2ms ... in any case way more than the 450ns needed to strobe the data into the LCD. --McD |
From: John J. M. <wb...@ar...> - 2007-07-25 14:55:37
|
----- Original Message ----- From: "Robert Bergfors" <ro...@pe...> Subject: [Sdcc-user] Passing data with function calls > device seems so make the device do *something*, but that seems quite > random as well, at different times, flashing the device with the exacttly I should have mentioned ... there is no harm in waiting too long for the LCD. In fact, when you are first trying to get things done, I would encourage you to wait VERY long. As I mentioned, the strobe only needs 450 ns, so that part can simply be a couple of nops. But if you don't wait long enough after sending a character, the processor on the LCD will get confused and will tend to start behaving randomly. Indeed, when you are debugging, it is sometimes helpful to wait -seconds- so you can see what is going on. The wait before, and after, the initialization is quite long, and things like clearing the display take longer than writing a character. The physical LCD itself is quite a bit slower than the processor, so in most applications, you can have excessive delays waiting for the processor without actually impacting the application. In addition, not all LCDs are up to spec. Sometimes cheap LCDs are available because they didn't quite meet the specifications, and sometimes it is the speed. I would suggest you read the datasheet for the controller, and initially wait at least double the required times until you get things running. Once everything is working, then back the times closer to the spec. Although some LCDs might not quite make the spec, my experience is that they rarely miss by much, so just a tiny bit more than the minimum is USUALLY enough. But until you get your code sorted, better to just send the commands to the LCD at a leisurely pace. --McD |
From: Robert B. <sd...@ro...> - 2007-07-25 17:30:17
|
Quoting "John J. McDonough" <wb...@ar...>: > > I should have mentioned ... there is no harm in waiting too long for the > LCD. In fact, when you are first trying to get things done, I would > encourage you to wait VERY long. As I mentioned, the strobe only needs 450 > ns, so that part can simply be a couple of nops. But if you don't wait long > enough after sending a character, the processor on the LCD will get confused > and will tend to start behaving randomly. Indeed, when you are debugging, > it is sometimes helpful to wait -seconds- so you can see what is going on. I have tested this particular LCD with much faster timing, it does what the function tells it to, however the main problem now is that the value i want to pass as an argument to the function call becomes 0. Everything works if I use global variables, but that wont be possible because of later things I want to add. If I call LCDputc(0x41), to the function, then c should be 0x41, but it is in fact 0x00 instead. If I print c+0x30, it prints "0" on the display whatever I pass as an argument to the function, however, if I inside the LCDputc function assign a value to c, for example 0x41, it prints "A". One interesting thing I noticed just no, if c is first assigned the value... for example 0x03, then I reflash the instrument with c=0x02, it still is 0x03, as if the previous value didn't get reset in the chips memory. Powercycling the chip will correct this. > > The wait before, and after, the initialization is quite long, and things > like clearing the display take longer than writing a character. The > physical LCD itself is quite a bit slower than the processor, so in most > applications, you can have excessive delays waiting for the processor > without actually impacting the application. > > In addition, not all LCDs are up to spec. Sometimes cheap LCDs are available > because they didn't quite meet the specifications, and sometimes it is the > speed. I would suggest you read the datasheet for the controller, and > initially wait at least double the required times until you get things > running. Once everything is working, then back the times closer to the > spec. Although some LCDs might not quite make the spec, my experience is > that they rarely miss by much, so just a tiny bit more than the minimum is > USUALLY enough. But until you get your code sorted, better to just send the > commands to the LCD at a leisurely pace. The final program will probably read the busy flag and then wait perhaps 10ms, but it's a long way there, in the meantime I just use slow timings. Actually, with the 16F690 at 8MHz, I needed no NOP:s at all between writes, and the LCD would still perform 100%, but I put some delays there anyway to be sure. For now, the problem is passing arguments along with the function calls. Where does it store an argument when passing it to a function call? Does this look right: (I suck at assembly code, but here is what I think is the actual function call): ; ; Starting pCode block S_hello__main code _main: ; .line 39; hello.c init(); CALL _init _00124_DS_: ; .line 41; hello.c blinkarg(5); MOVLW 0x05 MOVWF POSTDEC1 CALL _blinkarg INCF FSR1L, F ; .line 42; hello.c delay100ktcy(1); MOVLW 0x01 CALL _delay100ktcy GOTO _00124_DS_ RETURN ...and then the function seems to be here... ; ; Starting pCode block S_hello__blinkarg code _blinkarg: ; .line 23; hello.c void blinkarg(unsigned char blinks) MOVFF FSR2L, POSTDEC1 MOVFF FSR1L, FSR2L MOVFF r0x00, POSTDEC1 MOVFF r0x01, POSTDEC1 MOVFF r0x02, POSTDEC1 MOVFF r0x03, POSTDEC1 MOVFF r0x04, POSTDEC1 MOVLW 0x02 MOVFF PLUSW2, r0x00 ; .line 28; hello.c for(i=0;i<blinks;i++) { CLRF r0x01 CLRF r0x02 _00109_DS_: MOVFF r0x00, r0x03 CLRF r0x04 MOVF r0x02, W ADDLW 0x80 MOVWF PRODL ... and so on. Can anyone find a specific reason to why the argument is cleared before the LCDputc() function uses it? Here is the entire program again in C: #define __pic18f2550 #include <pic18fregs.h> #include <sdcc-lib.h> #include <delay.h> #define OUT LATCbits.LATC7 typedef unsigned int config; code char at __CONFIG3H _config4 = 0x00; //0b00000000 void init(void) { OSCCON=0xf7; //0b11110111 TRISA=0xff; //0b00000000 TRISB=0xff; //0b11111111 TRISC=0x00; //0b11111110 } void blinkarg(unsigned char blinks) { int i; //blinks=5; //blinks=+2; for(i=0;i<blinks;i++) { OUT=1; delay1ktcy(1); OUT=0; delay1ktcy(1); } blinks=0; } void main(void) { init(); while(1) { blinkarg(5); delay100ktcy(1); } } Robert Bergfors |
From: Matt B. <m-b...@no...> - 2007-07-25 17:13:50
|
On Jul 23, 2007, at 3:14 PM, Robert Bergfors wrote: > CFLAGS= -mpic16 -p18f2550 --pstack-model=large Isn't the large stack model for PIC16 still incomplete? I am running some fairly complicated programs without hitting the stack limit in the small model (#pragma stack 0x200 200). I'm not too terribly familiar with the stack options, but that might be a good place to start. On Jul 25, 2007, at 6:21 AM, John J. McDonough wrote: > Also, I'm not sure what delay1ktcy() exactly results in, but you > need a > substantial wait after sending the byte. I don't recall exactly > what it > needs to be but it seems like it is on the order of 2ms ... in any > case way > more than the 450ns needed to strobe the data into the LCD. If your PIC is running at 4MHz, delay1ktcy(x) will delay for x ms. delay1mtcy(x) will delay for x seconds. I always pause for a second after starting up to allow time for my LCD (and other external components) to turn on. If you start writing to the LCD too soon, it will probably simply display garbage. Hope this helps. Matt |