3

I have been learning(trying to at least) how to work with pic microcontrollers, and I have noticed this behavior that I am not sure whether it is just my fault or is supposed to happen. I wrote the below program with hopes to make an led blink. It does blink just fine, when connected to the pin labeled RA2, but when I connect the led to pin 15 (labeled RA6/OSC2/CLKO on datasheet) the led stays on, as though I had connected it to Vdd. Then when I put it back in RA2 where it belongs, it is off. The only way to get it back on again is connecting a 10k resistor between Vdd and MCLR (like how it is when programming). What is happening here? MCLR is also needed when tapping it to some other pins. Am I causing damage?
The circuit is 3 AA batteries powering the pic, with a 330 resistor and 3mm led in series running from pin 1 (RA2) to pin 5 (ground).
pic16f88 datasheet
Code:

#include <xc.h>

__CONFIG(MCLRE_ON & CP_OFF & WDTE_OFF);

void main(){

    TRISA = 0x0000;
   // RB6 = 0b000010;
    for(;;){
        RA2 = 1;
        Wait();
        RA2 = 0;
        Wait();
    }
}
int Wait(void) // gives me a delay of 1/3rd a second or so
{
for (int i = 0; i < 50; i++)
 {
 }
}
a sandwhich
  • 392
  • 5
  • 16

3 Answers3

4

You need to tie the MCLR pin high during normal operation otherwise the chip will be held in reset. Notice the bar over MCLR, this means it is active low.
Use a resistor between MCLR and Vdd of around 10kΩ (<40kΩ)
See p.132/133 of datasheet.

Oli Glaser
  • 54,990
  • 3
  • 76
  • 147
  • So I need to keep that 10kΩ resistor there permanently? It seemed to work ok when that wasn't there. What does being held in reset do? Would putting _MCLRE_OFF in the config portion of the program fix this? – a sandwhich Aug 25 '12 at 22:52
  • It will work intermittently when it's not there due to the very high impedance of the CMOS input - just touching it with your hand will make a difference when it's floating. If the part is held in reset (MCLR actually pulled to ground rather than floating) then the main oscillator is shut down and the part "sleeps" (very low power consumption) Turning MCLR off will make the pin state irrelevant, yes. – Oli Glaser Aug 25 '12 at 22:58
  • Which is better/safer/smarter for the mcu, keeping mclr off in the config, or keeping it on and keeping the resistor there. What is usually done? – a sandwhich Aug 25 '12 at 23:06
  • It's up to you, if you don't need to be able to externally reset the micro (e.g. button press) then turning it off and saving a couple of components is an option. Microchips have many app notes on these subjects, I'd have a search on their site and do a bit of reading. – Oli Glaser Aug 25 '12 at 23:19
  • That works well, thanks. I am noticing that if I touch pin 9 (RB3/PGM/CCP1) with my finger the led will hold on and then go off. After about 5 seconds it will turn back on. What is happening there? – a sandwhich Aug 26 '12 at 00:18
  • Hard to say exactly, but it's probably due to it floating (set to input) and the changing of value causing some issue. It could be that you have LVP (Low Voltage Programming) set and it enters into programming mode. Make sure you have the correct header and config declarations, and set all unused pins to output (high or low) to prevent floating related issues. – Oli Glaser Aug 26 '12 at 00:31
  • I mention the correct header and config bits as your Wait routine as shown should not last for 1/3rd of a second (should be more like a few tens of microseconds) Make sure you have the oscillator set correctly in the config bits. – Oli Glaser Aug 26 '12 at 00:33
  • Alright, thank you. So I should append LVP_OFF to the config, and what should I set the oscilator to? The mcu is rated at 20 mhz, is that an acceptable value? – a sandwhich Aug 26 '12 at 00:56
  • If you have an external 20 MHz crystal, then yes, you can set it to this. If not then use the 8MHz internal oscillator. You can turn the LVP off if not using it, yes, and it may stop what you are seeing (but the pin should be set to an output anyway) I advise having a thorough read of the datasheet, all the information about configuration (oscillator, reset, LVP, etc) is in there. – Oli Glaser Aug 26 '12 at 01:13
  • Everything is working correctly now, I think I know what has been happening now. I set it to use the internal oscillator with the config bit FOSC_INTOSCIO. I increased the wait loop to loop 500 times, and I get a little more than a second between each blink. When I put it down to fifty it blinks much more rapidly. – a sandwhich Aug 26 '12 at 16:53
2

Your problem lies on the !MCLR pin. When you program the PIC you are using the VPP function, but the same pin has the !MCLR (Master Clear) function, and since this function is active low, you need to assure this pin stays high so the PIC can run your code. As Oli said, you can achieve this by connecting a pull-up resistor for to the !MCLR pin.

As an alternative you can disable the MCLR function by reseting (writing a 0) the MCLRE bit on the CONFIG1 register.

__CONFIG(MCLRE_OFF & CP_OFF & WDTE_OFF);

Detail of the MCLRE bit from page 130 of the datasheet:

MCLRE: RA5/MCLR/VPP Pin Function Select bit
1 = RA5/MCLR/VPP pin function is MCLR
0 = RA5/MCLR/VPP pin function is digital I/O, MCLR internally tied to VDD


Added

Regarding the Read-Modify-Write issue, it happens due to the way the PIC works. 8 bit PICs need four clock cycles for each instruction cycle. Writes are made on the last clock cycle, while reads are made on the first clock cycle. This may cause problems when you are working with different bits of the same port.

Suppose you have the following code:

RA0 = 1;
RA1 = 1;

You would expect that both RA0 and RA1 be high after running this code. This may not be the case. If you have all bits set to 0 on PORTA, when you execute RA0 = 1 the PIC will read the value on PORTA on the first clock cycle, set the bit 0, and write the result back to PORTA. So far no problem, but when you execute the second instruction (RA1 = 1), the PIC will first read the value of PORTA, and most likely the RA0 pin had not time to rise to 1, then the value read for that pin is 0 instead of 1, then the bit 1 is set, then the result is written back to PORTA, but only the bit 1 is set.

To avoid this you can add delays between the instructions like this:

RA0 = 1;
asm("nop");  // No operation
RA1 = 1;

One nop instruction should be enough.

In you code you should not have this problem for two reasons:

  1. You are not changing different bits on PORTA
  2. You have a wait instruction between writes the bits of PORTA

The shadow register that Leon was talking about consists on a register where the individual bits are modified before writing the whole register to the PORT.

Bruno Ferreira
  • 4,470
  • 2
  • 25
  • 36
1

You may want to make sure your config fuses are set such that RA6 is a GPIO pin and not the CLKO function that the pin can also take on. I ran into this problem with a simple program and CCS' compiler. The compiler has such poor documentation that it's impossible to know exactly what is happening without looking at the fuse bits yourself.

I would have expected that whether the LED is on RA2 or RA6, you would have erratic behaviour if MCLR# isn't pulled high. Perhaps RA6 is closer to MCLR# and the problem is exacerbated; not sure.

akohlsmith
  • 11,162
  • 1
  • 35
  • 62