PIC16F1459 Problem - Page 1
Forum section: electronics / general

author: cjhofer
author_rank: Newbie
timestamp: August 14, 2015, 03:30:13 am
content: I am trying to run the I2C module and the USB module together. I have set the USB to run at 48MHz from the internal oscillator. I am using a pll of x3. When I run the USB at this speed, the I2C fails to send a start bit or drive the clock or data line at all. I have tried every CPU divider to try and run the I2C slower. I also set the baud rate register at 255. I am able to run the I2C at 16MHz with no PLL. I am powering this part with 3.3V.Is the I2C able to run with the PLL enabled?

author: Andy Watson
author_rank: Super Contributor
timestamp: August 14, 2015, 03:11:48 pm
content: I have only been able to get the I2C to work reliably with the 48MHz PLL divided down to a 8MHz cpu clock. I've not tried driving the clock directly from an external source. I'm using 5V.

author: cjhofer
author_rank: Newbie
timestamp: August 14, 2015, 04:41:57 pm
content: Andy,What do you set the OSCCON to? Are you using the USB? Do you see problems with the I2C when not using the CPU divide?

author: Andy Watson
author_rank: Super Contributor
timestamp: August 14, 2015, 05:49:45 pm
content: I've not set OSCCON - its important values appear to be overridden by the bits in the configuration words. I have just checked that changing the OSCCON,PLLMULT bit does not alter operation of the USB - and it doesn't - i.e. the chip is following the setting in the configuration word.I am running USB - which appears to function at both high and low speeds irrespective of the CPUDIV value. However, I can only get the I2C to work properly if I have the CPUDIV set to divide by 6. I sometimes got a response from the faster setting of CPUDIV, but it was, at best, flaky!Edit: When I said I hadn't tried an external clock source I meant an external oscillator - I am using the HS crystal mode with a 16MHz crystal.

author: cjhofer
author_rank: Newbie
timestamp: August 15, 2015, 04:40:00 am
content: Turns out I did not wait for the OSCSTAT bits to get set after I changed the OSCCON bits. Now I am able to get I2C to run at CPU/6 when running the USB at 48MHz. When I do this the USB still doesn't connect, it seems like the main loop is running too slow with CPU/6.

author: Howardlong
author_rank: Super Contributor
timestamp: August 15, 2015, 11:33:34 am
content: I realise you've fixed this now, but in the meantime I'd already breadboarded up a solution with an I2C LCD display. Attached is the code.

author: Andy Watson
author_rank: Super Contributor
timestamp: August 15, 2015, 12:52:23 pm
content: Quote from: cjhofer on August 15, 2015, 04:40:00 amThis is the header/configuration for my code (using external 16Mhz crystal):Code:processor16F1459__config 8007,38c2;/** USB Speed. defaults to Full Speed if Low_Speed is not defined */#define Low_Speed; Define division for CPU clock (after PLL clock)#define CPU_Clock 8;#if (CPU_Clock == 48)__config 8008,19c3 ; Define 48 MHz No division#endif#if (CPU_Clock == 24)__config 8008,19d3 ; Define 24 MHz Divide 2#endif#if (CPU_Clock == 16)__config 8008,19e3 ; Define 16 MHz Divide 3#endif#if (CPU_Clock == 8)__config 8008,19f3 ; Define 8 MHz Divide 6 Need this option for I2C to work.#endifThe definition of "Low_Speed" causes the USB UCFG register to be initialised with different valueCode:#ifdef Low_Speedmovlw 010 ; Select pull-up resistors and Low speed osc source#elsemovlw 014 ; Select pull-up resistors and High speed osc source#endifmovwf UCFGit also changes part of the USB "device descriptor" message as appropriate.Are you using library code or rolling your own? It appears that the USB Serial Interface Engine has been lifted from the 18f2455 family, gate for gate including the silicon bugs, and word for word including the erroneous documentation! This is useful to know because there is much more searchable history for the 18f family.

author: cjhofer
author_rank: Newbie
timestamp: August 15, 2015, 02:31:06 pm
content: I am using a USB stacked based on the Microchip HID example, and stripped down to use less chip resources. It seems to work when the CPU is running with no divide and 48MHz driven from the internal oscillator. I have even tried to setup the USB config register for low speed but Windows did not like this configuration.

author: Howardlong
author_rank: Super Contributor
timestamp: August 15, 2015, 06:50:06 pm
content: I've tried a number of options with I2C and USB today. I use the HID host app to send an 'x' character to the LCD when the dialogue box button is pressed. All worked. The I2C is operating at 400kHz, although I did try it at 67kHz too and that was successful. Each I2C transaction is 3 bytes.I haven't determined any problem in connecting or maintaining USB connection.This is based on the 2013-06-15 MLA stack, and the HID custom demo.All these alternatives work at both 3.3V and 5V:o Internal oscillator, no clkdivo 12MHz PLLx4, no clkdivo Internal oscillator, clkdiv6o 12MHz PLLx4, clkdiv6

author: Andy Watson
author_rank: Super Contributor
timestamp: August 15, 2015, 06:57:02 pm
content: o Internal oscillator, no clkdivo 12MHz PLLx4, no clkdivCan you confirm that the CPU core is operating at 48MHz? I have been looking at your code and, with the exception of the external crystal, I can't see any significant difference in the initialisation.

author: Howardlong
author_rank: Super Contributor
timestamp: August 15, 2015, 07:26:05 pm
content: I am sure you already know this, but for the avoidance of doubt at clkdiv6, the CPU clock will only run at 8MHz, you need noclkdiv for 48MHz. In main.c, the appropriate lines are commented in and out:Code:// __CONFIG(WRT_OFF & CPUDIV_NOCLKDIV & USBLSCLK_48MHz & PLLMULT_3x & PLLEN_ENABLED & STVREN_ON & BORV_LO & LPBOR_OFF & LVP_OFF);__CONFIG(WRT_OFF & CPUDIV_CLKDIV6 & USBLSCLK_48MHz & PLLMULT_3x & PLLEN_ENABLED & STVREN_ON & BORV_LO & LPBOR_OFF & LVP_OFF);As well as this, the main.h defines the _XTAL_FREQ which is used for __delay_xx() and calculating the I2C baud rate.Also in main.c:Code:#if defined(_PIC14E)//Configure all pins for digital mode, except RB4, which has a POT on itANSELA = 0x00;#if defined(_16F1459) || defined(_16LF1459)// HL*** ANSELB = 0x10; //RB4 has a POT on it, on the Low Pin Count USB Dev Kit boardANSELB=0;#endifANSELC = 0x00;#if defined (USE_INTERNAL_OSC)OSCTUNE = 0;OSCCON = 0xFC; //16MHz HFINTOSC with 3x PLL enabled (48MHz operation)ACTCON = 0x90; //Enable active clock tuning with USB#endif// HL***MyI2CInit(400000UL); // To the I2C LCDMyLCDInit();MyLCDPutS("Hello");#endifAlso in main.c, in the main while (1) loop generates a pulse, allowing you to check the processor frequency, which in this case is 89ns, close enough to suggest the processor's running at 12MHz, indicating a 48MHz clock. It's the green Ch 2 trace:Code:// HL***LATBbits.LATB7=1;LATBbits.LATB7=0;Apologies, it's messy, I just hacked the MLA USB code.

author: cjhofer
author_rank: Newbie
timestamp: August 16, 2015, 02:18:24 am
content: I found the problem with my code related to the I2C. I did not initialize the ANSELB. Once I set this register to 0 the I2C started working with 48 MHz oscillator. Apparently the I2C will work (at low oscillator speeds) with ANSELB set as analog inputs. Thank everyone for all your help!!!!!

author: Howardlong
author_rank: Super Contributor
timestamp: August 16, 2015, 08:32:35 am
content: Quote from: cjhofer on August 16, 2015, 02:18:24 amCoincidentally, the first time I put my I2C code into the MLA stack yesterday, I had exactly the same problem, but luckily I've been there so often placing a watch on ANSELB was the first place I looked, hence these lines in the code:Code:// HL*** ANSELB = 0x10; //RB4 has a POT on it, on the Low Pin Count USB Dev Kit boardANSELB=0;The other gotcha is to set your TRIS bits to 1 on SDA/SCL, but that is made very clear in the DS.When I write my own code from scratch, I have a habit of setting all the analogue pins to digital on PICs as a matter of course. Quite why Microchip took the decision to default to analogue I have no idea, I don't know how many man hours have been lost in the history of time to that one. But at least they are consistent about it across the entire range.

author: Andy Watson
author_rank: Super Contributor
timestamp: August 16, 2015, 11:43:25 pm
content: Quote from: cjhofer on August 16, 2015, 02:18:24 amI can confirm this is the case. I've spent the afternoon tracking down this problem because Iknewthat I had defined the state of the analogue inputs:Spot the error:Code:banksel ANSELB ;Turn off analogmovlw 0movfw ANSELAmovfw ANSELBmovfw ANSELCI am using gputils to assemble the code. The MOVFW is not a standard. It appears that a deep thinking code monkey has done the obvious and defined a the complementary to the instruction that I intended to use (MOVWF). So, a typo, some lazy line-copying, several hours of head scratching and I've learnt something new todayI was resigned to accepting this as another quirk of the PIC16F1459 - thanks for the inspiration to find this bug.

author: Howardlong
author_rank: Super Contributor
timestamp: August 17, 2015, 06:31:04 am
content: So one way or another, all three of us have been caught by the default analogue pins thing.