找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 8919|回复: 5
打印 上一主题 下一主题
收起左侧

STC15系列单片机利用硬件SPI可以提高显示速度一倍

[复制链接]
跳转到指定楼层
楼主
ID:328014 发表于 2018-8-9 03:28 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
买了1块SPI接口的OLED屏。
商家提供的51下的驱动代码是软件模拟SPI的方式实现的。
虽然速度上基本上可以达到应用的要求了,但是出于实验的目的,周末研究了一下15系列硬件SPI,改写了一下驱动,并且比较了利用软硬两种SPI之间的差距。发现利用硬件SPI至少可以提高显示速度50%以上的效率。

看来以后在条件允许的情况下,多利用硬件SPI对程序的执行效率的提高是很有帮助的。

具体思路如下:
1.改写驱动代码
将往OLED屏写入字节的函数改为硬件SPI方式写入。
用_HARD_SPI_宏来切换软硬SPI接口
  1.     #ifdef    _HARD_SPI_
  2.     void OLED_WR_Byte(u8 dat, u8 cmd)
  3.     {
  4.         if(cmd)
  5.             OLED_DC_Set();
  6.         else
  7.             OLED_DC_Clr();
  8.         SPDAT = dat;
  9.         while(!(SPSTAT&SPIF));
  10.         SPSTAT = SPIF | WCOL;
  11.         OLED_DC_Set();        
  12.     }
  13.     #else
  14.     void OLED_WR_Byte(u8 dat,u8 cmd)
  15.     {
  16.         u8 i;
  17.         if(cmd)
  18.             OLED_DC_Set();
  19.         else
  20.             OLED_DC_Clr();
  21.         OLED_CS_Clr();
  22.         for(i=0;i<8;i++)
  23.         {              
  24.             OLED_SCLK_Clr();
  25.             if(dat&0x80)
  26.             {
  27.                 OLED_SDIN_Set();
  28.             }
  29.             else
  30.             {
  31.                 OLED_SDIN_Clr();
  32.             }
  33.             OLED_SCLK_Set();
  34.             dat<<=1;  
  35.         }
  36.         OLED_CS_Set();
  37.         OLED_DC_Set();        
  38.     }
  39.     #endif
复制代码
2.在main函数中对显示函数调用10000次
在循环调用前清除计数器并打开定时中断(定时器设定为1ms,晶振主频为30M)
定时中断负责计数。
10000次显示结束后输出定时中断计数器的值。
以下是main.c
  1.     #include "STC15W4Kxxs4.h"
  2.     #include "__c_param__.h"
  3.     #include "display.h"
  4.     #include "resource.h"
  5.     unsigned long ulCount = 0;
  6.     void timer0_int (void) interrupt 1
  7.     {
  8.        ulCount++;
  9.     }
  10.     void Timer0Init(void)        //1毫秒@30.000MHz
  11.     {
  12.         AUXR |= 0x80;        //定时器时钟1T模式
  13.         TMOD &= 0xF0;        //设置定时器模式
  14.         TL0 = 0xD0;        //设置定时初值
  15.         TH0 = 0x8A;        //设置定时初值
  16.         TF0 = 0;        //清除TF0标志
  17.         TR0 = 1;        //定时器0开始计时
  18.     }
  19.     void main()
  20.     {
  21.         int    i;
  22.         unsigned char    col,row;
  23.         
  24.         Timer0Init();
  25.         
  26.         initial_lcd();
  27.         
  28.         clear_screen();
  29.         display_graphic_Nx8M(1,1, dabai, 0, 128, 8);
  30.         ulCount = 0;
  31.         EA = 1;
  32.         ET0 = 1;                 //Timer0中断允许
  33.         //显示10000次 17*32大小的数字
  34.         for(i = 0; i < 10000; i++)
  35.         {
  36.             display_graphic_Nx8M((i%2)*FONT_LARGE_H+1,1, font17x32, i % FONT_LARGE_C, FONT_LARGE_W, FONT_LARGE_H);
  37.     //        display_graphic_Nx8M(1,1, dabai, 0, 128, 8);
  38.     //        display_graphic_Nx8M((i%8),1,font7x8, i % FONT_SMALL_C, FONT_SMALL_W, FONT_SMALL_H);
  39.         }
  40.         ET0 = 0;                 //Timer0中断允许
  41.         EA = 0;
  42.         
  43.         clear_screen();
  44.         col = 1;
  45.         row = 4;
  46.         display_graphic_Nx8M(row,col, font11x24, (ulCount / 1000000) % 10, FONT_BIG_W, FONT_BIG_H);
  47.         col += FONT_BIG_W;
  48.         display_graphic_Nx8M(row,col, font11x24, (ulCount / 100000) % 10, FONT_BIG_W, FONT_BIG_H);
  49.         col += FONT_BIG_W;
  50.         display_graphic_Nx8M(row,col, font11x24, (ulCount / 10000) % 10, FONT_BIG_W, FONT_BIG_H);
  51.         col += FONT_BIG_W;
  52.         display_graphic_Nx8M(row,col, font11x24, (ulCount / 1000) % 10, FONT_BIG_W, FONT_BIG_H);
  53.         col += FONT_BIG_W;
  54.         display_graphic_Nx8M(row,col, font11x24, (ulCount / 100) % 10, FONT_BIG_W, FONT_BIG_H);
  55.         col += FONT_BIG_W;
  56.         display_graphic_Nx8M(row,col, font11x24, (ulCount / 10) % 10, FONT_BIG_W, FONT_BIG_H);
  57.         col += FONT_BIG_W;
  58.         display_graphic_Nx8M(row,col, font11x24, (ulCount) % 10, FONT_BIG_W, FONT_BIG_H);
  59.         
  60.         while(1);
  61.     }
复制代码
最后结果:
显示17x32大小数字时       硬件SPI:3605ms          软件SPI:8030ms         提高:56.3%
显示128x64大小的图像     硬件SPI:22458ms        软件SPI:51544ms       提高:56.4%
显示7x8大小的数字           硬件SPI:597ms            软件SPI:1156ms         提高:48.4%

对比测试的视频


弹来弹去的时间显示。



评分

参与人数 1黑币 +10 收起 理由
NPC-1024 + 10 很给力!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:371423 发表于 2018-8-15 10:57 | 只看该作者
有机会我也要学习一下硬件控制器
回复

使用道具 举报

板凳
ID:223707 发表于 2019-2-21 14:51 | 只看该作者
TFT_KMRTM24024: 2.4寸TFT触摸屏,4线SPI,
刷屏6次,软件SPI:7032ms, 硬件SPI:1920ms
差别很大
回复

使用道具 举报

地板
ID:419072 发表于 2019-6-6 17:30 | 只看该作者
正在学习硬件spi,和cs5530通信程序。
回复

使用道具 举报

5#
ID:292359 发表于 2019-12-2 11:52 | 只看该作者
最近无聊正在研究一块OLED小屏
回复

使用道具 举报

6#
ID:655943 发表于 2020-4-16 21:09 | 只看该作者
请教,带字库的TFT或OLCD有两处片选,但共用其它三个脚,怎么设置??
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表