64-QSPI-Flash_DMA_P2P_SPI_TFT_显示视频级动画效果程序,STC32G144K246实验箱演示程
64-QSPI-Flash_DMA_P2P_SPI_TFT_显示视频级动画效果程序,STC32G144K246实验箱演示程序主程序main.C代码如下(汇编版本在附件中):
/*---------------------------------------------------------------------*/
/* --- Web: www.STCAI.com ---------------------------------------------*/
/* --- BBS: www.STCAIMCU.com-----------------------------------------*/
/*---------------------------------------------------------------------*/
/*************功能说明 **************
本例程基于STC32G144K246为主控芯片的实验箱进行编写测试。
使用Keil C251编译器,Memory Model推荐设置XSmall模式,默认定义变量在edata,单时钟存取访问速度快。
edata建议保留1K给堆栈使用,空间不够时可将大数组、不常用变量加xdata关键字定义到xdata空间。
QSPI DMA + SPI DMA驱动液晶屏程序
按住P3.3后上电,芯片进入FLASH下载模式,使用6.94P以后版本的ISP下载软件中的“串行Flash编程器”
工具将多幅图片下载到实验箱的Flash中,然后重新上电(P3.3不要按),即可进入动画显示模式
显示时QSPI 读取Flash图片数据,通过P2P DMA直接发送数据到SPI-LCD显示。
QSPI读取Flash与LCD显示DMA的数据长度设置38400字节。
SPI LCD 接口:
sbit P_LCD_CLK= P2^5; //D0 SPI or II2 的时钟脚
sbit P_LCD_SDA= P2^3; //D1 SPI or II2 的数据脚
sbit P_LCD_RST= P2^4; //RES 复位脚, 低电平复位
sbit P_LCD_DC = P2^2; //DC 数据或命令脚
sbit P_LCD_CS = P2^6; //CS 片选脚
QSPI Flash 接口:
sbit CS = P7^5;
sbit SDI_IO0 = P7^0;
sbit SDO_IO1 = P7^2;
sbit SCK = P7^1;
sbit WP_IO2 = P7^3;
sbit HLD_IO3 = P7^4;
下载时, 选择IRC频率 48MHz,主时钟使用 PLL 60MHz 时钟频率.
本实验使用的1.3寸240*240的SPI接口彩屏
******************************************/
#include "config.h"
#include "qspi.h"
#include "w25qxx.h"
#include "tft.h"
#include "usbcdc.h"
#include "timer.h"
#define IMG_SIZE (240UL * 240 * 2)
#define DMA_AMT_LEN (38400UL)
#define DMA_CNT (IMG_SIZE / DMA_AMT_LEN)
void SYS_Init(void);
void QSPI2TFT_Start();
void QSPI2TFT_Next();
typedef struct
{
char strSign;
DWORD dwCount;
DWORD dwAddress;
} FAT;
FAT Fat; //文件分配表
DWORD dwOffset; //图片数据的偏移地址
int nIndex; //图片索引
int nCount; //图片数据装载次数
BOOL fLoading; //装载数据标志
void main()
{
EAXFR = 1;// 扩展寄存器(XFR)访问使能
CKCON = 1;//避免 DMA 与 CPU 同时访问 xdata 时产生总线冲突
P0M0 = 0x00; P0M1 = 0x00;
P1M0 = 0x00; P1M1 = 0x00;
P2M0 = 0x00; P2M1 = 0x00;
P3M0 = 0x00; P3M1 = 0x00;
P4M0 = 0xC0; P4M1 = 0x00;
P5M0 = 0x00; P5M1 = 0x00;
P3PU |= 0x0c; //使能P3.2,P3.3内部上拉电阻
SYS_Init();
TIMER0_Init();
QSPI_Init();
SPI_Init();
LCD_Init();
EA = 1;
W25Q_Enable_QE(); //使能QSPI FLASH的4线读写模式
if (!P33) //按住P3.3复位,进入图片数据下载模式
{
CDC_Init();
CDC_WaitStable(); //等待USB-CDC配置完成
while (1)
{
CDC_Process(); //CDC接口处理图片数据
}
}
W25Q_FastRead_6B(0, (BYTE *)&Fat, 256); //从FLASH第一页读取FAT
nIndex = 0; //从第一幅图片开始显示
while (1)
{
if (f100ms)
{
f100ms = 0;
QSPI2TFT_Start(); //每隔100ms自动显示下一幅图片
}
}
}
void SYS_Init(void)
{
#if(HPLL_SEL==SEL_HPLL2)
WTST = 1; //通过WTST增加等待时钟控制Flash读取速度在33MHz以内, 主时钟:480MHz/2/4=60MHz, 读Flash速度:60MHz/(1+1)=30MHz
HPLLCR |= 0x80; //使能HPLL(高速外设默认使用HPLL时钟,切换到HPLL2前要先使能HPLL,切换完再关闭HPLL)
//首先需要将HIRC主频调节到48MHz
HPLL2CR &= ~0x10; //选择HPLL2输入时钟源为HIRC
// HPLL2CR |= 0x10; //选择HPLL2输入时钟源为IRCM
HPLL2PDIV = 8; //设置HPLL2输入时钟预分频为8(HPLL输入频率必须为6MHz)
// HPLL2CR |= 0x00; //HPLL2=6MHz*52=312MHz
// HPLL2CR |= 0x01; //HPLL2=6MHz*54=324MHz
// HPLL2CR |= 0x02; //HPLL2=6MHz*56=336MHz
// HPLL2CR |= 0x03; //HPLL2=6MHz*58=348MHz
// HPLL2CR |= 0x04; //HPLL2=6MHz*60=360MHz
// HPLL2CR |= 0x05; //HPLL2=6MHz*62=372MHz
// HPLL2CR |= 0x06; //HPLL2=6MHz*64=384MHz
// HPLL2CR |= 0x07; //HPLL2=6MHz*66=396MHz
// HPLL2CR |= 0x08; //HPLL2=6MHz*68=408MHz
// HPLL2CR |= 0x09; //HPLL2=6MHz*70=420MHz
// HPLL2CR |= 0x0a; //HPLL2=6MHz*72=432MHz
// HPLL2CR |= 0x0b; //HPLL2=6MHz*74=444MHz
// HPLL2CR |= 0x0c; //HPLL2=6MHz*76=456MHz
// HPLL2CR |= 0x0d; //HPLL2=6MHz*78=468MHz
HPLL2CR |= 0x0e; //HPLL2=6MHz*80=480MHz
// HPLL2CR |= 0x0f; //HPLL2=6MHz*82=492MHz
HPLL2CR |= 0x20; //高速外设时钟选择 HPLL2/2
HPLL2CR |= 0x80; //使能HPLL2
HPLLCR &= ~0x80; //关闭HPLL(高速外设默认使用HPLL时钟,切换到HPLL2前要先使能HPLL,切换完再关闭HPLL)
CLKDIV = 4; //系统时钟 = 主时钟源/2 = HPLL2/2/4 = 60MHz
CLKSEL = 0x08; //选择HPLL2/2作为主时钟源
#else
WTST = 1; //通过WTST增加等待时钟控制Flash读取速度在33MHz以内, 主时钟:480MHz/2/4=60MHz, 读Flash速度:60MHz/(1+1)=30MHz
//首先需要将HIRC主频调节到48MHz
HPLLCR &= ~0x10; //选择HPLL输入时钟源为HIRC
// HPLLCR |= 0x10; //选择HPLL输入时钟源为IRCM
HPLLPDIV = 8; //设置HPLL输入时钟预分频为8(HPLL输入频率必须为6MHz)
// HPLLCR |= 0x00; //HPLL=6MHz*52=312MHz
// HPLLCR |= 0x01; //HPLL=6MHz*54=324MHz
// HPLLCR |= 0x02; //HPLL=6MHz*56=336MHz
// HPLLCR |= 0x03; //HPLL=6MHz*58=348MHz
// HPLLCR |= 0x04; //HPLL=6MHz*60=360MHz
// HPLLCR |= 0x05; //HPLL=6MHz*62=372MHz
// HPLLCR |= 0x06; //HPLL=6MHz*64=384MHz
// HPLLCR |= 0x07; //HPLL=6MHz*66=396MHz
// HPLLCR |= 0x08; //HPLL=6MHz*68=408MHz
// HPLLCR |= 0x09; //HPLL=6MHz*70=420MHz
// HPLLCR |= 0x0a; //HPLL=6MHz*72=432MHz
// HPLLCR |= 0x0b; //HPLL=6MHz*74=444MHz
// HPLLCR |= 0x0c; //HPLL=6MHz*76=456MHz
// HPLLCR |= 0x0d; //HPLL=6MHz*78=468MHz
HPLLCR |= 0x0e; //HPLL=6MHz*80=480MHz
// HPLLCR |= 0x0f; //HPLL=6MHz*82=492MHz
HPLL2CR &= ~0x60; //高速外设时钟选择 HPLL/2
HPLLCR |= 0x80; //使能HPLL
CLKDIV = 4; //系统时钟=主时钟源/2 = HPLL/2/4 = 60MHz
CLKSEL = 0x04; //选择HPLL/2作为主时钟源
#endif
// P5M0 |= 0x10; P5M1 &= ~0x10;//设置P5.4口为推挽输出
// P5SR &= ~0x10; //设置P5.4口为快速模式
// HIRCCR |= 0x10; //输出系统时钟
// MCLKOCR = 10; //系统时钟 10 分频到P5.4
}
void QSPI_DMA_Isr() interrupt DMA_QSPI_VECTOR
{
DMA_QSPI_STA = 0x00;
QSPI2TFT_Next(); //DMA传输下一包数据
}
void QSPI2TFT_Start()
{
if (fLoading) //如果正在装载图片,则退出
return;
if (nIndex >= Fat.dwCount) //如果图片索引达到最大值
nIndex = 0; //则从第一幅图片开始循环
dwOffset = Fat.dwAddress; //获取当前图片的偏移地址
nCount = 0; //初始化图片数据装载次数
while (QSPI_CheckBusy()); //检测忙状态
QSPI_SetReadMode(); //读模式
QSPI_SetDataLength(DMA_AMT_LEN-1);//设置数据长度
QSPI_SetAddressSize(2); //设置地址宽度为24位(2+1字节)
QSPI_SetDummyCycles(8); //设置DUMMY时钟
QSPI_NoInstruction(); //设置无指令模式(防止误触发)
QSPI_NoAddress(); //设置无地址模式(防止误触发)
QSPI_NoAlternate(); //无间隔字节
QSPI_DataQuadMode(); //设置数据为四线模式
QSPI_SetInstruction(0x6B); //设置指令
QSPI_InstructionSingMode(); //设置指令为单线模式
QSPI_NoAddress(); //设置无地址模式(防止误触发)
QSPI_SetAddress(dwOffset); //设置地址
QSPI_AddressSingMode(); //设置地址为单线模式
// QSPI_SetClockDivider(5); //设置QSPI时钟为系统时钟/(n+1),设置数据传输速度,如果速度太快SPI输出跟不上会导致传输异常
TFT_ShowStart(); //开始TFT彩屏显示
DMA_P2P1_SRC = P2P_SRC_QSPIRX;
DMA_P2P1_DEST = P2P_DEST_SPI1TX;
DMA_QSPI_CFG = 0xa0; //使能DMA读取操作
DMA_QSPI_STA = 0x00; //清除DMA状态
DMA_QSPI_AMT = (DMA_AMT_LEN-1); //设置DMA数据长度
DMA_QSPI_AMTH = (DMA_AMT_LEN-1) >> 8;
DMA_QSPI_CR = 0xa1; //启动DMA并触发QSPI读操作
P47 = 0;
fLoading = TRUE;
}
void QSPI2TFT_Next()
{
dwOffset += DMA_AMT_LEN; //更新偏移地址
nCount++; //装载次数+1
if (nCount < DMA_CNT) //判断图片数据装载次数
{
QSPI_NoAddress(); //设置无地址模式(防止误触发)
QSPI_SetAddress(dwOffset); //设置地址
QSPI_AddressSingMode(); //设置地址为单线模式
DMA_QSPI_CR = 0xa1; //启动DMA并触发QSPI读操作
}
else
{
P47 = 1;
fLoading = FALSE; //图片数据装载完成
DMA_QSPI_CR = 0x00; //停止QSPI_DMA
DMA_QSPI_CFG = 0x00;
DMA_P2P1_SRC = 0;
DMA_P2P1_DEST = 0;
TFT_ShowEnd(); //结束TFT彩屏显示数据输入
}
}
void delay_ms(WORD ms)
{
WORD i;
do
{
i = MAIN_Fosc / 6000;
while(--i);
} while(--ms);
}
页:
[1]