2016-05-18 17 views
0

Я ищу некоторые советы, поскольку я работаю над PIC18F452 на Proteus.Сохранение значения PORTD в массиве на pic18f452 (C)

Моя цель - получить значение PORTDbits.RD0 (устанавливается как вход) каждые 100 мс (установленное через timer1) и сохранить его в 8-битном массиве. Этот кадр будет позже отправлен через SPI в подчиненный.

На данный момент я реализовал только то, что я считаю заполнением массива и сдвигом бит. К сожалению, когда я запускаю симуляцию, только на бит массива в какой-то момент содержится значение PORTDbits.RD0.

Если кто-то имеет представление о том, что может помочь, это было бы здорово: D

Вот мой код

/* 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 ***************************************************************/ 

Если что-то отсутствует или неясно в этом сообщении, пожалуйста, не стесняйтесь скажите мне , Я сделаю все возможное, чтобы добавить подробности или передумать мой пост, чтобы облегчить понимание. Заранее спасибо;)

+0

Что ?? Вы читаете порт: «array [index] = PORTDbits.RD0;», и они немедленно перезаписывают прочитанное значение: «array [index] = array [index + 1];». Вы говорите, что этот код действительно работает, немного? –

+0

Кроме того, 'массив unsigned char [SIZE];' представляет собой массив 8 BYTE, а не 8 бит. Можете ли вы быть более ясными. ваше фактическое намерение? –

+0

Привет, Да, я знаю, что это абсолютно глупо и нелогично. Но я пробовал другой путь: array [index + 1] = array [index], и это было не лучше ... EDIT: Я искал помощь по смещению бит, и это то, что я нашел для сделайте это вручную – Daymov

ответ

2
  1. В основной функции у вас есть бесконечный цикл, который проходит без каких-либо задержек между двумя приобретениями. То, что вам нужно, - это задержка в 100 мс между двумя раз, когда вы читаете PORTD.

Что вы можете сделать, это ввести глобальный флаг. Это устанавливается в подпрограмме таймера и очищается в основном.

  1. Неправильный код для заполнения данных в массиве. Код ниже заполняет массив, начиная с местоположения arrray[0], array[1] до максимального порядка.

Таймер должен быть изменен, как этот

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

Основная функция цикла ниже

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 
    } 
}   
+0

Спасибо! Прежде чем я смог прочитать вам ответ, я переписал код для заполнения данных в массиве до очень близкого к тому, который вы предлагаете (просто имя переменных было другим). Что касается глобального флага, извините, но в действительности не понимаю его цели. При настройке моего таймера я установил регистры, предделитель, чтобы получить задержку в 100 мс.Не будет ли избыточность, если я использую флаг? – Daymov

+0

Флаг должен иметь задержку между двумя считаниями 'PORTDbits.RD0'. В исходном коде после завершения одной итерации цикла сбора данных while (1) 'он немедленно считывает данные. Цикл while будет выполнен в порядке выполнения микросекунд. Следующие данные считываются через несколько микросекунд, а не по 100 мс. –

+0

ОК. Большое спасибо за вашу помощь. – Daymov

 Смежные вопросы

  • Нет связанных вопросов^_^