0

Micro controller PIC16F887 // The task says: Write program who will invert PORTB and will make it output port and in every SECOND it will make inverse ON/OFF on the Led Diods

Here is my Code :

unsigned cnt ;

void interrupt(){
     if(TMR0IF_bit){ //if there is interrupt in timer0
      cnt++;         //increase the counter
      TMR0IF_bit=0;  //reset the timer
      TMR0 = 96;     //set the TMR0 to its default value
     }
}

void main() {
ANSEL = 0;
ANSELH = 0;
OPTION_REG = 0b00000100; //1:32 prescalar (last 3 bits are 100)
INTCON = 0xA0;          //enable interrupt generated by TMR0
TRISB = 0x00;           //make PORTB output port
PORTB = 0xFF;           //set PORTB to 1s
cnt =0;                 //initialize counter
TMR0 = 96;              //starting value of TMR0

do{
if(cnt==391){           
 PORTB = ~PORTB;       //invert PORTB
 cnt=0;                //reset the timer
}
cnt++;                 //increase counter if its not 391
}while(1);
}

IMPORTANT TMR0 = 96 is starting value and 256-96 = 160 OPTION_REG = 1:32 so prescalar is 32 we need to make close value to 2M cause 2M instructions are nearly 1 second as they say

2 000 000 / 32 (prescalar) * 160 (256-96) = ~ 391 so one second delay should be 2M / 32 * 160 when the counter reaches 391 but when i start it on 8Mhz simulation the LED DIODS inverse in much faster time than 1 second.

So can you help me figure out what's the problem and how to make it to invert on every second. Thank you

Boris Dedejski
  • 287
  • 2
  • 4
  • 17
  • You´re increasing your counter cnt twice in the interrupt and in the while loop. Can you remove the one in the while loop and let me know if it improves ? – hackela Dec 05 '17 at 01:10
  • @hackela if i remove the cnt in while it is too slow it may take more than 10 seconds to change the value – Boris Dedejski Dec 05 '17 at 02:32
  • you cannot increment your counter twice. A proper way to do that will be to check the TOIF flag in the while loop (main) and increment the counter only if the timer popped out (and not anymore in the timer interrupt function, this one should just restart the timer). I also agree with your calculation but what clock did you select for this test ? – hackela Dec 05 '17 at 03:19
  • http://ww1.microchip.com/downloads/en/DeviceDoc/51682A.pdf here you have an indication on how to build your architecture – hackela Dec 05 '17 at 03:20

2 Answers2

0

Suggest you to go through the datasheet of the PIC16F series. It is really important to understand each registers and its significance before start using it

You have mentioned that, if you remove the increment of cnt from while loop, it takes more than 10sec which clearly indicate that , clock, TMR0 value and loop value is out of sync.

For Simple timer implementation explained in below link, which may help you

http://www.microcontrollerboard.com/pic-timer0-tutorial.html

Sudhee

Sudhee
  • 151
  • 4
  • 10
0

It has been 7 months from when an answer for this homework question was requested. A variation of this problem gets assigned just about every term so here is one possible solution for you to plagiarize:

/*
 * file:        main.c
 * author:      dan1138
 * target:      PIC16F887
 * IDE:         MPLAB 8 v8.92
 * Compiler:    XC8 v1.45
 *
 * Description:
 *  program that will invert PORTB and will make
 *  it output port and in every SECOND it will make
 *  inverse ON/OFF on the Led Diodes.
 */
#include <xc.h>

/* Setup Configuration word 1 for the PIC16F887 */
__CONFIG( FOSC_INTRC_NOCLKOUT & WDTE_ON & PWRTE_OFF & MCLRE_ON & CP_OFF & CPD_OFF & BOREN_OFF & IESO_OFF & FCMEN_OFF & LVP_OFF );

/* Setup Configuration word 2 for the PIC16F887 */
__CONFIG( BOR4V_BOR21V & WRT_OFF );

#define FSYS 8000000L       /* target device system clock freqency */
#define FCYC (FSYS/4L)      /* target device instruction clock freqency */

#define _XTAL_FREQ FSYS     /* required for XC8 delay macros */

#define TIMER0_RELOAD_VALUE (250u)
/*
 * Handle Interrupt Events
 */
void interrupt ISR_Handler( void )
{
    static unsigned short OneSecondTick = 0;

    if(INTCONbits.TMR0IE)
    {
        if(INTCONbits.TMR0IF)
        {
            INTCONbits.TMR0IF = 0;
            TMR0 -= (TIMER0_RELOAD_VALUE - 3u);

            if(OneSecondTick == 0)
            {
                OneSecondTick = (FCYC / TIMER0_RELOAD_VALUE);
                PORTB ^= 0xFF;
            }
            OneSecondTick--;
        }
    }
}
/*
 * Main application
 */
void main(void)
{
    /* Initialisation */
    INTCON = 0x00;
    PIE1   = 0x00;
    PIE2   = 0x00;

    OSCCON = 0x70;          /* select 8MHz internal clock */
    CLRWDT();

    PORTA = 0x00;
    PORTB = 0x00;
    PORTC = 0x00;
    PORTD = 0x00;
    PORTE = 0x00;

    TRISA = 0x00;
    TRISB = 0x00;
    TRISC = 0xC0;  /* TRISC Bits 7 and 6 must be inputs when UART is used */
    TRISD = 0x00;
    TRISE = 0x00;

    OPTION_REG = 0xDF; /* PORTB pull up off, INT on low to high edge,           */
                       /* TMR0 clock is FCYC, WDT has prescaler, WDT rate 1:128 */

    /* Disable all analog inputs and use for digital I/O */
    ANSEL  = 0x00;
    ANSELH = 0x00;
    ADCON0 = 0xC0;
    ADCON1 = 0x00;

    /* Disable comparators */
    CM1CON0 = 0x00;
    CM2CON0 = 0x00;
    VRCON   = 0x00;

    /* Initialize TIMER0 */
    INTCONbits.TMR0IF = 0;
    INTCONbits.TMR0IE = 1;

    /* enable system interrupts */
    GIE   = 1;

    /* Application loop */
    for(;;)
    {
        CLRWDT();
    }
}

Maybe the instructors will come up with a new assignment for the next term.

Dan1138
  • 1,150
  • 8
  • 11