概览
本次使用Altera公司的NIOS II软核。
使用Quatus工具生成BSP并利用BSP打包工具生成UCOSII嵌入环境。
手动书写LCD驱动与显示函数,对UCOS II加入简单图像显示接口。
./
├── create-this-app
├── driver #板子的具体驱动(非操作系统)
│ ├── init.h #初始化
│ ├── irs.h #中断处理
│ ├── lcd.h #LCD驱动
│ ├── sys.h #系统驱动
│ └── tools.h #工具
├── lib #显示库
│ ├── ansii_lib.h
│ ├── cn_lib.h
│ ├── color.h
│ └── values.h
├── Makefile
├── obj
│ └── default
│ ├── sys_kernel.d
│ └── sys_kernel.o
├── readme.txt
├── sys_kernel.c #系统的主函数
├── sys_user_interface.elf
├── sys_user_interface.map
├── sys_user_interface.objdump
└── tasks #任务文件夹
├── task1.h
└── task2.h
NIOS II软核生成
由于这次没有加载其余IP核,这次的软核非常简单,没有预留过多IP核PIO接口:
软核工程中包含以下内容:
- NIOS II processer
- 软核时钟信号
- 外部存储器接口
- SPI总线接口
- 一个控制LCD屏幕亮度的接口
- 一个软核版本控制器
若是有其余IP核需要加入,则需要单独的PIO进行交互,或者选择其余总线协议与IP核交互。
总线的速度非常慢,在软核中推荐使用可编程布线来进行交互。
具体软核IP核交互可以参考我的博客中的DES核与卷积核,这里不做过多描述。
FPGA工程概览
其中由于板载频率问题,加入了PLL
然后右边接了一个处理LCD的亮度的PWM模块也非常简单,不做过多描述。
UCOS II环境配置
由于这里使用的是Altera公司提供的NIOS II软核,其有完整的BSP与系统移植。
这里只需要根据选择软核生成对于此板子的BSP。
选择一个UCOS的系统工程即可。(还提供了其他的RTOS)
LCD 驱动书写
显示器驱动
LCD显示屏初始化
void LCD_init() { //************* Reset LCD Driver ****************// IOWR_ALTERA_AVALON_PIO_DATA(LCD_RESET_BASE, 1); delay_ms(200); IOWR_ALTERA_AVALON_PIO_DATA(LCD_RESET_BASE, 0); delay_ms(200); IOWR_ALTERA_AVALON_PIO_DATA(LCD_RESET_BASE, 1); delay_ms(10); //************* Start Initial Sequence **********// //剩余参数配置见源代码,这里不予展示 }
LCD初始化可以直接利用芯片厂商提供的代码,或者参考芯片资料中的参数配置自行完成。
LCD显示驱动
查阅
ILI9481
芯片手册,可以将发送一次指令和内容打包成Index
与cmd
两个函数。这两个函数内容如下:
void LCD_ILI9481_INDEX(unsigned int data) { IOWR_ALTERA_AVALON_PIO_DATA(LCD_RS_BASE, 1); IOWR_ALTERA_AVALON_PIO_DATA(LCD_WR_BASE, 0); IOWR_ALTERA_AVALON_PIO_DATA(LCD_DATA_BASE, data); IOWR_ALTERA_AVALON_PIO_DATA(LCD_WR_BASE, 1); } void LCD_ILI9481_CMD(unsigned int data) { IOWR_ALTERA_AVALON_PIO_DATA(LCD_RS_BASE, 0); IOWR_ALTERA_AVALON_PIO_DATA(LCD_WR_BASE, 0); IOWR_ALTERA_AVALON_PIO_DATA(LCD_DATA_BASE, data); IOWR_ALTERA_AVALON_PIO_DATA(LCD_WR_BASE, 1); }
发送一个指令的流程为先利用
cmd
函数发送指令,再用INDEX
函数发送指令内容。再将LCD显示一个像素的图像打包为
set_addr
和send_data
两个步骤,先通过set_addr
发送像素地址,再用send_data
发送像素颜色信息。send_addr
的时序可以通过查阅芯片手册来得知,其代码如下:void set_addr(unsigned int x, unsigned int y){ LCD_ILI9481_CMD(0x002b); LCD_ILI9481_INDEX(x >> 8); LCD_ILI9481_INDEX(x & 0x00ff); LCD_ILI9481_INDEX(0x0001); LCD_ILI9481_INDEX(0x00df); LCD_ILI9481_CMD(0x002a); LCD_ILI9481_INDEX(y >> 8); LCD_ILI9481_INDEX(y & 0x00ff); LCD_ILI9481_INDEX(0x0001); LCD_ILI9481_INDEX(0x003f); LCD_ILI9481_CMD(0x002c); }
同样,可以写出
send_data
如下:void send_data(unsigned int data) { IOWR_ALTERA_AVALON_PIO_DATA(LCD_RS_BASE, 1); IOWR_ALTERA_AVALON_PIO_DATA(LCD_WR_BASE, 0); IOWR_ALTERA_AVALON_PIO_DATA(LCD_DATA_BASE, data); IOWR_ALTERA_AVALON_PIO_DATA(LCD_WR_BASE, 1); }
LCD显示工具
ascii码显示工具(中文显示工具原理相同),利用
lcd_buffer
传参数,字母数据保存在word_libc
void display_ascii(unsigned int x, unsigned int y, unsigned int w_color, unsigned int b_color) { unsigned int i, j, k = 0; unsigned char str; unsigned int OffSet, z; while (1) { if (lcd_buffer[k] == 0) { set_addr(<