串口监控死机液晶屏(TC1602A-21T(R)(3))

问题描述 投票:0回答:1

我的 LCD 屏幕 (TC1602A-21T(R)(3)) 遇到了最令人困惑的问题。这是随 Arduino 套件一起出售的屏幕。

上下文如下:我正在 Arduino UNO 上的 ATMega328p 上执行裸机编程。所以这只是 C 和带有 avrdude 的 Makefile,没有 Arduino 库。我的目标是制作一个非常基本的类似键盘的设备,用户可以使用按钮在 LCD 屏幕上循环输入字符,保存该字符(有点像旧的翻盖手机,您必须使用 0-9 按钮循环显示字符) ,然后第三个按钮会将用户通过 ATMega328p 的 UART、USB 建立的字发送到带有 puTTY 终端监控 /dev/ttyACM0 的 PC。截至目前,我的测试是使用三个按钮中的两个:一个用于循环屏幕上的字符,另一个用于发送它。

我独立验证了UART通信在不同的项目中工作,并学会了成功控制LCD(基于HD44780U驱动程序和数据表),所以我知道这些组件本身工作得很好。将它们放在一起,我可以循环 LCD 上的字符,并通过 UART 至 USB 连接与 PC 发送它们,但是一旦我将 puTTY 或 Arduino 串行监视器连接到 /dev/ttyACM0,LCD被扔掉了。我失去了使用按钮在屏幕上循环字符的能力,但我已经验证了按钮本身正在工作,并且当输入引脚上的电压变高时,程序通过闪烁板载 LED 来正确监视输入电压(这应该触发一个字符循环)。我已经将所有按钮都与 4.7k 下拉电阻配对,所以我想我已经排除了浮动电压。我还可以发送字符,但如果其他所有方法都失败,我的代码将仅发送默认字母“A”。所以 UART 仍然可以工作,但我的 LCD 不行。

现在关键是:将我的 C 文件复制粘贴到 Arduino IDE 中,并通过 Arduino 闪存工具(我知道在 Linux 上使用 avrdude)进行闪存,将程序写入 LCD,问题就消失了!通过 PuTTY 或 Arduino 串行监视器进行监控时,通信不会崩溃。

我怀疑问题在于我的 Makefile 或我与 Arduino 引导加载程序交互的方式(或者更确切地说是缺乏)。我知道 UNO 上还有第二个 USB 桥协处理器,我在任何开发过程中都没有接触过它,所以这是一个很大的未知数。我希望它是 Makefile,因为它很容易纠正。我可以成功地编译并刷新这个文件,但出现上述问题。

CC = avr-gcc
CFLAGS = -g -mmcu=atmega328p -DF_CPU=16000000UL 
OBJCOPY = avr-objcopy
AVR = sudo avrdude
AVRFLAGS = -F -v -p m328p -c arduino -P /dev/ttyACM0 -U flash:w:lcd.hex

default: lcd.elf
    ${OBJCOPY} -O ihex lcd.elf lcd.hex

lcd.o:
    ${CC} ${CFLAGS} -Os -c lcd.c -o lcd.o

lcd.elf: lcd.o
    ${CC} ${CFLAGS} -o lcd.elf lcd.o

flash:
    ${AVR} ${AVRFLAGS} lcd.hex

clean:
    rm -rf *.o *.elf *.hex

作为参考,我还添加了程序的 UART 设置和主驱动程序代码,编辑了(大量)已完成的 LCD 设置代码。由于使用 Arduino 工具刷新时一切正常,因此我保守地假设我的设置不会破坏 LCD,并且我已正确阅读数据表。

这是基于 ATMega328p 数据表的 UART 设置:

void USART_Init()
{
   
    /* 
       set baud rate. Baud prescaler is #def'ed to (((F_CPU / (BAUD_RATE * 16UL))) - 1u)
       formula from Table 19-1 of ATMega328p datasheet
    */
    UBRR0H = (uint8_t)(BAUD_PRESCALER >> 8u);
    UBRR0L = (uint8_t)(BAUD_PRESCALER & 0xFFu);

    /* bit format 8N1: 8data, 1stop, no parity */
    UCSR0C |= (_BV(UCSZ01) | _BV(UCSZ00));

    /* enable Tx line. Also tested with Rx line enabled with no difference */
    UCSR0B |= _BV(TXEN0);
}

这是主要代码:

int main()
{
    /* LOW is #def to 0; HIGH #def to 1 in redacted code */
    uint8_t lastCharCycleState = LOW;
    uint8_t lastSendState = LOW;
    uint8_t pos = 0u;
    uint8_t letter = (uint8_t)'A';
    
    /* explicitly set PD7, PB1, PB0 to input */
    DDRD &= ~_BV(DDD7);

    /* currently unused third button */
    /* DDRB &= ~_BV(DDB1); */
    DDRB &= ~_BV(DDB0);

    // arbitrarily large wait time for testing
    _delay_ms(1000u);
    LCD_Configure();

    USART_Init();

    // arbitrarily large wait time to ensure everything is setup right
    _delay_ms(1000u);

    while (1u)
    {
        /* 
          button press defined as transition from low to high state. PROCESS
          macros are #def'ed in redacted code
        */
        if ((LOW == lastCharCycleState) && (HIGH == PROCESS_CYCLE_INPUT))
        {
            lastCharCycleState = HIGH;
            LCD_Write8Bits((uint8_t)DATA, letter);

            /* reset DDRAM address after it autoincrements from the above data write */
            LCD_Write8Bits((uint8_t)INSTRUCTION, (uint8_t)(0x80U | pos));
            
            /* using characters 32 - 126 to include spaces, letters, and common symbols */
            letter = (++letter % 126u);
            if (32u > letter)
            {
                letter = 32u;
            }
        }
        else if ((HIGH == lastCharCycleState) && (LOW == PROCESS_CYCLE_INPUT))
        {/* button release defined as transition from high to low state */
            lastCharCycleState = LOW;
        }

        if ((LOW == lastSendState) && (HIGH == PROCESS_SEND_INPUT))
        {
            USART_Transmit(letter);
            _delay_ms(5u);
            pos = 0u;
            lastSendState = HIGH;

            /* resets letter after display clear */
            letter = (uint8_t)'A';
            LCD_Write8Bits((uint8_t)INSTRUCTION, (uint8_t)CLEAR_DISPLAY);
        }
        else if ((HIGH == lastSendState) && (LOW == PROCESS_SEND_INPUT))
        {
            lastSendState = LOW;
        }

    }

    // should not reach this point
    return 0;
}

我已经进行了一些谷歌搜索,但还没有找到遇到此问题的人,而且我仍在查看 avrdude 文档,看看我是否破坏了某些内容。目前还没有运气。

c makefile arduino serial-port avrdude
1个回答
0
投票

正如 Dimich 所解释的,将 puTTY 连接到串行端口会将 DTR 信号发送到我的 MPU,重置它但不重置 LCD。通过手动重置测试解决了问题,因此我只需重置 LCD 即可恢复正常功能。

© www.soinside.com 2019 - 2024. All rights reserved.