【STM32】硬件SPI+DMA驱动ILI9341的TFT屏
【STM32】硬件SPI+DMA驱动ILI9341的TFT屏
一、前言
TFT屏的驱动芯片常见的有ST7789、SSD1289、ILI9341等,本项目中使用的TFT屏由ILI9341驱动芯片控制。为了提升显示效果与系统效率,对原有只使用硬件SPI驱动程序(【STM32项目】智慧鱼缸 )进行了优化,并使用DMA(直接内存访问)和硬件SPI的控制方式提升数据传输效率并降低处理器负载。

二、系统介绍
1. 项目实现的功能
(1)使用DMA+硬件SPI控制方式实现全屏快速刷新。
(2)通过优化的数据传输方式处理图像、字符及文字内容显示输出。
2. 项目硬件组成
(1)主控芯片:该项目使用的是STM32F103RCT6。
(2)TFT显示屏:该显示屏是2.8寸彩屏,采用4线制SPI通信方式,驱动芯片是ILI9341,分辨率为320*240。


三、项目软件开发
1.初始化操作
(1)硬件SPI的初始化:配置SPI对应使用管脚;再根据ILI9341驱动芯片要求设置SPI参数,使用8bit数据传输格式,波特率预分频器数值(用于配置发送和接收SCK时钟)应考虑系统时钟频率并满足TFT控制器的时钟要求;最后使能SPI功能模块。
//* @name :void SPI2_Init(void)
//* @function :硬件SPI2初始化
void SPI2_Init(void)
{
SPI_InitTypeDef SPI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
//配置SPI2管脚
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//SPI2配置选项
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2 ,ENABLE);
SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx; //单线发送模式
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //8bit数据
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //传输时序:CPOL=0;(时钟相位)
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; // CPHA=0;(时钟极性)
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI2, &SPI_InitStructure);
//使能SPI2
SPI_Cmd(SPI2, ENABLE);
}
(2)DMA控制器配置:配置DMA参数以适配不同使用场景。
配置参数说明:
● 数据传输方向设为从内存到外设模式。
● 外设地址设为不变,对于外设SPI发送的地址寄存器具有固定地址不需要自增,每次数据传输都写入或读取该地址的值。
● 内存地址设为递增模式,由于传输的颜色数据会发生变化。若刷新整屏或某个区域的颜色不变,则内存地址可设为不变。
● 数据宽度配置为8bit,与SPI接口数据格式保持一致。
//* @name : void MYDMA_Config(DMA_Channel_TypeDef* DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)
//* @function: DMA配置
//* @parameters : DMA_CHx: DMA通道CHx
// cpar: 外设地址
// cmar: 存储器地址
// cndtr: 数据传输量
void MYDMA_Config(DMA_Channel_TypeDef* DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)
{
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能DMA传输
DMA_DeInit(DMA_CHx); //将DMA的通道1寄存器重设为缺省值
DMA1_MEM_LEN=cndtr;
DMA_InitStructure.DMA_PeripheralBaseAddr = cpar; //DMA外设ADC基地址
DMA_InitStructure.DMA_MemoryBaseAddr = cmar; //DMA内存基地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //数据传输方向,从内存读取发送到外设
DMA_InitStructure.DMA_BufferSize = cndtr; //DMA通道的DMA缓存的大小
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址寄存器不变
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址寄存器递增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //数据宽度为8位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //数据宽度为8位
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //工作在正常缓存模式
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //DMA通道 x拥有中优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x没有设置为内存到内存传输
DMA_Init(DMA_CHx, &DMA_InitStructure);
}
DMA配置通道可查看STM32主控芯片的DMA控制器;外设地址设为SPI对应的数据寄存器;内存地址指向自定义的数组,由于显示屏16bitRGB颜色显示,则该数组大小设为显示屏宽度的2倍;则数据传输量也应设为显示屏宽度的2倍。

MYDMA_Config(DMA1_Channel5,(u32)&(SPI2->DR),(u32)SendBuff,2*320); //DMA配置
(3)TFT屏的初始化:将显示屏引脚初始化;再对显示屏的驱动芯片ILI9341初始化,可根据实际应用需求参考ILI9341指令集调整相关参数。
// * @name :void LCD_GPIOInit(void)
// * @function :LCD屏幕引脚初始化
void LCD_GPIOInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB ,ENABLE); //使能GPIOB时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9| GPIO_Pin_10| GPIO_Pin_11| GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_Init(GPIOB, &GPIO_InitStructure);
LCD_CS_SET;
}
// * @name :void LCD_Init(void)
// * @function :LCD屏幕初始化
u8 SendBuff[2*320]; //横屏宽度320,用于缓存一行数据
void LCD_Init(void)
{
SPI2_Init(); //硬件SPI2初始化
MYDMA_Config(DMA1_Channel5,(u32)&(SPI2->DR),(u32)SendBuff,2*lcddev.width); //DMA配置
LCD_GPIOInit(); //LCD GPIO初始化
//****************LCD复位*************//
LCD_RST_CLR;
delay_ms(10);
LCD_RST_SET;
delay_ms(130);
//*************ILI9341初始化**********//
LCD_CS_CLR; //CS低电平
delay_ms(10);
LCD_WR_REG(0xCF);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0xC9);
LCD_WR_DATA(0X30);
LCD_WR_REG(0xED);
LCD_WR_DATA(0x64);
LCD_WR_DATA(0x03);
LCD_WR_DATA(0X12);
LCD_WR_DATA(0X81);
LCD_WR_REG(0xE8);
LCD_WR_DATA(0x85);
LCD_WR_DATA(0x10);
LCD_WR_DATA(0x7A);
LCD_WR_REG(0xCB);
LCD_WR_DATA(0x39);
LCD_WR_DATA(0x2C);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x34);
LCD_WR_DATA(0x02);
LCD_WR_REG(0xF7);
LCD_WR_DATA(0x20);
LCD_WR_REG(0xEA);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_REG(0xC0); //Power control
LCD_WR_DATA(0x1B); //VRH[5:0]
LCD_WR_REG(0xC1); //Power control
LCD_WR_DATA(0x00); //SAP[2:0];BT[3:0] 01
LCD_WR_REG(0xC5); //VCM control
LCD_WR_DATA(0x30);
LCD_WR_DATA(0x30);
LCD_WR_REG(0xC7); //VCM control2
LCD_WR_DATA(0XB7);
LCD_WR_REG(0x36); // Memory Access Control
LCD_WR_DATA(0x08);
LCD_WR_REG(0x3A);
LCD_WR_DATA(0x55);
LCD_WR_REG(0xB1);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x1A);
LCD_WR_REG(0xB6); // Display Function Control
LCD_WR_DATA(0x0A);
LCD_WR_DATA(0xA2);
LCD_WR_REG(0xF2); // 3Gamma Function Disable
LCD_WR_DATA(0x00);
LCD_WR_REG(0x26); //Gamma curve selected
LCD_WR_DATA(0x01);
LCD_WR_REG(0xE0); //Set Gamma
LCD_WR_DATA(0x0F);
LCD_WR_DATA(0x2A);
LCD_WR_DATA(0x28);
LCD_WR_DATA(0x08);
LCD_WR_DATA(0x0E);
LCD_WR_DATA(0x08);
LCD_WR_DATA(0x54);
LCD_WR_DATA(0XA9);
LCD_WR_DATA(0x43);
LCD_WR_DATA(0x0A);
LCD_WR_DATA(0x0F);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_REG(0XE1); //Set Gamma
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x15);
LCD_WR_DATA(0x17);
LCD_WR_DATA(0x07);
LCD_WR_DATA(0x11);
LCD_WR_DATA(0x06);
LCD_WR_DATA(0x2B);
LCD_WR_DATA(0x56);
LCD_WR_DATA(0x3C);
LCD_WR_DATA(0x05);
LCD_WR_DATA(0x10);
LCD_WR_DATA(0x0F);
LCD_WR_DATA(0x3F);
LCD_WR_DATA(0x3F);
LCD_WR_DATA(0x0F);
LCD_WR_REG(0x2B);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x01);
LCD_WR_DATA(0x3f);
LCD_WR_REG(0x2A);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0xef);
LCD_WR_REG(0x11); //Exit Sleep
delay_ms(120);
LCD_WR_REG(0x29); //display on
LCD_direction(USE_HORIZONTAL);//设置LCD显示方向
LCD_LED=1;//点亮背光
LCD_Clear(WHITE);//清全屏白色
}
为提升数据传输效率,可在显示屏复位完成后将CS片选信号脚置为低电平使能状态,此后在连续的数据或命令写入操作中无需反复切换片选信号。
2.写命令和数据函数
(1)写一个字节数据:若无需处理返回值,接收方可以根据需要选择是否接收返回数据。
// * @name : void SPI_WriteByte(SPI_TypeDef* SPIx,u8 Byte)
// * @function : 使用硬件SPI写入一个字节的数据
// * @parameters : SPIx: SPI类型,x表示1,2,3
// Byte:待写入数据
void SPI_WriteByte(SPI_TypeDef* SPIx,u8 Byte)//u8 SPI_WriteByte(SPI_TypeDef* SPIx,u8 Byte)
{
while((SPIx->SR&SPI_I2S_FLAG_TXE)==RESET); //等待发送缓冲为空
SPIx->DR=Byte; //发送一个byte
while ((SPIx->SR&SPI_I2S_FLAG_BSY)); //等待通信停止
//return SPIx->DR; //返回收到的数据
}
(2)写命令值:写入命令值前,需先将寄存器/数据选择信号脚设置为低电平以选择写命令指令,然后执行8bit命令值的写入操作。
// * @name : void LCD_WR_REG(u8 data)
// * @function : 在LCD屏幕上写入8位命令
// * @parameters : data:要写入的命令值
void LCD_WR_REG(u8 data)
{
//LCD_CS_CLR;
LCD_RS_CLR; //GPIOB->BRR = 1<<10;//直接寄存器操作,可减少执行时间
SPI_WriteByte(SPI2,data);
//LCD_CS_SET;
}
(3)写数据值:写入数据值前,需先将寄存器/数据选择信号脚设置为高电平以选择写数据指令,然后执行8bit数据值的写入操作。
// * @name : void LCD_WR_DATA(u8 data)
// * @function : 将8位数据写入LCD屏幕
// * @parameters : data:要写入的数据值
void LCD_WR_DATA(u8 data)
{
//LCD_CS_CLR;
LCD_RS_SET; //GPIOB->BSRR = 1<<10;//直接寄存器操作,可减少执行时间
SPI_WriteByte(SPI2,data);
//LCD_CS_SET;
}
3.设置显示窗口函数
在向外设写入显存数据之前,必须先配置显示窗口的x轴和y轴坐标地址,以确定数据写入的具体显示位置。
// * @name : void LCD_SetWindows(u16 xStar, u16 yStar,u16 xEnd,u16 yEnd)
// * @function : 设置LCD显示窗口
// * @parameters : xStar : 显示窗口的x起始坐标
// yStar : 显示窗口的y起始坐标
// xEnd : 显示窗口的x末端坐标
// yEnd : 显示窗口的y末端坐标
void LCD_SetWindows(u16 xStar, u16 yStar,u16 xEnd,u16 yEnd)
{
LCD_WR_REG(0x2A);
Lcd_WriteData_16Bit(xStar);
Lcd_WriteData_16Bit(xEnd);
LCD_WR_REG(0x2B);
Lcd_WriteData_16Bit(yStar);
Lcd_WriteData_16Bit(yEnd);
LCD_WR_REG(0x2C); //开始写入GRAM
}
4. DMA传输函数
DMA相关函数位于stm32f10x_dma.c库文件中,本项目采用SPI通信传输方式。需先通过SPI_I2S_DMACmd函数启用SPI2的DMA接口,然后使能DMA通道进行数据传输,最后在传输完成后清除通道传输标志位以完成一次完整的DMA传输操作。
u16 DMA1_MEM_LEN;//保存DMA每次数据传送的长度
// * @name : void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx)
// * @function : 开启一次DMA传输
// * @parameters :DMA_CHx : DMA通道CHx
void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx)
{
DMA_Cmd(DMA_CHx, DISABLE ); //关闭 TX DMA1 所指示的通道
DMA_SetCurrDataCounter(DMA_CHx,DMA1_MEM_LEN); //DMA通道的DMA缓存的大小
DMA_Cmd(DMA_CHx, ENABLE); //使能 TX DMA1 所指示的通道
}
// * @name : void DMA_Start(void)
// * @function : 启动DMA传输
void DMA_Start(void)
{
//LCD_CS_CLR; //关闭片选
LCD_RS_SET; //写数据
SPI_I2S_DMACmd(SPI2,SPI_I2S_DMAReq_Tx,ENABLE); //启用SPI2 DMA通道。
MYDMA_Enable(DMA1_Channel5);
while(DMA_GetFlagStatus(DMA1_FLAG_TC5)==RESET); //等待传输完成
DMA_ClearFlag(DMA1_FLAG_TC5); //清除通道5传输完成标志
}
5. 填充函数
通过复用单行颜色数据实现批量填充,只需将一行数据(16bit颜色值)写入传送数组,然后启动传输并发送所需行数即可完成填充操作。由于传输数据方式是8bit发送,初始化配置的是先发送高位,因此当16bit颜色值按高位在前、低位在后排列时,需要将数值的高位放在前8位数值、低位放在后8位数值中进行发送。
// * @name : void LCD_Fill(u16 sx,u16 sy,u16 ex,u16 ey,u16 color)
// * @function : 填充规定的区域
// * @parameters : sx : 规定区域的x起始坐标
// sy : 规定区域的y起始坐标
// ex : 规定区域的x末端坐标
// ey : 规定区域的y末端坐标
// color : 填充的颜色数值
void LCD_Fill(u16 sx,u16 sy,u16 ex,u16 ey,u16 color)
{
u16 i,j;
DMA1_MEM_LEN=2*(ex-sx+1); //一行数据长度
LCD_SetWindows(sx,sy,ex,ey); //设置显示窗口
for(i=0;i<(ex-sx+1);i++)
{
SendBuff[2*i] = color>>8; //数据高位在前
SendBuff[2*i+1] = color;
}
for(j=0;j<(ey-sy+1);j++)
DMA_Start(); //启动传输
}
当显示区域设置为全屏尺寸时,可实现全屏填充颜色效果。
6. 图像显示函数
原理与填充函数相同,区别在于每行数据(16bit颜色值)不相同,只能一行一行传输完成填充预设区域。图像数组使用的时Image2Lcd取模软件生成,取模选项设置为水平扫描、不好含图像头数据、自左向右扫描、自顶向底扫描和低位在前。
// * @name : void Gui_Drawbmp(u16 x,u16 y,u16 w,u16 h,u16 bc,const unsigned char *p)
// * @function : 显示16位图像
// * @parameters : x : 图像x起始坐标
// y : 图像y起始坐标
// w : 图像显示的宽度
// h : 图像显示的高度
// bc : 图像背景的颜色数值
// p : 图像数组的起始地址
void Gui_Drawbmp(u16 x,u16 y,u16 w,u16 h,u16 bc,const unsigned char *p)
{
u16 i,j;
u32 k=0;
unsigned char picH,picL;
DMA1_MEM_LEN=2*w;
LCD_SetWindows(x,y,x+w-1,y+h-1); //窗口设置
for(j=0;j<h;j++)
{
for(i=0;i<w;i++)
{
picH=*(p+k+1);
picL=*(p+k);
if((picL==0xff)&&(picH==0xff)) //0xffff -> 白色
{
SendBuff[2*i] = bc>>8; //数据高位在前
SendBuff[2*i+1] = bc;
}
else
{
SendBuff[2*i] = picH; //数据高位在前
SendBuff[2*i+1] = picL;
}
k+=2;
}
DMA_Start(); //启动传输
}
}
7. 英文和数字字符显示函数
使用PCtoLCD2002取模软件生成所需字符的点阵数据并填入预定义数组中,通过获取字符数组的总个数来判断数据传输是否完成,最终完成字符数据的传输和显示填充。取模选项设置为阴码格式、逐行取模和顺向走向。
// * @name : void LCD_ShowChar(u16 x,u16 y,u16 fc, u16 bc, u8 num,u8 size,u8 mode)
// * @function : 显示英文和数字字符(自定义字符,非标准ASCII码)
// * @parameters : x:字符显示位置的x坐标
// y:字符显示位置的y坐标
// fc:字符的颜色数值
// bc:字符背景的颜色数值
// num:字符的第num位
// size:字符的尺寸
// mode:0非叠加(用指定的背景色填充),1叠加(保持原背景不变)
void LCD_ShowChar(u16 x,u16 y,u16 fc, u16 bc, u8 num,u8 size,u8 mode)
{
u8 temp,t1,t,i=0;
u16 x0=x;
u8 csize=(size/8+((size%8)?1:0)+1)*(size/2); //得到字体一个字符对应点阵集所占的字节数
//设置窗口
DMA1_MEM_LEN=size; //字体尺寸横向宽度为纵向宽度的一半
LCD_SetWindows(x,y,x+size/2-1,y+size-1); //设置单个文字显示窗口
for(t=0;t<csize;t++)
{
if(size==36)
temp=asc2_3618[num][t]; //调用3618字体
else if(size==20)
temp=asc2_2010[num][t]; //调用1608字体
else if(size==24)
temp=asc2_2412[num][t]; //调用2412字体
else return; //没有的字库
for(t1=0;t1<8;t1++)
{
if(!mode)
{
if(temp&0x80)
{
SendBuff[2*i] = fc>>8;
SendBuff[2*i+1] = fc;
}
else
{
SendBuff[2*i] = bc>>8;
SendBuff[2*i+1] = bc;
}
temp<<=1;
i++;
if(i>=(size/2))
{
i=0;
DMA_Start(); //启动传输
break;
}
}
else
{
if(temp&0x80) LCD_Fill(x,y,x,y,fc);
temp <<= 1;
x++;
if((x-x0)>=size/2)
{
x=x0;
y++;
break;
}
}
}
}
}
8. 中文字符显示函数
原理与英文和数字字符显示相同,同样使用PCtoLCD2002取模软件生成所需字符的点阵数据,取模选项设置也相同。
// * @name : void LCD_ShowChinese(u16 x, u16 y, u16 fc, u16 bc, u8 *str,u8 size,u8 mode)
// * @function : 显示中文字符
// * @parameters : x:中文字符x起始坐标
// y:中文字符y起始坐标
// fc:中文字符的颜色数值
// bc:中文字符背景的颜色数值
// str:中文字符的起始地址
// size:中文字符
// mode:0非叠加,1叠加
void LCD_ShowChinese(u16 x, u16 y, u16 fc, u16 bc, u8 *str,u8 size,u8 mode)
{
while(*str!=0)//数据未结束
{
if(x>(lcddev.width-size)||y>(lcddev.height-size))
return;
if(size==24)
GUI_DrawFont24(x,y,fc,bc,str,mode);
else if(size==20)
GUI_DrawFont20(x,y,fc,bc,str,mode);
else
GUI_DrawFont12(x,y,fc,bc,str,mode);
str+=2;
x+=size;//下一个汉字偏移
}
}
// * @name : void GUI_DrawFont12(u16 x, u16 y, u16 fc, u16 bc, u8 *s,u8 mode)
// * @function : 显示12x12中文字符
// * @parameters : x:汉字的x坐标
// y:汉字的y坐标
// fc:汉字的颜色数值
// bc:汉字的背景颜色数值
// s:汉字的起始地址
// mode:0非叠加,1叠加
void GUI_DrawFont12(u16 x, u16 y, u16 fc, u16 bc, u8 *s,u8 mode)
{
u8 i,j;
u16 k;
u16 HZnum;
u16 y0=y;
HZnum=sizeof(tfont12)/sizeof(typFNT_GB12); //自动统计汉字数目
for (k=0;k<HZnum;k++)
{
if ((tfont12[k].Index[0]==*(s))&&(tfont12[k].Index[1]==*(s+1))) //判断显示字体是否存在于tfont12数组中
{
LCD_SetWindows(x,y,x+10-1,y+10-1);
for(i=0;i<12*2;i++)
{
for(j=0;j<8;j++)
{
if(!mode) //非叠加方式
{
if(tfont12[k].Msk[i]&(0x80>>j))
LCD_Fill(x,y,x,y,fc);
else
LCD_Fill(x,y,x,y,bc);
}
else
{
if(tfont12[k].Msk[i]&(0x80>>j))
LCD_Fill(x,y,x,y,fc);
}
y++;
if((y-y0)==12)
{
y=y0;
x++;
break;
}
}
}
}
continue; //查找到对应点阵字库立即退出,防止多个汉字重复取模带来影响
}
}
四、总结
使用DMA配合硬件SPI可以显著提升数据传输速度。若希望进一步提高性能,可尝试启用16位数据传输模式,但需确认所用外设是否支持该模式。例如,在本项目中采用的TFT显示屏由ILI9341芯片驱动。该芯片支持多种MCU接口类型,包括8080系列并行接口与3线/4线串行接口。查表可知,ILI9341并不支持16位4线串行接口,因此无法通过此方式进一步提升传输效率。




更多推荐

所有评论(0)