繁体   English   中英

PIC24F开发板上不能通过UART收发数据

[英]Cannot send or receive data through UART on PIC24F development board

我正在尝试使用 MPLAB X 将一个简单的 UART 测试程序上传到 PIC24F Curiosity Board,并使用 TeraTerm 验证数据传输。 该评估板使用 PIC24FJ128GA204 微控制器。 我已经确保在 TeraTerm 上设置串行端口配置,因为它在程序中定义。

对于数据传输,我使用 USB 转 RS-232 UART 电缆连接到我的桌面。 我已经仔细检查了我的电缆连接,它们与程序中定义的一样。 我没有在电缆上使用 +5 Vcc 并且我已将电缆接地,但我已尝试连接和断开接地。

目前不会传输任何数据,尽管我注意到当我对电路板进行编程时,有时 TeraTerm 会显示一些随机值,我不确定这是否意味着存在能够传输数据的连接,或者只是随机噪声。

目前,我的UART初始化如下:

#include <xc.h>
#define U_ENABLE                 0x8008                   // enable UART, BREGH=1, 1 stop, 8 data bits, no parity, RTS/CTS flow control
#define U_TX                     0x0400                  // enable transmission, clear all flags

#define _XTAL_FREQ               8000000 //set to internal oscillator frequency

//** UART2 RS232 asynchronous communication demonstration
void initialize_UART(void) {

    U1BRG =  104;                                                  // initialize the baud rate generator to 104, an equivalent value of 9524
    U1MODE = U_ENABLE;                                             // initialize the UART module  
    U1STA = U_TX;                                                  // enable the receiver
    
    //****CONFIGURING FOR UART****
    //MICROCONTROLLER PIN || UART WIRE
    //RP0/RB0 = U1RX
    //RP1/RB1 = U1CTS (Clear to send)
    //RP2/RB2 = U1TX
    //RP3/RB3 = UR1RTS ()
    
    // Unlock Registers (per MCU data sheet)
    asm volatile ("MOV #OSCCON, w1 \n"
     "MOV #0x46, w2 \n"
     "MOV #0x57, w3 \n"
     "MOV.b w2, [w1] \n"
     "MOV.b w3, [w1] \n"
     "BCLR OSCCON, #6") ;
 
 // Configure Input Functions (Table 11-3 in Datasheet)
    // Assign U1RX To Pin RP0
    //RPINR
    RPINR18bits.U1RXR = 0;
    
    // Assign U1CTS To Pin RP1
    RPINR18bits.U1CTSR = 1;

// Configure Output Functions (Table 11-4 in Datasheet)
    // Assign U1TX To Pin RP2
    RPOR1bits.RP2R = 3;
    
    // Assign U1RTS To Pin RP3
    RPOR1bits.RP3R = 4;
    
    // Lock Registers
    asm volatile ("MOV #OSCCON, w1 \n"
    "MOV #0x46, w2 \n"
    "MOV #0x57, w3 \n"
    "MOV.b w2, [w1] \n"
    "MOV.b w3, [w1] \n"
    "BSET OSCCON, #6") ; 

}

我通过 UART 发送数据的功能:

char UART_send_char(char a) 
{
    while (PORTBbits.RB1 == 1); //wait for clear to send
    while (U1STAbits.UTXBF); //wait while Tx buffer is full
    U1TXREG = a;
    return a;
}

我如何测试 main() 中的函数:

int main(void) 
{
    TRISA = 0;
    
    // init the UART1 serial port
    initialize_UART();

     // main loop
     while (1)
    {
        PORTAbits.RA10 = 1; //for debugging purposes
        UART_send_char('>');
    }
}

这个程序应该不断地将字符“>”发送到 TeraTerm 控制台,但我什么也没收到。 RA10 连接到一个 LED,它确实亮了,所以我知道程序已经进入主循环,但没有发送数据。 我将配置位设置为以 8 MHz 运行并禁用了 PLL 的内部振荡器。 BREGH 设置为 1,因此我使用了第 247 页数据表中给出的波特率发生器的相应公式,其 Fcy 值为 8 MHz/2。

我是 MCU 编程的新手,花了几个小时试图解决这个问题但无济于事,因此非常感谢任何帮助。

这是一个完整的单文件应用程序,它使用 MikroElektronical USB UART click 在 DM240004 PIC24F Curiosity 开发板上运行。

/*
 * https://github.com/dsoze1138/24FJ128GA204_DM240004
 *
 * File:   main.c
 * Author: dan1138
 * Target: PIC24FJ128GA204
 * Compiler: XC16 v1.60
 * IDE: MPLABX v5.45
 *
 * Created on November 24, 2020, 12:02 PM
 *
 *                                                           PIC24FJ128GA204
 *               +----------------+               +--------------+                +-----------+                +--------------+
 * J4_MOSI <>  1 : RB9/RP9        :    LED2 <> 12 : RA10         :   J4_SDA <> 23 : RB2/RP2   : X2-32KHZ <> 34 : RA4/SOSCO    :
 *  RGB_G  <>  2 : RC6/RP22       :         <> 13 : RA7          :   J4_SCL <> 24 : RB3/RP3   :     LED1 <> 35 : RA9          :
 *  RGB_B  <>  3 : RC7/RP23       :         <> 14 : RB14/RP14    :      POT <> 25 : RC0/RP16  :    J4_CS <> 36 : RC3/RP19     :
 *     S2  <>  4 : RC8/RP24       :         <> 15 : RB15/RP15    :          <> 26 : RC1/RP17  :   J4_SCK <> 37 : RC4/RP20     :
 *     S1  <>  5 : RC9/RP25       :     GND -> 16 : AVSS         :          <> 27 : RC2/RP18  :    RGB_R <> 38 : RC5/RP21     :
 *    3v3  <>  6 : VBAT           :     3v3 -> 17 : AVDD         :      3v3 -> 28 : VDD       :      GND -> 39 : VSS          :
 *   10uF  ->  7 : VCAP           : ICD_VPP -> 18 : MCLR         :      GND -> 29 : VSS       :      3v3 -> 40 : VDD          :
 *         <>  8 : RB10/RP11/PGD2 :   J4_AN <> 19 : RA0/AN0      :          <> 30 : RA2/OSCI  :    J4_RX <> 41 : RB5/RP5/PGD3 :
 *         <>  9 : RB11/RP11/PGC2 :  J4_RST <> 20 : RA1/AN1      :          <> 31 : RA3/OSCO  :    J4_TX <> 42 : RB6/RP6/PGC3 :
 *         <> 10 : RB12/RP12      : ICD_PGD <> 21 : RB0/RP0/PGD1 :          <> 32 : RA8       :          <> 43 : RB7/RP7      :
 *         <> 11 : RB13/RP13      : ICD_PGC <> 22 : RB1/RP1/PGC1 : X2-32KHZ <> 33 : RB4/SOSCI :  J4_MISO <> 44 : RB8/RP8      :
 *               +----------------+               +--------------+                +-----------+                +--------------+
 *                                                              TQFP-44
 * 
 * Description:
 * 
 * Bare metal initialization of the DM240004 Curiosity Board
 * 
 * Setup the system oscillator for 32MHz using the internal FRC and the 4x PLL.
 * Turn on the 32.768KHz secondary oscillator.
 * Use UART1 and printf to send a message as 9600 baud.
 * Flash LED2 on for 500 milliseconds then off for 500 milliseconds.
 * 
 */
// CONFIG4
#pragma config DSWDTPS = DSWDTPS1F      // Deep Sleep Watchdog Timer Postscale Select bits (1:68719476736 (25.7 Days))
#pragma config DSWDTOSC = LPRC          // DSWDT Reference Clock Select (DSWDT uses LPRC as reference clock)
#pragma config DSBOREN = OFF            // Deep Sleep BOR Enable bit (DSBOR Disabled)
#pragma config DSWDTEN = OFF            // Deep Sleep Watchdog Timer Enable (DSWDT Disabled)
#pragma config DSSWEN = OFF             // DSEN Bit Enable (Deep Sleep operation is always disabled)
#pragma config PLLDIV = PLL4X           // USB 96 MHz PLL Prescaler Select bits (4x PLL selected)
#pragma config I2C1SEL = DISABLE        // Alternate I2C1 enable bit (I2C1 uses SCL1 and SDA1 pins)
#pragma config IOL1WAY = OFF            // PPS IOLOCK Set Only Once Enable bit (The IOLOCK bit can be set and cleared using the unlock sequence)

// CONFIG3
#pragma config WPFP = WPFP127           // Write Protection Flash Page Segment Boundary (Page 127 (0x1FC00))
#pragma config SOSCSEL = ON             // SOSC Selection bits (SOSC circuit selected)
#pragma config WDTWIN = PS25_0          // Window Mode Watchdog Timer Window Width Select (Watch Dog Timer Window Width is 25 percent)
#pragma config PLLSS = PLL_FRC          // PLL Secondary Selection Configuration bit (PLL is fed by the on-chip Fast RC (FRC) oscillator)
#pragma config BOREN = OFF              // Brown-out Reset Enable (Brown-out Reset Disabled)
#pragma config WPDIS = WPDIS            // Segment Write Protection Disable (Disabled)
#pragma config WPCFG = WPCFGDIS         // Write Protect Configuration Page Select (Disabled)
#pragma config WPEND = WPENDMEM         // Segment Write Protection End Page Select (Write Protect from WPFP to the last page of memory)

// CONFIG2
#pragma config POSCMD = NONE            // Primary Oscillator Select (Primary Oscillator Disabled)
#pragma config WDTCLK = LPRC            // WDT Clock Source Select bits (WDT uses LPRC)
#pragma config OSCIOFCN = ON            // OSCO Pin Configuration (OSCO/CLKO/RA3 functions as port I/O (RA3))
#pragma config FCKSM = CSECMD           // Clock Switching and Fail-Safe Clock Monitor Configuration bits (Clock switching is enabled, Fail-Safe Clock Monitor is disabled)
#pragma config FNOSC = FRC              // Initial Oscillator Select (Fast RC Oscillator (FRC))
#pragma config ALTCMPI = CxINC_RB       // Alternate Comparator Input bit (C1INC is on RB13, C2INC is on RB9 and C3INC is on RA0)
#pragma config WDTCMX = WDTCLK          // WDT Clock Source Select bits (WDT clock source is determined by the WDTCLK Configuration bits)
#pragma config IESO = OFF               // Internal External Switchover (Disabled)

// CONFIG1
#pragma config WDTPS = PS32768          // Watchdog Timer Postscaler Select (1:32,768)
#pragma config FWPSA = PR128            // WDT Prescaler Ratio Select (1:128)
#pragma config WINDIS = OFF             // Windowed WDT Disable (Standard Watchdog Timer)
#pragma config FWDTEN = OFF             // Watchdog Timer Enable (WDT disabled in hardware; SWDTEN bit disabled)
#pragma config ICS = PGx1               // Emulator Pin Placement Select bits (Emulator functions are shared with PGEC1/PGED1)
#pragma config LPCFG = OFF              // Low power regulator control (Disabled - regardless of RETEN)
#pragma config GWRP = OFF               // General Segment Write Protect (Write to program memory allowed)
#pragma config GCP = OFF                // General Segment Code Protect (Code protection is disabled)
#pragma config JTAGEN = OFF             // JTAG Port Enable (Disabled)
/*
 * Defines for system oscillator frequency.
 * Make sure that the PIC initialization selects this frequency.
 */
#define FSYS (32000000ul)
#define FCY  (FSYS/2ul)
/*
 * Target specific Special Function Register definitions
 */
#include <xc.h>
/*
 * Standard header files
 */
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
/*
 * Initialize this PIC
 */
void PIC_Init(void)
{
    uint16_t ClockSwitchTimeout;

    /* 
     * Disable all interrupt sources 
     */ 
    __builtin_disi(0x3FFF); /* disable interrupts for 16383 cycles */ 
    IEC0 = 0; 
    IEC1 = 0; 
    IEC2 = 0; 
    IEC3 = 0; 
    IEC4 = 0; 
    IEC5 = 0; 
    IEC6 = 0; 
    IEC7 = 0; 
    __builtin_disi(0x0000); /* enable interrupts */ 
    
    INTCON1bits.NSTDIS = 1; /* Disable interrupt nesting */
    
    /*
     * At Power On Reset the configuration words set the system clock
     * to use the FRC oscillator. At this point we need to enable the
     * PLL to get the system clock running at 32MHz.
     * 
     * Clock switching on the 24FJ family with the PLL can be a bit tricky.
     * 
     * First we need to check if the configuration words enabled clock
     * switching at all, then turn off the PLL, then setup the PLL and
     * finally enable it. Sounds simple, I know. Make sure you verify this 
     * clock setup on the real hardware.
     */

    if(!OSCCONbits.CLKLOCK) /* if primary oscillator switching is unlocked */
    {
        /* Select primary oscillator as FRC */
        __builtin_write_OSCCONH(0b000);

        /* Request switch primary to new selection */
        __builtin_write_OSCCONL(OSCCON | (1 << _OSCCON_OSWEN_POSITION));

        /* wait, with timeout, for clock switch to complete */
        for(ClockSwitchTimeout=10000; --ClockSwitchTimeout && OSCCONbits.OSWEN;);

        CLKDIV   = 0x0000; /* set for FRC clock 8MHZ operations */

        /* Select primary oscillator as FRCPLL */
        __builtin_write_OSCCONH(0b001);
        /* Request switch primary to new selection */
        __builtin_write_OSCCONL(OSCCON | (1 << _OSCCON_OSWEN_POSITION));
        
        /* ALERT: This may be required only when the 96MHz PLL is used */
        CLKDIVbits.PLLEN = 1;

        /* wait, with timeout, for clock switch to complete */
        for(ClockSwitchTimeout=10000; --ClockSwitchTimeout && OSCCONbits.OSWEN;);

        /* wait, with timeout, for the PLL to lock */
        for(ClockSwitchTimeout=10000; --ClockSwitchTimeout && !OSCCONbits.LOCK;);
        
        /* at this point the system oscillator should be 32MHz */
    }
    
    /* Turn on Secondary Oscillation Amplifier */
    __builtin_write_OSCCONL(OSCCON | (1 << _OSCCON_SOSCEN_POSITION));
    
    /* Turn off all analog inputs */
    ANSA = 0;
    ANSB = 0;
    ANSC = 0;
}
/*
 * WARNING: Not a portable function.
 *          Maximum delay 16384 instruction cycles.
 *          At 16 MIPS this is 1024 microseconds.
 *
 *          Minimum  1MHz instruction cycle clock.
 */
void delay_us(unsigned short delay)
{
    if (delay > (uint16_t)(16383.0 / (FCY/1E6)))
    {
        asm("   repeat  #16383\n"
            "   clrwdt        \n"
            ::);

    }
    else
    {
        asm("   repeat  %0    \n"
            "   clrwdt        \n"
        :: "r" (delay*(uint16_t)(FCY/1000000ul)-1));
    }
}
/*
 * WARNING: Not a portable function.
 *          Maximum 16MHz instruction cycle clock.
 *          Minimum  8Khz instruction cycle clock.
 */
void delay_ms(unsigned long delay)
{
    if(delay)
    {
        asm("1: repeat  %0    \n"
            "   clrwdt        \n"
            "   sub  %1,#1    \n"
            "   subb %d1,#0   \n"
            "   bra  nz,1b    \n"
        :: "r" (FCY/1000ul-6ul), "C" (delay));
    }
}
/*
 * Initialize the UART
 */
void UART_Init(void)
{
/**    
     Set the UART1 module to run at 9600 baud with RB6 as TX out and RB5 as RX in.
*/
    TRISBbits.TRISB6 = 0;
    LATBbits.LATB6 = 1;
    __builtin_write_OSCCONL(OSCCON & ~_OSCCON_IOLOCK_MASK); // unlock PPS

    RPINR18bits.U1RXR = 0x0005;    //RB5->UART1:U1RX
    RPOR3bits.RP6R    = 0x0003;    //RB6->UART1:U1TX

    __builtin_write_OSCCONL(OSCCON | _OSCCON_IOLOCK_MASK); // lock PPS
    
    // STSEL 1; IREN disabled; PDSEL 8N; UARTEN enabled; RTSMD disabled; USIDL disabled; WAKE disabled; ABAUD disabled; LPBACK disabled; BRGH enabled; URXINV disabled; UEN TX_RX; 
    // Data Bits = 8; Parity = None; Stop Bits = 1;
    U1MODE = (0x8008 & ~(1<<15));  // disabling UARTEN bit
    // UTXISEL0 TX_ONE_CHAR; UTXINV disabled; URXEN disabled; OERR NO_ERROR_cleared; URXISEL RX_ONE_CHAR; UTXBRK COMPLETED; UTXEN disabled; ADDEN disabled; 
    U1STA = 0x00;
    // BaudRate = 9600; Frequency = 16000000 Hz; U1BRG 416; 
    U1BRG = 0x1A0;
    // ADMADDR 0; ADMMASK 0; 
    U1ADMD = 0x00;
    // T0PD 1 ETU; PTRCL T0; TXRPT Retransmits the error byte once; CONV Direct; SCEN disabled; 
    U1SCCON = 0x00;
    // TXRPTIF disabled; TXRPTIE disabled; WTCIF disabled; WTCIE disabled; PARIE disabled; GTCIF disabled; GTCIE disabled; RXRPTIE disabled; RXRPTIF disabled; 
    U1SCINT = 0x00;
    // GTC 0; 
    U1GTC = 0x00;
    // WTCL 0; 
    U1WTCL = 0x00;
    // WTCH 0; 
    U1WTCH = 0x00;
    
    U1MODEbits.UARTEN = 1;   // enabling UART ON bit
    U1STAbits.UTXEN = 1;
}

uint8_t UART1_Read(void)
{
    while(!(U1STAbits.URXDA == 1));

    if ((U1STAbits.OERR == 1))
    {
        U1STAbits.OERR = 0;
    }
    
    return U1RXREG;
}

void UART1_Write(uint8_t txData)
{
    while(U1STAbits.UTXBF == 1);

    U1TXREG = txData;    // Write the data byte to the USART.
}

bool UART1_IsRxReady(void)
{
    return U1STAbits.URXDA;
}

bool UART1_IsTxReady(void)
{
    return ((!U1STAbits.UTXBF) && U1STAbits.UTXEN );
}

bool UART1_IsTxDone(void)
{
    return U1STAbits.TRMT;
}

int __attribute__((__section__(".libc.write"))) write(int handle, void *buffer, unsigned int len) 
{
    unsigned int i;

    for (i = len; i; --i)
    {
        UART1_Write(*(char*)buffer++);
    }
    return(len);
}
/*
 * Main Application
 */
int main(void) 
{
    /*
     * Application initialization
     */
    PIC_Init();
    UART_Init();
    
    /* Set RA10 for output to drive LED2 */
    LATAbits.LATA10 = 0;
    TRISAbits.TRISA10 = 0;

    printf("\r\nPIC24FJ128GA204 built on " __DATE__ " at " __TIME__ " Start\r\n");
    /*
     * Application process loop
     */
    for(;;)
    {
        LATAbits.LATA10 ^= 1;
        delay_ms(500);
    }
    return 0;
}

我怀疑您的问题可能是尝试使用 RTS/CTS 信号实现硬件握手。

首先尝试让串行数据从 PIC 传输到 PC 以低波特率工作。

另一件事是 RB0 和 RB1 用于编程(和调试)PIC24FJ128GA204。 板载在线串行编程器可能会干扰将这些引脚用于其他功能。 在调试会话中,应用程序根本无法使用它们。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM