1

我目前是第一次使用 PIC 微控制器。在代码中,我准确指定了我正在使用的 PIC、编译器等。也许这有帮助。

我正在尝试在 PIC32 上设置 UART 通信,并通过 RS232 将 0x41 之类的十六进制代码发送到我计算机上的终端。要将信号从 PIC UART 转换为 RS232 电平,我使用的是 MAX232EPE。

目前我遇到的问题是,当我将 0x41 例如从 PIC32 发送到终端或反之亦然时,接收到的数据不匹配。我认为这是由我的波特率设置错误引起的,但我不确定。有人可以查看我的代码,看看是否有人能看到问题吗?我忘了定义什么吗?我定义错了吗?我是不是计算错了波特率?

PS 我知道接收到的数据与发送的数据不匹配,因为我在 mplab 的调试模式下检查了“watches”,当我将从终端发送到 PIC32 的数据回显到终端时,它也不匹配.

延迟和中断代码可以忽略,它们按预期工作,所以我真的相信问题与 PIC/buad 速率的初始设置有关。

我希望这足够清楚,非常感谢任何帮助

谢谢,

请参阅下面的代码

/*
The configuration below and in void UART1_Init should set up the UART correctly.
I want to achieve a buadrate of 9600. My external Crystal is 8MHz. So:
FPLLIDIV=2, FPLLMUL=20, FPLLODIV=1, FPBDIV=2, FNOSC=PRIPLL, BRGH = 0, and U1BRG = 259.
This should give me the desired baudrate of 9600.
- ((8MHz / 2) * 20)/2) = 40MHz PBclk.
- U1BRG = (PBclk/(16*Buad rate))-1 so 259
- 16*Buad rate because BRGH = 0

PIC32MX795F512H
MPLAB X IDE V3.26
XC32 Compiler
PICKit3
*/

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

// Give useful names to pins
#define LED1_TRIS   TRISDbits.TRISD6
#define LED1        LATDbits.LATD6
#define UART1TX_TRIS    TRISDbits.TRISD3
#define UART1RX_TRIS    TRISDbits.TRISD2

#define FOSC 8000000                // Crystal frequency = 8 MHz
#define SYS_FREQ (80000000UL)       // SYSCLK is 80 MHz
#define GetSystemClock()       (FOSC) // For delay

#pragma config FPLLIDIV=DIV_2       // PLL Input Divider Value (Divide by 2)
#pragma config FPLLMUL=MUL_20       // Phase-Locked Loop (PPL) muiltiplier, multiplier of 20
#pragma config FPLLODIV=DIV_1       // Postscaler for PLL, output divided by 1
#pragma config FPBDIV=DIV_2         // 2 = PBCLK is SYSCLK divided by 2 (80MHz/2 = 40MHz)
#pragma config FWDTEN=OFF           // Watch Dog Timer (WDT) is not enabled. It can be enabled by software
#pragma config CP=OFF               // Code-Protect, 1 = OFF/Disabled
#pragma config BWP=OFF              // Boot Flash Write-protect, 1 = OFF/Disabled
#pragma config POSCMOD=XT           // Primary oscillator configuration, HS = HS Oscillator mode selection
#pragma config FNOSC=PRIPLL         // Oscillator selection, PRIPLL = Primary Oscillator with PLL module
#pragma config OSCIOFNC=OFF         // CLKO output disabled
#pragma config FSOSCEN=OFF          // Disable secondary Oscillator

int UART_RX_Count;                  // Counter variable for the UART1 receiver interrupt
int UART_TX_Count;                  // Counter varible for the UART1 transmitted interrupt  
unsigned char RD_SER_NUM;           // Variable to store command to read serial number
unsigned char UART_RX_OUTPUT;       // Variable to store the UART output
unsigned char i;

void UART1_Init(void){
// UART1 initialization
    U1MODEbits.ON = 1;          // UART1 is enabled
    U1MODEbits.SIDL = 0;        // Continue operation in idle mode
    U1MODEbits.IREN = 0;        // Disable IrDA (IrDA Encoder and Decoder Enable bit)
    U1MODEbits.RTSMD = 1;       // !U1RTS! pin is in Simplex mode, 0 = !U1RTS! pin is in Flow Control mode
    U1MODEbits.UEN = 0;         // UxTX and UxRX pins are enabled and used; UxCTS and UxRTS/UxBCLK pins are controlled by corresponding bits in the PORTx register
    U1MODEbits.WAKE = 1;        // Enable Wake-up on Start bit Detect During Sleep Mode bit
    U1MODEbits.LPBACK = 0;      // UARTx Loopback Mode Select bit, 0 = disabled, loopback = UxTX output is internally connected to the UxRX input
    U1MODEbits.PDSEL = 2;       // Parity and Data Selection bits, 10 = 8-bit data, odd parity
    U1MODEbits.STSEL = 0;       // Stop Selection bit, 0 = 1 stop bit
    U1MODEbits.BRGH = 0;        // High Baud Rate Enable bit, 0 = Standard Speed mode 16x baud clock enabled
    U1MODEbits.RXINV = 1;       // Receive Polarity Inversion bit, 1 = UxRX Idle state is 0

    U1STAbits.URXEN = 1;        // 1 = UART1 receiver is enabled. U1RX pin is controlled by UARTx (if ON = 1)
    U1STAbits.UTXEN = 1;        // 1 = UART1 transmitter is enabled. U1TX pin is controlled by UARTx (if ON = 1)
    U1STAbits.UTXINV = 1;       // Transmit Polarity Inversion bit, 1 = UxTX Idle state is 0
    U1STAbits.ADM_EN = 0;       // 0 = Automatic Address Detect mode is disabled
    U1BRG = 259;                // Baud Rate Divisor bits (0-15 bits), set baud rate, 9600 @ 40 MHz PBclk

    __builtin_disable_interrupts();     // Tell CPU to stop paying attention to interrupts
    INTCONbits.MVEC = 1;                // Multi Vector interrupts
    U1STAbits.URXISEL = 0;              // 0x = Interrupt flag bit is set when a character is received
    U1STAbits.UTXISEL = 1;              // 01 = Interrupt flag bit is set when all characters have been transmitted
    IPC6bits.U1IP = 5;                  // Set UART1 priority 5 of 7
    IPC6bits.U1IS = 0;                  // Set UART1 sub priority to 0
    IFS0bits.U1RXIF = 0;                // Clear UART1 RX interrupt flag
    IFS0bits.U1TXIF = 0;                // Clear UART1 TX interrupt flag
    IEC0bits.U1RXIE = 1;                // Enable UART1 RX ISR
    __builtin_enable_interrupts();      // Tell CPU to start paying attention to interrupts again

    UART_RX_Count = 0;                  // Set initial UART1 received interrupts count to 0
    UART_TX_Count = 0;                  // Set initial UART1 transmit interrupts count to 0
}

void __ISR(_UART_1_VECTOR, IPL5SRS) UART1_INT(void){
    if(INTGetFlag(INT_U1RX)){           // Check if UART1 RX interrupt was triggered
        LED1 = ~LED1;                   // Toggle LED1
        UART_RX_Count++;                // Add 1 to UART1 RX interrupt occurrence counter
//        UART_RX_OUTPUT = U1RXREG;       // Read UART1 RX buffer/register
        U1TXREG = U1RXREG;      // Transmit the received data back
//        U1STAbits.OERR = 0;             // Clear UART1 buffer overflow
        IFS0bits.U1RXIF = 0;            // Clear UART1 RX interrupt flag
    }else{
        if(INTGetFlag(INT_U1TX)){       // Check if UART1 TX interrupt was triggered
            UART_TX_Count++;            // Add 1 to UART1 TX interrupt occurrence counter
            IEC0bits.U1TXIE = 0;        // Disable UART1 TX ISR
            IFS0bits.U1TXIF = 0;        // Clear UART1 TX interrupt flag
        }
}
}

  // DelayMs creates a delay of given milliseconds using the Core Timer
  void DelayMs(WORD delay){
     unsigned int int_status;
     while( delay-- ){
         int_status = INTDisableInterrupts();
         OpenCoreTimer(GetSystemClock() / 200);
         INTRestoreInterrupts(int_status);
         mCTClearIntFlag();
         while( !mCTGetIntFlag() );
     }
     mCTClearIntFlag();
 }

int main(){
    UART1_Init();               // Call the initializations function of UART1
    LED1_TRIS = 0;              // Set the LED1 as an output
    UART1TX_TRIS = 0;           // Set UART1 TX pin as output
    UART1RX_TRIS = 1;           // Set UART1 RX pin as input
    LED1 = 0;                   // Turn off LED1

    while(1){
//        DelayMs(1000);
//        IEC0bits.U1TXIE = 1;            // Enable UART1 TX ISR
//       U1TXREG = 0x41;           // Send command to U1TXREG
    }
return 0;
}
4

2 回答 2

1

由于您使用的是 PIC32MX795F512H,您可以使用 MPLAB Harmony 框架工具来创建您的项目。这样您就不必在位级别上玩游戏并陷入小错误或很可能是拼写错误。它可以方便地正确生成驱动程序和所有框架。

感谢和问候拉维

于 2016-09-28T06:39:10.510 回答
0

使用 Harmony 实际上可以帮助您避免遇到的简单错误。特别是对于时钟,您甚至可以使用自动计算功能显着减少您的实施时间。

于 2018-06-20T15:23:40.703 回答