我用的是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);
}
}发布于 2015-09-02 18:57:47
因此,代码编译后,您可以逐步完成它(大概是使用一个内部调试器),但它并不能实现您的期望。你对问题的描述--或者说,实际行为和预期行为之间的不匹配--是液晶显示器似乎没有初始化,它显示的是与你预期不同的东西。
所以要调试这个问题,分解问题。检查你的假设和期望。我建议你通过程序,并检查,对每一条指令(至少在最初),程序做你所期望的。如果发生了其他事情,找出原因,尝试修复,然后再进行测试。现在,这将很快变得乏味,所以在调试器中使用断点或“运行到游标”来跳过已知的好部分,然后回到受检查的部分。
您的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();
/*...*/
}delay_ms(20);,你有没有检查过,这实际上是20 you的延迟?您可以通过设置一个引脚,调用delay_ms(20)并清除该引脚,然后用示波器或逻辑分析器或类似的方法测量脉冲持续时间。(我知道这可能有点基础,但我了解到这一点,因为delay_ms()是在没有参数的情况下定义的,这使我认为编译器可能会抱怨它)。有多个对delay_ms(20)的调用;稍后在上面的片段中,我将跳过它们LCD_RS = 0;您是否检查了实际的引脚在执行此操作时是否发生了更改?我再问一次,因为我看不到你设置引脚,所以它很可能配置不正确。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 >> 4是0b0010,这是“按位或编辑”,值为_LATA4,即0或1 (但我们称之为Y),因此您可以分配0b001Y。现在,我认为您打算将数据线设置为cmd的顶部咬口和LCD_EN位集。但是在C语言中,你不能这样做。
3.2。从左边看,您只将它分配给_LATB12 --逗号运算符没有执行您明显认为的操作。在不知道xc16如何处理赋值给位变量(位是非标准的)的情况下,我猜您要么赋值1,因为值是非零,要么分配LSB,这将是_LATA4。我将在此结束对您代码的分析。希望这能帮助您调试和修复代码,并可能引发更多的问题。
一旦代码达到了与您的意图和期望相匹配的程度,您就可以进行第二轮调试了--代码(以及您的意图/期望)是否与硬件所期望的相匹配?这将通过类似的技术来解决--分解问题,检查实际和预期的行为,找出需要修复的是实际的还是预期的行为,修复它,并重新测试。
希望这能有所帮助。
https://stackoverflow.com/questions/32333922
复制相似问题