Embedded 在PIC18上写UART

Embedded 在PIC18上写UART,embedded,microcontroller,uart,pic18,Embedded,Microcontroller,Uart,Pic18,我需要uart通信方面的帮助,我正试图在我的Proteus模拟上实现uart通信。我使用PIC18f4520,我想在虚拟终端上显示微控制器计算的值 现在,我的UART代码是这样的: #define _XTAL_FREQ 20000000 #define _BAUDRATE 9600 void Configuration_ISR(void) { IPR1bits.TMR1IP = 1; // TMR1 Overflow Interrupt Priority - Hi

我需要uart通信方面的帮助,我正试图在我的Proteus模拟上实现uart通信。我使用PIC18f4520,我想在虚拟终端上显示微控制器计算的值

现在,我的UART代码是这样的:

#define _XTAL_FREQ  20000000
#define _BAUDRATE   9600

void Configuration_ISR(void) {
    IPR1bits.TMR1IP = 1;        // TMR1 Overflow Interrupt Priority - High
    PIE1bits.TMR1IE = 1;        // TMR1 Overflow Interrupt Enable
    PIR1bits.TMR1IF = 0;        // TMR1 Overflow Interrupt Flag
                            //   0 = TMR1 register did not overflow
                            //   1 = TMR1 register overflowed (must be cleared in software)
    RCONbits.IPEN   = 1;        // Interrupt Priority High level
    INTCONbits.PEIE = 1;        // Enables all low-priority peripheral interrupts
    //INTCONbits.GIE  = 1;          // Enables all high-priority interrupts
}

void Configuration_UART(void) {
    TRISCbits.TRISC6 = 0;
    TRISCbits.TRISC7 = 1;

    SPBRG = ((_XTAL_FREQ/16)/_BAUDRATE)-1;

    //RCSTA REG
    RCSTAbits.SPEN = 1;     // enable serial port pins    
    RCSTAbits.RX9 = 0;

    //TXSTA REG
    TXSTAbits.BRGH = 1;     // fast baudrate
    TXSTAbits.SYNC = 0;     // asynchronous
    TXSTAbits.TX9 = 0;      // 8-bit transmission
    TXSTAbits.TXEN = 1;     // enble transmitter
}

void WriteByte_UART(unsigned char ch) {
    while(!PIR1bits.TXIF);  // Wait for TXIF flag Set which indicates
                            // TXREG register is empty
    TXREG = ch;             // Transmitt data to UART
}

void WriteString_UART(char *data) { 
       while(*data){ 
          WriteByte_UART(*data++); 
       }
}

unsigned char ReceiveByte_UART(void) {
    if(RCSTAbits.OERR) {
        RCSTAbits.CREN = 0;
        RCSTAbits.CREN = 1;
    }
    while(!PIR1bits.RCIF); //Wait for a byte
    return RCREG;
}
在主循环中:

while(1) {
    WriteByte_UART('a'); // This works. I can see the As in the terminal
    WriteString_UART("Hello World !"); //Nothing displayed :(
}//end while(1)
我尝试了不同的解决方案,但到目前为止还没有一个有效

我不想使用printf,因为它会增加延迟,从而影响我对PIC的其他操作。 所以我真的想让它与WriteString\u UART一起工作。 最后,我希望在终端上有类似“错误率为:[a值]%”的内容

谢谢你的帮助,如果有什么不清楚的请告诉我

  • 在测线后增加几毫秒的延迟 TXREG=ch

  • 验证WriteString\u UART(char*data)的指针*数据是否实际指向
    字符串“你好,世界!”


  • WriteByte\u UART()函数中,尝试轮询TRMT位。特别是,变化:

    while(!PIR1bits.TXIF);
    

    我不知道这是否是您的特殊问题,但由于加载TXREG后TXIF未立即清除,因此存在一个竞赛条件。另一种选择是尝试:

    ...
    Nop();
    while(!PIR1bits.TXIF);
    ...
    
    根据评论进行编辑


    这个问题是由于PIC18基于数据内存和程序内存使用了两种不同的指针类型。尝试将您的声明更改为
    void WriteString\u UART(const-rom char*data)
    ,看看会发生什么。您还需要将
    WriteByte\u UART()
    声明更改为
    void WriteByte\u UART(const unsigned char ch)

    看起来您找到了一个解决方案,但它最初不起作用的原因仍然不清楚。你在用什么编译器

    我从中学到了C18和XC8在内存空间方面的不同用法。在这两种编译器中,一个按字面意思声明的字符串(如
    charstring[]=“Hello!”
    )将存储在ROM(程序内存)中。它们在函数使用字符串的方式上有所不同

    C18字符串函数将具有访问RAM或ROM中字符串的变体(例如
    strcpypgm2ram
    strcpyram2pgm
    等)。另一方面,XC8为您完成这项工作,您不需要使用特定的函数来选择要访问的内存

    如果您使用的是C18,我强烈建议您切换到XC8,因为XC8更新,更容易使用。如果您仍然想使用C18或其他需要处理程序/数据内存空间的编译器,那么下面是两个您可能想尝试的解决方案。C18数据表显示,
    putsuart
    将一个字符串从数据内存打印到USART。函数
    putrsUSART
    将从程序内存打印字符串。因此,您可以简单地使用
    putrsUSART
    打印字符串

    您可能还想尝试以下方法,将字符串从程序内存复制到数据内存(如果应用程序内存紧张,则可能会浪费内存):

    在本例中,指针
    pgmstring
    datstring
    将存储在数据存储器中。字符串
    “Hello”
    将存储在程序内存中。因此,即使指针
    pgmstring
    本身在数据内存中,它最初也会指向内存地址(“Hello”
    )的地址。在数据内存中指向同一字符串的唯一方法是在数据内存中创建该字符串的副本。这是因为接受存储在数据存储器中的字符串(如
    putsuart
    )的函数不能直接与存储在程序存储器中的字符串一起使用


    我希望这能帮助您更好地理解如何使用哈佛微处理器,在那里程序和数据存储器是分开的。

    PIR1bits在哪里声明?它在另一个函数中。我现在就编辑这篇文章。在我的程序中,我使用一个高ISR。在例程中,我对两个PIC交换的两个值进行比较(使用SPI)。我想做的是在终端上显示比较结果:)PIR1bits的类型是什么?向我显示声明,而不是定义。
    TXREG
    传输到
    UART
    后是否自动清空自身?我尝试了您提出的两个建议
    WriteByte\u UART()
    一如既往地完美工作。如果我尝试预定义的函数
    putsuart(“Hello World!”)
    我会在终端上看到文本。现在,如果我声明一个变量
    unsigned char MyString=“Hello World\r\n”然后我做
    WriteByte\u UART(MyString)
    它可以工作!为什么
    WriteByte\u UART(“Hello World”)
    不会,这是一个100万美元的问题。@tealif,您的问题可能是因为程序内存和数据内存的单独地址空间使用不同的指针类型。尝试将您的声明更改为
    void WriteString\u UART(const-rom char*data)
    ,看看会发生什么。您还需要将
    WriteByte\u UART()
    声明更改为
    void WriteByte\u UART(const unsigned char ch)
    @Tealyf,只是出于好奇,指针类型是否有问题?是的。我按照你8月4日评论中的建议进行了更改,这就是我如何使其生效的原因。谢谢,将进行更新以确保正确捕获答案。恐怕不会。无论地址
    *数据
    指向什么,其值都保持为0。。。例如:
    数据0x025E
    -->
    *数据0x025E'\0'
    (地址、值)谢谢@A.Saucet。由于我只处理使用C18的更大项目的一部分,所以无法更改编译器。我会试试你善意的建议。为了综合我的想法,我还想找到一种方法来使用变量
    putsUASRT
    (例如打印计数器的不同值)。因此我尝试了
    putsuart
    putsuart
    。结果如下:
    ...
    Nop();
    while(!PIR1bits.TXIF);
    ...
    
    char pgmstring[] = "Hello";
    char datstring[16];
    strcpypgm2ram(datstring, pgmstring);
    putsUSART(datstring);