Daymov
Daymov

Reputation: 45

Storing PORTD value in array on pic18f452 (C)

I'm a looking for some advice as I'm working on a PIC18F452 on Proteus.

My objective is to acquire the value of PORTDbits.RD0 (set as input) every 100ms (set through timer1) and store it in an 8-bit array. This frame would be later sent through SPI to slave.

For the moment I have only implemented what I consider to be the filling of the array and the bit shifting. Sadly, when I start the simulation, only on bit of the array contains at some point the value of PORTDbits.RD0.

If anyone has an idea that might help, it would be great :D

Here's my code

/* CONFIG *******************************************************************/
#pragma config PWRT  = ON    // Power-up Timer
#pragma config OSC   = HS    // High-Speed Oscillator
#pragma config LVP   = OFF   // Low-Voltage In-Circuit Serial Programming
#pragma config DEBUG = ON    //

/* INCLUDES *****************************************************************/
#include "project_config.h"  // All headers inclusion

/* MACROS *******************************************************************/
#define nop() {_asm nop _endasm}

/* DEFINES ******************************************************************/
#define SIZE 8

/* FUNCTIONS PROTOTYPES *****************************************************/
void main(void);

void isr_config(void);
void io_config(void);

void timer1_config(void);
void timer1_isr(void);

/* PROTOTYPES ***************************************************************/

/* VARIABLES DEFINITION *****************************************************/
unsigned int filling_cnt = 0; 

/* MAIN *********************************************************************/
void main(void) {
    unsigned char array[SIZE]; 
    unsigned int index = 0; 
    int j; 

    /// Initialization
    io_config();
    timer1_config();
    isr_config();

    /// Interruption
    timer1_isr();

    /// Data acquisiton
    while(1){
        array[index] = PORTDbits.RD0;          // Read RD0 and save in array        
        for(index = 0; index < SIZE; index++){ // Fill array
            array[index] = array[index+1];     // shifting n_value to insert n+1_value
            //printf("%s\n", array);
         } //rof

         filling_cnt++;                         // Array counter for filling control

         if(filling_cnt > SIZE){                  // Reached the end of array ?
            index = 0;                         // Reset counter
            printf("%s\n", array);             // Send data to terminal
            for (j=0; j<SIZE; j++){
                array[j] = '\0';               // Empty array
            } //rof
         } //fi
    }
}

/* FUNCTIONS ****************************************************************/
/// Configurations
void timer1_config(void) {
    T1CONbits.RD16 = 1;    // Timer/Counter 8-bits/16-bits Control bit: 0=8-bits / 1=16-bits
    T1CONbits.T1CKPS1 = 1; // Prescaler
    T1CONbits.T1CKPS0 = 1; //   1 = 0b00
                           //   2 = 0b01
                           //   4 = 0b10
                           //   8 = 0b11
    T1CONbits.T1OSCEN = 1; // Timer1 Oscillator shut off
    T1CONbits.TMR1CS = 0;  // Timer1 Clock Source Select bit
                           //   0 = Internal Clock (Fosc/4)
                           //   1 = Transition on T1CKI pin
    T1CONbits.TMR1ON = 1;  // Timer1 On/Off Control bit
                           //   1 = Enables Timer1
                           //   0 = Stops Timer1
    TMR1H=0x0B;            // Preset timer1 value for MSB register
    TMR1L=0xDB;            // Preset timer1 value for LSB register
                           // to get a 100ms delay
}

void isr_config(void) {
    PIE1bits.TMR1IE = 1;   // Enable Timer1 interrupts
    PIR1bits.TMR1IF = 0;   // Clear Timer1 interrupt flag
    IPR1bits.TMR1IP = 1;   // Non high priority interrupt

    RCONbits.IPEN   = 1;   // Interrupt High level

    INTCONbits.PEIE = 1;   // All peripherals interrutps verified
    INTCONbits.GIE  = 1;   // All interrupts verified
}

void io_config(void) {
    TRISB = 0x00;          // PORTB as output
    TRISDbits.TRISD0 = 1;  // COMP_OUT as input
    TRISDbits.TRISD1 = 0;  // DATA as output
}

/// Interruptions
#pragma code highVector = 0x08 //lowVector = 0x18
void InterruptHigh (void) {
   _asm
   goto timer1_isr
   _endasm
}
#pragma code

#pragma interrupt timer1_isr
void timer1_isr(void) {
     if (PIR1bits.TMR1IF == 1) {  // check that timer1 overflow is reason for ISR.
                                  // even though there is only one Interrupt source
                                  // trigger enabled, it is good programming practice to
                                  // test why we have arrived at the ISR.
        PIR1bits.TMR1IF = 0; // Timer1 interrupt flag clear

        TMR1H = 0x0B;        // Preset timer1 value for MSB register
        TMR1L = 0xDC;        // Preset timer1 value for LSB register
                             // with a 20MHz xtal, Timer1 Prescalar set to /8
                             // decimal 3036 (0x0B 0xDC) is the counter start point
                             // which will result in Timer1 overflow 1 per 100ms
                             // 65536 - 3036 = 62500 cycles
                             // 10 interrupts per second

        LATBbits.LATB4 = !LATBbits.LATB4; // invert the condition of LED to show program
                                          // has entered the Interrupt routine
        PORTDbits.RD1 = !PORTDbits.RD1;   // invert the condition of DATA to show program
                                          // has entered the Interrupt routine                              
     } //fi
}

/* EOF main.c ***************************************************************/

If anything is missing or unclear in this message, please do not hesitate do tell me. I'll do my best to add details or to re-think my post in order to facilitate the comprehension. Thanks in advance ;)

Upvotes: 0

Views: 288

Answers (1)

Rishikesh Raje
Rishikesh Raje

Reputation: 8614

  1. In the main function you have an infinite loop, which runs without any delay between two acquisitions. What you need is to have a delay of 100ms between the two times that you read PORTD.

What you can do is introduce a global flag. This is set in the timer subroutine, and is cleared in main.

  1. The code for filling the data into the array is not correct. The code below fills the array starting from location arrray[0], array[1] to max in order.

The timer should be modified like this

void timer1_isr(void) {
    if (PIR1bits.TMR1IF == 1) {
        blTimeOverFlag = 1;
        // Other code here
    }
}

Main function loop is below

while(1){
  if (blTimeOverFlag == 1)
  {   
    blTimeOverFlag = 0;
    array[filling_cnt] = PORTDbits.RD0;          // Read RD0 and save in array        
     filling_cnt++;                         // Array counter for filling control

     if(filling_cnt >= SIZE){                  // Reached the end of array ?
        filling_cnt = 0;
        printf("%s\n", array);             // Send data to terminal
        for (j=0; j<SIZE; j++){
            array[j] = '\0';               // Empty array
        } //rof
     } //fi
  }
}           

Upvotes: 2

Related Questions