微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

UART 只传输字符串的第一个和最后一个字符PIC16F877A 通过 proteus 模拟

如何解决UART 只传输字符串的第一个和最后一个字符PIC16F877A 通过 proteus 模拟

我是 PIC 微控制器的初学者,正在尝试通过教程学习并同时实施一个我需要为 PIC 微控制器编程的项目。我已经在各种教程中尝试了 3 种不同的 UART 传输程序,但我仍然遇到同样的问题。

当我尝试传输一个字符串时,说“abcd”,我只会得到adadadad .... 重复。可能是什么问题?我检查了波特率,它是正确的。我试过引入延迟,但它没有帮助。将不胜感激任何建议。 UART 传输功能是频率计数器程序的一部分,它在收到中断时计算频率并将其显示在 LCD 上。 LCD 上显示的值也将通过 UART 传输,但首先我试图使其适用于随机字符串“abcd”。我正在使用 proteus 进行模拟。目前使用以下函数传输数据串:

void UART_send_char(char bt)
{
    while(!TXIF);  // hold the program till TX buffer is free
    TXREG = bt; //Load the transmitter buffer with the received value
}
void UART_send_string(char* st_pt)
        {
        while(*st_pt) //if there is a char
        UART_send_char(*st_pt++); //process it as a byte data
        }

以下是我的主要功能

void main() {
char op[12];                 // display string for ascii converted long.
char opdb[12];               // double buffer to stop flicker.
unsigned long  freq = 0;     // display frequency value to use.
unsigned short blinkc=0;     // blink counter
int i,n,num;
unsigned char letter;
unsigned char test[]="abcd";

   init_ports();
   init_interrupts();

   Lcd_Init ();
   Lcd_Cmd ( _LCD_CLEAR );
   Lcd_Cmd ( _LCD_CURSOR_OFF );

   start_timer_count();

   for(;;) {

      if (update_LCD) {

         INTCON.GIE = 0;         // disable All interrupts.
         INTCON.PEIE = 0;        // disable All Extended interrupts.

         freq = (st_TMR1L+(st_TMR1H<<8)+(st_TMR1_ovfl<<16));//*1000;
         ltoa(freq,op,10);

         n=ltoa(freq,opdb,10);        // Build string in non display buffer
         memcpy(op,n);             // copy digits
         memset(&op[n],' ',12-n);       // Blank the rest.

         LCD_Out(1,1,"FREQ:");
         LCD_Out(1,7,op);
     
        
         UART_send_string("abcd"); //<-----------TRANSMISSION FUNCTION CALLED HERE
         
         update_LCD=0;
         
         TMR1_counter=0;
         TMR0_counter=0;

         start_timer_count();
      }

      if (toggle_LED) {  // Also check for signal presence at TMR1.
         blinkc=~blinkc;
         if (blinkc==0) { setBit(PORTD,0); } else { resBit(PORTD,0); }
         toggle_LED=0;

           if (freq==0) {
              for ( i=0;i<12;i++) { op[i]=' ';}
              LCD_Out(1,op);
          }
      }
   }
}

解决方法

这是一个使用 MPLABX 和 XC8 构建的完整应用程序,用于展示 PIC16F877A 异步 UART 与 Microchip 仿真工具的配合:

/*
 * File:     main.c
 * Author:   dan1138
 * Target:   PIC16F877A
 * Compiler: XC8 v2.32
 * IDE:      MPLABX v5.50
 *
 * Created on July 21,2021,1:29 PM
 *
 *                         PIC16F877A
 *                 +----------:_:----------+
 *       VPP ->  1 : MCLR/VPP      PGD/RB7 : 40 <> PGD
 *           <>  2 : RA0/AN0       PGC/RB6 : 39 <> PGC
 *           <>  3 : RA1/AN1           RB5 : 38 <>
 *           <>  4 : RA2/AN2           RB4 : 37 <>
 *           <>  5 : RA3/AN3           RB3 : 36 <> 
 *           <>  6 : RA4               RB2 : 35 <> 
 *           <>  7 : RA5/AN4           RB1 : 34 <> 
 *           <>  8 : RE0/AN5           RB0 : 33 <> 
 *           <>  9 : RE1/AN6           VDD : 32 <- 5v0
 *           <> 10 : RE2/AN7           VSS : 31 <- GND
 *       5v0 -> 11 : VDD               RD7 : 30 -> 
 *       GND -> 12 : VSS               RD6 : 29 -> 
 * 20.000MHz -> 13 : OSC1              RD5 : 28 -> 
 * 20.000MHz <- 14 : OSC2              RD4 : 27 -> 
 *           <> 15 : RC0/SOSCO   RX/DT/RC7 : 26 <> 
 *           <> 16 : RC1/SOSCI   TX/CK/RC6 : 25 <> 
 *           <> 17 : RC2/CCP1          RC5 : 24 <>
 *           <> 18 : RC3/SCL       SDA/RC4 : 23 <> 
 *           <> 19 : RD0               RD3 : 22 <> 
 *           <> 20 : RD1               RD2 : 21 <> 
 *                 +-----------------------:
 *                          DIP-40
 * 
 * Description:
 * 
 *  Unit test for the UART transmit output implementation.
 *  
 *  Test runs using the MPLABX v5.50 simulator.
 * 
 *  Read the Microchip documentation about how to setup the simulator to show UART output.
 *
 */

#pragma config FOSC = HS        /* Oscillator Selection bits (HS oscillator) */
#pragma config WDTE = OFF       /* Watchdog Timer Enable bit (WDT disabled) */
#pragma config PWRTE = OFF      /* Power-up Timer Enable bit (PWRT disabled) */
#pragma config BOREN = OFF      /* Brown-out Reset Enable bit (BOR disabled) */
#pragma config LVP = OFF        /* Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O,HV on MCLR must be used for programming) */
#pragma config CPD = OFF        /* Data EEPROM Memory Code Protection bit (Data EEPROM code protection off) */
#pragma config WRT = OFF        /* Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control) */
#pragma config CP = OFF         /* Flash Program Memory Code Protection bit (Code protection off) */
/*
 * Include defines for target specific Special Function Registers
 */
#include <xc.h>
/*
 * Tell XC8 compiler what frequency this code sets for system oscillator
 */
#define _XTAL_FREQ 20000000UL
/*
 * function to convert unsigned long to ASCII string
 */
void ultoa(void * str,unsigned long data,unsigned char radix)
{
    char buffer[32];
    char * outstr = 0;
    unsigned char index;
    unsigned char temp;
    
    outstr = (char *)str;
    if(outstr)
    {
        if((radix > 1) && (radix <= 16))
        {
            index = 0;
            do 
            {
                temp = data % radix;
                data = data / radix;
                temp = temp + '0';
                if (temp > '9') temp = temp + ('A'-'9')-1;
                buffer[index++] = temp;
            } while (data);
            do
            {
                *outstr++ = buffer[--index];                
            } while(index);
            *outstr = 0;
        }
    }
}
/*
 * Initialize UART
 */
void UART_Init(void)
{
    /* Disable UART interrupts */
    PIE1bits.TXIE = 0;
    PIE1bits.RCIE = 0;

    /* Turn off USART module */
    RCSTA = 0; 
    TXSTA = 0;
    SPBRG = (_XTAL_FREQ/(16UL *  9600UL) - 1);
    TXSTAbits.BRGH = 1;
    RCSTAbits.CREN = 1; /* Enable continuous receive  */
    TXSTAbits.TXEN = 1; /* Enables Transmission */
    RCSTAbits.SPEN = 1; /* Enables Serial Port */
    /*
     * Flush UART receive buffer
     */
    RCREG;
    RCREG;
    RCREG;
}
/*
 * Send a character to serial interface
 */
void UART_Write(unsigned char data) {
  while(!TRMT); /* Wait for buffer to be empty */
  TXREG = data;
}
/*
 * Send a string of characters to serial interface
 */
void UART_WriteString(char *pBuffer) {
    if (pBuffer)
    {
        while(*pBuffer)
        {
            UART_Write(*pBuffer++);
        }
    }
}
/*
 * Test if character is available from serial interface
 */
unsigned char UART_Data_Ready( void )
{
  return (RCIF!=0?1:0);
}
/*
 * Read a character from serial interface
 * Returns a zero if successful.
 * Returns non-zero on framing error or overrun error.
 */
unsigned char UART_Read(void *data)
{ 
    unsigned char Result;
    char * buffer = (char *)data;
    
    Result = 0;
    
    if (PIR1bits.RCIF) 
    {
        unsigned char rxerr = 0;
        
        if (RCSTAbits.OERR) {
            rxerr = 1;
            RCSTAbits.CREN = 0; /* reset receiver */
            RCSTAbits.CREN = 1;
            RCREG;
            RCREG;
            RCREG;
        }
        
        if (RCSTAbits.FERR) {
            rxerr = 1;
            RCREG; /* Discard character with framing error */
        } 
        
        if (!rxerr) { /* No error detected during reception */
            if(buffer) *buffer = RCREG;
            Result = 1;
        }
    }
    return Result;
}
/*
 * Initialize this PIC
 */
void PIC_Init( void )
{
    /* Disable all interrupt sources */
    INTCON = 0;
    PIE1   = 0;
    PIE2   = 0;

    /*
     * Pull-ups off,INT edge low to high,WDT prescale 1:1
     * TMR0 clock edge low to high,TMR0 clock = _XTAL_FREQ/4,TMR0 prescale 1:16
     * TIMER0 will assert the overflow flag every 256*16 (4096)
     * instruction cycles,with a 20MHz oscillator this is 0.8192 milliseconds.
     */
    OPTION_REG = 0b11000011;
    
    /* Make all GPIO pins digital */
    CMCON  = 0x07;
    ADCON1 = 0x06;
}
/*
 * Main application
 */
void main(void) 
{
    char output[40];
    unsigned long Count;
    
    /*
     * Initialize application
     */
    PIC_Init();
    UART_Init();
    UART_WriteString("PIC16F877A UART test build on " __DATE__ " at " __TIME__ "\r\n");
    Count = 0;
    /*
     * Application process loop
     */
    for(;;)
    {
        ultoa(output,Count,10);
        UART_WriteString("Count: ");
        UART_WriteString(output);
        UART_WriteString("\r\n");
        Count++;
    }
    /* 
     * Keep XC8 from whining about functions not being called
     */
    UART_Data_Ready();
    UART_Read(0);
}

我希望这也适用于您的 Proteus 环境。

将此代码移植到您的项目中。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。