LCD Firmware
Phần trước giới thiệu xong phần import customer hadware, phần này giới thiệu về driver cho LCD.
Sau khi import lcd_port vào bus hệ thống, XPS tự động tạo ra thư viện hỗ trợ cho việc phát triển phần mềm. Ngoài ra các file hệ thống cũng được cập nhật.
file: system.mhs
file: system.mss
Driver được tạo ra trong đường dẫn :
...drivers/lcd_port_v1_00_a/src/
/lcd_port.c
/lcd_port.h
/lcd_port_selftest.c
/Makefile
File lcd_port_selftest.c được tạo ra cho việc test thanh ghi reg0 (lcd_port), ta có thể tham khảo, sữa chữa tùy vào mục đích xử dụng.
Các prototype cho các hàm truy xuất thanh ghi được khai báo trong lcd_port.h
Sau đây là các bước tạo project mới dùng công cụ phát triển phần mềm SDK của xilinx.
1> Trên tool bar của XPS:
Chọn Software -> Lauch Platform Studio SDK
2> Trong hộp thoại Application Wizard:
Chọn Creat a New SDK Application Project -> Next
3> Trong mục New Project
Đặt tên project -> Next
Lấy thông số mặc định Xilinx MicroBlaze Executable -> Next
Finish thao tác create new project
Sau khi hoàn tất các bước trên xilinx tự động tạo các thư mục và các file trong thư mục có tên project name, và một danh sách các thư viện có liên quan đến microblaze.
4> Tạo Linker Script :
Trong mục Navigator, click chuột phải lcd_disp -> Gnenerate Linker Script...
Trong crop down list chọn DDRAM, dùng làm vùng nhớ data , text ....
6> Creat New Source file
Click vào biểu tượng C+ trên tool bar
Đặt tên file lcd.c
Để viết chương trình giao tiếp lcd, tức là dùng microblaze xuất tín hiệu điều khiển lên port_lcd, ngoài lcd_port còn có các ngoại vi khác. Microblaze là processor có cấu trúc tổ chức bộ nhớ Havard, Vùng Intruction và vùng IO, memory nằm riêng biệt. Các IO được truy xuất thông qua địa chỉ, mỗi IO chiếm một vùng nhớ có tầm từ C_BASEADDR - C_HIGHADDR. Các base add được cập nhật trong file system.mhs sau khi thực hiện thao tác Generate Address trong mục trình bày trên. Ta có thể tham khảo C_BASEADDR thông qua bước sau:
Trong XPS -> System Essembly View -> chọn IO -> click chuột phải -> Conigure IP ...
Và địa chỉ đầu tiên 0x77400000 được dùng cho việc truy xuất thanh ghi reg0 (Do phần creat custom hardware ta chọn option cho 1 thanh ghi, trong trường hợp tạo nhiều thanh ghi, ví dụ như reg0, reg1, reg2 thì địa chỉ truy xuất các thanh ghi này sẽ lần lượt là C_BASEADDR,C_BASEADDR+0x04,C_BASEADDR +0x08...)
Hàm LCD_PORT_mWriteSlaveReg0(LCD_PORT_BASE_ADDR, (value)) được định nghĩa sẵn bởi Xilinx, ghi giá trị "value" ra lcd_port.
7> Edit lcd.c
Công việc kế tiếp là soạn thảo code điểu khiển LCD, hầu hết các board FPGA đều thiết kế cho việc giao tiếp mode 4 bit. Trong phần thiết kế này dùng 1 port xuất để điểu khiển, lcd_port<6:0> <-> (E, RW,RS,D7,D6,D5,D4)
8> Edit main.c
Chương trình chạy thử hiển thị ký tự trên LCD.
Sau khi edit xong phần code
CTRL+S : Save file
CTRL+B : Build ( Hoặc click vào mục Build trên tool bar)
Phần trước giới thiệu xong phần import customer hadware, phần này giới thiệu về driver cho LCD.
Sau khi import lcd_port vào bus hệ thống, XPS tự động tạo ra thư viện hỗ trợ cho việc phát triển phần mềm. Ngoài ra các file hệ thống cũng được cập nhật.
file: system.mhs
Code:
BEGIN lcd_port PARAMETER INSTANCE = lcd_port_0 PARAMETER HW_VER = 1.00.a PARAMETER C_BASEADDR = 0x77400000 PARAMETER C_HIGHADDR = 0x7740ffff BUS_INTERFACE SOPB = mb_opb PORT lcd_port_pin = lcd_port_0_lcd_port_pin PORT OPB_Clk = sys_clk_s END
Code:
BEGIN DRIVER PARAMETER DRIVER_NAME = lcd_port PARAMETER DRIVER_VER = 1.00.a PARAMETER HW_INSTANCE = lcd_port_0 END
...drivers/lcd_port_v1_00_a/src/
/lcd_port.c
/lcd_port.h
/lcd_port_selftest.c
/Makefile
File lcd_port_selftest.c được tạo ra cho việc test thanh ghi reg0 (lcd_port), ta có thể tham khảo, sữa chữa tùy vào mục đích xử dụng.
Các prototype cho các hàm truy xuất thanh ghi được khai báo trong lcd_port.h
Sau đây là các bước tạo project mới dùng công cụ phát triển phần mềm SDK của xilinx.
1> Trên tool bar của XPS:
Chọn Software -> Lauch Platform Studio SDK
2> Trong hộp thoại Application Wizard:
Chọn Creat a New SDK Application Project -> Next
3> Trong mục New Project
Đặt tên project -> Next
Lấy thông số mặc định Xilinx MicroBlaze Executable -> Next
Finish thao tác create new project
Sau khi hoàn tất các bước trên xilinx tự động tạo các thư mục và các file trong thư mục có tên project name, và một danh sách các thư viện có liên quan đến microblaze.
4> Tạo Linker Script :
Trong mục Navigator, click chuột phải lcd_disp -> Gnenerate Linker Script...
Trong crop down list chọn DDRAM, dùng làm vùng nhớ data , text ....
6> Creat New Source file
Click vào biểu tượng C+ trên tool bar
Đặt tên file lcd.c
Để viết chương trình giao tiếp lcd, tức là dùng microblaze xuất tín hiệu điều khiển lên port_lcd, ngoài lcd_port còn có các ngoại vi khác. Microblaze là processor có cấu trúc tổ chức bộ nhớ Havard, Vùng Intruction và vùng IO, memory nằm riêng biệt. Các IO được truy xuất thông qua địa chỉ, mỗi IO chiếm một vùng nhớ có tầm từ C_BASEADDR - C_HIGHADDR. Các base add được cập nhật trong file system.mhs sau khi thực hiện thao tác Generate Address trong mục trình bày trên. Ta có thể tham khảo C_BASEADDR thông qua bước sau:
Trong XPS -> System Essembly View -> chọn IO -> click chuột phải -> Conigure IP ...
Và địa chỉ đầu tiên 0x77400000 được dùng cho việc truy xuất thanh ghi reg0 (Do phần creat custom hardware ta chọn option cho 1 thanh ghi, trong trường hợp tạo nhiều thanh ghi, ví dụ như reg0, reg1, reg2 thì địa chỉ truy xuất các thanh ghi này sẽ lần lượt là C_BASEADDR,C_BASEADDR+0x04,C_BASEADDR +0x08...)
Hàm LCD_PORT_mWriteSlaveReg0(LCD_PORT_BASE_ADDR, (value)) được định nghĩa sẵn bởi Xilinx, ghi giá trị "value" ra lcd_port.
7> Edit lcd.c
Công việc kế tiếp là soạn thảo code điểu khiển LCD, hầu hết các board FPGA đều thiết kế cho việc giao tiếp mode 4 bit. Trong phần thiết kế này dùng 1 port xuất để điểu khiển, lcd_port<6:0> <-> (E, RW,RS,D7,D6,D5,D4)
Code:
////////////////////////////////////////////////////////////////////////////// // Filename: lcd.c // Version: 1.00.a // Description: lcd_port Driver Source File // Date: 21/09/2007 ////////////////////////////////////////////////////////////////////////////// /***************************** Include Files *******************************/ #include "lcd_port.h" #include "string.h" /************************* Constant Definitions ****************************/ #define LCD_PORT_BASE_ADDR 0x77400000 /************************* Macro Definitions *******************************/ #define LCD_PORT_WRITE(value)\ LCD_PORT_mWriteSlaveReg0(LCD_PORT_BASE_ADDR, (value)) /************************************************************************** /* @Function name : wait_us() /* Description : wait n micro seconds /* Argument : unsigned int n /* Return value : void /* Author : Kamejoko80 /* Date : 21/09/2007 **************************************************************************/ void wait_us(unsigned int n) { unsigned int i,j; for(i=1;i<=n;i++) { for(j=1;j<=50;j++) { } } } /************************************************************************** /* @Function name : write_lcd_reg() /* Description : write lcd command /* Argument : char value /* Return value : void /* Author : Kamejoko80 /* Date : 21/09/2007 **************************************************************************/ void write_lcd_reg(char value) { char temp; temp = (value>>4)&0x0F; /* get nibble high */ LCD_PORT_WRITE(temp); /* write to lcd port */ wait_us(1); LCD_PORT_WRITE(temp|0x40); /* E=1 */ wait_us(1); LCD_PORT_WRITE(temp); /* E=0 */ wait_us(2); temp = value&0x0F; /* get nibble low */ LCD_PORT_WRITE(temp); /* write to lcd port */ wait_us(1); LCD_PORT_WRITE(temp|0x40); /* E=1 */ wait_us(1); LCD_PORT_WRITE(temp); /* E=0 */ wait_us(2); } /************************************************************************** /* @Function name : write_lcd_reg() /* Description : write lcd command /* Argument : char value /* Return value : void /* Author : Kamejoko80 /* Date : 21/09/2007 **************************************************************************/ void write_lcd_data(char value) { char temp; temp = (value>>4)&0x0F; /* get nibble high */ temp |= 0x10; /* RS=1 */ LCD_PORT_WRITE(temp); /* write to lcd port */ wait_us(2); LCD_PORT_WRITE(temp|0x40); /* E=1 */ wait_us(2); LCD_PORT_WRITE(temp); /* E=0 */ wait_us(4); temp = value&0x0F; /* get nibble low */ temp |= 0x10; /* RS=1 */ LCD_PORT_WRITE(temp); /* write to lcd port */ wait_us(2); LCD_PORT_WRITE(temp|0x40); /* E=1 */ wait_us(2); LCD_PORT_WRITE(temp); /* E=0 */ wait_us(40); } /************************************************************************** /* @Function name : lcd_mode_init() /* Description : 4 bit mode initialization /* Argument : void /* Return value : void /* Author : Kamejoko80 /* Date : 21/09/2007 **************************************************************************/ void lcd_mode_init(void) { wait_us(10000); /* waits 10ms */ write_lcd_reg(0x18); /* set 8 bit mode */ wait_us(5000); write_lcd_reg(0x18); /* set 8 bit mode */ wait_us(500); write_lcd_reg(0x18); /* set 8 bit mode */ wait_us(40); write_lcd_reg(0x08); /* set 4 bit mode */ wait_us(40); write_lcd_reg(0x28); /* set 2 lines */ wait_us(40); write_lcd_reg(0x08); /* display off */ wait_us(40); write_lcd_reg(0x01); /* clear display */ wait_us(2000); write_lcd_reg(0x06); /* entry mode */ wait_us(40); write_lcd_reg(0x0C); /* display on */ wait_us(10000); /* waits 10ms */ } /************************************************************************** /* @Function name : lcd_clr_disp() /* Description : clear display & cursor home /* Argument : void /* Return value : void /* Author : Kamejoko80 /* Date : 21/09/2007 **************************************************************************/ void lcd_clr_disp(void) { write_lcd_reg(0x01); /* clear lcd */ wait_us(2000); write_lcd_reg(0x02); /* cursor home */ wait_us(2000); } /************************************************************************** /* @Function name : lcd_line_feed() /* Description : goto 2th line /* Argument : void /* Return value : void /* Author : Kamejoko80 /* Date : 21/09/2007 **************************************************************************/ void lcd_line_feed() { write_lcd_reg(0x80|0x40); /* goto line 2 */ wait_us(40); } /************************************************************************** /* @Function name : lcd_print_str() /* Description : lcd print string /* Argument : char *s /* Return value : void /* Author : Kamejoko80 /* Date : 21/09/2007 **************************************************************************/ void lcd_print_str(char *s) { int i=0; while(i<strlen(s)) { write_lcd_data(s[i++]); } }
Chương trình chạy thử hiển thị ký tự trên LCD.
Code:
// Welcome to Xilinx Platform Studio SDK ! // // This is an automatically created source file to help you get started. // To add more files, navigate to File -> New -> File // You may delete this file if you want to use only other files for your project. // int main() { print("Enter main program \r\n"); lcd_mode_init(); lcd_print_str("ML403 LCD DEMO"); lcd_line_feed(); lcd_print_str("microblaze v5.00"); print("Exit main program \r\n"); return 0; }
Sau khi edit xong phần code
CTRL+S : Save file
CTRL+B : Build ( Hoặc click vào mục Build trên tool bar)
Comment