开始使用板子了,官网给了两个例程,一个是linux系统移植例程,还有一个是裸机定时器例程。ZedBoard板有张SD卡,里面包含5个文件如下图所示,为boot和linux根文件系统:
- Linux系统移植
SD卡只有编译好的文件,所以只能走下流程和看演示效果。板级连接如下图所示:
最重要的是JP7~JP115个跳针的选择,具体作用参考datasheet。之后UART的打印结果如下:
总共有7个Demo,都是在linux环境下的外设驱动开发。
- 裸机定时器例程
这是目前为止我们做开发的一张最有用的框图。PS可通过MIO或EMIO的形式配置管脚,PL通过AXI总线与A9核相连。本例程中的PL模块配置,中断配置,ChipScope模块以及PS的相应GPIO的配置都有详细的步骤。最后分别通过PL和PS的GPIO模块实现定时器计数的实现。
- 使用心得
测评的目标是实现音频信号分析仪,使用ZedBoard板已有几天了,各种纠结呀。先需要OLED屏点亮,本人是做硬件的,以前对软件基本都没写过,为了写OLED的驱动代码,各种网上参考、东拼西凑,终于把代码憋出来了。具体功能是通过PL的AXI转GPIO接口实现OLED需要的SPI接口。下板没得任何效果,这也算正常,程序员高手也不可能一次性成功。果断耐心细致的调试找错误。
首先考虑是GPIO配置的问题,将本来连在OLED的接口转至LED灯上,发现没得问题,SPI接口的传输速率也满足;之后考虑OLED的初始化的问题,毕竟初始化需对SSD1306芯片的寄存器进行各种配置,参考数据手册的寄存器配置,具体的配置如下:
OLED_WR_Byte(0xAE,OLED_CMD); //关闭显示
OLED_WR_Byte(0xD5,OLED_CMD); //设置时钟分频因子,震荡频率
OLED_WR_Byte(0x80,OLED_CMD); //[3:0],分频因子;[7:4],震荡频率
OLED_WR_Byte(0xA8,OLED_CMD); //设置驱动路数
OLED_WR_Byte(0X3F,OLED_CMD); //默认0X3F(1/64)
OLED_WR_Byte(0xD3,OLED_CMD); //设置显示偏移
OLED_WR_Byte(0X00,OLED_CMD); //默认为0
OLED_WR_Byte(0x40,OLED_CMD); //设置显示开始行[5:0],行数.
OLED_WR_Byte(0x8D,OLED_CMD); //电荷泵设置
OLED_WR_Byte(0x14,OLED_CMD); //bit2,开启/关闭,/********此处为内部DC/DC;0x10为外部电源********/
OLED_WR_Byte(0x20,OLED_CMD); //设置内存地址模式
OLED_WR_Byte(0x02,OLED_CMD); //[1:0],00,列地址模式;01,行地址模式;10,页地址模式;默认10;
OLED_WR_Byte(0xA1,OLED_CMD); //段重定义设置,bit0:0,0->0;1,0->127;
OLED_WR_Byte(0xC0,OLED_CMD); //设置COM 扫描方向;bit3:0,普通模式;1,重定义模式COM[N-1]->COM0;N:驱动路数
OLED_WR_Byte(0xDA,OLED_CMD); //设置COM 硬件引脚配置
OLED_WR_Byte(0x12,OLED_CMD); //[5:4]配置
OLED_WR_Byte(0x81,OLED_CMD); //对比度设置
OLED_WR_Byte(0xEF,OLED_CMD); //1~255;默认0X7F (亮度设置,越大越亮)
OLED_WR_Byte(0xD9,OLED_CMD); //设置预充电周期
OLED_WR_Byte(0xf1,OLED_CMD); //[3:0],PHASE 1;[7:4],PHASE 2;
OLED_WR_Byte(0xDB,OLED_CMD); //设置VCOMH 电压倍率
OLED_WR_Byte(0x30, OLED_CMD); //[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc;
OLED_WR_Byte(0xA4,OLED_CMD); //全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏)
OLED_WR_Byte(0xA6,OLED_CMD); //设置显示方式;bit0:1,反相显示;0,正常显示
OLED_WR_Byte(0xAF,OLED_CMD); //开启显示
print("Into OLED_Clear Begin\n\r");
OLED_Clear();
OLED_WR_Byte(0x8D,OLED_CMD)函数为SPI并串转换写命令,OLED_CMD为命令/数据指示(D/C#管脚),此处有个问题,OLED_WR_Byte(0xD5,OLED_CMD)中D5对应寄存器的地址,而OLED_WR_Byte(0x80,OLED_CMD)中80为寄存器的值,为什么两个都是命令字段,当时这部分纠结了好半天,最后的理解是这两个命令都是必须要给的,是SSD1306默认的配置方式而已。
GPIO和初始化都正常,但屏还是没有任何反应,软件该做的都做的,只有用示波器和万用表看管脚了。通过对比发现VDD和VBAT两个管脚的电压为2.7V左右(正常为3.3V),刚开始以为是正常范围内,但VCC输出却只有2.5V(正常7.5V)。输入电压控制只有这两个Pin控制,所以问题应该是处在VDD和VBAT输出。通过参考原理图发现,OLED_VDD是低有效。。。尼玛。。。datasheet不是高有效么,再重新查datasheet,Pin的配置如下:
里面的RES#代表的是低有效,VDD明明代表的是高有效的嘛,重新配置管脚,下板,屏亮了。顿时感觉。。。只想说写数据手册的哥哥姐姐,不要直接抄SSD1306上的管脚定义,然后加上FPGA的管脚名称就完事了,这让我们产生多大的误解。。。
屏点亮之后的字符虽然是乱码,但调试的结果可以判断是字符库的原因,之前是在网上找的16*8的字符库font.h,在此处不符,网上也找了很久没找到,实在是被之前的事郁闷到了,就果断自己编了几个想输出的字符库。下板结果如下:
- 总结
作为一个程序员菜鸟,使用ZedBoard板已有3天了,现在对于在软硬件设计都存在问题的情况下能做出来已经很欣慰了,但是作为力推的开发板,linux系统都移植上来的,为什么不能在我们得到的资料里没有其底层驱动呢,我们本身就是做相关实现的,连底层驱动都要自己写的话太花时间了,甚至PS的API函数都只能在SDK软件中看其功能,XGpioPs_LookupConfig函数在Google上搜索只有两个结果,全是我们的参考文档的参考代码,baidu直接就没有。所以我们现在只能用GPIO玩玩而已,而且板子下载容易出错,一般都是重启下板子就可以了,估计是下载的软件数据流和硬件配置有冲突吧。
对于初次使用后也存在很多疑问:为什么PS的GPIO方向配置为output时使用XGpioPs_SetDirectionPin函数写入1而PL的GPIO使用XGpio_SetDataDirection函数写入0;XPS内核配置的详细文档没有,只能一点点试出来;PS的GPIO寄存器如何读或写出1个以上Pin的值(可配置多个Pin方向,但用XGpioPs_ReadPin函数每次只能读出一个Pin的值,当然不是用这个函数,可找半天也没找到用那个函数)等等。
继续写代码了,之后是音频模块的声音信号读取,有了SPI的编写经验,I2C的接口实现难度不大,接下来将继续吐槽,哈哈。。。