【问题标题】:LCD 8-bit mode to 4-bit modeLCD 8 位模式到 4 位模式
【发布时间】:2008-10-30 00:50:21
【问题描述】:

我们有一个字符 LCD (www.cloverlcd.com/pdf/S6A0069.pdf),我们必须在 8 位模式下工作。然而,现在我们正试图让它在 4 位模式下工作,但它似乎没有显示任何内容。我认为没有编写功能集指令。有人可以检查我是否以正确的方式接近这个?我将发布我的 8 位代码(正在工作)和我的 4 位代码(我正在尝试开始工作)

//8位工作 COMPortC(0x3C); //函数集 延迟1KTCYx(10); COMPortC(0x0F); //开启显示并配置光标设置 延迟1KTCYx(10); COMPortC(0x01); //清除显示 延迟1KTCYx(10); COMPortC(0x06); //增量模式和增量方向(入口模式设置) 延迟1KTCYx(10); COMPortC(0x02); //回家 //4位 COMPortC(0x20); //函数集 延迟1KTCYx(10); COMPortC(0x20); //函数集 延迟1KTCYx(10); COMPortC(0x80); //函数集 延迟1KTCYx(10); COMPortC(0x00); //开启显示并配置光标设置 延迟1KTCYx(10); COMPortC(0xF0); //开启显示并配置光标设置 延迟1KTCYx(10);

【问题讨论】:

  • 问题:如果它在 8 位模式下工作,为什么要使用 4 位?
  • 我们正在尝试切换到 4 位模式,因为我们需要 4 根额外的电线连接到连接到我们微控制器的其他组件。

标签: lcd color-depth


【解决方案1】:

在某种程度上看起来不错,但我想知道一些事情:

1/ 为什么要输出两次 0x20 来设置 4-bit 部分的 CGRAM 地址?当然这只需要一次。

2/ 其他两个写入(0x00 和 0xf0),我从文档中无法理解。您能否修复 cmets 以指示它们的用途?

3/ 切换到 4 位模式后,是否需要重做其他指令(递增和返回原点)?可能是切换模式会重置所有数据。

4/ 我注意到的一件事是忙标志表明系统还不能接收另一条指令。可能是您传递它们的速度太快了。当您将延迟从 10 增加到 100 时会发生什么。

只是一些尝试 - 让我们知道结果。

=====

回应:

感谢回复

1 和 2) 我根据数据表 (www.cloverlcd.com/pdf/S6A0069.pdf) 第 29 页编写这些值。

3) 你是对的,我确实需要执行其他指令,但现在,我只是想让光标在 4 位模式下闪烁(所以前两个指令就足够了)

4) 我只是尝试了 100 次延迟,但没有成功。

对不起,糟糕的cmets,我下次会尝试发布更好的代码。

谢谢

=====

编辑:

我知道它现在是如何工作的。在 4 位模式下,它只使用 d7,d6,d5,d4 但每条指令都是 2 次写入(形成一条 8 位指令)。因此,它使用一种技巧来编写指令 20(8 位模式)或 22(4 位模式下的 2020),这两个指令都将模式设置为 4 位。非常聪明,三星,让我印象深刻。

尝试遍历整个初始化序列。可能是在初始化完成之前显示器没有完全启动。

所以你需要输出(十六进制)20,20,80,00,f0,00,10,00,60,00,20。粗体是您需要添加的。

另外,我需要再问两个问题(请以评论的形式回复此答案,而不是发布另一个答案)

1/ COMPortC() 在输出数据之前是否真的检查忙信号?

2/ 10的延迟,单位是什么,毫秒,微秒等?

【讨论】:

  • 1) 是 COMPortC() 确实检查 a 是否忙 2) 延迟以周期为单位。我不确定 uC 的确切频率是多少,但有人告诉我延迟函数是每 1000 个周期,所以 delay(10) 是 10000 个周期。此外,我们使用了与 8 位完全相同的延迟。所以可能不是时间。
  • 好吧,如果那是基于 270kHz 的 fosc,10k 周期大约是 37 毫秒。对于所需的最长等待时间,这应该绰绰有余,尤其是在您同时检查忙标志的情况下。
  • 你试过完整的初始化序列了吗?
  • 目前,我正在做的是写第一个半字节,延迟,写第二个半字节,延迟,检查繁忙标志
  • 好的,让我们看看它是否正在切换到 4 位。输出初始化序列 20,20,80,0f,01,06,02 看看是否有效。如果 20,20,80 不切换,应该可以正常工作。如果它已切换,您只需将 0 写入 RDRAM,仍然看不到任何显示。
【解决方案2】:

我不确定你的 4 位是如何连接的,但我的猜测是......因为你在上半字节(0x*0 - 星星所在的位置)发送位,你可能想要使用较低或最不重要的半字节,即 0x0*。

COMPortCWithoutBusy(0x02);      //function set first nibble                                     
Delay1KTCYx(10);
COMPortCWithoutBusy(0x02);      //function set second nibble                                    
Delay1KTCYx(10);
BusyEnable();
Delay1KTCYx(10);
...

【讨论】:

    【解决方案3】:

    这里有一段注释更好的 4 位模式代码

    COMPortC(0x20); //函数设置第一个半字节 延迟1KTCYx(10); COMPortC(0x20); //函数设置第二个半字节 延迟1KTCYx(10); COMPortC(0x80); //函数设置第三个半字节 延迟1KTCYx(10); COMPortC(0x00); //开启显示并配置光标设置第一个半字节 延迟1KTCYx(10); COMPortC(0xF0); //开启显示并配置光标设置第二个半字节 延迟1KTCYx(10);

    我还是不知道怎么了。此外,在数据表的第 18 页上,它显示了与 8 位模式的时序图几乎相同的时序图,只是有一个 AC3。那个AC3是什么意思?

    【讨论】:

      【解决方案4】:
      无效液晶显示器初始化(无效) { COMPortCWithoutBusy(0x20); //函数设置第一个半字节 延迟1KTCYx(10); COMPortCWithoutBusy(0x20); //函数设置第二个半字节 延迟1KTCYx(10); BusyEnable(); 延迟1KTCYx(10); COMPortCWithoutBusy(0x80); //函数设置第三个半字节 延迟1KTCYx(10); BusyEnable(); 延迟1KTCYx(10); COMPortCWithoutBusy(0x00); //开启显示并配置光标设置第一个半字节 延迟1KTCYx(10); COMPortCWithoutBusy(0xF0); //开启显示并配置光标设置第二个半字节 延迟1KTCYx(10); BusyEnable(); 延迟1KTCYx(10); COMPortCWithoutBusy(0x00); //disp 清除第一个半字节 延迟1KTCYx(10); COMPortCWithoutBusy(0x10); //disp 清除第二个半字节 延迟1KTCYx(10); BusyEnable(); 延迟1KTCYx(10); COMPortCWithoutBusy(0x00); //进入模式设置第一个半字节 延迟1KTCYx(10); COMPortCWithoutBusy(0x60); //进入模式设置第二个半字节 延迟1KTCYx(10); BusyEnable(); 延迟1KTCYx(10); COMPortCWithoutBusy(0x20); //20 第一个半字节 延迟1KTCYx(10); BusyEnable(); 延迟1KTCYx(10); }

      【讨论】:

        【解决方案5】:

        这只是 HD44780 LCD 驱动程序的另一种变体,因此它应该可以与以下初始化例程一起正常工作:

        void initlcd(void)
        {
            delayms(20);    // Wait for LCD to power up ( >15ms )
            RS=0;       // Set RS low for instruction 
            write4(3);  // Set interface to 8 bits 
            delayms(5); // Wait for LCD execute instruction ( >4.1ms )
            write4(3);  // Set interface to 8 bits 
            delayms(1); // Wait for LCD execute instruction ( >100us )
            write4(3);  // Set interface to 8 bits 
            delayms(5);     // Wait for LCD execute instruction (At this point 
                    // we could actually start using the busy flag) 
            write4(2);  // Set the display to 4 bit interface 
            delayms(5); // Wait for LCD execute instruction 
            write8(0x28);   // Set the display to two line and ???
            delayms(5); // Wait for LCD execute instruction 
            write8(6);  // ???
            delayms(5); // Wait for LCD execute instruction 
            write8(1);  // Clear the LCD
            delayms(5); // Wait for LCD execute instruction
            write8(0xf);    // ???
            delayms(5); // Wait for LCD execute instruction
            return;
        }
        

        您需要定义自己的 write4、write8 和 delayms 函数,但它们相对容易。确保将寄存器选择 (RS) 设置为命令模式。 write4 发送一个 4 位命令,而 write 8 连续发送两个 4 位命令,先高半字节,再低半字节:

        void write8(uns8 byte)
        {
            uns8 nibble;
            nibble = (byte & 0xf0) >> 4;    // Rotate the high 4 bits (7-4) of byte into bits (3-0) of nibble
            write4(nibble);         // Write the high 4 bits to the LCD
            nibble = byte & 0xf;        // Copy the low four bits of byte into the low four bits of nibble
            write4(nibble);         // Write the low 4 bits to the LCD
        }
        

        我写的code 是为PIC 微控制器设计的,使用的是cc5x 编译器的免费版本。应该可以理解并移植到其他语言。

        通过多年的 LCD 初始化,初始化例程大量借鉴了许多其他例程 - 发现并克服了 HD44780 和变体的各种怪癖。它应该适用于大多数类似的 LCD。

        【讨论】:

          【解决方案6】:

          1 和 2) 我根据数据表 (www.cloverlcd.com/pdf/S6A0069.pdf) 第 29 页编写这些值。

          3) 你是对的,我确实需要执行其他指令,但现在,我只是想让光标在 4 位模式下闪烁(所以前两个指令就足够了)

          4) 我只是尝试了 100 次延迟,但没有成功。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-07-29
            • 1970-01-01
            • 1970-01-01
            • 2013-06-07
            • 1970-01-01
            相关资源
            最近更新 更多