Board logo

标题: Xilinx FPGA中使用LCD1602的方法 [打印本页]

作者: pengpengpang    时间: 2014-8-20 10:08     标题: Xilinx FPGA中使用LCD1602的方法

一、XPS中的设置
1.在XPS添加一个XPS General Purpose IO,并将其命名为“Char_LCD”。
注:这里的命名有一定的规则,将其命名为“Char_LCD”,是因为在后来的C程序中调用LCD基地址的时候使用的名字为“XPAR_CHAR_LCD_BASEADDR”,如果将这个命名为其他的(比如XX),那么在下面的lcd.h中也要将
#define LCD_BASEADDR XPAR_CHAR_LCD_BASEADDR

这一句中的"CHAR_LCD"改成对应的名称。
2.配置Char_LCD中Channel 1的GPIO Data Channel Width为11并在Ports中设置为Connected to External Ports。
3.在System.ucf加入相应的管教约束,这里提供Genesys Digilent开发板中对应的管脚约束,管脚的名称自然而言和上面使用的名称对应。
#Char_LCD constraints
#Char_LCD_GPIO_IO_pin<0> corresponds to LCD_E
#Char_LCD_GPIO_IO_pin<1> corresponds to LCD_RS
#Char_LCD_GPIO_IO_pin<2> corresponds to LCD_RW
#Char_LCD_GPIO_IO_pin<3> corresponds to LCD_D7, <4> to LCD_D6... <10> to LCD_D0

Net Char_LCD_GPIO_IO_pin<0> LOC = AA5 | IOSTANDARD=LVCMOS33 | TIG | PULLDOWN;
Net Char_LCD_GPIO_IO_pin<1> LOC = V7 | IOSTANDARD=LVCMOS33 | TIG | PULLDOWN;
Net Char_LCD_GPIO_IO_pin<2> LOC = W6 | IOSTANDARD=LVCMOS33 | TIG | PULLDOWN;
Net Char_LCD_GPIO_IO_pin<3> LOC = AD7 | IOSTANDARD=LVCMOS33 |TIG | PULLDOWN;
Net Char_LCD_GPIO_IO_pin<4> LOC = AC7 | IOSTANDARD=LVCMOS33 | TIG | PULLDOWN;
Net Char_LCD_GPIO_IO_pin<5> LOC = AC5 | IOSTANDARD=LVCMOS33 | TIG | PULLDOWN;
Net Char_LCD_GPIO_IO_pin<6> LOC = AB6 | IOSTANDARD=LVCMOS33 | TIG | PULLDOWN;
Net Char_LCD_GPIO_IO_pin<7> LOC = AC4 | IOSTANDARD=LVCMOS33 | TIG | PULLDOWN;
Net Char_LCD_GPIO_IO_pin<8> LOC = AB5 | IOSTANDARD=LVCMOS33 | TIG | PULLDOWN;
Net Char_LCD_GPIO_IO_pin<9> LOC = AB7 | IOSTANDARD=LVCMOS33 | TIG | PULLDOWN;
Net Char_LCD_GPIO_IO_pin<10> LOC = Y8 | IOSTANDARD=LVCMOS33 | TIG | PULLDOWN;

二、SDK中的代码模板
1.将lcd.h、lcd.c、sleep.h和sleep.c添加到工程的src文件夹中,并在需要调用LCD的代码中添加
#include "lcd.h"

2.在使用LCD之前需要进行初始化,添加下面代码:
LCDOff();
LCDClear();
LCDOn();
LCDInit();

3.需要在LCD中显示时,调用下面函数
LCDPrintString(First_Line, Second_Line; //First_Line和Second_Line都是char*类型

附件:博文中提到文件的源代码:
1.lcd.h
/*******************************************************************************
*
* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
* SOLELY FOR USE IN DEVELOPING PROGRAMS AND SOLUTIONS FOR
* XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION
* AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION
* OR STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS
* IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,
* AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
* FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY
* WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE
* IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR
* REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF
* INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE.
*
* (c) Copyright 2007 Xilinx, Inc.
* All rights reserved.
*
******************************************************************************/

#ifndef LCD_H
#define LCD_H

//=====================
//        TEST FUNCTIONS
//=====================
void LCDTest();
void LCDTestMenu();
void LCDTestInput(char ch);

//=====================
//        EXTERNAL FUNCTIONS
//=====================

#define LCD_BASEADDR XPAR_CHAR_LCD_BASEADDR //根据需要修改这里
void LCDOn();
void LCDOff();
void LCDClear();
void LCDInit();

void LCDEnableDisplayShift();
void LCDEnableCursorBlink();

void LCDDisableDisplayShift();
void LCDDisableCursorBlink();

void MoveCursorHome();
void MoveCursorRight();
void MoveCursorLeft();

void LCDSetLine(int line);
void LCDPrintChar(char c);
void LCDPrintString(char * line1, char * line2);

//=====================
//        INTERNAL FUNCTIONS
//=====================
void InitInst(void);
void WriteInst(unsigned long inst1, unsigned long inst2);
void WriteData(unsigned long data1, unsigned long data2);
void WriteInst8(unsigned long inst);
void WriteData8(unsigned long data);

#endif
2.lcd.c
/******************************************************************************
*
* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
* AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND
* SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE,
* OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,
* APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION
* THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,
* AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
* FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY
* WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE
* IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR
* REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF
* INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE.
*
* (c) Copyright 2007 Xilinx Inc.
* All rights reserved.
*
******************************************************************************/

#include
#include "sleep.h"
#include "xgpio_l.h"
#include "xparameters.h"
#include "lcd.h"

// usec delay timer during initialization, important to change if
// clock speed changes
#define INIT_DELAY 10000
#define INST_DELAY 1000 //usec delay timer between instructions
#define DATA_DELAY 1000 //usec delay timer between data

/*
#------------------------------------------------------------------------------
# IO Pad Location Constraints / Properties for Character LCD GPIO
#------------------------------------------------------------------------------

Net Char_LCD_GPIO_IO<0> LOC = AA5 | IOSTANDARD=LVCMOS33 | TIG | PULLDOWN; #LCD_E
Net Char_LCD_GPIO_IO<1> LOC = V7 | IOSTANDARD=LVCMOS33 | TIG | PULLDOWN; #LCD_RS
Net Char_LCD_GPIO_IO<2> LOC = W6 | IOSTANDARD=LVCMOS33 | TIG | PULLDOWN; #LCD_RW
Net Char_LCD_GPIO_IO<3> LOC = AD7 | IOSTANDARD=LVCMOS33 |TIG | PULLDOWN; #LCD_D7
Net Char_LCD_GPIO_IO<4> LOC = AC7 | IOSTANDARD=LVCMOS33 | TIG | PULLDOWN; #LCD_D6
Net Char_LCD_GPIO_IO<5> LOC = AC5 | IOSTANDARD=LVCMOS33 | TIG | PULLDOWN; #LCD_D5
Net Char_LCD_GPIO_IO<6> LOC = AB6 | IOSTANDARD=LVCMOS33 | TIG | PULLDOWN; #LCD_D4
Net Char_LCD_GPIO_IO<7> LOC = AC4 | IOSTANDARD=LVCMOS33 | TIG | PULLDOWN; #LCD_D3
Net Char_LCD_GPIO_IO<8> LOC = AB5 | IOSTANDARD=LVCMOS33 | TIG | PULLDOWN; #LCD_D2
Net Char_LCD_GPIO_IO<9> LOC = AB7 | IOSTANDARD=LVCMOS33 | TIG | PULLDOWN; #LCD_D1
Net Char_LCD_GPIO_IO<10> LOC = Y8 | IOSTANDARD=LVCMOS33 | TIG | PULLDOWN; #LCD_D0
*/

//==============================================================================
//
//         INTERNAL FUNCTIONS
//
//==============================================================================

void WaitForBusyFlag(void)
{
Xuint32 LCD_Status;

XGpio_mSetDataDirection(LCD_BASEADDR, 1, 0xFFFFF8FF);
XGpio_mSetDataReg(LCD_BASEADDR, 1, 0x00000100);
usleep(10);
XGpio_mSetDataReg(LCD_BASEADDR, 1, 0x00000500);
usleep(10);
LCD_Status = XGpio_mReadReg(LCD_BASEADDR, 1);
usleep(10);
XGpio_mSetDataReg(LCD_BASEADDR, 1, 0x00000100);
usleep(10);
//xil_printf("\r\nLCD status = 0x%X", LCD_Status);

while (LCD_Status & 0x00000080){
XGpio_mSetDataReg(LCD_BASEADDR, 1, 0x00000100);
usleep(10);
XGpio_mSetDataReg(LCD_BASEADDR, 1, 0x00000500);
usleep(10);
LCD_Status = XGpio_mReadReg(LCD_BASEADDR, 1);
//xil_printf("\r\nLCD status = 0x%X", LCD_Status);
XGpio_mSetDataReg(LCD_BASEADDR, 1, 0x00000100);
usleep(10);
}
//set LCD data to output again
XGpio_mSetDataDirection(LCD_BASEADDR, 1, 0xFFFFF800);
}

void InitInst(void)
{

Xuint32 LCD_Status;
/* 4-bit mode
XGpio_mSetDataReg(LCD_BASEADDR, 1, 0x00000003); //function set 4-bit mode,
usleep(10);
XGpio_mSetDataReg(LCD_BASEADDR, 1, 0x00000043); //set enable and data
usleep(10);
XGpio_mSetDataReg(LCD_BASEADDR, 1, 0x00000003);
usleep(INIT_DELAY);
*/
XGpio_mSetDataDirection(LCD_BASEADDR, 1, 0xFFFFF800);

XGpio_mSetDataReg(LCD_BASEADDR, 1, 0x0000003C);//function set, 8-bit mode, 2 lines, 8 X 11 dots
usleep(10);
XGpio_mSetDataReg(LCD_BASEADDR, 1, 0x0000043C); //set enable and data
usleep(10);
XGpio_mSetDataReg(LCD_BASEADDR, 1, 0x0000003C);

//read the Busy Flag
XGpio_mSetDataDirection(LCD_BASEADDR, 1, 0xFFFFF8FF);
XGpio_mSetDataReg(LCD_BASEADDR, 1, 0x00000100);
XGpio_mSetDataReg(LCD_BASEADDR, 1, 0x00000500);
LCD_Status = XGpio_mReadReg(LCD_BASEADDR, 1);
//xil_printf("\r\nLCD status = 0x%X", LCD_Status);

XGpio_mSetDataReg(LCD_BASEADDR, 1, 0x00000100);
while (LCD_Status & 0x00000080){
XGpio_mSetDataReg(LCD_BASEADDR, 1, 0x00000100);
XGpio_mSetDataReg(LCD_BASEADDR, 1, 0x00000500);
LCD_Status = XGpio_mReadReg(LCD_BASEADDR, 1);
//xil_printf("\r\nLCD status = 0x%X", LCD_Status);
XGpio_mSetDataReg(LCD_BASEADDR, 1, 0x00000100);
}
//set LCD data to output again
XGpio_mSetDataDirection(LCD_BASEADDR, 1, 0xFFFFF800);
}

//write instruction on 8 bits
void WriteInst8(unsigned long inst)
{
unsigned long printinst;

XGpio_mSetDataDirection(LCD_BASEADDR, 1, 0xFFFFF800);
printinst = 0x00000400 | inst;
XGpio_mSetDataReg(LCD_BASEADDR, 1, inst); //write data
usleep(10);
XGpio_mSetDataReg(LCD_BASEADDR, 1, printinst); //set enable
usleep(10);
XGpio_mSetDataReg(LCD_BASEADDR, 1, inst); //turn off enable
usleep(10);

WaitForBusyFlag();
// usleep(INST_DELAY);
}

void WriteInst(unsigned long inst1, unsigned long inst2)
{
unsigned long printinst;

printinst = 0x00000040 | inst1;
XGpio_mSetDataReg(LCD_BASEADDR, 1, inst1); //write data
usleep(10);
XGpio_mSetDataReg(LCD_BASEADDR, 1, printinst); //set enable
usleep(10);
XGpio_mSetDataReg(LCD_BASEADDR, 1, inst1); //turn off enable
usleep(10);

printinst = 0x00000040 | inst2;
XGpio_mSetDataReg(LCD_BASEADDR, 1, printinst); //set enable and data
usleep(10);
XGpio_mSetDataReg(LCD_BASEADDR, 1, inst2); //turn off enable

usleep(INST_DELAY);
}

void WriteData8(unsigned long data)
{
unsigned long rs_data, enable_rs_data;
//        int busy=true;

rs_data = 0x00000200 | data; //sets rs, data1
enable_rs_data = 0x00000600 | data;

XGpio_mSetDataReg(LCD_BASEADDR, 1, rs_data); //write data, rs
usleep(10);
XGpio_mSetDataReg(LCD_BASEADDR, 1, enable_rs_data); //set enable, keep data, rs
usleep(10);
XGpio_mSetDataReg(LCD_BASEADDR, 1, rs_data); //turn off enable
usleep(10);

WaitForBusyFlag();
// usleep(DATA_DELAY);
}

void WriteData(unsigned long data1, unsigned long data2)
{
unsigned long rs_data, enable_rs_data;
//        int busy=true;

rs_data = 0x00000020 | data1; //sets rs, data1
enable_rs_data = 0x00000060 | data1;

XGpio_mSetDataReg(LCD_BASEADDR, 1, rs_data); //write data, rs
usleep(10);
XGpio_mSetDataReg(LCD_BASEADDR, 1, enable_rs_data); //set enable, keep data, rs
usleep(10);
XGpio_mSetDataReg(LCD_BASEADDR, 1, rs_data); //turn off enable
usleep(10);

rs_data = 0x00000020 | data2; //sets rs, data2
enable_rs_data = 0x00000060 | data2; //sets rs, data2

XGpio_mSetDataReg(LCD_BASEADDR, 1, enable_rs_data); //set enable, rs, data
usleep(10);
XGpio_mSetDataReg(LCD_BASEADDR, 1, rs_data); //turn off enable

usleep(DATA_DELAY);
}

//==================================================================================
//
//         EXTERNAL FUNCTIONS
//
//==================================================================================

void LCDOn()
{
//printf("DISPLAY ON\r\n");
// WriteInst(0x00000000, 0x0000000E);
WriteInst8(0x0000000E); //display on, cursor on, cursor blink off
}

void LCDOff()
{
// printf("DISPLAY OFF\r\n");
// WriteInst(0x00000000, 0x00000008);
WriteInst8(0x00000008); //display off, cursor off
}

void LCDClear()
{
// printf("DISPLAY CLEAR\r\n");
// WriteInst(0x00000000, 0x00000001);
// WriteInst(0x00000000, 0x00000010);

WriteInst8(0x00000001); //clear display
WriteInst8(0x00000002); //return home

}
void LCDInit()
{
// Sets CHAR LCD Reg to Write Mode
XGpio_mSetDataDirection(LCD_BASEADDR, 1, 0x00000000);
// Zeroes CHAR LCD Reg
XGpio_mSetDataReg(LCD_BASEADDR, 1, 0x00000000);

// LCD INIT
usleep(15000); //After VCC>4.5V Wait 15ms to Init Char LCD
InitInst();

usleep(4100); //Wait 4.1ms
InitInst();
usleep(100); //Wait 100us
InitInst();
InitInst();

// Function Set
// WriteInst(0x00000002, 0x00000002);
WriteInst8(0x00000038);

// Display Off
// WriteInst(0x00000000, 0x00000008);
WriteInst8(0x00000008);

// Display Clear
// WriteInst(0x00000000, 0x00000001);
WriteInst8(0x00000001);

// Entry Mode Set
// WriteInst(0x00000000, 0x00000006);
WriteInst8(0x00000006); //cursor moves right, no shift

// Display On
// WriteInst(0x00000000, 0x0000000E);
WriteInst8(0x0000000E);//display on, cursor on, cursor blink off
}

void LCDEnableDisplayShift()
{
WriteInst8(0x00000007); //cursor moves right, shift enabled
}
void LCDEnableCursorBlink()
{
WriteInst8(0x0000000F);//display on, cursor on, cursor blink on
}

void LCDDisableDisplayShift()
{
WriteInst8(0x00000006); //cursor moves right, no shift

}
void LCDDisableCursorBlink()
{
WriteInst8(0x0000000E);//display on, cursor on, cursor blink off
}

void MoveCursorHome()
{
// WriteInst(0x00000000, 0x00000002);
WriteInst8(0x00000002);
}

void MoveCursorLeft()
{
// WriteInst(0x00000001, 0x00000000);
WriteInst8(0x00000010);
}

void MoveCursorRight()
{
// WriteInst(0x00000001, 0x00000004);
WriteInst8(0x00000014);
}

void LCDSetLine(int line)
{
//line1 = 1, line2 = 2
int i;

if((line - 1))
{
MoveCursorHome();
for(i=0; i<40; i++)
{
MoveCursorRight();
}
}
else
{
MoveCursorHome();
}

}
void LCDPrintChar(char c)
{
// WriteData(((c >> 4) & 0x0000000F), (c & 0x0000000F));
WriteData8(c);
}

void LCDPrintString(char * line1, char * line2)
{
int i=0;

LCDSetLine(1);
for(i=0; i<16; i++)
{
if(line1)
LCDPrintChar(line1);
else
break;
}
i=0;
//xil_printf ("\r\nFirst Line printed");
LCDSetLine(2);

//        WriteInst8(0x000000C0);
for(i=0; i<16; i++)
{
if(line2)
LCDPrintChar(line2);
else
break;
}
//xil_printf ("\r\nSecond Line printed");
return;
}

3.sleep.h
/*******************************************************************************
*
* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
* SOLELY FOR USE IN DEVELOPING PROGRAMS AND SOLUTIONS FOR
* XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION
* AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION
* OR STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS
* IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,
* AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
* FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY
* WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE
* IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR
* REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF
* INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE.
*
* (c) Copyright 2007 Xilinx, Inc.
* All rights reserved.
*
******************************************************************************/

#ifndef SLEEP_H
#define SLEEP_H

void nanosleep(unsigned int nanoseconds);
void usleep(unsigned int useconds);
void sleep(unsigned int seconds);

#endif
4.sleep.c
/******************************************************************************
*
* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
* AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND
* SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE,
* OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,
* APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION
* THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,
* AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
* FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY
* WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE
* IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR
* REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF
* INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE.
*
* (c) Copyright 2007 Xilinx Inc.
* All rights reserved.
*
******************************************************************************/

#include "sleep.h"
//#include "xtime_l.h"
#include "xparameters.h"

void nanosleep(unsigned int nanoseconds)
{
/* not implemented */
}

void usleep(unsigned int useconds)
{

int i,j;
for (j=0;j<useconds;j++)
for (i=0;i<26;i++) asm("nop");</useconds;j++)

// XTime tEnd, tCur;
// XTime_GetTime(&tCur);
// tEnd = tCur + ((XTime) useconds) * (XPAR_CPU_PPC405_CORE_CLOCK_FREQ_HZ / 1000000);
// do
// {
// XTime_GetTime(&tCur);
// } while (tCur < tEnd);
}

void sleep(unsigned int seconds)
{

int i,j;
for (j=0;j<seconds;j++)
for (i=0;i<25000000;i++) asm("nop");</seconds;j++)

// XTime tEnd, tCur;
// XTime_GetTime(&tCur);
// tEnd = tCur + ((XTime) seconds) * XPAR_CPU_PPC405_CORE_CLOCK_FREQ_HZ;
// do
// {
// XTime_GetTime(&tCur);
// } while (tCur < tEnd);
}


文章来源:tianshilei1992的专栏





欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0