using any frequency other than 1MHz prevents the LCD from working - Page 1
Forum section: electronics / beginners

author: MAD MACRO
author_rank: Regular Contributor
timestamp: June 04, 2016, 06:02:45 pm
content: with 1MHz speed it worked fine, but when I switch to any other freq, it doesn't workSo, right now i'm testing it with 4MHzThis line is used before and after including <xc.h> , in main, and in the lcd driver, it's everywhere.Code:#define _XTAL_FREQ 4000000This line to use the internal oscCode:#pragma config FOSC = INTOSC_ECThis line(kinda) for prescaling the internal clock to reach 4MHz.Code:IRCF2 = 1; IRCF1 = 1; IRCF0 = 0;Does this have something to do with Start-up time ? i'm really not sure what i'm missing.

author: Simon
author_rank: Unknown
timestamp: June 04, 2016, 06:33:06 pm
content: What clock speed at datasheet permit?

author: MAD MACRO
author_rank: Regular Contributor
timestamp: June 04, 2016, 06:51:40 pm
content: Quote from: Simon on June 04, 2016, 06:33:06 pmI think it depends on the delay after instructions, i'm not sure though.but page 52 in the datasheet seems to be relevanthttps://www.sparkfun.com/datasheets/LCD/HD44780.pdf

author: madires
author_rank: Super Contributor
timestamp: June 04, 2016, 07:12:39 pm
content: There's the signal/bus timing (pages 52 and 58+) and the time required for processing instructions. Both have to be correct and your code needs to adjust the delay loops based on the clock frequency.

author: MAD MACRO
author_rank: Regular Contributor
timestamp: June 04, 2016, 07:28:04 pm
content: Quote from: madires on June 04, 2016, 07:12:39 pmbut my chip will give the same delays when working with different frequencies, cuz I set the _XTAL_FREQ accordingly to each different freq, right ?

author: madires
author_rank: Super Contributor
timestamp: June 04, 2016, 07:42:10 pm
content: Quote from: MAD MACRO on June 04, 2016, 07:28:04 pmSince I don't know your source code I can't answer your question.

author: MAD MACRO
author_rank: Regular Contributor
timestamp: June 04, 2016, 07:54:40 pm
content: Quote from: madires on June 04, 2016, 07:42:10 pmI don't want to bother you with a big long chunk of code.here are the most important bits.this is part of the initialize function:Code:// Initial delay after power-updelay_us(16000);LCD_DATA1_LAT |= _BV(LCD_DATA1_PIN);LCD_DATA0_LAT |= _BV(LCD_DATA0_PIN);lcd_e_cycle();delay_us(4992); /* delay, busy flag can't be checked here *//* repeat last command a second time */lcd_e_cycle();delay_us(64); /* delay, busy flag can't be checked here *//* repeat last command a third time */lcd_e_cycle();delay_us(64); /* delay, busy flag can't be checked here *//* now configure for 4bit mode */LCD_DATA0_LAT &= ~_BV(LCD_DATA0_PIN);lcd_e_cycle();delay_us(64); /* some displays need this additional delay */// Configure display after power uplcd_command(LCD_DISP_OFF); /* display off */lcd_clrscr(); /* display clear */lcd_command(LCD_MODE_DEFAULT); /* set entry mode */lcd_command(dispAttr); /* display/cursor control */}This is the main codeCode:#include "lcd.h"//BEGIN CONFIG#pragma config FOSC = INTOSC_EC //High speed external oscillater, with PLL not allowed//#pragma config CPUDIV = OSC4_PLL6 //postscale divide by 4#pragma config WDT = OFF //watch dog off#pragma config LVP = OFF#pragma config CPD = OFF//END CONFIGint main(){IRCF2 = 1;IRCF1 = 1;IRCF0 = 0;set_output(TRISC,0);RBPU = 0; // enable internal pullups on PORTBADCON1 =0x0F; // Make all ADC ANx pins digitalCMCON =0x07; // Make all Comparator CMx pins digitaldelay_ms(30);while(1){lcd_init(LCD_DISP_ON);lcd_clrscr();//put something on the screenlcd_gotoxy(0 ,1);lcd_puts(" soylent green");//just wait a couple of seconds, clear screen, and wait again*/lcd_gotoxy(0 ,2);lcd_puts(" is people");delay_10ms(250);lcd_clrscr();delay_10ms(20);toggle(LATC,0);}return 0;}the e delayCode:#define lcd_e_delay()delay_us(4)the e cycle functionCode:static void cycle_e(void){lcd_e_high();lcd_e_delay();lcd_e_low();}The thoroughly tested delay functions...Code:#define delay_ms(x)_delay((unsigned long)((x)*(_XTAL_FREQ/4000.0)))#define delay_us(x)_delay((unsigned long)((x)*(_XTAL_FREQ/4000000.0)))

author: madires
author_rank: Super Contributor
timestamp: June 04, 2016, 08:17:22 pm
content: Quote from: MAD MACRO on June 04, 2016, 07:54:40 pmWhen _XTAL_FREQ is 4MHz you get (x * 1) for delay_us() and at 1 MHz it's (x * 0). For delay_ms() it's (x * 1000) at 4MHz and (x * 250) at 1 MHz.What does _delay() and which parameter does it expect?

author: MAD MACRO
author_rank: Regular Contributor
timestamp: June 04, 2016, 08:22:35 pm
content: Quote from: madires on June 04, 2016, 08:17:22 pmGood job, I wouldn't have spotted that, this is very strange, why would it work at 1MHz then ?it's the native function _delay() from the xc8 compiler, it's most likely a cycle delay. _delay(1) = one cycle delay

author: madires
author_rank: Super Contributor
timestamp: June 05, 2016, 02:55:37 pm
content: For a 1MHz clock one cycle is 1µs. When calling _delay() some registers might be pushed to the stack, the call of the function, the loop inside the _delay() function, returning and popping registers back from the stack all need some MCU cycles. A call of _delay(0) could need 15 cycles (just an estimate), i.e. 15µs. And since delay_us() is _delay(0) any call results in a delay of 15 cycles or 15 µs. As long as you don't need more than 15µs delay everything is fineWith 4 MHz we get 250ns for each clock cycle. So any call of _delay() would need 15 cycles plus the given value times loop logic. Let's say we call delay_us(10). We might burn 15 cycles plus 10 for the loop runs (each loop run might need 3 cycles and the function therefore takes the given value divided by three). 25 cycles are 6.25µs. It's just an example. Based on how _delay() is implemented it could be better or worse.Proper delay functions can be tricky.