打印
[PIC®/AVR®/dsPIC®产品]

新手请教:dsPIC33EP512MC806 串口中断异常

[复制链接]
2688|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
102856|  楼主 | 2017-6-27 20:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
刚接触PIC单片机,现在用dsPIC33系列单片机做一个串口收发测试:采用串口接收中断,大概每隔5ms接收20个字节的数据,并将接收到的数据通过另一个串口转发出去,波特率设的是115200;现在测试时发现串口正常接收发送一段时间后,停止发送,等过一段时间后,又开始接收发送.总是间断性工作,一直查不出是怎么回事,在线仿真,就运行不了.代码如下,请大神帮忙看一下有没有问题,应该如何解决?


#include "P33ep512mc806.h"


// DSPIC33EP512MC806 Configuration Bit Settings

// 'C' source line config statements

/*******系统初始化**********************
将时钟配置为外部高速石英振荡器,其余均采用默认模式。
*************************************/
#define DELAY_76uS asm volatile ("REPEAT, #4201"); Nop();
#define DELAY_8uS asm volatile ("REPEAT, #467"); Nop();

// FGS
#pragma config GWRP = OFF               // General Segment Write-Protect bit (General Segment may be written)
#pragma config GSS = OFF                // General Segment Code-Protect bit (General Segment Code protect is disabled)
#pragma config GSSK = OFF               // General Segment Key bits (General Segment Write Protection and Code Protection is Disabled)

// FOSCSEL
#pragma config FNOSC = PRIPLL           // Initial Oscillator Source Selection bits (Primary Oscillator (XT, HS, EC) with PLL)
#pragma config IESO = OFF               // Two-speed Oscillator Start-up Enable bit (Start up with user-selected oscillator source)

// FOSC
#pragma config POSCMD = HS              // Primary Oscillator Mode Select bits (HS Crystal Oscillator Mode)
#pragma config OSCIOFNC = OFF           // OSC2 Pin Function bit (OSC2 is clock output)
#pragma config IOL1WAY = ON             // Peripheral pin select configuration (Allow only one reconfiguration)
#pragma config FCKSM = CSDCMD           // Clock Switching Mode bits (Both Clock switching and Fail-safe Clock Monitor are disabled)

// FWDT
#pragma config WDTPOST = PS32768        // Watchdog Timer Postscaler bits (1:32,768)
#pragma config WDTPRE = PR128           // Watchdog Timer Prescaler bit (1:128)
#pragma config PLLKEN = ON              // PLL Lock Wait Enable bit (Clock switch to PLL source will wait until the PLL lock signal is valid.)
#pragma config WINDIS = OFF             // Watchdog Timer Window Enable bit (Watchdog Timer in Non-Window mode)
#pragma config FWDTEN = ON              // Watchdog Timer Enable bit (Watchdog timer always enabled)

// FPOR
#pragma config FPWRT = PWR128           // Power-on Reset Timer Value Select bits (128ms)
#pragma config BOREN = ON               // Brown-out Reset (BOR) Detection Enable bit (BOR is enabled)
#pragma config ALTI2C1 = OFF            // Alternate I2C pins for I2C1 (SDA1/SCK1 pins are selected as the I/O pins for I2C1)

// FICD
#pragma config ICS = PGD1               // ICD Communication Channel Select bits (Communicate on PGEC1 and PGED1)
#pragma config RSTPRI = PF              // Reset Target Vector Select bit (Device will obtain reset instruction from Primary flash)
#pragma config JTAGEN = OFF             // JTAG Enable bit (JTAG is disabled)

// FAS
#pragma config AWRP = OFF               // Auxiliary Segment Write-protect bit (Aux Flash may be written)
#pragma config APL = OFF                // Auxiliary Segment Code-protect bit (Aux Flash Code protect is disabled)
#pragma config APLK = OFF               // Auxiliary Segment Key bits (Aux Flash Write Protection and Code Protection is Disabled)


unsigned char flag=0,head=0,head1=0xa5;


//配置PLL,将系统时钟配置为60MHz,外部输入时钟为12MHz。
void System_Colck(void)
{
    CLKDIVbits.PLLPRE = 0;              //N1 = 2  24/2=12MHz
    PLLFBDbits.PLLDIV = 8;              //M = 10  12*10=120MHz
    CLKDIVbits.PLLPOST = 0;             //N2 = 2 120/2 = 60MHz
    while (OSCCONbits.COSC!= 0b011)
    while (OSCCONbits.LOCK!= 1) {};     //PLL 配置完成
}

/****************UART1_TX初始化***************/
void UART1_TX_Init(void)
{
    RPOR2bits.RP68R = 0b000001;               //将GPIORP68配置为UART1_TX
    U1MODEbits.STSEL = 0;                     //1个停止位
    U1MODEbits.PDSEL = 0;                     //8位数据,无奇偶校验位
    U1MODEbits.ABAUD = 0;                     //禁止自动调整波特率
    U1MODEbits.BRGH = 0;                      //UART标准模式,每个周期内产生16个时钟信号
    U1BRG = ((30000000/115200)/16)-1;         //设置波特率为115200
    U1STAbits.UTXISEL0 = 0;
    U1STAbits.URXISEL1 = 0;                   //发送中断模式选择,当一个字符被传输到发送移位寄存器时产生中断
    IEC0bits.U1TXIE = 1;                      //使能发送中断
    U1MODEbits.UARTEN = 1;                    //使能UART
    U1STAbits.UTXEN = 1;                      //发送使能
}

/****************UART1_RX初始化***************/
void UART1_RX_Init(void)
{
    RPINR18bits.U1RXR = 0b1000101;              //将GPIORP65配置为UART1_RX
    TRISDbits.TRISD3 = 1;                       //寄存器映射
    U1MODEbits.STSEL = 0;                       //1个停止位
    U1MODEbits.PDSEL = 0;                       // 8位数据,无奇偶校验位
    U1MODEbits.ABAUD = 0;                       //禁止自动调整波特率
    U1MODEbits.BRGH = 0;                        //UART标准模式,每个周期内产生16个时钟信号
    U1BRG = ((30000000/115200)/16)-1;           //设置波特率为115200
    IEC0bits.U1RXIE = 1;                        //使能接收中断
    IPC2bits.U1RXIP=1;
    U1STAbits.URXISEL = 0b00;                   //接收中断模式选择,接收到任意一个字符产生中断
    U1MODEbits.UARTEN = 1;                      //使能UART   
}

/****************UART3_TX初始化***************/
void UART3_TX_Init(void)
{
    RPOR7bits.RP97R = 0b011011;              //将GPIORP97配置为UART2_TX
    U3MODEbits.STSEL = 0;                    //1个停止位
    U3MODEbits.PDSEL = 0;                    //8位数据,无奇偶校验位
    U3MODEbits.ABAUD = 0;                    //禁止自动调整波特率
    U3MODEbits.BRGH = 0;                     //UART标准模式,每个周期内产生16个时钟信号
    U3BRG = ((30000000/115200)/16)-1;        //设置波特率为115200
    U3STAbits.UTXISEL0 = 0;
    U3STAbits.URXISEL1 = 0;                  //发送中断模式选择,当一个字符被传输到发送移位寄存器时产生中断
    IEC5bits.U3TXIE = 1;                     //使能发送中断
    U3MODEbits.UARTEN = 1;                   //使能UART
    U3STAbits.UTXEN = 1;                     //发送使能
}

/****************UART3_RX初始化***************/
void UART3_RX_Init(void)
{
    RPINR27bits.U3RXR = 0b1100000;         //将GPIORP96配置为UAR3_RX
    TRISFbits.TRISF0 = 1;                  //寄存器映射
    U3MODEbits.STSEL = 0;                  //1个停止位
    U3MODEbits.PDSEL = 0;                  // 8位数据,无奇偶校验位
    U3MODEbits.ABAUD = 0;                  // 禁止自动调整波特率
    U3MODEbits.BRGH = 0;                   //UART标准模式,每个周期内产生16个时钟信号
    U3BRG = ((30000000/115200)/16)-1;      //设置波特率为115200
    U3STAbits.URXISEL = 0b00;              //接收中断模式选择,接收到任意一个字符产生中断
    IEC5bits.U3RXIE = 1;                   //使能接收中断
    U3MODEbits.UARTEN = 1;                 //使能UART
}

int main()
{
    System_Colck();                             //时钟初始化
    System_Init();                              //系统初始化
    UART1_RX_Init();                            //UART1_RX初始化
    UART1_TX_Init();                            //UART1_TX初始化
    UART3_RX_Init();                            //UART3_RX初始化
    UART3_TX_Init();                            //ART3_TX初始化
    IFS0bits.U1RXIF = 0;
    while(1)
    {
       //UART1_TX_Init();
       //DELAY_76uS;
       //U1TXREG = head1;
    }

}

void __attribute__((__interrupt__, auto_psv)) _U1TXInterrupt(void)//UART1发送中断
{
    IFS0bits.U1TXIF = 0;
}

void __attribute__((__interrupt__, auto_psv)) _U1RXInterrupt(void)//UART1接收中断
{

   
        //UART1_RX_Init();
    if(U1STAbits.OERR == 1)
    {
        U1STAbits.OERR = 0;
    }


    while(U1STAbits.URXDA ==1)
    {
        head=U1RXREG;
                U3TXREG = head;
    }
        IFS0bits.U1RXIF = 0;
}

void __attribute__((__interrupt__, auto_psv)) _U3TXInterrupt(void)////UART3发送中断
{
    IFS5bits.U3TXIF = 0;
}
void __attribute__((__interrupt__, auto_psv)) _U3RXInterrupt(void)//UART3接收中断
{
   
    IFS5bits.U3RXIF = 0;
}






沙发
STM32F103ZE| | 2017-7-1 21:49 | 只看该作者
程序跑死了,看门狗拉复位了吧。
2个串口开四个中断,不好弄,别开那么多中断,用定时跑轮询安全,就开一个定时器中断多好。

使用特权

评论回复
板凳
kingkits| | 2017-7-3 11:47 | 只看该作者
1  你发送时应该有缓冲区,在发送中断出现时,读取缓冲区并发送一个字节到硬件端口
2  如果你的发送中断不用,就不要打开。
3
   if(U1STAbits.OERR == 1)
    {
        U1STAbits.OERR = 0;
    }
   这里应该清除接收缓冲区并直接返回

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

11

帖子

0

粉丝