Help! I want my PORT PINS BACK! - Page 1
Forum section: electronics / general

author: SuzyC
author_rank: Frequent Contributor
timestamp: June 19, 2015, 10:49:54 pm
content: I am totally astonished that the prioritized unprogramed, reset pin assignment of most of the pins on the PIC18F25K22 are not I/O.I seem to be playing musical chairs trying to accomplish what used to a simple task, setting all the PORTA, PORTB, PORTC pins to I/O.Someone must have found a simple way to do this with XC8 or Hi-Tech C-code. I seem stuck again.I have attached LEDs and 1k resistors to Vss on each PORTB pin except INT0, bbit0, which is for INT0, it has a momentary Sw to ground a pullup to Vdd.For example, bbit3 has five other pin use priorities above it, at the bottom of the list is digital I/O!I have RTFM, but I cannot quite seem to understand what I doing wrong.For instance, I can get some of PORTB's pins to revert from their unprogrammed PIN PRIORITY to I/O, but not all.bbit6, bbit1 seem to be out of control and under the influence of some other MCU internal peripheral function.//------------------------------------------/*NOTE: TMR1 is working correctly and blinking the LEDs on bbit2 is doing what it is supposed to, bbit0 INT0 is doing its IRQ ok.bbit6 flashes properly, bbit7 is erratic, bbit3 is out to lunch, bbit1 is controlled by evil zombies.I seem to have tried without success to initialize all pins of PORTA, PORTB, PORTC, to be just I/O pins set for only input-output mode.In this program, every PORTB pin seems to blink properly except for PORTB.1 and PORTB.3 and PORTB.6.PORTB.0 INT0IE is working as INT0 , PORTB.1 lights on reset, turns off within a second, but then doesn't light again.PORTB.7 will turn off a visible fraction of a second after it and PORTB.6 are both turned off by code?So, obviously some mysterious MCU operation has hijacked control of bbit1 an bbit6!*///----------------------// Target: PIC18F45K22 Hi-Tech 9.80 or MPLABX v3.00 Compiler: XC8 v1.30// #include <xc.h> //only for XC compiler// I am using Hi-Tech and XC8, has been compiled on both XC8 1.34 and Hi-Tech P18 ver 9.80 , get exactly the same results// PIC configuration words#include <htc.h>#include <string.h>#include <stdio.h>#include <math.h>#include <P18f25k22.h>#include <stdint.h>__PROG_CONFIG(1,0x8800); //Internal Osc Block at 16MHz,IES0 enabled-//#pragma config FOSC = INTIO67 wks with XC not 9.80#pragma config FCMEN = OFF#pragma config IESO = ON //originally set to off#pragma config BOREN = OFF#pragma config WDTEN = OFF#pragma config WDTPS = 1024#pragma config PBADEN = OFF //PORTB is I/O at reset not A2D#pragma config HFOFST = ON#pragma config LVP = OFF //bit2 of CONFIG#pragma config STVREN = ON#pragma config XINST = OFF#pragma config PWRTEN = OFF#pragma config BORV = 190#pragma config MCLRE = EXTMCLR#pragma config CCP2MX = PORTC1#pragma config CCP3MX = PORTB5#pragma config T3CMX = PORTC0#pragma config P2BMX = PORTD2#pragma config PLLCFG = OFF#pragma config PRICLKEN = OFF//Bit 7 6 5 4 <3:0>// IESO FCMEM PRICLKEN PLLCFG OSC SELECT// Int-Ext FailSafe no effect 0010 Xtal// ClkSwEn Clock Mon HFINTOSC 1000 INTHFOSC// 1=En 0=off 0=Dis x 1000//OSCCON SCS=0 else no 64MHz PLL operation/*__PROG_CONFIG(1,0x8800); //Internal Osc Block at 16MHz,IES0 enabled-__PROG_CONFIG(2,0x0); //BOREN and WDTEN both disabled__PROG_CONFIG(3,0xBD00); //PBADEN disabled PORTB<5:0>are I/O not A2d at reset__PROG_CONFIG(4,0x81); //bit2 =0 LVP disabled, default for all =0x85*/__PROG_CONFIG(5,0xC00F); //CONFIG5 to CONFIG7 just set Read and Write protects__PROG_CONFIG(6,0xE00F); //All mem reads and writes are enabled, no protect__PROG_CONFIG(7,0x400F); //Default BulkErase settings for CONFIG5--CONFIG7#pragma config IESO=1; //Needs to be=1 for SCS to work to set clk source.#pragma config PBADEN=0;#pragma config WDTEN=0; //WatchDog Enable Disabled 0003=0x3F ater erase#define Off 0#define OFF 0#define off 0#define On 1#define ON 1#define on 1#define None 0//Break the ports down to their bits#define PB(port,bit) ((unsigned) & (port)*8 + (bit))static bit abit0 @ PB(PORTA,0);static bit abit1 @ PB(PORTA,1);static bit abit2 @ PB(PORTA,2);static bit abit3 @ PB(PORTA,3);static bit abit4 @ PB(PORTA,4);static bit abit5 @ PB(PORTA,5);static bit abit6 @ PB(PORTA,6);static bit abit7 @ PB(PORTA,7);static bit bbit0 @ PB(PORTB,0);static bit bbit1 @ PB(PORTB,1);static bit bbit2 @ PB(PORTB,2);static bit bbit3 @ PB(PORTB,3);static bit bbit4 @ PB(PORTB,4);static bit bbit5 @ PB(PORTB,5);static bit bbit6 @ PB(PORTB,6);static bit bbit7 @ PB(PORTB,7);static bit cbit0 @ PB(PORTC,0);static bit cbit1 @ PB(PORTC,1);static bit cbit2 @ PB(PORTC,2);static bit cbit3 @ PB(PORTC,3);static bit cbit4 @ PB(PORTC,4);static bit cbit5 @ PB(PORTC,5);static bit cbit6 @ PB(PORTC,6);static bit cbit7 @ PB(PORTC,7);static double ttemp=0;void interrupt high_priority(void){if (INT0IF){ INT0IF = 0;bbit3=1;bbit4=0;}if (TMR1IF) //at 64MHz approx 18.5mSec with H=0x80 L=0{ TMR1ON = 0;TMR1IF = 0;TMR1H = 0x80;TMR1L = 0x0;TMR1ON = 1;if(bbit2==0){ bbit2=1;}else bbit2=0;}}void interrupt low_priority lp(void){INT0IF=0;bbit3=0;bbit4=1;if (TMR1IF) //at 64MHz takes 37mSec for rollover with H=0,L=0{TMR1ON = 0;TMR1IF = 0;TMR1H = 0x0;TMR1L = 0x0;TMR1ON = 1;if(bbit2==0){ bbit2=1;}else bbit2=0;}}// end of Low priority interrupt#define _XTAL_FREQ 64000000L#define FCYC (_XTAL_FREQ/4L)void Init_TIMER1( void ){ // TIMER1 overflows at 65536 clocksT1CON = 0; // stop TIMER1TMR1IE = 0; // disable TIMER1 interrupt for nowT1GCON = 0; // disable TIMER1 gate inputTMR1H = 0; // set TIMER1 initial count valueTMR1L = 0;//TICON settings TICKPS,TMR1CS don't work with 9.80//TMR1ON =TICON<0>=0 TMR1ON=off//T1RD16 =TICON<1>=0 do not set TMR1 H,L with one 16bit word//T1SYNC =TICON<2>=1 do not sync external clock input with system clock(either way works the same for this pgm)// T1SYNC=0 was setting in SETINT//TISOSCEN=TICON<3>=0 Dedicated 2ndary Osc disabled//TMR1CKPS=TICON<5:4>=0x10 1/4 prescaler of system clock//TMR1CS =TICON<7:6>=0x01 TMR1 uses system clock,0x00=sysclk/4 instructClkT1CON = 0b0110100;TMR1IP = 1; // select high priority interrupt level //TMR1IF = 0; // clear TIMER1 interrupt request //TMR1IE = 1; // enable TIMER1 interrupt //PEIE = 1; // enable peripheral interrupts //TMR1ON = 1; // start TIMER1 //}void Init_PIC( void ){INTCON = 0; // disable interrupts //INTCON2 = 0xF5;INTCON3 = 0xC0;PIE1 = 0;PIE2 = 0;PIE3 = 0;OSCTUNE=0x1F; //Highest Internal OSC Freq OSCTUNE<0:5> set freq.//OSCTUNE<5:0>set freq 011111 =16MHz PLLEN=bit6// Turn on the PLL ////OSCTUNEbits.PLLEN = 1; //also works 9.80PLLEN=1; //if=1 Fosc=Fosc*4//OSCCON =0x70; //Selects Int Osc Block 16Mhz internal clock source//OSCCON bit7 IDLEN=0 Enter Sleep,=1 Enter Idle//OSCCON<1:0> SCS..SCS=1x IntSysClk, 01=SecOsc SOSC,00=Clk set by CONFIG1OSCCON = 0b01110000; // Enter Sleep mode for sleep, not IDLE// set internal oscillator to 16MHz,// use primary clock set by CONFIG1H<3:0>// disable ADC inputs //ANSELA = 0;ANSELB = 0;ANSELC = 0;ANSELD = 0;ANSELE = 0;// disable Comparators //CM1CON0 = 0;CM2CON0 = 0;// make all available GPIOs outputs and set low //LATA = 0x00;TRISA = 0x00; // originally RA6,RA7 as inputs //LATB = 0x01;TRISB = 0x01; //INT0 Sw on bbit0LATC = 0x00;TRISC = 0x00; // originally RC0,RC1 as inputs //LATD = 0x00;TRISD = 0x00;LATE = 0x00;TRISE = TRISE & ~0x07; // touch only PORTE direction bits //}//------------------------------main-----------------------------------------void main(void){Init_PIC();Init_TIMER1();IPEN = 1; //Priority interrupts enabled//RCONbits.IPEN = 1; //also works 9.80LATB =1;TRISB =1; //INT0IE sw on bbit0INT0IF=0;INT0IE=1;PEIE=1; //Needed for TMRx interrupts//PIE1=1; //Not Needed for TMRx// PIE2=1; //Not Needed for TMRxGIEL=1;GIEH=1; //Ok also to use INTCONbits.GIE = 1; to enable all interrupts//===================================================================Start:for(ttemp=0;ttemp<60000;ttemp++)//a few secs, timed loop at 16MHz *4{ INT0IE=1;bbit1 =1; //Hey, why aren't you blinking!//bbit2 blinks just fine, as it is supposed tobbit5 =1;bbit6 =1;bbit7 =1;TMR1IP=1;}for(ttemp=0;ttemp<60000;ttemp++) //a few seconds at 16MHz *4{INT0IE=0;bbit1 =0;bbit5 =0;bbit6 =0;bbit7 =0;TMR1IP=0;}goto Start;}

author: vini_i
author_rank: Regular Contributor
timestamp: June 19, 2015, 11:58:48 pm
content: i have never used the hi tech compiler but i have used xc8 extensively. i don't entirely understand your code but a few things to point out.write to LATx registers and read from PORTx registers.also xc8, when using xc.h has bit wise operations built in. for example LATBbits.LATB2 = 1;mplabx has auto fill when using this syntax. this works for every register that the pic hasREGISTERNAMEbits.BITNAMEthere may also be unexpected "read modify write" interactions. i see that your timer interrupt changes PORTB bit 2 but your for() loops are also changing PORTB bits at the same time 60000 times while being interrupted by the timer.ps. it is considered bad form to use GoTo statments in C programming. instead wrapping everyting in a while(1){....} will have the same effect.

author: Andy Watson
author_rank: Super Contributor
timestamp: June 20, 2015, 12:26:58 am
content: This I have observed about the PIC16F1459, it may or may not be applicable to the 18F25K22.PICs do not have an instruction to set or reset individual port pins - what they have is a read-modify-write sequence, i.e. the whole byte from the port is read, the appropriate bit is modified (either set or reset) and the resulting byte is written back to the port. This creates problems when two bit modifications happen back-to-back. i.e. we have [read port byte, modify bit 1, write port byte], [read port byte modify bit 2, write port byte]. The problem occurs in the middle, we have a write that is immediately followed by a read. At higher clock speeds the signals generated by the write have not had time to propagate through the logic before the following read occurs - result: the modification of bit 1 disappears into the ether. In assembly the solution is to interpose a NOP between the two bit-modifyiing instructions, e.g.Code:bsf porta,1nop ; allow time for signal to propagatebsf porta,2....etc.I'm guessing that the overheads introduced by compiled C would hide this problem, although, a good optimising compiler would probably translate bit-setting operations directly into bsf and bcf instructions (without the nop). A simple test for this issue is to reduce the clock speed by several orders of magnitude and see if the problem persists.A second problem regards the reading of a port. Back in the good ol' days a read-modify-write would have read back the values on the port pins but it appears that Microchip have thrown another spanner in the works - particularly when the port pins potentially have other functions (it doesn't matter whether those functions are enabled, or not). The only safe method of performing a read-modify-write cycle is to do it on the "LAT" values. I.e. bit setting, or resetting operations should be performed on the LAT,x bits rather than the PORT,x bit.

author: SuzyC
author_rank: Frequent Contributor
timestamp: June 20, 2015, 03:34:41 am
content: Merci, Andy and Vini_i for your generous and comprehensive help.Switching from my old mindset working with 16F series of MCU to the 18F species has shown me that the idea of code portability can be thrown out with the cat litter.The P18 is a whole new ballgame.I switched my I/O output syntax from bbitx=n; to LATBx=n; and everything works!

author: Howardlong
author_rank: Super Contributor
timestamp: June 20, 2015, 11:26:17 am
content: Using the LATXbits data structures, you can do read-modify-write on all but the older/entry level devices.The default analogue pin selection is indeed a choice that has and will continue to confuse. The register naming also differs across devices.Back in the old days we also had odd random pins that were open drain, another source of confusion.Facepalm, just think facepalm.

author: MarkF
author_rank: Super Contributor
timestamp: June 25, 2015, 06:09:10 am
content: I've been using MPLAB X and the xc8 compiler. With the pic16f877 and pic16f876, I had to use PORTx to write to the port registers (no LATx defined). Then when I started to use the 18f2550, nothing worked any more. Found out that I had to use LATx to write to the port registers. Apparently, there's no consistency on how to write to the ports with the xc8 compiler.

author: Howardlong
author_rank: Super Contributor
timestamp: June 25, 2015, 10:46:13 pm
content: Quote from: MarkF on June 25, 2015, 06:09:10 amI think rather than it being the compiler, it's the device family. The 16F876/7 are pretty old, I was using them 15 years ago. I remember having to put in delays to cope with capacitance on the pins when doing read-modify-writes on the ports. Hence the LAT registers in newer devices.

author: Ian.M
author_rank: Super Contributor
timestamp: June 25, 2015, 11:00:50 pm
content: +1.The newer PICs are faster and many of them have lower output drive capability which makes them more sensitive to the RMW effect if you try to manipulate PORT bits directly. If its got LAT registers use them or weep. The topicRMW and solutions for itover at Microchip's forum should also be mandatory reading.It is possible to write XC8 code that will handle both the older PICs and the newer ones correctly, but it gets a little gnarly.

author: BloodyCactus
author_rank: Frequent Contributor
timestamp: June 25, 2015, 11:54:20 pm
content: are you running this at 64mhz on a breadboard?

author: MarkF
author_rank: Super Contributor
timestamp: June 26, 2015, 01:32:43 am
content: Quote from: Howardlong on June 25, 2015, 10:46:13 pmI agree. It's not the compiler. The pic16f877/6 don't have LAT registers. It would just be nice if the header file for this PIC would define LAT to be the same as the PORT registers so that your code could be transportable across the newer PICs.I haven't had any of the RMW problems as of yet. But, it's just a matter of time. My first microcontroller was the pic16f877 used on a module from DLP Designs (DLP-2232PB) that I bought several years ago.

author: macboy
author_rank: Super Contributor
timestamp: June 26, 2015, 01:20:48 pm
content: As a rule, one shouldneverdo a RMW operation (like clear bit, set bit, or nibble swap) on a port register. Instead, maintain a shadow copy of your intended output in a RAM register. Do the RMW operations on that, then copy it to the port register. This way you will never set the output to an unintended value based on how the external circuit is loading the pins at any given moment. The LAT registers achieve the same effect, but they are not available on older or low-end devices.

author: Howardlong
author_rank: Super Contributor
timestamp: June 27, 2015, 07:45:58 pm
content: Quote from: BloodyCactus on June 25, 2015, 11:54:20 pmPerhaps somewhat surprisingly, these devices work quite well on a breadboard even at 64MHz. That does assume reasonable closely placed decoupling cap(s), meaning at the very least a 100nF across pins 19 and 20. On the device in question, I have one (well a 18f26k22, essentially the same device with more flash & RAM) working fine on a breadboard. Typically I use locally placed 3 pin linear regs on breadboards too, but I just tried it with an external supply with 1m leads at 5V instead and it still runs fine.Remember, all the high speed 64MHz stuff is internal on the die, the highest frequency you'll see on the pins is 16MHz.

author: Ian.M
author_rank: Super Contributor
timestamp: June 27, 2015, 09:35:16 pm
content: ... and that's only the Fosc/4 output on the OSC2 pin. PWM pins can be toggled at up to 8MHz, but all bit-banged pins will be even slower. Its really not a problem running any 8 bit PIC at full speed on breadboard if you are careful with your layout and decoupling.

author: jaromir
author_rank: Unknown
timestamp: June 27, 2015, 09:39:44 pm
content: When in doubt, one can switch (either by config bits or in sotfware) to internal 16MHz RC oscillator and crank it to 64MHz via internal PLL. This way all HF circuits stay on chip.Obviously - as Howard suggested - the need for proper decoupling is still valid (as usual for digital ICs), as well as is necessary to connect both GND pins on 28-pin package.

author: Skimask
author_rank: Super Contributor
timestamp: June 27, 2015, 11:45:24 pm
content: Quote from: jaromir on June 27, 2015, 09:39:44 pmRTFDS...You can't run 64Mhz off an external xtal anyways...

author: jaromir
author_rank: Unknown
timestamp: June 28, 2015, 05:42:53 am
content: RTF thread and then DS, pleaseWe are talking about running from internal RC oscillator or external 16MHz crystal and using PLL to produce 64MHz, both of them normally feasible options.

author: Ian.M
author_rank: Super Contributor
timestamp: June 28, 2015, 10:32:53 am
content: Older PIC16 devices are actually worse here. Most of them have a max rated Fosc of 20MHz with NO PLL so need a 20MHz crystal. With good layout and short leads even that is fine on a breadboard though I prefer an external 'canned' XTAL oscillator module for better stability when probing round pins near the OSC1,OSC2 ones.

author: Howardlong
author_rank: Super Contributor
timestamp: June 28, 2015, 11:39:47 am
content: Although I'm not recommending it for breadboards, but you could run the device with an external 64MHz oscillator. Max xtal is 20MHz though.You can attempt to squeeze out a 15.6ns pulse using the CCP if you contrive it so to do, but you need to probe it carefully as the drive and slew rate on the pins is pretty low.

author: 22swg
author_rank: Frequent Contributor
timestamp: June 28, 2015, 03:37:16 pm
content: How about 70MIPS on a BB ... (dsPIC33EV256GM104)

author: Howardlong
author_rank: Super Contributor
timestamp: July 01, 2015, 10:14:30 pm
content: Indeed, PIC24EP256GP202 running FRC and PLL at 140MHz, giving 70MHz CLKO pin 10 probed with spring ground on pin 8, VSS.Processor draws about 45mA at 3.3V at this clock rate though.

author: 22swg
author_rank: Frequent Contributor
timestamp: July 02, 2015, 08:03:55 pm
content: Howard , Think we are on the same wavelength here. I built the little dsPIC33EV board to investigate programming / using the various core peripherals, I wonder why the 16bit PIC’s do not seem to be in favour. My C is pretty poor… but the code making the pins do what I want develops fast and debug is straight forward , plus having the advantage of 256k /16k program / data memory, humungus speed, PPS , 35 GPIO and also the EV is 5V . Must measure the Amps .

author: jnz
author_rank: Frequent Contributor
timestamp: July 02, 2015, 09:26:47 pm
content: Quote from: 22swg on July 02, 2015, 08:03:55 pmKeep going. You'll figure that out. Try the other thread on the forum right now:https://www.eevblog.com/forum/microcontrollers/abysmal-microchip-experience/You'll figure out why the 16bit Microchips aren't popular when you get to using a 32bit ARMyou're not fighting erratas, you have plenty of code sources / tools / IDEs / debuggers to choose from, and the parts end up being cheaper.

author: Howardlong
author_rank: Super Contributor
timestamp: July 03, 2015, 12:40:55 am
content: FWIW I'm using a PIC24FV device for a multi voltage switch mode PSU and Li ion battery charger/gas gauge in a product because it's cheaper than using off the shelf devices. I have the product's current draw down far enough to allow 6 months on standby on a fully charged battery. The primary device in the product is a triple core M4F/M0/M0, and taking the power management away from this device has turned out to be a good engineering decision.The peripheral selection has been what makes the PIC work for me in this part of the application, plus the not inconsequential value of having many years of PIC experience already. Having comparators and opamps as well as your more usual ADC and PWM, reduces chip count and therefore BOM cost. Even just being available as 5V devices has a bearing in this type of application, but on balance it's horses for courses.It does worry me that Microchip have been somewhat losing their way recently, typically releasing immature products many months too early. In that regard they seem a bit rudderless at the moment, possibly being too marketing and stockholder driven for the short term, and caring little for their medium to long term reputation.

author: 22swg
author_rank: Frequent Contributor
timestamp: July 03, 2015, 06:51:55 am
content: jnz. I see where you are coming from... Purely from a hobbyist perspective, the PIC24 families, more than fit my purpose, May seem strange but I don't use libraries , but build my own drivers relying on code examples and the www . I have found MPLABX and PICkit 3 ( all be it sometimes frustrating ) all that i need. buying one or two devices cost is not a factor , I have followed the mcu wars posted here , but not seen any reason to experiment with other devices, I did start my controller story with a diy board with a RCA1702 back in the 1970'sI'm not really an EE , shouldn't be on here

author: andersm
author_rank: Super Contributor
timestamp: July 03, 2015, 07:13:24 am
content: Quote from: jnz on July 02, 2015, 09:26:47 pmBaaaaahahahahaaahhhahahahahaaahhhahahahahahahahaaahhhahahahahahahahaaaaaaaaa

author: Howardlong
author_rank: Super Contributor
timestamp: July 03, 2015, 07:24:19 am
content: Quote from: 22swg on July 03, 2015, 06:51:55 amOne of the joys and frustrations as you go across the vast range of PICs is the array of peripherlas. Joy in that there are similarities, frustration in that, even between devices in the same family, they are not the same. Things like I2C and SPI implementations differ markedly, with some devices going the dedicated peripheral route and others using the more generic MSSP route. UARTS and PWMs too, I've lost count of the number of implementations.Largely because of this, the provision of peripheral libraries can be patchy across the full device range to say the least.Apart from complex peripherals like USB and Ethernet, irrespective of whether or not there's a PLIB for a given device's peripheral, almost certainly you'll need to get out the device's and peripheral's datasheets plus the errata and have at least some understanding of the device at the register and hardware implementation level. While the PLIB provides maintainability from a readability standpoint, it doesn't allow you carte blanche to drop your code onto another device without some prior investigation.I tend to agree regarding having your own "utility belt" of code ready to cut and paste though. All too often when there is a PLIB formyour device's peripheral, it doesn't quite do what you want it to without coercing it which in itself makes it nasty.I don't think there's a right or wrong answer as to whether to use the PLIBs, at the end of the day if they can't support the peripheral you're going to have to do it your own way anyway. The downside is that you need to spend time documenting more closely what you're doing to avoid too much unnecessary cross referencing with datasheets when it comes to maintainance.My own journey in micros started with the General Instrument LP8000 in the mid 70s. That was the precursor to CP1600 which I also used which coincidentally spawned the PIC in the first place. I'm sure like you I've lost count of the different devices I've dealt with in the meantime!

author: andersm
author_rank: Super Contributor
timestamp: July 03, 2015, 08:29:39 am
content: Quote from: 22swg on July 02, 2015, 08:03:55 pmI think 16-bit MCUs in general are a dying breed. In my opinion, if you've outgrown an 8-bitter you've simultaneously outgrown the 16-bitters too. Unless there's some specific feature you need, you'll just end up paying more for less. You'll also have to deal with the architectural kludges used to extend the address space, that invariably break C in some way.In the olden days, when every transistor counted, 16-bitters were a reasonable compromise between performance (esp. compared to the 8-bitters of the day) and cost. These days, they don't really serve a purpose.

author: BloodyCactus
author_rank: Frequent Contributor
timestamp: July 04, 2015, 11:12:36 pm
content: I'll add that the pic32mx 170 variant in soic/dip is a sweet sweet chip!