完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
一、SPI简介
SPI( Serial Peripheral Interface-串行外设接口)总线系统是一种同步串行外设接口,它可以使MCU与各种外围设备以串行方式进行通信以交换信息。SPI有三个寄存器分别为: 控制寄存器SPCR,状态寄存器SPSR,数据寄存器SPDR。外围设备包括 FLASHRAN、网络控制器、LCD显示驱动器、A/D转换器和MCU等。SPI总线系统可直接与各个厂家生产的多种标准外围器件直接接口,该接口一般使用4条线:串行时钟线(SCLK)、主机输入/从机输出数据线MISO、主机输出/从机输入数据线MOS和低电平有效的从机选择线NSS(有的SP接口芯片带有中断信号线NT、有的SPI接口芯片没有主机输出/从机输入数据线MOSI)。 接口信号
上升沿、下降沿、前沿、后沿触发。还有MSB和LSB传输方式 二、资料获取 店铺资料有卖的,下载相应的资料,选择自己喜欢的OLED,即可,这里我做的就是0.96寸SPI 7针和0.96寸SPI4针。 三、SPI接口实验 1)准备工作 step0:打开工程文件 这个是我已经做好的。 setp1:查看工程下的文件(1) 这两个文件对应的是对应的SPI相关的操作实现与OLED的读入写入函数。 spi.c中定义了下列函数 这三个函数分别用于写入函数、初始化函数、与设置SPI速率 而oled.c函数中包含了如下控制函数 比较重要的就有OLED_WR_Byte、OLED_Set_Pixel函数。其中前者定义如下 经过SPI_WriteByte函数往SPI函数里写东西。 setp2:查看工程下的文件(2) 在USER文件夹下,gui.c函数给出了厂家已经定义好的一些现实函数,包括了显示不同大小的函数,显示字符串、汉字、字符的函数。而在test.c里则是写了一些测试的函数test.c的测试函数不用理会。我们可以在里面加入我们自己的函数,通过调用gui.c里的函数,或者直接操作OLED来实现我们的功能。 step3:生成中文点阵字模,与修改oledfont.c 在正式做之前,必须的一步就是生成字模 在OLED上如果要显示汉字,就必须生成字模,OLED显示的汉字大多都属于点阵汉字,需要按照需求生成字模,调用指针才行,同样,店铺资料可以下载取模软件,在字符取模里选择PCtoLCD2002.exe文件,根据要求设置相应的选项,输入汉字,即可得到想要的文字 操作界面如下: 然后打开oledfont.c文件,这里因为要显示16*16的大小,生成字模就是宋体、16乘16、逐行式、顺向,对应选择相应的选项: 这里有必要介绍一下,例程里的字模库,例程里的字模库通过定义结构体,为字模创建好索引 typedef struct { unsigned char Index[2]; char Msk[32]; }typFNT_GB16; 再通过font函数里,字模库字模个数,循环查找一一对比,找到即返回,这样做就使得调用时可以直接传递想要显示的汉字,(前提是把需要的汉字全都取了字模,加进去)。 num = sizeof(cfont16)/sizeof(typFNT_GB16); for(i=0;i if((cfont16.Index[0]==*s)&&(cfont16.Index[1]==*(s+1))) 这里我在大小为16的数组里加,因为考虑尽量显示多的内容,就用小号字 这样,就做好了,就可以编写函数了。 2)显示学号姓名 定义show_my_num函数,这里直接根据GUI函数里的show_string函数来写,需要留意,OLED的屏幕为每页8行,每行128个像素点 gui.c中的GUI_ShowString与GUI_ShowCHinese的前两行参数分别为横纵坐标的值,GUI_ShowString的第三个参数和GUI_ShowCHinese的第第四个参数分别是显示内容,最后一个参数为颜色,1白,0黑。而剩下的一个参数对应大小,调用不同font函数。最后代码如下。 /*显示学号代码*/ void show_my_num(void) { //GUI_Fill(0,0,WIDTH-1,HEIGHT/2-1,0); GUI_ShowString(15,0,"631807030509",16,1);//显示学号 } /*显示姓名*/ void show_my_name(void) { GUI_ShowCHinese(45,16,16,"李卓",1); } 然后在test.h文件里面做出声明,就可以了。 3)显示温湿度 接着上篇的工程,将相应的文件拷入,添加进去,得到如下: 在test.c下构造如下函数,参数为传递的温湿度。 void show_tem(int c1,int t1) { GUI_ShowString(8,32,"Hem: ",16,1); GUI_ShowNum(48,32,c1,2,16,1); GUI_ShowString(64,32,"%",16,1); GUI_ShowString(8,48,"Tem: ",16,1); GUI_ShowNum(48,48,t1,2,16,1); GUI_ShowCHinese(64,48,16,"℃",1); } 加入声明。 在主函数中计算温度并传递给此函数。具体温度采集可以参考上一篇博客。 4)滚动显示 滚动字现实,我用了两种方法,第一种是直接控制硬件刷新效果,第二种就是通过调用函数算法实现。 1、直接控制硬件刷新效果 原理:左右滚动滑动的实现,是使用单独的1KB内存,去处理图片拼接后的图像。而由于刷屏方式比较特殊,左右拼接的方式就是内存移位,而且是Byte与Byte间的移位,这就更方便了。 一般有如下滚动方式: 0x2F:激活滚动 0x2E:关闭滚动 0x26:水平滚动右向 0x27:水平滚动左向 0x29:水平和垂直滚动右向 0x2A:水平和垂直滚动左向 0xA3:垂直滚动 因为函数中已经有如下函数定义,当然也可以直接写SPI_WriteByte(SPI2,dat) 在test.c定义如下函数并声明: //硬件滚动 void roll(void) { OLED_WR_Byte(0x2F, OLED_CMD); OLED_WR_Byte(0x27, OLED_CMD); OLED_WR_Byte(0x00,OLED_CMD); OLED_WR_Byte(0x00,OLED_CMD); OLED_WR_Byte(0x07,OLED_CMD); OLED_WR_Byte(0x2E,OLED_CMD); while(1); } 这样就能实现滚动了。 这种滚动方式更为平滑,实现也相对简单。目前多采用这种方法。 2、通过编程实现改变坐标来实现滚动 可能刚上手之后不知道有第一种方法,直接想到的就是坐标来实现滚动,这种方法也是可行的。我通过操作GUI_ShowFont16(u8 x,u8 y,u8 *s,u8 mode)来实现了这种方法。但是相对来说就没那么流畅了。 具体代码如下: void Roll_display(void) { int i,j; for(j=0;j<=1;j++) for(i=120;i>=-176;i-=8) { if(i<120&&i>0) GUI_ShowFont16(i,22,"信",1); if(i+16<120&&i+16>0) GUI_ShowFont16(i+16,22,"息",1); if(i+32<120&&i+32>0) GUI_ShowFont16(i+32,22,"科",1); if(i+48<120&&i+48>0) GUI_ShowFont16(i+48,22,"学",1); if(i+64<120&&i+64>0) GUI_ShowFont16(i+64,22,"与",1); if(i+80<120&&i+80>0) GUI_ShowFont16(i+80,22,"工",1); if(i+96<120&&i+96>0) GUI_ShowFont16(i+96,22,"程",1); if(i+112<120&&i+112>0) GUI_ShowFont16(i+112,22,"学",1); if(i+128<120&&i+128>0) GUI_ShowFont16(i+128,22,"院",1); if(i+144<120&&i+144>0) GUI_ShowFont16(i+144,22,"通",1); if(i+160<120&&i+160>0) GUI_ShowFont16(i+160,22,"信",1); if(i+176<120&&i+176>0) GUI_ShowFont16(i+176,22,"工",1); if(i+192<120&&i+192>0) GUI_ShowFont16(i+192,22,"程",1); delay_ms(200); OLED_Clear(0); //清屏 } } 5)主函数 显示姓名、学号、温湿度切屏显示滚动效果 硬件就注释Roll_display();加入roll()即可 #include "delay.h" #include "sys.h" #include "oled.h" #include "gui.h" #include "test.h" #include "24cxx.h" #include "AHT20.h" struct m_AHT20 AHT20; int main(void) { int c1,t1; delay_init(); //延时函数初始化 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级 IIC_Init(); //IIC初始化 AHT20.alive=!AHT20_Init(); //AHT20初始化 OLED_Init(); //初始化OLED OLED_Clear(0); //清屏(全黑) while(1) { show_my_num(); //显示学号 show_my_name();//显示姓名 /*读取测量温湿度数据*/ if(AHT20.alive)//是否存活 { //读取其原始数据 AHT20.flag = AHT20_ReadHT(AHT20.HT); c1 = AHT20.HT[0]*100*10/1024/1024/10; //湿度 t1 = (AHT20.HT[1]*200*10/1024/1024-500)/10;//温度计算公式 } show_tem(c1,t1);//显示温湿度 delay_ms(9000);//延时切屏 delay_ms(9000);//延时切屏 OLED_Clear(0); //清屏 Roll_display();//滚动显示 delay_ms(100); } } 6)接线及演示效果(软硬件) 按照提示接线: 三、附加:IIC接口实验 区别: IIC介绍,前面博客有提到过,这里不再说了 IIC其实同SPI的实验步骤一样,但是不同的就是字模不再有索引了,定义二维数组,根据顺序读出值。同样倒入字模如下: 根据数组标号进行索引 OLED_Clear(); OLED_ShowCHinese(18,0,0);//通 OLED_ShowCHinese(36,0,1);//信 OLED_ShowCHinese(54,0,2);//工 OLED_ShowCHinese(72,0,3);//程 接口: 最终显示(这里没有加温度采集,故没有给与显示) 四、总结 分别做了SPI与IIC的OLED显示实验,实现了显示姓名、学号、滚动等。熟悉了取字模显示中文,等。对SPI写入等有了更好的认识。收获很大,也十分有趣。 |
|
|
|
只有小组成员才能发言,加入小组>>
3278 浏览 9 评论
2955 浏览 16 评论
3455 浏览 1 评论
8987 浏览 16 评论
4050 浏览 18 评论
1102浏览 3评论
570浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
568浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2301浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1857浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 10:06 , Processed in 1.285365 second(s), Total 81, Slave 61 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号