简体   繁体   English

PIC18f4550 XC8 编译器:启用中断服务程序 function 时 LCD 屏幕停止工作

[英]PIC18f4550 XC8 compiler: LCD screen stop working when interrupt service routine function is enabled

Background背景

I am trying to make 16x2 generic LCD display(HD44780) shows some texts on the screen when data is received from HC-05 Bluetooth module via USART interface using PIC184550.当使用 PIC184550 通过 USART 接口从 HC-05 蓝牙模块接收数据时,我正在尝试使 16x2 通用 LCD 显示器(HD44780)在屏幕上显示一些文本。

The simplified connection looks something like this:简化的连接如下所示: 在此处输入图像描述

I have tested the HC05 Bluetooth communication via USART (8bits asynchronous with 9600 baud rates) and found that it is able to respond to the data send to it from another mobile phone.我已经通过USART(8位异步,9600波特率)测试了HC05蓝牙通信,发现它能够响应另一部手机发送给它的数据。

I have also tested the LCD screen by trying to display some strings at the specific locations and found to be working.我还通过尝试在特定位置显示一些字符串来测试 LCD 屏幕并发现它可以正常工作。

Issue问题

The USART communication is handled by following interrupt function: USART 通信由以下中断 function 处理:

__interrupt() void ISR(void)
{
if(RCIF == 1)
{
    data = RCREG;
    TXREG = data;
    
    if(data == 'a')
    {
        LED = 1;
    }
    else if(data == 'b')
    {
        LED = 0;
    }
    RCIF = 0;
}

Basically, when the data "a" is received, it will turn the LED connected to RB0 ON and turn off when "b" is received.基本上,当接收到数据“a”时,它将打开连接到 RB0 的 LED,并在接收到“b”时关闭。

The issue arise when I try to combine these two functionality together (USART with interrupt and LCD).当我尝试将这两个功能结合在一起(USART 与中断和 LCD)时,就会出现问题。

As soon as this ISR function is included in the code, the LCD screen stop displaying anything and stop responding to any command whatsoever.一旦此 ISR function 包含在代码中,LCD 屏幕就会停止显示任何内容并停止响应任何命令。

If I remove it from the code and upload it back to the PIC18f4550, after recycling the power, the LCD start working and displaying the texts again.如果我从代码中删除它并将其上传回 PIC18f4550,在回收电源后,LCD 开始工作并再次显示文本。

Note that the ISR function itself is working (ie LED turn on and off based on the USART data)请注意,ISR function 本身正在工作(即根据 USART 数据打开和关闭 LED)

This is how I initialize everything:这就是我初始化所有内容的方式:

//oscillator setup
OSCCON = 0x72;

//initial setup for LCD screen
TRISD = 0;
LATD = 0;
delay_ms(50); // wait for LCD to power up
send_command(0x30);
send_command(0x30);
send_command(0x30);

send_command(0x02);
send_command(0x28); // 4 bits, 2 lines and 5x8 font             
send_command(0x01); // display clear
send_command(0x0C); // display on, cursor off, no blink
send_command(0x06); // increase cursor to the right

//interrupts setup
INTCONbits.GIE = 1;
INTCONbits.PEIE = 1;
PIE1bits.RCIE = 1;
PIE1bits.TXIE = 1;

//led test
TRISB = 0;
LATB = 0;

//USART setup
TRISCbits.TRISC6 = 0; //TX pin as output
TRISCbits.TRISC7 = 1; //RX pin as input
SPBRG = 51; // BRG value for 8MHZ & 9600 baud rate
TXSTA = 0x24;
RCSTA = 0x90;

Does any one know why the inclusion of ISR() function will cause LCD screen to stop working?有谁知道为什么包含ISR() function 会导致液晶屏停止工作?

Perhaps it's a mistake for me to try answering this question, not being overly familiar with the PIC18F4550 (I have used it, but not a lot and not recently).也许我尝试回答这个问题是一个错误,对 PIC18F4550 不太熟悉(我使用过它,但不是很多,最近也不是)。 But, here goes anyway.但是,无论如何。

You have PIE1bits.TXIE = 1;你有PIE1bits.TXIE = 1; that would seem to enable the interrupt for the transmitter side of the EUSART.这似乎会启用 EUSART 发送器端的中断。 If you're not actually handling this condition, or rather clearing it's associated flag, the ISR would re-enter repeatedly.如果您实际上并没有处理这种情况,或者更确切地说是清除它的关联标志,ISR 将反复重新进入。 Some microcontrollers will always execute one instruction out of the interrupt context before dispatching again;一些微控制器在再次调度之前总是会在中断上下文之外执行一条指令; I don't remember whether or not the PIC18F4550 is one of these.我不记得 PIC18F4550 是否是其中之一。 Depending on whether or not it does, the unhandled interrupt will result in control never being transferred back to the main line of execution or it will but will make it very slow, to the point where it may look locked up.取决于它是否这样做,未处理的中断将导致控制永远不会被转移回主执行线,或者它会但会使其非常慢,以至于它看起来可能被锁定。

Incidentally, according to the datasheet, the receive interrupt flag is cleared by reading RCREG .顺便说一下,根据数据表,接收中断标志通过读取RCREG来清除。 Similar logic applies to writing TXREG with respect to clearing its own associated flag.类似的逻辑适用于写入TXREG以清除其自己的关联标志。

As is, it seems if you receive an character on the EUSART, RCIF gets sets, your code executes the ISR.实际上,如果您在 EUSART 上收到一个字符, RCIF得到集合,您的代码就会执行 ISR。 It reads the character from RCREG , thereby clearing the receive flag (which you later do again manually).它从RCREG读取字符,从而清除接收标志(稍后您将再次手动执行)。 It transmits via TXREG , clearing any existing transmit interrupt flag, but then later causing one.它通过TXREG发送,清除任何现有的发送中断标志,但随后会导致一个。 Once the transmit interrupt flag is set, you are now in your loop of death.一旦设置了发送中断标志,您现在就处于死亡循环中。

Either you need to clear the TXIF manually, or by sending when it is set, or don't enable the TXIE .您需要手动清除TXIF ,或者在设置时发送,或者不启用TXIE

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM