我使用dspic33fj128mc802和mplab xc16。我想在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);
}
}
答案 0 :(得分:0)
因此代码编译,您可以逐步完成它(可能是使用在线调试器),但它并没有按照您的预期进行操作。您对问题的描述 - 或者说实际和预期行为之间的不匹配是LCD似乎没有被初始化,并且它显示的内容与您期望的不同。
所以要调试它,分解问题。检查您的假设和期望。我建议您逐步完成该程序,并在每条指令(至少最初)上检查该程序是否符合您的预期。如果发生其他事情,找出原因,尝试修复,然后重新测试。现在,这将很快变得乏味,所以使用断点或"运行光标"在调试器中跳过已知良好的部分,并在详细审查的部分回家。
你的main()
包含一个无限循环,循环体首先调用LCD_Init()
,所以让我们暂时关注它。下面,我已经内联了#39;一些调用,所以我们可以更好地看到程序流程:
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();
/*...*/
}
delay_ms(20);
您是否检查过这实际上有20毫秒的延迟?您可以通过设置引脚,调用delay_ms(20)并清零引脚,然后使用示波器或逻辑分析仪或类似工具测量脉冲持续时间来完成此操作。
(我知道这可能有点基础,但我接受了这个,因为delay_ms()
的定义没有参数,这让我觉得编译器可能会抱怨它)。有多次调用delay_ms(20);后来在上面的剪辑中,我将跳过它们
LCD_RS = 0;
执行此操作时,您是否检查过实际引脚是否发生了变化?我再次问,因为我无法看到你设置引脚,所以它可能配置不正确。
然后我们进入LCD_Command( 0b0000101000 )
(顺便说一句,你将10位二进制文字传递给char参数,前两位不会传递),第一个那里的陈述是lcdport = ((cmd >> 4) & 0x0F)|LCD_EN;
。让我们对该语句进行预处理器替换,最后我们得到以下的怪物:_LATB11,_LATA4,_LATB15,_LATB14,_LATB13,_LATB12 = ((cmd >> 4) & 0x0F)|_LATA4;
让我们稍微打破一下:
3.1。查看赋值运算符的右侧,我们有((cmd >> 4) & 0x0F)|_LATA4;
。 cmd >> 4
是0b0010
,这是"按位或&#34}"价值为_LATA4
,即0
或1
(但我们称之为Y),因此您指定0b001Y
。现在,我认为你想要的是将数据线设置为cmd
的顶部半字节和LCD_EN位集。但是在C中,你不能这样做。
3.2。查看左侧,仅将此值分配给_LATB12
- 逗号运算符不会执行您显然认为的操作。在不知道xc16如何处理int变量到位变量(bit是非标准的)的情况下,我猜你要么分配1因为值是非零,要么你分配LSB,这将是_LATA4
我将停止分析您的代码。希望这可以帮助您调试和修复代码,并可能引发更多问题。
一旦您获得了与您的意图和期望相匹配的代码,您就可以进行第二轮调试 - 代码(以及您的意图/期望)是否与硬件匹配预计?这将通过类似的技术解决 - 分解问题,检查实际和预期的行为,找出是否需要修复,修复和重新测试的实际或预期行为。
希望有所帮助。