PIC16F1829 UART RX中断不能使用MPLABX和XC8编译器
我是8位PIC的固件编写新手,可以使用我的代码。我正在使用PIC16F1829来获取RX命令的LED模块。我只是试图在RX引脚接收到特定值时开启LED等基本设置,但甚至无法获得该设置。PIC16F1829 UART RX中断不能使用MPLABX和XC8编译器
想通过中断让UART工作,但在主循环中甚至无法使用轮询工作。我的中断向量在下面的代码中被注释掉了。
RX引脚:RC5
TX引脚:RB7
引脚来开启和关闭切换LED:RA5
引脚RA5工作正常打开和关闭切换LED。 TX引脚工作,虽然我还没有确认如果中断TXIF也不像RCIF不工作一样工作。
我试过阅读RCIF和PIR1bits.RCIF。他们都编译了。两人都没有工作。我已经在两个不同的LED模块上对两个不同的PIC进行了尝试。他们打开了,但读取RX引脚也没有工作。
变量RXIN最初定义为3,因此由于主循环内的RXIN--循环,灯在启动时会闪烁3次,所以我知道它正在进入主循环。但据我所知,RCIF中断在RX引脚接收时不会触发。
我已经在示波器上确认信号进入RX并且使用相同的波特率从TX引脚输出,所以我认为波特率配置正确(300波特,8N1)。我还确认在示波器RX引脚接收强和干净5V信号。到目前为止,轮询RCIF或使用中断服务路由都没有工作。如果任何人都可以看到我的代码,我没有看到的问题,您的帮助将不胜感激。
我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
// This is for 300 baud rate
#define _BAUD_PRESCALER_LOW_ 0x2A
#define _BAUD_PRESCALER_HIGH_ 0x68
#define _XTAL_FREQ 32000000
#pragma config FOSC = INTOSC // Oscillator Selection->INTOSC oscillator: I/O function on CLKIN pin
#pragma config WDTE = OFF // Watchdog Timer Enable->WDT enabled
#pragma config PWRTE = OFF // Power-up Timer Enable->PWRT disabled
#pragma config MCLRE = OFF // MCLR Pin Function Select->MCLR/VPP pin function is digital input
#pragma config CP = OFF // Flash Program Memory Code Protection->Program memory code protection is disabled
#pragma config CPD = OFF // Data Memory Code Protection->Data memory code protection is disabled
#pragma config BOREN = ON // Brown-out Reset Enable->Brown-out Reset enabled
#pragma config CLKOUTEN = OFF // Clock Out Enable->CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin
#pragma config IESO = OFF // Internal/External Switchover->Internal/External Switchover mode is disabled
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable->Fail-Safe Clock Monitor is disabled
// CONFIG2
#pragma config WRT = OFF // Flash Memory Self-Write Protection->Write protection off
#pragma config PLLEN = ON // PLL Enable->4x PLL enabled
#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable->Stack Overflow or Underflow will cause a Reset
#pragma config BORV = LO // Brown-out Reset Voltage Selection->Brown-out Reset Voltage (Vbor), low trip point selected.
#pragma config LVP = OFF
int flagRXFramingError = 0;
int flagRXOverrunError = 0;
volatile unsigned char RXIN = 3;
unsigned char UARTRead(){
return RCREG;
}
void writeRXIN(unsigned char a){
RXIN = a;
}
void TX(unsigned char a){
while(!TXIF){}
TXREG = a;
}
int main(int argc, char** argv) {
// SCS FOSC; SPLLEN disabled; IRCF 8MHz_HF;
OSCCON = 0xF0;
// TUN 0;
OSCTUNE = 0x00;
// Set the secondary oscillator
// Wait for PLL to stabilize
while(PLLR == 0)
{
}
// WDTPS 1:65536; SWDTEN OFF;
WDTCON = 0x16;
__delay_ms(5);
GIE = 1; // Global interrupts enabled
__delay_ms(5);
PEIE = 1; // Active peripheral interrupts enabled
__delay_ms(5);
RCIE = 1; // Enable USART Receive interrupt
__delay_ms(5);
TXIE = 1; // Enable USART Transmitter interrupt
__delay_ms(5);
ADIE = 1; // Enable ADC interrupts
__delay_ms(5);
RXDTSEL = 0; // RX is on RC5 pin
__delay_ms(5);
TXCKSEL = 0; // TX is on RB7 pin
__delay_ms(5);
TRISC5 = 1; // RX pin set as input
__delay_ms(5);
SPEN = 1; // Serial Port Enabled
__delay_ms(5);
SYNC = 0; // Asynchronous mode
__delay_ms(5);
RX9 = 0; // 8 bit reception
__delay_ms(5);
TX9 = 0; // 8-bit transmission
__delay_ms(5);
CREN = 1; // Receiver enabled
__delay_ms(5);
TXEN = 1; // Transmitter enabled
__delay_ms(5);
BRG16 = 1; // 16-bit baud generation
__delay_ms(5);
BRGH = 1; // High baud rate enabled
__delay_ms(5);
ABDEN = 0; // Auto baud detect disabled
__delay_ms(5);
// Baud prescaler n = [Fosc/(D*BR)] - 1
SPBRGH = _BAUD_PRESCALER_HIGH_;
__delay_ms(5);
SPBRGL = _BAUD_PRESCALER_LOW_;
__delay_ms(5);
TRISC6 = 0; // IadjPWM pin configured as output
__delay_ms(5);
ANSC6 = 0; // IadjPWM pin not analog input
__delay_ms(5);
TRISA5 = 0; // DimPWM pin configured as output
__delay_ms(5);
LATC6 = 1; // Max current for now until PWM written
__delay_ms(5);
while(1){
// Inline assembly code to clear watchdog timer
//asm("CLRWDT");
/*if(RXIN == 5){
RA5 = 1;
}
else{
RA5 = 0;
}*/
if(PIR1bits.RCIF){
writeRXIN(UARTRead());
//RA5 = 0;
TX(RXIN);
} // end if RCIF
while(RXIN > 0){
RA5 = 1;
__delay_ms(100);
RA5 = 0;
__delay_ms(100);
RXIN--;
}
}
// infinite loop
// never leave this loop
RA5 = 1;
return (EXIT_SUCCESS);
} // end main
/*void interrupt ISR(void){
if(RCIF){// if USART Receive interrupt flag
RA5 = 1;
if(FERR){
flagRXFramingError = 1;
SPEN = 0;
SPEN = 1;
}
if(OERR){
flagRXOverrunError = 1;
CREN = 0;
CREN = 1;
}
while(RCIF){ // RCIF high as long as there is data in FIFO register. Read RCREG to clear RCIF flag
writeRXIN(UARTRead());
}
RA5 = 0;
}
if (TXIF){// if USART Transmit interrupt
TXIF = 0; // Clear interrupt flag
}
} // end ISRs*/
解决了这个问题
我不知道究竟解决了这个问题,但我会分享我做了重大的变化和新的代码。
我启用了TXIE。 TXIF几乎总是高电平,所以它会产生连续中断 。我没有看到启用TX中断的原因, 虽然可能是一个很好的。如果要TX等到TXIF 不为零并传输,否则为什么要使用该标志?
我有中断启用错误的顺序。我应该有 启用外围设备,然后他们的个别中断,如果 必要,然后PEIE,最后是GIE。
我没有在我的中断中处理FERR和OERR,虽然他们可能会触发并导致中断。
另外我的RXDTSEL在我原来的代码中设置错误。这是新的工作代码。现在它所做的只是回显RX信号,并使LED闪烁指示发送的次数。
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
// This is for 300 baud rate
#define _BAUD_PRESCALER_LOW_ 0x2A
#define _BAUD_PRESCALER_HIGH_ 0x68
#define _XTAL_FREQ 32000000
#define _PIN_DIMPWMPIN_ RA5
#pragma config FOSC = INTOSC // Oscillator Selection->INTOSC oscillator: I/O function on CLKIN pin
#pragma config WDTE = OFF // Watchdog Timer Enable->WDT enabled
#pragma config PWRTE = OFF // Power-up Timer Enable->PWRT disabled
#pragma config MCLRE = OFF // MCLR Pin Function Select->MCLR/VPP pin function is digital input
#pragma config CP = OFF // Flash Program Memory Code Protection->Program memory code protection is disabled
#pragma config CPD = OFF // Data Memory Code Protection->Data memory code protection is disabled
#pragma config BOREN = ON // Brown-out Reset Enable->Brown-out Reset enabled
#pragma config CLKOUTEN = OFF // Clock Out Enable->CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin
#pragma config IESO = OFF // Internal/External Switchover->Internal/External Switchover mode is disabled
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable->Fail-Safe Clock Monitor is disabled
// CONFIG2
#pragma config WRT = OFF // Flash Memory Self-Write Protection->Write protection off
#pragma config PLLEN = ON // PLL Enable->4x PLL enabled
#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable->Stack Overflow or Underflow will cause a Reset
#pragma config BORV = LO // Brown-out Reset Voltage Selection->Brown-out Reset Voltage (Vbor), low trip point selected.
#pragma config LVP = OFF
int flagRXFramingError = 0;
int flagRXOverrunError = 0;
volatile unsigned char RXIN = 3;
unsigned char RX(){
return RCREG;
}
void writeRXIN(volatile unsigned char a){
RXIN = a;
}
void TX(unsigned char a){
while(!PIR1bits.TXIF); // TXIF is usually 1, only 0 when busy transmitting
TXREG = a;
}
int main(int argc, char** argv) {
// SCS FOSC; SPLLEN disabled; IRCF 8MHz_HF;
OSCCON = 0xF0;
// TUN 0;
OSCTUNE = 0x00;
// Set the secondary oscillator
// Wait for PLL to stabilize
while(OSCSTATbits.PLLR == 0){}
ADCON0bits.ADON = 0;
ANSELA = 0x00;
ANSELB = 0x00;
ANSELC = 0x00;
PIE1bits.ADIE = 0; // Disable ADC interrupts
TRISCbits.TRISC5 = 1; // RX pin set to input
TRISCbits.TRISC6 = 0; // IadjPWM pin configured as output
TRISAbits.TRISA5 = 0; // DimPWM pin configured as output
LATCbits.LATC6 = 1; // Max current for now until PWM written
//UART Init
BAUDCONbits.BRG16 = 1; // 16-bit baud generation
TXSTAbits.BRGH = 1; // High baud rate enabled
BAUDCONbits.ABDEN = 0; // Auto baud detect disabled
// Baud prescaler n = [Fosc/(D*BR)] - 1
SPBRGH = _BAUD_PRESCALER_HIGH_;
__delay_ms(1);
SPBRGL = _BAUD_PRESCALER_LOW_;
__delay_ms(1);
APFCON0bits.RXDTSEL = 1; // RX is on RC5 pin
APFCON0bits.TXCKSEL = 0; // TX is on RB7 pin
TXSTAbits.SYNC = 0; // Asynchronous mode
RCSTAbits.SPEN = 1; // Serial Port Enabled
RCSTAbits.RX9 = 0; // 8 bit reception
TXSTAbits.TX9 = 0; // 8-bit transmission
RCSTAbits.CREN = 1; // Receiver enabled
TXSTAbits.TXEN = 1; // Transmitter enabled
PIE1bits.TXIE = 0; // Enable USART Transmitter interrupt
PIE1bits.RCIE = 1; // Enable USART Receive interrupt
while(PIR1bits.RCIF){
writeRXIN(RX());
}
INTCONbits.PEIE = 1; // Enable peripheral interrupts
INTCONbits.GIE = 1; // Enable global interrupts
while(1){
while(RXIN > 0){
TX(RXIN);
_PIN_DIMPWMPIN_ = 1;
__delay_ms(100);
_PIN_DIMPWMPIN_ = 0;
__delay_ms(100);
RXIN--;
}
}
// infinite loop
// never leave this loop
return (EXIT_SUCCESS);
} // end main
void interrupt ISR(void){
if(PIE1bits.RCIE && PIR1bits.RCIF){ // handle RX pin interrupts
while(PIR1bits.RCIF){
writeRXIN(RX());
}
if(RCSTAbits.FERR){
flagRXFramingError = 1;
SPEN = 0;
SPEN = 1;
}
if(RCSTAbits.OERR){
flagRXOverrunError = 1;
CREN = 0;
CREN = 1;
}
} // end RX pin interrupt handlers
} // end ISRs*/
我想你现在正在清除外设的任何未决错误(通过重置外设),然后接收器再次开始工作...... –
某些微控制器停止接收字节,如果存在某种错误。一定要清除这些错误。通常通过清除一些UART控制寄存器位。
写入寄存器之间的5ms延迟是完全无意义的。 5毫秒即使在蹩脚的PIC上也是永恒的。这些是片上存储器映射寄存器 - 你根本不需要任何延迟。 (在某些特殊情况下,在为端口I/O设置数据方向后,您可能需要等待几个时钟周期,但这只是关于它。)首先删除所有5ms延迟。 – Lundin
(作为未来参考的一个便笺:虽然这个问题没有问题,但是如果您有关于特定硬件外设的问题,最好在https://electronics.stackexchange.com/上询问,例如在某些PIC上的UART,潜伏在该站点上的许多PIC专家以及微控制器固件问题也完全在此处讨论)。 – Lundin
尽管如此,我不得不赞成这一点,只是为了'已经在示波器上确认信号进入RX并且使用相同波特率在TX引脚之外,所以我认为波特率配置正确(300波特,8N1)。我还在示波器RX引脚上接收到强烈干净的5V信号。我们得到了太多的嵌入式问题,绝对没有任何硬件工作的迹象,因此必须立即下载/关闭/删除投票,因为软件问答网站本质上是无法解析的;( –