打印
[AT32F423]

【AT-START-F423测评】 + IO口模拟方式,测试SPI-OLED刷新速度

[复制链接]
1215|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 suncat0504 于 2023-11-7 18:07 编辑

#申请原创# @21小跑堂
本次使用SPI接口的OLED测试显示刷新速度。依旧使用128*64点阵的OLED,


接口定义:
这个OLED的时钟信号要求,SCK时钟最小支持到20ns,完全不用担心和这个开发板的匹配问题。

为了减少接口连接线,CS固定接地。使用4个GPIO口模拟SPI时钟、SPI数据、RESET、DC。感觉如果不是考虑到RESET和DC数据/指令选择,好像和IIC方式也没啥区别了。测试程序使用Work Bench进行重新设计。
使用定时器1溢出中断,用来实现1秒的计时。
使用GPIO的C0、C1、C2、C3模拟通讯口的SCK时钟、SDA(数据)、RESET(复位信号)、DC(数据、指令选择)。CS常态接地,就不用程序控制了。
为了方便观察,注册是刷新图像过程中,加入标试点的显示,以证明刷新在不断进行中。
以下是主程序处理代码:
/* add user code begin Header */
/**
  **************************************************************************
  * [url=home.php?mod=space&uid=288409]@file[/url]     main.c
  * [url=home.php?mod=space&uid=247401]@brief[/url]    main program
  **************************************************************************
  *                       Copyright notice & Disclaimer
  *
  * The software Board Support Package (BSP) that is made available to
  * download from Artery official website is the copyrighted work of Artery.
  * Artery authorizes customers to use, copy, and distribute the BSP
  * software and its related documentation for the purpose of design and
  * development in conjunction with Artery microcontrollers. Use of the
  * software is governed by this copyright notice and the following disclaimer.
  *
  * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
  * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
  * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
  * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
  * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
  *
  **************************************************************************
  */
/* add user code end Header */

/* Includes ------------------------------------------------------------------*/
#include "at32f423_wk_config.h"
#include "delay.h"
#include "spi_oled.h"
#include "bmp.h"

/* private includes ----------------------------------------------------------*/
/* add user code begin private includes */

/* add user code end private includes */

/* private typedef -----------------------------------------------------------*/
/* add user code begin private typedef */

/* add user code end private typedef */

/* private define ------------------------------------------------------------*/
/* add user code begin private define */

/* add user code end private define */

/* private macro -------------------------------------------------------------*/
/* add user code begin private macro */

/* add user code end private macro */

/* private variables ---------------------------------------------------------*/
/* add user code begin private variables */
uint32_t gi_us=0;           // 微秒计数
uint32_t gi_us_dao=0;       // 微秒倒计时
uint32_t gi_ms_dao=0;       // 微秒倒计时
uint8_t gi_1sflag=0;                // 1秒中断标志
/* add user code end private variables */

/* private function prototypes --------------------------------------------*/
/* add user code begin function prototypes */

/* add user code end function prototypes */

/* private user code ---------------------------------------------------------*/
/* add user code begin 0 */

/* add user code end 0 */


/**
  * [url=home.php?mod=space&uid=247401]@brief[/url]  take some delay for waiting power stable, delay is about 60ms with frequency 8MHz.
  * @param  none
  * @retval none
  */
static void wk_wait_for_power_stable(void)
{
  volatile uint32_t delay = 0;
  for(delay = 0; delay < 50000; delay++);
}

/**
  * [url=home.php?mod=space&uid=247401]@brief[/url] main function.
  * @param  none
  * @retval none
  */
int main(void) {
  /* add user code begin 1 */
  uint32_t cnt = 0, pos=0,dir=0;

  /* add user code end 1 */

  /* add a necessary delay to ensure that Vdd is higher than the operating
     voltage of battery powered domain (2.57V) when the battery powered
     domain is powered on for the first time and being operated. */
  wk_wait_for_power_stable();
  
  /* system clock config. */
  wk_system_clock_config();

  /* config periph clock. */
  wk_periph_clock_config();

  /* nvic config. */
  wk_nvic_config();

  /* init usart1 function. */
  wk_usart1_init();

  /* init gpio function. */
  wk_gpio_config();

  /* init tmr1 function. */
  wk_tmr1_init();

  /* init tmr2 function. */
  //wk_tmr2_init();

  /* add user code begin 2 */
  cnt=0;    // 清除计数次数变量
  SPI_OLED_Init();  // 初始化SPI OLED
  gi_1sflag=0;    // 清除1秒计数标志
  gi_us=0;        // 清除10微秒计数标志
  /* add user code end 2 */
  while(1) {
    /* add user code begin 3 */
          for (int i=0;i<128;i++) {
                  BMP[i]=0;
          }
          // 动态标识标试点,以证明刷新处理进行中
          BMP[pos] = 1;
          // 显示手的图案
          SPI_OLED_DrawBMP(0,0,128,64,BMP);
          cnt++;
          if (dir) {
                  // 反向移动标识点
                  pos--;
                  if (pos==0) {
                          dir=0;
                          pos=1;
                  }
          } else {
                  // 正向移动标识点
                  pos++;
                  if (pos==128) {
                          dir=1;
                          pos=126;
                  }
          }

          // 一秒时间到
          if (gi_1sflag>0) {
                  // 串口输出刷新次数
                  usart_data_transmit(USART1, '=');
                  while ((USART1->sts & 0x80)==0);
                  usart_data_transmit(USART1, (cnt/100)+48);
                  while ((USART1->sts & 0x80)==0);
                  usart_data_transmit(USART1, ((cnt%100)/10)+48);
                  while ((USART1->sts & 0x80)==0);
                  usart_data_transmit(USART1, (cnt%10)+48);
                  while ((USART1->sts & 0x80)==0);
                  usart_data_transmit(USART1, 10);
                  while ((USART1->sts & 0x80)==0);
                  usart_data_transmit(USART1, 13);
                  while ((USART1->sts & 0x80)==0);

                  // 清除中间记录信息和标志
          cnt=0;
                  gi_1sflag = 0;
                  gi_us=0;

          }
    /* add user code end 3 */
  }
}
定时器处理的代码:
void TMR1_OVF_TMR10_IRQHandler(void)
{
  /* add user code begin TMR1_OVF_TMR10_IRQ 0 */
         if(tmr_flag_get(TMR1, TMR_OVF_FLAG) == SET) {
                 gpio_bits_toggle(LED2_GPIO_PORT, LED2_PIN);

                 if (gi_us_dao>0) {
                         gi_us_dao--;
                 }
                 if (gi_ms_dao>0) {
                          gi_ms_dao--;
                 }

                 gi_us++;
                 //gpio_bits_toggle(LED2_GPIO_PORT, LED2_PIN);
                 if (gi_us == 100000) {
                         // 1秒
                         gi_1sflag = 1;
                         gi_us = 0;
                         gpio_bits_toggle(LED4_GPIO_PORT, LED4_PIN);
                 }
                 if (gi_us == 50000) {
                         // 0.5秒
                         gpio_bits_toggle(LED3_GPIO_PORT, LED3_PIN);
                 }

            // 清除溢出标志
            tmr_flag_clear(TMR1, TMR_OVF_FLAG);
        }

实测刷新能力为每秒111帧。这里面如果去掉标试点的处理部分,可以提高到112帧。刷新一页图片的时间在9ms以下。可以看到刷新速度比IIC方式快了近一倍。

以下是OLED上的测试结果:



附上工程: SPIOLED.zip (6.12 MB)



使用特权

评论回复
沙发
claretttt| | 2023-12-3 22:49 | 只看该作者
可以通过计时器或者其他方式来测量每次刷新所需的时间。这个时间就是OLED的刷新速度。

使用特权

评论回复
板凳
51xlf| | 2023-12-4 10:20 | 只看该作者
SPI速度相较于IIC会快上一些,硬件IIC相较于模拟IIC速度又会快上一些。

使用特权

评论回复
地板
geraldbetty| | 2023-12-4 15:28 | 只看该作者
配置IO口模拟SPI通信              

使用特权

评论回复
5
suncat0504|  楼主 | 2023-12-5 08:46 | 只看该作者
51xlf 发表于 2023-12-4 10:20
SPI速度相较于IIC会快上一些,硬件IIC相较于模拟IIC速度又会快上一些。

做过IIC硬件外设的通讯处理,感觉挺麻烦的。需要判断中间状态。还是觉得软件模拟来得方便一些。

使用特权

评论回复
6
houjiakai| | 2023-12-5 11:58 | 只看该作者
在程序中设置正确的SPI模式,以确保数据的正确传输和接收。

使用特权

评论回复
7
i1mcu| | 2023-12-5 13:37 | 只看该作者
使用合适的SPI缓冲器,以避免出现数据包丢失或错误的情况。

使用特权

评论回复
8
eefas| | 2023-12-5 14:40 | 只看该作者
可以通过计算每秒刷新的次数来得到OLED的刷新频率

使用特权

评论回复
9
xiaoyaodz| | 2023-12-5 16:53 | 只看该作者
减少不必要的延时和等待时间,避免在刷新过程中执行其他任务等。

使用特权

评论回复
10
macpherson| | 2023-12-5 18:46 | 只看该作者
在模拟SPI接口时,可能会产生噪声和干扰,需要注意如何消除这些噪声和干扰

使用特权

评论回复
11
houjiakai| | 2023-12-5 20:11 | 只看该作者
通常需要通过SPI接口发送一组特定的命令来完成。

使用特权

评论回复
12
suncat0504|  楼主 | 2023-12-6 08:40 | 只看该作者
macpherson 发表于 2023-12-5 18:46
在模拟SPI接口时,可能会产生噪声和干扰,需要注意如何消除这些噪声和干扰 ...

谢谢提醒

使用特权

评论回复
13
suncat0504|  楼主 | 2023-12-6 08:41 | 只看该作者
houjiakai 发表于 2023-12-5 20:11
通常需要通过SPI接口发送一组特定的命令来完成。

是,相比IIC操作,SPI还是要好很多

使用特权

评论回复
14
suncat0504|  楼主 | 2023-12-6 08:42 | 只看该作者
xiaoyaodz 发表于 2023-12-5 16:53
减少不必要的延时和等待时间,避免在刷新过程中执行其他任务等。

其实使用DMA方式传输SPI数据,更方便。也无需分担中央处理器的时间片

使用特权

评论回复
15
jonas222| | 2023-12-6 15:48 | 只看该作者
测试SPI-OLED刷新速度需要注意以上几个方面。只有正确设置和调整参数,才能确保测试结果的准确性和可靠性。

使用特权

评论回复
16
suncat0504|  楼主 | 2023-12-7 00:44 | 只看该作者
jonas222 发表于 2023-12-6 15:48
测试SPI-OLED刷新速度需要注意以上几个方面。只有正确设置和调整参数,才能确保测试结果的准确性和可靠性。 ...

谢谢大佬提醒。有时间需要在这方面下下功夫。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:大连伊飞特信息技术有限公司软件工程师
简介:本人于1993年毕业于大连理工大学。毕业后从事单片机开发工作5年,之后转入软件开发工作至今。

88

主题

2422

帖子

5

粉丝