Weird problem regarding outputs from PIC - Page 1
Forum section: electronics / general

author: JoeP
author_rank: Contributor
timestamp: December 28, 2018, 08:28:03 pm
content: I've written a code to flash an LED using the TMR0 module. Here is the code:Code:// CONFIG1#pragma config FOSC = INTOSC // Oscillator Selection Bits (Internal HFINTOSC. I/O function on RA4 and RA5.)#pragma config WDTE = OFF // Watchdog Timer Enable (WDT disabled)#pragma config PWRTE = OFF // Power-up Timer Enable (PWRT disabled)#pragma config MCLRE = OFF //#pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled)#pragma config BOREN = ON // Brown-out Reset Enable (Brown-out Reset enabled)#pragma config CLKOUTEN = OFF // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)// CONFIG2#pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off)#pragma config PPS1WAY = ON // Peripheral Pin Select one-way control (The PPSLOCK bit cannot be cleared once it is set by software)#pragma config ZCDDIS = ON // Zero-cross detect disable (Zero-cross detect circuit is disabled at POR)#pragma config PLLEN = ON // Phase Lock Loop enable (4x PLL is always enabled)#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)#pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)#pragma config LPBOR = OFF // Low-Power Brown Out Reset (Low-Power BOR is disabled)#pragma config LVP = OFF // Low-Voltage Programming Enable// #pragma config statements should precede project file includes.// Use project enums instead of #define for ON and OFF.#include <xc.h>void main(){OSCCON = 0b01101010; //4MHz internal oscillatorOPTION_REG = 0b10000011; //16* prescalerTRISC = 0x00;PORTC = 0x00;while(1){PORTC=0xFF;for(int i=0;i<200;i++){TMR0 = 0;while(TMR0<250);}PORTCbits.RC0 = 0;for(int i=0;i<200;i++){TMR0 = 0;while(TMR0<250);}}}What is supposed to happen is that all the PORTC pins turn on, then RC0 turns on and off (while the other pins remain on). However, the other pins all seem to flash with RC0. I tried changing it so that all the pins are turned off, then only RC0 is turned back on each cycle, and this worked as expected (all other pins remained off).Code:PORTC=0x00;for(int i=0;i<200;i++){TMR0 = 0;while(TMR0<250);}PORTCbits.RC0 = 1;for(int i=0;i<200;i++){TMR0 = 0;while(TMR0<250);}Essentially, what seems to be happening is that the lineCode:PORTCbits.RC0 = 0;is setting the whole of PORTC to 0, yet the commandCode:PORTCbits.RC0 = 1;is only setting RC0 to 1.Why is this happening, and how can I stop it?The microcontroller in question is the PIC16F1703, and the datasheet is here:http://ww1.microchip.com/downloads/en/DeviceDoc/40001722C.pdf

author: JPortici
author_rank: Super Contributor
timestamp: December 28, 2018, 08:38:34 pm
content: Before some start quoting other datasheeds regarding PORTx, LATx and RMW Issues, the datasheet for this pic says that writes to PORTx are actually writes to LATx, while reading PORTx reads the actual state of the IOsBut just for kicks, try to use the LATC register and see what happens...Also, if you are using the simulator i wouldn't trust it over the real pic

author: JoeP
author_rank: Contributor
timestamp: December 28, 2018, 08:43:01 pm
content: I never really understood the difference between the latches and the ports. It says that writes to either do the same thing, and I've never needed to read outputs.I am using an actual microcontroller, with LEDs to indicate the pin states.EDIT: I just tried using LATC, and it worked! So that's the 'how can I stop it?' solved, now for the 'why is this happening?'.

author: SiliconWizard
author_rank: Super Contributor
timestamp: December 28, 2018, 08:57:57 pm
content: Not all operations leading to a port write are created equal. Many instructions issue what are called "read-modify-write operations" which can have unexpected results in some cases. This is why, especially if you don't write directly in assembly language (and thus you can't know exactly what instructions are going to be used), you should use LATx instead or PORTx for any write operation.Look up "read-modify-write" in Microchip docs.

author: Ian.M
author_rank: Super Contributor
timestamp: December 28, 2018, 09:27:52 pm
content: Although the official documentation does cover RMW (read modify write) issues, its pretty minimal as they weren't keen on hiliting a known disadvantage of the original PIC12/16 baseline and midrange IO port implementation in a competitive marketplace. For the real skinny on RMW, read the threadRMW and solutions for itover on the Microchip forum, and follow up the links in the first post.Edit: It looks like piclist.org has gone to domain parkingso for what Micheal Rigby-Jones had to say, you'll have to go to the wayback machine:www.piclist.org/techref/readmodwrite.htm from 2009

author: JPortici
author_rank: Super Contributor
timestamp: December 29, 2018, 03:49:43 am
content: Quote from: Ian.M on December 28, 2018, 09:27:52 pmwasn't it piclist.com?

author: Ian.M
author_rank: Super Contributor
timestamp: December 29, 2018, 04:07:35 am
content: It looks like its only their .org domain that's gone to parking. Still not good as it breaks old 3rd party links, but that's Internet bit-rot for you!http://www.piclist.com/techref/readmodwrite.htm

author: TomS_
author_rank: Frequent Contributor
timestamp: January 01, 2019, 10:16:22 pm
content: Quote from: JoeP on December 28, 2018, 08:28:03 pmNot sure why it is acting up, but you could simplify your code a little as such:Code:#include <xc.h>void main(){OSCCON = 0b01101010; //4MHz internal oscillatorOPTION_REG = 0b10000011; //16* prescalerTRISC = 0x00;PORTC = 0x00;PORTC = 0xFF;while(1){for(int i=0;i<200;i++){TMR0 = 0;while(TMR0<250);}PORTC ^= 0x01;}}This does an XOR on bit 0 which will toggle it for each iteration of the while(1) loop. Replace PORTC with LATC if that is what ended up working (sounds like it did!)

author: cv007
author_rank: Frequent Contributor
timestamp: January 01, 2019, 11:10:22 pm
content: QuoteThe problem is well known. Even though a write to a 'port' will write to the 'lat', a read from a 'port' is a read from the 'port'. When ansel is 1, which in this case it is, a read from a 'port' will read a 0 no matter what the pin state actually is.When doing a bcf/bsf (the compiler) you are really doing a read/modify/write on the whole port- the read in the middle is producing a '0' for every bit in 'port' that has ansel set (which again, in this case the result is all 0's since anselc is in the default state). (that may not be 100% correct as I'm not sure if every pin in portc is analog capable for this particular chip, but I think most are).Even in your example-PORTC ^= 0x01;you will not get what you intended.result-x = PORTC; //all 0's as anselc is set for all pins, so x=0x ^= 1; //0 xor 1 is 1, so x=1PORTC = x; //LATC now equals 1 (you just clobbered all the other pins by setting them to 0)correct-LATC ^= 1;x = LATC; /x=0bnnnnnnnn <<--HERE the read in R/M/W actually gets what you wanted to knowx ^= 1; //x=0bnnnnnnn/n (inverted bit0)LATC = x; //all bits remain the same, except bit0 is invertedNow you may get what you intended if you have cleared ansel bit(s), and choose to write to 'port' for some reason- but there is no reason to do so.Long story short, and a repeating story- write to LAT (TRISCn=0), read from PORT if you want the actual pin state (TRISCn=1, ANSELCn=0).Maybe they should rename PORT, LAT-PORTC -> INPUTCLATC-> OUTPUTCthen it makes little sense to do- INPUTC ^= 1 or INPUTCbits.C2 = 1;and does makes sens to do- OUTPUTC ^= 1 or OUTPUTCbits.C4 = 0;or you can come up with some functions to keep you out of trouble-https://github.com/cv007/SNaPmate/blob/master/pins.c

author: TomS_
author_rank: Frequent Contributor
timestamp: January 02, 2019, 06:12:22 pm
content: Quote from: cv007 on January 01, 2019, 11:10:22 pmAh yes, makes sense. I was just rolling in to bed when I wrote that message. Quite familiar with RMW stuff, but wasnt thinking about it very hard at the time.

author: IDEngineer
author_rank: Super Contributor
timestamp: January 06, 2019, 07:22:21 pm
content: How the PIC GPIO pins work is actually very clear if you look at the hardware diagrams in the part's spec sheet. I've actually used this "feature" intentionally a couple of times for things like error detection; as an example, where the LATch is written to one state yet the pin reads as the other state. It's also useful for using a single pin for collision detection style bidirectional I/O. My point is that while it may seem strange at first, once you understand the hardware it's not hard to use and can, in fact, be useful once in a while.

author: MarkF
author_rank: Super Contributor
timestamp: January 06, 2019, 07:57:13 pm
content: Quote from: JoeP on December 28, 2018, 08:43:01 pmQuote from: IDEngineer on January 06, 2019, 07:22:21 pmYes. The port I/O hardware port diagram in the datasheet for this PIC says it all.I don't believe all PICs have the same port circuit.You need to look in the datasheet for the PIC you are using.It shows the point on the port I/O bus that the read/write instruction addresses.

author: IDEngineer
author_rank: Super Contributor
timestamp: January 06, 2019, 08:22:11 pm
content: Quote from: MarkF on January 06, 2019, 07:57:13 pmI agree, which is why I said:Quote from: IDEngineer on January 06, 2019, 07:22:21 pm

author: JPortici
author_rank: Super Contributor
timestamp: January 06, 2019, 08:38:21 pm
content: Quote from: cv007 on January 01, 2019, 11:10:22 pmoooh that was really bugging me

author: NorthGuy
author_rank: Super Contributor
timestamp: January 06, 2019, 08:58:56 pm
content: Quote from: JPortici on January 06, 2019, 08:38:21 pmIt's a good thing. ANSEL protects the digital logic from analog signals.

author: MarkF
author_rank: Super Contributor
timestamp: January 06, 2019, 11:01:28 pm
content: Quote from: IDEngineer on January 06, 2019, 08:22:11 pmI believe a few more examples may be instructive to this conversation.The actual circuit explains Read-Modify-Write issues for some MCUs.From a pic18f2550From a pic16f876a

author: mikerj
author_rank: Super Contributor
timestamp: January 07, 2019, 01:32:25 pm
content: Quote from: Ian.M on December 29, 2018, 04:07:35 amI wrote that entry back when I worked for Nortel Networks, must be around 20 years ago! Time flies.