2016-01-13 15 views
0

Следуя this tutorial, я хотел отправить и получить данные с PIC18f4520 на свой компьютер. Отправка данных на компьютер с использованием последовательного порта работает для меня отлично. Теперь я пытаюсь получить данные с моего компьютера с помощью последовательного порта. Я отправляю данные из приложения C#, которое было создано моим учителем (он отлично работает для других студентов), поэтому это не может быть проблемой.PIC 18f4520 - Получение данных из последовательного интерфейса с использованием прерывания Rx

Чтобы получать данные, мне нужно сделать это с помощью прерываний. Я изменил USART_RX_INT_OFF на USART_RX_INT_ON и включил периферийное прерывание.

Используя инструмент отладки, я заметил, что моя программа никогда не вводилась, это прерывание (я должен использовать высокоприоритетный).

Что моя программа делает в основном (это работает отлично):

  • Я сбора аналоговых данных с выводами RA5 с помощью АЦП
  • Отправка ВЫСОКИЙ или НИЗКИЙ приколоть RE2, чтобы зажечь лампочку или повернуть это от
  • Использование пин RA1 для управления сервомотором
  • Использование ЖК-экран для печати информации на нем

Init_Inte Предполагается, что прерывания() должны инициировать прерывания. ADC_Init() должен инициировать ADC

Вот мой код, я попытался добавить как можно больше комментариев, чтобы быть ясными. Дайте мне знать, если вы можете мне помочь, это было бы очень оценено.

#include <stdio.h> 
#include <stdlib.h> 

#include "p18f4520.h" 

#include <stdio.h> 
#include <stdlib.h> 
#include <plib/adc.h> 
#include <plib/usart.h> 
#include <plib/portb.h> 
#include <plib/delays.h> 
#include <plib/timers.h> 
#include <plib/pwm.h> 
#include <string.h> 
#include <xc.h> 
#include <stdlib.h> 
#include "config.h" 
#include "hd44780/hd44780.h" 

#define delay1S for(uint8_t i = 0 ; i < 20 ; i++) __delay_ms(50) 

int counter; 
unsigned char textTx[10]; 
unsigned char JourMSG[]= "jour"; 
unsigned char NuitMSG[]= "nuit"; 
     /*char chaine[10]= ""; 
     char buffer[10]; 
     char * s1, * s2; 
     unsigned int i, j;*/ 

//Servo motor signal sending functions 
void turn_middle() { //0° 
     PORTAbits.RA1 = 1; 
     __delay_us(1500); 
     PORTAbits.RA1 = 0; 
     __delay_us(18500); 
} 

void turn_left() { //-90° 
     PORTAbits.RA1 = 1; 
     __delay_us(1000); 
     PORTAbits.RA1 = 0; 
     __delay_us(19000); 
} 

void turn_right() { //90° 
     PORTAbits.RA1 = 1; 
     __delay_us(2000); 
     PORTAbits.RA1 = 0; 
     __delay_us(18000); 
} 
////////////////////////////////////// 

//Delay functions 
void DelayxmSecond(unsigned int tempo_ms) 
{ 
    for(int i=0;i<tempo_ms;i++) 
     __delay_ms(1); 
} 


void DelayxSecond(unsigned int tempo_s) 
{ 

    for(int j=0;j<tempo_s;j++) 
     DelayxmSecond(1000); 


} 
//////////////////////////////////////// 


void Init_Timer1(void) 
{ 
    OpenTimer1(TIMER_INT_ON & T1_16BIT_RW & T1_SOURCE_EXT & T1_PS_1_1 & T1_OSC1EN_ON & T1_SYNC_EXT_ON); 
    IPR1bits.TMR1IP=0; 
    WriteTimer1(32768); 
} 

void Init_Interruptions(void) 
{ 
     PIR1bits.RCIF = 0; //reset RX pin flag 
     IPR1bits.RCIP = 1; //high priority 
     PIE1bits.RCIE = 1; //Enable RX interrupt 
     INTCONbits.PEIE = 1; //Enable pheripheral interrupt (serial port is a pheripheral) 

     RCONbits.IPEN = 1; 
     INTCONbits.GIEH = 1; 
     INTCONbits.GIEL = 1; 
} 

void interrupt high_priority Int_haute() 
{ 
    //check if the interrupt is caused by RX pin 
    if(PIR1bits.RCIF == 1) 
    { 
     INTCONbits.GIEH = 0; 

     getsUSART(textTx,10); 
     PIR1bits.RCIF = 0; // clear rx flag 

     INTCONbits.GIEH = 1; 
    } 
} 

void interrupt low_priority Int_basse() //Not doing anything here 
{ 
    INTCONbits.GIEL = 0; 

    INTCONbits.GIEL = 1; 
} 

void ADC_Init() //ADC init 
{ 
    ADCON1bits.VCFG1 = 0; //-Vref VSS 
    ADCON1bits.VCFG0 = 0; //+Vref VDD 
    ADCON1bits.PCFG3 = 1110; 
    ADCON1bits.PCFG2 = 1110; 
    ADCON1bits.PCFG1 = 1110; 
    ADCON1bits.PCFG0 = 1110; 

    ADCON0bits.CHS3 = 0000; 
    ADCON0bits.CHS2 = 0000; 
    ADCON0bits.CHS1 = 0000; 
    ADCON0bits.CHS0 = 0000; 
    ADCON0bits.GODONE = 0; 
    ADCON0bits.ADON = 1; 

    ADCON2bits.ADFM = 0; 
    ADCON2bits.ACQT2 = 101; 
    ADCON2bits.ACQT1 = 101; 
    ADCON2bits.ACQT0 = 101; 
    ADCON2bits.ADCS2 = 010; 
    ADCON2bits.ADCS2 = 010; 
    ADCON2bits.ADCS2 = 010; 

    ADCON0bits.ADON = 1; //TURN ON AD MODULE 

    ADCON1 = 0xC0; //All pins as Analog Input 
       //With reference voltages VDD and VSS 
} 

void main(){ 

    TRISCbits.TRISC7 = 1; 
    TRISCbits.TRISC6 = 0; 
    OpenUSART(USART_TX_INT_OFF &USART_RX_INT_ON &USART_ASYNCH_MODE &USART_EIGHT_BIT &USART_BRGH_HIGH,12); 

    Init_Interruptions(); 

    //Set LCD pins to output 
    TRISD=0x00; 

    //PIC2DEMPLUS related stuffs. Not needed on board without LCD power control and with R/W wired to ground 
    LATDbits.LD7 = 1;   // LCD power on 
    __delay_ms(50);    // LCD power up delay 
    LATDbits.LD5 = 0;   // R/W set to W 

    //LCD init 
    LCDinit(LCD_INIT_CURSOR_DISABLED); 
    __delay_ms(2); 

    ADC_Init(); 

    TRISAbits.TRISA5 = 1; // configure RA5 as analog input 

    ADCON0   = 0b01100000; // Set channel select to AN5 
    ADCON1   = 0b00001011; // Configure RA5/AN5 as analogue 
    ADCON2   = 0b10101010; // Right justified result 
    // configure voltage reference 
    //ADCON1bits.VCFG1 = 0;  // -ve ref = Vss 
    //ADCON1bits.VCFG0 = 1; // +ve ref = Vdd 
    // select ADC input channel 
    ADCON0bits.CHS = 100; // input = AN5 
    ADCON2bits.ACQT = 100; // input = AN5 
    ADCON2bits.ADCS = 100; // input = AN5 
    ADCON2bits.ADFM = 1; 
    ADCON0bits.ADON = 1; // turn on ADC module 

    TRISAbits.TRISA1 = 0; //RA1 output -> SERVOMOTOR 
    TRISEbits.TRISE2 = 0; //RB1 output -> BULB 
    PORTBbits.RB1 = 1; 
    int compteur=0; 
    int modejour=1; //Starting with day mode 
    unsigned int N; 
    while(1) 
    { 
     ADCON0bits.GO_DONE = 1; //LAUNCH CONVERSION 
     while(ADCON0bits.GO_DONE != 0); 
     LCDpos(0,3); 
     N=(ADRESH<<8)+ADRESL; 
     putsUSART(textTx); 
     if(N>800 && modejour==0) 
     { 
      LCDpos(0,3); 
      LCDprintConst("PLEIN JOUR"); 
      putsUSART(JourMSG); 
      PORTEbits.RE2 = 0; 
      modejour=1; 
      compteur=0; 
      while(compteur<20) 
      { 
       turn_right(); 
       compteur++; 
      } 
     } 
     if(N<800 && modejour==1) 
     { 
      LCDpos(0,3); 
      LCDprintConst("MODE NUIT "); 
      putsUSART(NuitMSG); 
      PORTEbits.RE2 = 1; 
      modejour=0; 
      compteur=0; 
      while(compteur<20) 
      { 
       turn_left(); 
       compteur++; 
      } 
     } 
    } 
} 
+0

такие цифры: 'ADCON2bits.ADCS2 = 010;' - восьмеричные значения, это то, что вы на самом деле хотите? – user3629249

+0

опубликованный код не инициализирует периферийное устройство часов, я бы подумал, что этот шаг необходим для получения точных скоростей передачи, таймингов задержки и т. Д. – user3629249

+0

Указанный учебник включает в себя соответствующий код для использования PIC81 в качестве эхо-устройства. Помимо всего прочего, периферийное устройство ADC необходимо отключить, чтобы иметь возможность использовать соответствующий вывод ввода-вывода для бит данных «rx». Я не вижу, чтобы этот шаг выполнялся в коде. – user3629249

ответ

2

Похоже, что вы не разрешили глобальные прерывания.

Из урока вы вывесили:

ei();  //remember the master switch for interrupt? 

Этот вызов отсутствует в вашем коде.

+0

Я попробую это завтра утром в классе. Я скажу вам, если это решение или нет. Спасибо – nico1717

+0

Мне любопытно, это сработало? –

+0

После добавления "ei();" к моей программе, он работал не так, как ожидалось. Я использовал «SparkFun FTDI Basic Breakout - 5V» для подключения через последовательный порт. Я поменял свой путь, чтобы подключить ПК и PIC, используя кабель RS-232, и это сработало! – nico1717

0

После добавления «ei();» к моей программе, он работал не так, как ожидалось. Я использовал «SparkFun FTDI Basic Breakout - 5V» для подключения через последовательный порт. Я поменял свой путь, чтобы подключить ПК и PIC, используя кабель RS-232, и это сработало! - nico1717 9 мин. Назад

Так что я действительно не знаю, почему, но я думаю, что плата FTDI не отправляла данные с компьютера на изображение правильно (даже если светодиод Rx моргнул каждый раз, когда я отправлял информацию). Все в порядке, теперь я передаю и получаю информацию (я по-прежнему вызываю ei(), в своей программе).