HC32F460 SPI DMA 驱动 TFT显示屏

  • 前言
  • 一、驱动代码
  • 二、测试代码
  • 三、实测效果

前言

嵌入式系统里面,人机界面显示屏这块,不管CPU还是RAM,基本都是很耗资源的,所以在驱动这块,尽量选择DMA去驱动。

这次板子用的性价比很高的SPI接口TFT屏,320*240分辨率,565(16BIT)色深

显示屏下指令使用SPI POLLING模式,因为数据量少,用DMA反而不划算,显示屏送图形使用DMA,图片数据长度3202402 = 153600字节

一、驱动代码

#include "board.h"#define LCDCODE_REGFLAG_DELAY       0xFFFE
#define LCDCODE_REGFLAG_END         0xFFFF
#define LCDCODE_DATA_LEN            32typedef struct
{uint16_t reg;uint16_t len;uint8_t  dat[LCDCODE_DATA_LEN];
}lcd_code_t;static struct rt_semaphore spi3_tx_wait = {0x00};static void spi3_tx_dma_tc0_irq_cb(void)
{DMA_ClearIrqFlag(SPI3_DMA_UNIT, SPI3_DMA_TX_CHANNEL, TrnCpltIrq);rt_sem_release(&spi3_tx_wait);
}static void spi3_dma_config(void)
{stc_dma_config_t stcDmaCfg;stc_irq_regi_conf_t stcIrqRegiConf;/* configuration structure initialization */MEM_ZERO_STRUCT(stcDmaCfg);/* Configuration peripheral clock */PWC_Fcg0PeriphClockCmd(SPI3_DMA_CLOCK_UNIT, Enable);PWC_Fcg0PeriphClockCmd(PWC_FCG0_PERIPH_AOS, Enable);/* Configure TX DMA */stcDmaCfg.u16BlockSize           = 1;stcDmaCfg.u16TransferCnt         = 1;stcDmaCfg.u32SrcAddr             = (uint32_t)(0);stcDmaCfg.u32DesAddr             = (uint32_t)(&SPI3_UNIT->DR);stcDmaCfg.stcDmaChCfg.enSrcInc   = AddressIncrease;stcDmaCfg.stcDmaChCfg.enDesInc   = AddressFix;stcDmaCfg.stcDmaChCfg.enTrnWidth = Dma8Bit;stcDmaCfg.stcDmaChCfg.enIntEn    = Enable;DMA_InitChannel(SPI3_DMA_UNIT, SPI3_DMA_TX_CHANNEL, &stcDmaCfg);DMA_SetTriggerSrc(SPI3_DMA_UNIT, SPI3_DMA_TX_CHANNEL, SPI3_DMA_TX_TRIG_SOURCE);/* Enable DMA. */DMA_Cmd(SPI3_DMA_UNIT, Enable);/* Set DMA block transfer complete IRQ */stcIrqRegiConf.enIRQn      = IRQ_SPI3_DMA_TX;stcIrqRegiConf.pfnCallback = &spi3_tx_dma_tc0_irq_cb;stcIrqRegiConf.enIntSrc    = INT_DMA1_TC0;enIrqRegistration(&stcIrqRegiConf);NVIC_SetPriority(stcIrqRegiConf.enIRQn, IRQ_PRIORITY_SPI3_DMA_TX);NVIC_ClearPendingIRQ(stcIrqRegiConf.enIRQn);NVIC_EnableIRQ(stcIrqRegiConf.enIRQn);
}static void bsp_spi3_init(void)
{stc_spi_init_t stcSpiInit;/* configuration structure initialization */MEM_ZERO_STRUCT(stcSpiInit);/* Configuration peripheral clock */PWC_Fcg1PeriphClockCmd(SPI3_UNIT_CLOCK, Enable);/* Configuration peripheral clock */PWC_Fcg1PeriphClockCmd(SPI3_UNIT_CLOCK, Enable);/* Configuration SPI structure */stcSpiInit.enClkDiv                 = SpiClkDiv2;stcSpiInit.enFrameNumber            = SpiFrameNumber1;stcSpiInit.enDataLength             = SpiDataLengthBit8;stcSpiInit.enFirstBitPosition       = SpiFirstBitPositionMSB;stcSpiInit.enSckPolarity            = SpiSckIdleLevelLow;stcSpiInit.enSckPhase               = SpiSckOddSampleEvenChange;stcSpiInit.enReadBufferObject       = SpiReadReceiverBuffer;stcSpiInit.enWorkMode               = SpiWorkMode3Line;stcSpiInit.enTransMode              = SpiTransOnlySend;stcSpiInit.enCommAutoSuspendEn      = Disable;stcSpiInit.enModeFaultErrorDetectEn = Disable;stcSpiInit.enParitySelfDetectEn     = Disable;stcSpiInit.enParityEn               = Disable;stcSpiInit.enParity                 = SpiParityEven;stcSpiInit.enMasterSlaveMode = SpiModeMaster;stcSpiInit.stcDelayConfig.enSsSetupDelayOption   = SpiSsSetupDelayCustomValue;stcSpiInit.stcDelayConfig.enSsSetupDelayTime     = SpiSsSetupDelaySck1;stcSpiInit.stcDelayConfig.enSsHoldDelayOption    = SpiSsHoldDelayCustomValue;stcSpiInit.stcDelayConfig.enSsHoldDelayTime      = SpiSsHoldDelaySck1;stcSpiInit.stcDelayConfig.enSsIntervalTimeOption = SpiSsIntervalCustomValue;stcSpiInit.stcDelayConfig.enSsIntervalTime       = SpiSsIntervalSck1PlusPck2;SPI_Init(SPI3_UNIT, &stcSpiInit);spi3_dma_config();rt_sem_init(&spi3_tx_wait, "spi3tx", 0, RT_IPC_FLAG_FIFO);
}static void lcd_spi_send(uint8_t dat)
{ SPI_Cmd(SPI3_UNIT, Enable);  while (Reset == SPI_GetFlag(SPI3_UNIT, SpiFlagSendBufferEmpty)){;}SPI_SendData8(SPI3_UNIT, dat);while (Reset == SPI_GetFlag(SPI3_UNIT, SpiFlagSpiIdle)){;}SPI_Cmd(SPI3_UNIT, Disable);
}static void lcd_spi_trans(uint8_t *dat, uint16_t len)
{DMA_SetSrcAddress (SPI3_DMA_UNIT, SPI3_DMA_TX_CHANNEL, (uint32_t)dat);DMA_SetTransferCnt(SPI3_DMA_UNIT, SPI3_DMA_TX_CHANNEL, len);LCD_A0_H;LCD_CS_L;/* Enable DMA channel */DMA_ChannelCmd(SPI3_DMA_UNIT, SPI3_DMA_TX_CHANNEL, Enable);/* Enable SPI to start DMA */SPI_Cmd(SPI3_UNIT, Enable);   rt_sem_take(&spi3_tx_wait, RT_WAITING_FOREVER);LCD_CS_H;/* Disable SPI */SPI_Cmd(SPI3_UNIT, Disable);DMA_ChannelCmd(SPI3_DMA_UNIT, SPI3_DMA_TX_CHANNEL, Disable);
}static void delayms(uint16_t ms)
{rt_thread_delay(ms);
}static void write_codetable(lcd_code_t *code, uint32_t count)
{lcd_code_t *pcode = code;//传输指令和参数for (uint32_t i = 0; i < count; i++){   if (pcode->reg == LCDCODE_REGFLAG_END){                                   //结束跳出break;}else if (pcode->reg == LCDCODE_REGFLAG_DELAY){                                   //延时MSdelayms(pcode->len);}else{                                   //常规发送指令LCD_A0_L;LCD_CS_L;lcd_spi_send(pcode->reg);for (uint32_t j = 0; j < pcode->len; j++){LCD_A0_H;lcd_spi_send(pcode->dat[j]);}LCD_CS_H;}pcode++;                            //下一个寄存器}
}//初始化指令表
static lcd_code_t st7789v_initcode[] = {
{0x11,  0, {0x00} },
{LCDCODE_REGFLAG_DELAY, 120, {0x00}},
{0xb2,  5, {0x0c, 0x0c, 0x00, 0x33, 0x33} },
{0xb7,  1, {0x35} },
{0xbb,  1, {0x35} },
{0xc0,  1, {0x2c} },
{0xc2,  1, {0x01} },
{0xc3,  1, {0x0b} },
{0xc4,  1, {0x20} },
{0xc6,  1, {0x0f} },
{0xd0,  2, {0xa4, 0xa1} },
{0xe0, 14, {0xd0, 0x00, 0x02, 0x07, 0x0b, 0x1a, 0x32, 0x54, 0x40, 0x29, 0x12, 0x12, 0x12, 0x17} },
{0xe1, 14, {0xd0, 0x00, 0x02, 0x07, 0x05, 0x25, 0x2d, 0x44, 0x45, 0x1c, 0x18, 0x16, 0x1c, 0x1d} },
{0x36,  1, {0x00} },
{0x3a,  1, {0x05} },
{0x21,  0, {0x00} },
{0x29,  0, {0x00} },
{LCDCODE_REGFLAG_END, 0x00, {0x00} }
};/*显示区域设置*/
static lcd_code_t st7789v_blockcode[] = {
{0x2a,  4, {0x00, 0x00, 0x00, 0x00} },
{0x2b,  4, {0x00, 0x00, 0x00, 0x00} },
{0x2c,  0, {0x00} },
{LCDCODE_REGFLAG_END, 0x00, {0x00} }
};static void write_block(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1)
{st7789v_blockcode[0].dat[0] = 0x00;st7789v_blockcode[0].dat[1] = x0;st7789v_blockcode[0].dat[2] = 0x00;st7789v_blockcode[0].dat[3] = x1;st7789v_blockcode[1].dat[0] = y0 >> 8;st7789v_blockcode[1].dat[1] = y0 & 0xff;st7789v_blockcode[1].dat[2] = y1 >> 8;st7789v_blockcode[1].dat[3] = y1 & 0xff;write_codetable(st7789v_blockcode, 3);
}void st7789v_init(void)
{stc_port_init_t stcPortInit;MEM_ZERO_STRUCT(stcPortInit);PWC_Fcg1PeriphClockCmd(SPI3_UNIT_CLOCK, Enable);/* Configuration SPI pin */PORT_SetFunc(SPI3_NSS_PORT, SPI3_NSS_PIN, Func_Gpio,     Disable);    PORT_SetFunc(SPI3_SCK_PORT, SPI3_SCK_PIN, SPI3_SCK_FUNC, Disable);PORT_SetFunc(SPI3_SDI_PORT, SPI3_SDI_PIN, SPI3_SDI_FUNC, Disable);PORT_SetFunc(LCD_RST_PORT,  LCD_RST_PIN,  Func_Gpio,     Disable);PORT_SetFunc(LCD_A0_PORT,   LCD_A0_PIN,   Func_Gpio,     Disable);stcPortInit.enPinMode = Pin_Mode_Out;stcPortInit.enPinDrv  = Pin_Drv_H;PORT_Init(LCD_RST_PORT, LCD_RST_PIN, &stcPortInit);PORT_Init(LCD_A0_PORT,  LCD_A0_PIN,  &stcPortInit);PORT_Init(LCD_CS_PORT,  LCD_CS_PIN,  &stcPortInit);bsp_spi3_init();LCD_RST_H;LCD_A0_H;LCD_CS_H;delayms(10);LCD_RST_L;delayms(10);LCD_RST_H;delayms(120);write_codetable(st7789v_initcode, sizeof(st7789v_initcode)/sizeof(lcd_code_t));
}void st7789v_test(void)
{LCD_RST_H;LCD_A0_H;LCD_CS_H;delayms(10);LCD_RST_L;delayms(10);LCD_RST_H;delayms(120);// write_codetable(st7789v_initcode, sizeof(st7789v_initcode)/sizeof(lcd_code_t));delayms(10);//write_block(1, 1, 128, 300);
}void st7789v_disp_pic(uint8_t *dat, uint16_t x, uint16_t y, uint16_t width, uint16_t height)
{uint32_t len, n;uint8_t *ptr = dat;len = width * 2 * height;write_block(x, y, x + width - 1, y + height - 1);while (len > 0){n = (len >= 60000)?(60000):(len);lcd_spi_trans(ptr, n);ptr += n;len -= n;}
}

二、测试代码


#include "rtthread.h"
#include "board.h"void st7789v_disp_pic(uint8_t *dat, uint16_t x, uint16_t y, uint16_t width, uint16_t height);extern const unsigned char gImage_pic1[];
extern const unsigned char gImage_pic2[];static void test_entry(void* parameter)
{ st7789v_init();while (1){st7789v_disp_pic((uint8_t *)gImage_pic1, 0, 0, 240, 320);rt_thread_delay(1000);st7789v_disp_pic((uint8_t *)gImage_pic2, 0, 0, 240, 320);rt_thread_delay(1000);}
}static int test_init(void)
{rt_thread_t th = rt_thread_create("test", test_entry, RT_NULL, 1024, 10, 50);if (th != RT_NULL)rt_thread_startup(th);return 0;
}INIT_APP_EXPORT(test_init);

三、实测效果


一次刷图耗时35ms,刷图时候丝毫不会影响跑马灯的显示,说明DMA还是蛮好用的

HC32F460 SPI DMA TFT

HC32F460 SPI DMA 驱动 TFT显示屏相关推荐

  1. 小熊派 FreeRTOS+SPI+DMA 驱动 TFT-LCD

    文章目录 小熊派 FreeRTOS+SPI+DMA 驱动 TFT-LCD 一.文章前言 二.SPI+DMA 配置 三.FreeRTOS 配置 四.代码编写 五.实验现象 小熊派 FreeRTOS+SP ...

  2. [SPI+DMA] 驱动WS2812B显示时钟

    [SPI+DMA] 驱动WS2812B显示时钟 实现原理 本人一个大学萌新,偶然间发现RGB时钟这神奇的玩意,就想试试.目前初步实现时钟显示,第一次写博客,只是为了记录自己的学习成果方便以后查看,大家 ...

  3. 【STM32】基于STM32CubeIDE SPI+DMA驱动WS2812

    [STM32]基于STM32CubeIDE SPI+DMA驱动WS2812 ✨申明:本文章仅发表在CSDN网站,任何其他网见此内容均为盗链和爬取,请多多尊重和支持原创!

  4. STM32 SPI+DMA 驱动 SRAM LY68L6400SLIT 应用笔记

    关键词:库函数,STM32F407,SPI+DMA ,SPI-DMA,SRAM , LY68L6400SLIT,STM32CubeMX 编 辑:大黄蜂 说明:本笔记记录 基于 STM32F407 + ...

  5. STM32 SPI+DMA驱动WS2812

    [举报再看养成习惯,噢 不对,点赞再看养成习惯.感谢支持] 开头不多叨叨,直接进入主题: WS2812的驱动原理: 首先明白高低电平的表示方法: 低电平(0 code): 0.35us的高电平+0.8 ...

  6. 基于MT7688 原厂SDK 使用SPI控制器驱动TFT屏幕ILI9225驱动器(spi接口)

    以下是我的一个利用SPI控制器操作屏的一个操作实例 包含一个bpeer_tft.c 和一个bpeer_tft.h 这是我基于flash驱动剥离出来的spi控制器驱动 好的话,顶起来~~~~~~~~~~ ...

  7. 基于STM32F411使用SPI+DMA驱动LCD

    先看效果 F411CE 硬件SPI+DMA驱动LCD 基于HAL库 其实HAL库我用不太习惯,一直也是用的标准库 但HAL库确实是好上手一些,就迅速创建一个新的template 这次就当尝试一下吧,因 ...

  8. [HAL]STM32 SPI+DMA驱动WS2812

    该程序是纯手敲,非Cube生成!所有代码均注释. 源码在文章后面获取 WS2818 简介 Keyword: 单线通讯.归零码.Reset.RGB顺序 RGB一共有24bit位 ->相当于驱动一个 ...

  9. 嵌入式开发-STM32硬件SPI驱动TFT屏

    嵌入式开发-STM32硬件SPI驱动TFT屏 这次用到的TFT屏 CubeMX设置 代码编写 增加的内容 需要注意问题 代码下载 这次用到的TFT屏 现在的TFT屏幕已经很便宜了,65536色屏幕,2 ...

  10. Arduino与Proteus仿真实例-TFT显示屏(ILI9341驱动器)SPI驱动仿真

    TFT显示屏(ILI9341驱动器)SPI驱动仿真 薄膜晶体管液晶显示器 (TFT LCD) 是一种利用薄膜晶体管技术来提高对比度和可寻址性等品质的液晶显示器 (LCD). TFT 技术意味着使用单独 ...

最新文章

  1. exe一机一码加密工具_Python代码加密混淆
  2. CH341SER CH340SER USB转串口驱动
  3. 吃完降压药多久能睡觉 降压药什么时候吃好
  4. 01背包问题从简单到复杂
  5. 《Python》进程收尾线程初识
  6. java新建对象校验_验证某个对象是否是一个mock对象或者一个spy对象
  7. vs2015软件系统开源_2015年开源亮点的多样性
  8. kylin启动:Failed to create /kylin
  9. Azure CLI 简单入门
  10. 《四 spring源码》spring的事务注解@Transactional 原理分析
  11. 嵌入式学习文章推荐+资料下载
  12. Edge浏览器+百度翻译:识别图片类PDF中的文字并翻译
  13. springboot集成微信app支付
  14. IEEE802.15.4、ZigBee、ZigBee协议栈、Zstack、ZigBee联盟、CC2530、IAR的关系?
  15. XZ_icp金融经营许可证相关的文档和相关问题
  16. 计算机编程的双引号怎么打,计算机双引号怎么打出来
  17. python制作恶搞_Python:恶搞,将你朋友照片做成熊猫人表情包
  18. linux工程师前景_嵌入式Linux工程师发展前景 嵌入式工程师待遇怎样?
  19. 2022 CCF中国软件大会(CCF Chinasoft)“CCF-华为胡杨林基金-系统软件专项”论坛成功召开...
  20. Android图片背景朦胧效果,android 图片的模糊化处理,效果类似超级课程表的“我的中心里头像背景,看起来很炫...

热门文章

  1. Hopping Rabbit---牛客
  2. 文本分类(0)——scrapy爬新浪滚动新闻
  3. 2021年中式面点师(中级)最新解析及中式面点师(中级)模拟考试题库
  4. ceph 代码分析 读_Ceph代码分析
  5. Python 粒子群算法 PSO
  6. 真实性能大揭秘 热门移动显卡横向测试
  7. Exchange 2003 反垃圾邮件
  8. BootStrap左侧菜单栏
  9. centons7安装k8s集群
  10. 红帽子linux5.5安装,红帽子企业Linux 5安装  硬盘安装