我需要帮助uart通讯,我正试图实现我的Proteus模拟。我使用一个PIC18f4520,我想在虚拟终端上显示由微控制器计算出来的值。
这是我在Proteus上设计的一个快照
现在,我的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)我为WriteString_UART尝试过不同的解决方案,但到目前为止都没有奏效。
我不想使用printf,因为它通过添加延迟来影响我正在用PIC做的其他操作。所以我真的很想让它与WriteString_UART一起工作。最后,我希望在终端上有“错误率是:值%”之类的东西。
谢谢你的帮助,如果有什么不清楚的话请告诉我。
发布于 2016-08-03 18:47:38
在您的WriteByte_UART()函数中,尝试轮询TRMT位。特别是,改变:
while(!PIR1bits.TXIF);至
while(!TXSTA1bits.TRMT);我不知道这是否是您的特定问题,但是由于TXIF在加载TXREG时没有立即被清除,存在一个竞赛条件。另一种选择是尝试:
...
Nop();
while(!PIR1bits.TXIF);
...基于注释的编辑
这个问题是由于PIC18使用了基于数据内存和程序内存的两种不同的指针类型。尝试将声明更改为void WriteString_UART(const rom char * data),看看会发生什么。您还需要将WriteByte_UART()声明更改为void WriteByte_UART(const unsigned char ch)。
发布于 2016-08-03 16:09:48
发布于 2016-08-25 16:02:08
你似乎找到了一个解决方案,但它一开始不起作用的原因还不清楚。你在使用什么编译器?
我学到了C18和XC8在内存空间方面的不同用法。使用这两个编译器,一个声明为char string[]="Hello!"的字符串将存储在ROM (程序内存)中。它们在函数使用字符串的方式上有所不同。
C18字符串函数将具有访问RAM或ROM中字符串的变体(例如,strcpypgm2ram、strcpyram2pgm等)。另一方面,XC8为您执行任务,您不需要使用特定的函数来选择要访问的内存。
如果您正在使用C18,我强烈建议您切换到XC8,这是最近才使用的,而且使用起来更容易。如果您仍然希望使用C18或另一个需要处理程序/数据内存空间的编译器,那么下面是您可能要尝试的两种解决方案。C18数据表表示,putsUSART从数据内存中打印一个字符串到USART。函数putrsUSART将从程序内存中打印一个字符串。因此,您可以简单地使用putrsUSART打印字符串。
您还可以尝试以下方法,这包括将字符串从程序内存复制到数据内存(如果应用程序内存紧张,则可能会浪费内存):
char pgmstring[] = "Hello";
char datstring[16];
strcpypgm2ram(datstring, pgmstring);
putsUSART(datstring);在本例中,指针pgmstring和datstring将存储在数据内存中。字符串"Hello"将存储在程序内存中。因此,即使指针pgmstring本身在数据内存中,它也最初指向一个内存地址("Hello"地址)。指向数据内存中相同字符串的唯一方法是在数据内存中创建该字符串的副本。这是因为接受存储在数据内存(如putsUSART)中的字符串的函数不能直接与存储在程序内存中的字符串一起使用。
我希望这能帮助你更好地理解如何使用哈佛微处理器,在那里程序和数据记忆是分开的。
https://stackoverflow.com/questions/38714798
复制相似问题