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 100 ms (set through timer1) and store it in an 8-bit array. This frame would be later sent through SPI to the 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.
What should I do?
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 100 ms 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 interrupts 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
}
/// Interrupts
#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 20 MHz quartz crystal, Timer1 prescaler set to /8
// decimal 3036 (0x0B 0xDC) is the counter start point
// which will result in Timer1 overflow 1 per 100 ms
// 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 ***************************************************************/
In the main function, you have an infinite loop, which runs without any delay between two acquisitions. You need to have a delay of 100 ms between the two times that you read PORTD.
You can introduce a global flag. This is set in the timer subroutine, and is cleared in main.
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 maximum in order.
The timer should be modified like this:
void timer1_isr(void) {
if (PIR1bits.TMR1IF == 1) {
blTimeOverFlag = 1;
// Other code here
}
}
The 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
}
}