如何解决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 举报,一经查实,本站将立刻删除。