PIC 18f4520-使用Rx中断从串行接收数据

PIC 18f4520-使用Rx中断从串行接收数据,c,pic,microchip,C,Pic,Microchip,接下来,我想从PIC18f4520向我的计算机发送和接收数据。使用串行端口向计算机发送数据对我来说很好。 我现在正尝试使用串行端口从我的计算机接收数据。我从一个C#应用程序发送数据,这个应用程序是我的老师创建的(对其他学生来说效果很好),所以这不成问题 要接收数据,我需要使用中断。我将USART\u RX\u INT\u OFF更改为USART\u RX\u INT\u ON,并启用了外围中断 使用调试工具,我注意到我的程序从未进入中断(我必须使用高优先级的中断) 我的程序的基本功能(工作正常)

接下来,我想从PIC18f4520向我的计算机发送和接收数据。使用串行端口向计算机发送数据对我来说很好。 我现在正尝试使用串行端口从我的计算机接收数据。我从一个C#应用程序发送数据,这个应用程序是我的老师创建的(对其他学生来说效果很好),所以这不成问题

要接收数据,我需要使用中断。我将USART\u RX\u INT\u OFF更改为USART\u RX\u INT\u ON,并启用了外围中断

使用调试工具,我注意到我的程序从未进入中断(我必须使用高优先级的中断)

我的程序的基本功能(工作正常):

  • 我正在使用ADC从RA5引脚收集模拟数据
  • 将高电平或低电平发送至针脚RE2以点亮或关闭灯泡
  • 使用引脚RA1控制伺服电机
  • 使用LCD屏幕在其上打印信息
Init_Interruptions()应该初始化中断 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++;
            }
        }
    }
}
#包括
#包括
#包括“p18f4520.h”
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括“config.h”
#包括“hd44780/hd44780.h”
#为(uint8\u t i=0;i<20;i++)定义延迟1\u延迟(50)
整数计数器;
无符号字符textx[10];
无符号字符JourMSG[]=“jour”;
无符号字符NuitMSG[]=“nuit”;
/*字符链[10]=“”;
字符缓冲区[10];
字符*s1,*s2;
无符号整数i,j*/
//伺服电机信号发送功能
无效旋转_中间(){//0°
PORTAbits.RA1=1;
__延期付款(1500美元);
PORTAbits.RA1=0;
__延期付款(18500);
}
无效左转(){/-90°
PORTAbits.RA1=1;
__延迟(1000);
PORTAbits.RA1=0;
__延期付款(19000美元);
}
无效右转(){//90°
PORTAbits.RA1=1;
__delay_us(2000年);
PORTAbits.RA1=0;
__延期付款(18000);
}
//////////////////////////////////////
//延迟函数
void DelayxmSecond(无符号整数节拍)
{
对于(int i=0;i)
PORTBbits.RB1=1;
内部计算机=0;
int modejour=1;//从日模式开始
无符号整数N;
而(1)
{
ADCON0bits.GO_DONE=1;//启动转换
while(ADCON0bits.GO_DONE!=0);
LCDPO(0,3);

N=(ADRESH似乎您没有启用全局中断

从您发布的教程中:

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

代码中缺少此调用。

似乎您没有启用全局中断

从您发布的教程中:

ei();       //remember the master switch for interrupt?
您的代码中缺少此调用。

在将“ei();”添加到我的程序后,它没有按预期工作。 我使用“SparkFun FTDI基本突破-5V”通过串行端口进行连接。 我改变了使用RS-232电缆连接PC和PIC的方式,它成功了


所以我真的不知道为什么,但我认为FTDI板没有正确地将数据从计算机发送到pic(即使每次我发送信息时Rx led都闪烁)。现在一切都好了,我发送和接收信息(我仍然在我的程序中调用ei())。

在我的程序中添加“ei();”后,它没有按预期工作。 我使用“SparkFun FTDI基本突破-5V”通过串行端口进行连接。 我改变了使用RS-232电缆连接PC和PIC的方式,它成功了


所以我真的不知道为什么,但我认为FTDI板没有正确地将数据从计算机发送到pic(即使每次我发送信息时Rx led都闪烁)。现在一切都好了,我发送和接收信息(我仍然在程序中调用ei().

我将在明天早上的课堂上尝试。我将告诉您这是否是解决方案。谢谢您在我的程序中添加“ei();”后,它没有按预期工作。我使用的是“SparkFun FTDI基本突破-5V”通过串行端口连接。我改变了使用RS-232电缆连接PC和PIC的方式,它工作了!所以我真的不知道为什么,但我认为FTDI板没有正确地将数据从计算机发送到PIC(即使每次我发送信息时Rx led都闪烁)。无论如何,感谢您的回复:)明天早上我会在课堂上尝试。我会告诉你这是否是解决方案。谢谢你在我的程序中添加“ei();”后,它没有按预期工作。我使用的是“SparkFun FTDI Basic Breakout-5V”通过串行端口连接。我改变了使用RS-232电缆连接PC和PIC的方式,它工作了!所以我真的不知道为什么,但我认为FTDI板没有正确地将数据从计算机发送到PIC(即使每次我发送信息时Rx led都闪烁)。无论如何,感谢您的回复:)像这样的数字:
ADCON2bits.ADCS2=010;
是八进制值,这是您真正想要的吗?发布的代码不是初始化时钟外围设备,我认为这是获得准确波特率、延迟计时等所必需的步骤。参考教程包括将PIC81用作回波设备的适当代码另外,需要禁用ADC外围设备,以便能够为“rx”数据位使用适当的I/O引脚。我看不到代码中正在执行该步骤。在
Int\u haute()
函数中,调用
getsUSART()
第二个参数为10时,将导致代码在该中断中至少停留10次“char”。这是一个很长的中断时间。
getsuart()
执行轮询而不是中断驱动的I/O。建议删除中断代码,然后调用:
char DataRdyUSART(void)
定期。保持输入缓冲区中当前有多少字节的状态