STM32F4VET6使用硬件SPI+DMA驱动st7735s

①配置SPI和GPIO

SPI.h

void SPI2_Init(void);
u8 SPI_WriteByte(SPI_TypeDef* SPIx,u8 Byte);

SPI.c

//SPI和GPIO初始化
void SPI2_Init(void)
{
	SPI_InitTypeDef SPI_InitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);
	//设置GPIOB_Pin13为SCL,设置GPIOB_Pin15为SDA
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_13|GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
	GPIO_Init(GPIOB,&GPIO_InitStructure);
	
	GPIO_PinAFConfig(GPIOB,GPIO_PinSource13,GPIO_AF_SPI2);
	GPIO_PinAFConfig(GPIOB,GPIO_PinSource15,GPIO_AF_SPI2);
	
	RCC_APB2PeriphResetCmd(RCC_APB1Periph_SPI2,ENABLE);
	RCC_APB2PeriphResetCmd(RCC_APB1Periph_SPI2,DISABLE);
	
    //设置GPIOB_Pin10为DC,设置GPIOB_Pin12为CS
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10|GPIO_Pin_12;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;
	GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;
	GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStructure);
	
	SPI_InitStructure.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_2;
	SPI_InitStructure.SPI_CPHA=SPI_CPHA_1Edge;
	SPI_InitStructure.SPI_CPOL=SPI_CPOL_Low;
	SPI_InitStructure.SPI_CRCPolynomial=7;
	SPI_InitStructure.SPI_DataSize=SPI_DataSize_8b;
	SPI_InitStructure.SPI_Direction=SPI_Direction_2Lines_FullDuplex;
	SPI_InitStructure.SPI_FirstBit=SPI_FirstBit_MSB;
	SPI_InitStructure.SPI_Mode=SPI_Mode_Master;
	SPI_InitStructure.SPI_NSS=SPI_NSS_Soft;
	SPI_Init(SPI2,&SPI_InitStructure);
	SPI_Cmd(SPI2,ENABLE);
}

//硬件SPI写字节
u8 SPI_WriteByte(SPI_TypeDef* SPIx,u8 Byte)
{
	while((SPIx->SR&SPI_I2S_FLAG_TXE)==RESET);
	SPIx->DR=Byte;
	while((SPIx->SR&SPI_I2S_FLAG_RXNE)==RESET);
	return SPIx->DR;
}

②配置DMA

DMA.h

void MYDMA_Config(DMA_Stream_TypeDef* DMA_CHx,u32 cpar,u32 cmar,u16 cndtr);
void MYDMA_Enable(DMA_Stream_TypeDef*DMA_CHx);
void DMA_GO(void);

DMA.c

u32 DMA1_MEM_LEN;
extern u8 SendBuff[2*128];//全局设置SendBuff缓冲区
DMA_InitTypeDef DMA_InitStructure;

void MYDMA_Config(DMA_Stream_TypeDef* DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)
{
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);
	
	DMA_DeInit(DMA_CHx);
	DMA1_MEM_LEN=cndtr;
	DMA_InitStructure.DMA_Channel=DMA_Channel_0;
	DMA_InitStructure.DMA_Memory0BaseAddr=cmar;
	DMA_InitStructure.DMA_PeripheralBaseAddr=cpar;
	DMA_InitStructure.DMA_DIR=DMA_DIR_MemoryToPeripheral;
	DMA_InitStructure.DMA_BufferSize=cndtr;
	DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;
	DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;
	DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;
	DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;
	DMA_InitStructure.DMA_Mode=DMA_Mode_Normal;
	DMA_InitStructure.DMA_Priority=DMA_Priority_Medium;
	DMA_InitStructure.DMA_FIFOMode=DMA_FIFOMode_Disable;
	DMA_InitStructure.DMA_FIFOThreshold=DMA_FIFOThreshold_Full;
	DMA_InitStructure.DMA_MemoryBurst=DMA_MemoryBurst_Single;
	DMA_InitStructure.DMA_PeripheralBurst=DMA_PeripheralBurst_Single;
	DMA_Init(DMA_CHx,&DMA_InitStructure);
}
void MYDMA_Enable(DMA_Stream_TypeDef*DMA_CHx)
{
	DMA_Cmd(DMA_CHx,DISABLE);
	while (DMA_GetCmdStatus(DMA1_Stream4)!= DISABLE){}
	DMA_SetCurrDataCounter(DMA1_Stream4,DMA1_MEM_LEN);
	DMA_Cmd(DMA_CHx,ENABLE);
}
void DMA_GO(void)
{
	CS_Low;
	RS_High;
	SPI_I2S_DMACmd(SPI2,SPI_I2S_DMAReq_Tx,ENABLE);
	MYDMA_Enable(DMA1_Stream4);
	while(1)
	{
		if(DMA_GetFlagStatus(DMA1_Stream4,DMA_FLAG_TCIF4)!=RESET)
		{
			DMA_ClearFlag(DMA1_Stream4,DMA_FLAG_TCIF4);
			break;
		}
	}
}

DMA刷屏

void LCD_CL_DMA(u16 Color);
void LCD_CL_DMA(u16 Color)
{
	DMA1_MEM_LEN=2*128;//DMA数据缓冲区大小
	LCD_SetWindow(0,0,127,159);
	RS_High;
	for(u16 j=0;j<2*128;)
	{
		SendBuff[j]=Color>>8;
		SendBuff[j+1]=Color;
		j+=2;
	}
	for(u16 i=0;i<160;i++)
	{
		DMA_GO();
	}
}

st7735头文件

//引脚宏定义
#define SCL GPIO_Pin_13
#define SDA GPIO_Pin_15
#define RS GPIO_Pin_10
#define CS GPIO_Pin_12

//管脚高低电平切换
#define SCL_Low GPIO_ResetBits(GPIOB,GPIO_Pin_13)
#define SDA_Low GPIO_ResetBits(GPIOB,GPIO_Pin_15)
#define RS_Low GPIO_ResetBits(GPIOB,GPIO_Pin_10)
#define CS_Low GPIO_ResetBits(GPIOB,GPIO_Pin_12)

#define SCL_High GPIO_SetBits(GPIOB,GPIO_Pin_13)
#define SDA_High GPIO_SetBits(GPIOB,GPIO_Pin_15)
#define RS_High GPIO_SetBits(GPIOB,GPIO_Pin_10)
#define CS_High GPIO_SetBits(GPIOB,GPIO_Pin_12)

//颜色代码
#define RED  	0xf800
#define GREEN	0x07e0
#define BLUE 	0x001f
#define WHITE	0xffff
#define BLACK	0x0000
#define YELLOW  0xFFE0
#define GRAY0   0xEF7D
#define GRAY1   0x8410 
#define GRAY2   0x4208

typedef struct
{
	u16 width;			//LCD 宽度
	u16 height;		//LCD 高度
}_lcd_dev;

extern _lcd_dev lcd_setting;

void LCD_Init(void);
void WR_Cmd(u8 Cmd);
void WR_Data(u8 Data);
void WR_Data16(u16 Data);
void WR_Reg(u8 Cmd,u16 Data);
void LCD_RESET(void);//复位
void LCD_SetPos(u16 X,u16 Y);//设置光标位置
void LCD_SetWindow(u16 XS,u16 YS,u16 XE,u16 YE);//设置显示窗口并准备写入数据
void LCD_Clear(u16 Color);//硬件SPI刷屏

③初始化st7735

_lcd_dev lcd_setting;//LCD参数
u8 SendBuff[2*128];//调用DMA的SendBuff

void LCD_Init(void)
{
	SPI2_Init();			 
 	LCD_RESET();

	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);
	MYDMA_Config(DMA1_Stream4,(u32)&SPI2->DR,(u32)SendBuff,2*128);
	//************* Start Initial Sequence **********//		
	WR_Cmd(0x11);//Sleep exit 
	delay_ms (120);		
//ST7735R Frame Rate
	WR_Cmd(0xB1); 
	WR_Data(0x01); 
	WR_Data(0x2C); 
	WR_Data(0x2D); 

	WR_Cmd(0xB2); 
	WR_Data(0x01); 
	WR_Data(0x2C); 
	WR_Data(0x2D); 

	WR_Cmd(0xB3); 
	WR_Data(0x01); 
	WR_Data(0x2C); 
	WR_Data(0x2D); 
	WR_Data(0x01); 
	WR_Data(0x2C); 
	WR_Data(0x2D); 
	
	WR_Cmd(0xB4); //Column inversion 
	WR_Data(0x07); 
	
	//ST7735R Power Sequence
	WR_Cmd(0xC0); 
	WR_Data(0xA2); 
	WR_Data(0x02); 
	WR_Data(0x84); 
	WR_Cmd(0xC1); 
	WR_Data(0xC5); 

	WR_Cmd(0xC2); 
	WR_Data(0x0A); 
	WR_Data(0x00); 

	WR_Cmd(0xC3); 
	WR_Data(0x8A); 
	WR_Data(0x2A); 
	WR_Cmd(0xC4); 
	WR_Data(0x8A); 
	WR_Data(0xEE); 
	
	WR_Cmd(0xC5); //VCOM 
	WR_Data(0x0E); 
	
	WR_Cmd(0x36); //MX, MY, RGB mode 				 
	WR_Data(0xC8); 
	
	//ST7735R Gamma Sequence
	WR_Cmd(0xe0); 
	WR_Data(0x0f); 
	WR_Data(0x1a); 
	WR_Data(0x0f); 
	WR_Data(0x18); 
	WR_Data(0x2f); 
	WR_Data(0x28); 
	WR_Data(0x20); 
	WR_Data(0x22); 
	WR_Data(0x1f); 
	WR_Data(0x1b); 
	WR_Data(0x23); 
	WR_Data(0x37); 
	WR_Data(0x00); 	
	WR_Data(0x07); 
	WR_Data(0x02); 
	WR_Data(0x10); 

	WR_Cmd(0xe1); 
	WR_Data(0x0f); 
	WR_Data(0x1b); 
	WR_Data(0x0f); 
	WR_Data(0x17); 
	WR_Data(0x33); 
	WR_Data(0x2c); 
	WR_Data(0x29); 
	WR_Data(0x2e); 
	WR_Data(0x30); 
	WR_Data(0x30); 
	WR_Data(0x39); 
	WR_Data(0x3f); 
	WR_Data(0x00); 
	WR_Data(0x07); 
	WR_Data(0x03); 
	WR_Data(0x10);  
	
	WR_Cmd(0x2a);
	WR_Data(0x00);
	WR_Data(0x00);
	WR_Data(0x00);
	WR_Data(0x7f);

	WR_Cmd(0x2b);
	WR_Data(0x00);
	WR_Data(0x00);
	WR_Data(0x00);
	WR_Data(0x9f);
	
	WR_Cmd(0xF0); //Enable test command  
	WR_Data(0x01); 
	WR_Cmd(0xF6); //Disable ram power save mode 
	WR_Data(0x00); 
	
	WR_Cmd(0x3A); //65k mode 
	WR_Data(0x05); 	
	WR_Cmd(0x29);//Display on	
	
	lcd_setting.width=128;//设置宽度
	lcd_setting.height=160;//设置高度
	WR_Reg(0x36,0xA8);
}

各种LCD必要函数

//写指令
void WR_Cmd(u8 Cmd)
{
	CS_Low;
	RS_Low;
	SPI_WriteByte(SPI2,Cmd);
	CS_High;
}
//写数据
void WR_Data(u8 Data)
{
	CS_Low;
	RS_High;
	SPI_WriteByte(SPI2,Data);
	CS_High;
}
//写16位数据(颜色)
void WR_Data16(u16 Data)
{
	CS_Low;
	RS_High;
	SPI_WriteByte(SPI2,Data>>8);
	SPI_WriteByte(SPI2,Data);
	CS_High;
}
//同时写指令和数据
void WR_Reg(u8 Cmd,u16 Data)
{
	WR_Cmd(Cmd);
	WR_Data16(Data);
}
//复位
void LCD_RESET(void)
{
		delay_ms(100);
	
		delay_ms(50);
}
//设置光标位置
void LCD_SetPos(u16 X,u16 Y)
{
	LCD_SetWindow(X,Y,X,Y);
}
//设置显示窗口
void LCD_SetWindow(u16 XS,u16 YS,u16 XE,u16 YE)
{
	WR_Cmd(0x2A);
	WR_Data(XS>>8);
	WR_Data(XS);
	WR_Data(XE>>8);
	WR_Data(XE);
	WR_Cmd(0x2B);
	WR_Data(YS>>8);
	WR_Data(YS);
	WR_Data(YE>>8);
	WR_Data(YE);
	WR_Cmd(0x2C);
}

硬件SPI刷屏

void LCD_Clear(u16 Color)
{
	u16 i,j;
LCD_SetWindow(0,0,lcd_setting.width-1,lcd_setting.height-1);	  
	for(i=0;i<lcd_setting.width;i++)
	{
		for(j=0;j<lcd_setting.height;j++)
		WR_Data16(Color);	//写入数据 	 
	}

}

main.c

int main(void)
{
	delay_init(168);
	LCD_Init();
	LCD_Clear(WHITE);
	while(1)
		{
			LCD_CL_DMA(RED);
			LCD_CL_DMA(BLUE);
			LCD_CL_DMA(GREEN);
            //LCD_Clear(RED);
            //LCD_Clear(BLUE);
            //LCD_Clear(GREEN);
		}
}

效果视频:

SPI STM32F407VET6学习笔记

SPI+DMA STM32F407VET6学习笔记

 踩坑地方:

初始化屏幕函数不对

写指令要先拉低CS和DC,写数据就要拉低CS,拉高DC,写完都要拉高CS

配置DMA要注意流和道的说明

如F4的说明指南:

现在我的代码使用的是SPI2的DMA1

所以要设置成DMA1_Stream4和DMA1_Channel0才可以正常使用

F4框图:

如图可以知道你配置RCC_AxBxPeriphClockCmd();AxBx所对应的线

文中配置的SPI2就得使用APB1的时钟使能

其他如DMA,I2C,USART等等都是如此时钟使能再进行管脚配置初始化

F4管脚图:

如图中的SPI2定义的管脚为PB12—PB15

在管脚定义的时候就使能GPIOB和SPI2,然后把GPIOB的管脚GPIO_Pin配置成对应的12—15

SPI2,DMA根据所需来配置

  • 6
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值