1

我正在使用带有 mplab xc16 的 dspic33fj128mc802。我想在 4 位模式下使用 LCD,但似乎无法初始化它,也不知道我在做什么错。任何帮助将不胜感激调试。我查看了其他示例,我的代码看起来与其他示例相似,但仍然无法正常工作

    //LCD Control pins

    #define LCD_RS       _LATB11
    #define LCD_EN       _LATA4

    #define TRIS_EN      TRISAbits.TRISA4    /* TRIS for E */
    #define TRIS_RS      TRISBbits.TRISB11   /* TRIS for RS */

    #define D7           LATBbits.LATB15
    #define D6           LATBbits.LATB14
    #define D5           LATBbits.LATB13
    #define D4           LATBbits.LATB12

    #define D7_TRIS           TRISBbits.TRISB15
    #define D6_TRIS           TRISBbits.TRISB14
    #define D5_TRIS           TRISBbits.TRISB13
    #define D4_TRIS           TRISBbits.TRISB12

    //LCD Data pins
    #define lcdport     _LATB11,_LATA4,_LATB15,_LATB14,_LATB13,_LATB12


    void delay_ms();
    void delay_us();
    void LCD_Init();
    void LCD_Command(char cmd);
    void LCD_ClearDisp();
    void LCD_RetHome();
    void LCD_Display();
    void LCD_ShiftR();
    void LCD_ShiftL();
    void LCD_4BitMode();
    void LCD_Init();


    void delay_ms()
    {
        __delay32(40000);
    }

    void delay_us()
    {
        __delay32(40);
    }

    void LCD_Command(char cmd) //LCD Command routine
    { 
        lcdport = ((cmd >> 4) & 0x0F)|LCD_EN;
        delay_ms(20);
        lcdport = ((cmd >> 4) & 0x0F);
        delay_ms(20);
        lcdport = (cmd & 0x0F)|LCD_EN;
        delay_ms(20);
        lcdport = (cmd & 0x0F);
        delay_ms(20);
     }

    void LCD_ClearDisp()
    {
        delay_ms(20);
        LCD_Command(0b0000000001);
        delay_ms(20);
    }

    void LCD_RetHome() //set cursor to first digit
    {
        delay_ms(20);
        LCD_Command(0b0000000010);
        delay_ms(20);
    }

    void LCD_Display()//disp on, cursor on, blinking on
    {
        delay_ms(20);
        LCD_Command(0b0000001111);
        delay_ms(20);
    }

    void LCD_ShiftR()//shift right
    {
        delay_ms(20);
        LCD_Command(0b000001100);
        delay_ms(20);
    }

    void LCD_ShiftL()//shift right
    {
        delay_ms(20);
        LCD_Command(0b000001000);
        delay_ms(20);
   }

   void LCD_4BitMode()//4 bit mode, 2 line, 5x7 dots
   {
       delay_ms(20);
       LCD_Command(0b0000101000);
       delay_ms(20);
   }

   void LCD_EntrySet()
   {
       delay_ms(20);
       LCD_Command(0b0000000110);
       delay_ms(20);
   }

   void DDRAM_address()
   {
       delay_ms(20);
       LCD_Command(0b0010000000);
       delay_ms(20);
   }
   void LCD_Strobe(void)  //This function pulls the enable line high and then low
   {    
       LCD_EN = 1;
       delay_ms(20);
       LCD_EN =  0;
       delay_ms(20);
   }
  
   void write_lcd(char dat)
   {
       LCD_RS = 1; // RS = 1
       LCD_EN = 1; // E = 1
       lcdport = dat;
       delay_ms(20);
       LCD_EN = 0; // E = 0
       delay_ms(20);
   }

   void LCD_Write_String(char *ptr)
   {
       while(*ptr)
       {
           write_lcd(*ptr);
           delay_ms(1);
           ptr++;
       }
   }

   void LCD_Init()
   {
       delay_ms(20);
       LCD_RS = 0;
       LCD_4BitMode();
       delay_ms(1);
       LCD_Strobe();
       delay_ms(1);
       LCD_Strobe();
       delay_ms(1);
       LCD_Strobe();
       LCD_ShiftR();
       delay_ms(1);
       LCD_EntrySet();
       delay_ms(1);
       DDRAM_address();
       delay_ms(1);
       LCD_ClearDisp();
   }

   int main ()
   {
       while(1)
       {
           LCD_Init();                  //Intilize LCD in 4-Bit Mode
           delay_ms(20);
           LCD_Command(0X80);          // Start Cursor From First Line
           delay_ms(20);
           LCD_Write_String("Hello");  //Print HELLO on LCD
           delay_ms(20);
           LCD_Command(0XC0);         // Start Cursor From Second Line
           delay_ms(20);
           LCD_Write_String("World"); //Print HELLO on LCD
           delay_ms(20);
           LCD_Strobe();
           delay_ms(20);
       }
   }
4

1 回答 1

0

所以代码编译了,你可以单步调试它(可能使用在线调试器),但它并没有达到你的预期。您对问题的描述 - 或者更确切地说实际行为和预期行为之间的不匹配是 LCD 似乎没有被初始化,并且它显示的内容与您的预期不同。

所以要调试这个,分解问题。检查您的假设和期望。我建议您逐步完成该程序,并在每条指令上(至少在最初)检查该程序是否符合您的预期。如果发生其他事情,找出原因,尝试修复,然后再次测试。现在,这很快就会变得乏味,所以在调试器中使用断点或“运行到光标”来跳过已知良好的部分,并回到正在审查的部分。

main()包含一个无限循环,循环体以调用开始LCD_Init(),所以现在让我们关注它。下面,我已经“内联”了一些调用,因此我们可以更好地查看程序流程:

void LCD_Init()
{
    delay_ms(20);
    LCD_RS = 0;
    //LCD_4BitMode();
        delay_ms(20);
        //LCD_Command(0b0000101000);
            lcdport = ((cmd >> 4) & 0x0F)|LCD_EN;
            delay_ms(20);
            lcdport = ((cmd >> 4) & 0x0F);
            delay_ms(20);
            lcdport = (cmd & 0x0F)|LCD_EN;
            delay_ms(20);
            lcdport = (cmd & 0x0F);
            delay_ms(20);
        // end of LCD_Command(0b0000101000);
        delay_ms(20);
    // end of LCD_4BitMode();
    /*...*/
}
  1. delay_ms(20);你检查过这实际上有 20 毫秒的延迟吗?您可以通过设置引脚、调用 delay_ms(20) 并清除引脚来完成此操作,然后使用示波器或逻辑分析仪或类似设备测量脉冲持续时间。(我知道这可能有点基本,但我接受了这一点,因为delay_ms()它没有参数定义,这让我认为编译器可能会抱怨它)。对 delay_ms(20) 有多次调用;稍后在上面剪断了,我会跳过它们

  2. LCD_RS = 0;您是否检查过执行此操作时实际的引脚是否发生了变化?我再问一次,因为我看不到你设置了 pin,所以很可能配置不正确。

  3. 然后我们进入LCD_Command( 0b0000101000 )(顺便说一句,您将 10 位二进制文​​字传递给 char 参数,不会传递前 2 位),其中的第一条语句是lcdport = ((cmd >> 4) & 0x0F)|LCD_EN;. 让我们对该语句进行预处理器替换,最终得到以下怪物:_LATB11,_LATA4,_LATB15,_LATB14,_LATB13,_LATB12 = ((cmd >> 4) & 0x0F)|_LATA4;让我们稍微分解一下:

    3.1。查看赋值运算符的右侧,我们有((cmd >> 4) & 0x0F)|_LATA4;. cmd >> 40b0010,这是“按位或”,值为_LATA4,即01(但我们称其为 Y),因此您分配0b001Y. 现在,我认为您打算将数据线设置为最高半字节cmd并设置 LCD_EN 位。但是在 C 中,你不能这样做。

    3.2. 查看左侧,您仅将_LATB12其分配给 - 逗号运算符不会执行您显然认为它会执行的操作。在不知道 xc16 如何处理将整数分配给位变量(位是非标准的)的情况下,我猜您要么分配 1,因为该值非零,要么分配 LSB,这将是_LATA4

我将停止对您的代码的分析。希望这能让您调试和修复代码,并可能引发更多问题。

一旦你的代码与你的意图和期望相匹配,你就可以为第二轮调试做好准备——代码(和你的意图/期望)是否符合硬件的期望?这将通过类似的技术来解决 - 分解问题,检查实际和预期的行为,找出需要修复的实际或预期的行为,修复它并重新测试。

希望有帮助。

于 2015-09-02T18:57:47.490 回答