本帖最后由 sujingliang 于 2024-7-3 11:55 编辑
一、SPI初始化
1、SPI_InitStruct.SPI_BaudRatePrescaler设置越小,SPI频率越高,16好像是极限了,不能再小了。
2、SPI1用于驱动板上的flash了,所以驱动LCD要用SPI2。
void LCD_SPI_Configure(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
SPI_InitTypeDef SPI_InitStruct;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
SPI_StructInit(&SPI_InitStruct);
SPI_InitStruct.SPI_Mode = SPI_Mode_Master;
SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStruct.SPI_DataWidth = 8;
SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStruct.SPI_NSS = SPI_NSS_Soft;
SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_Init(SPI2, &SPI_InitStruct);
SPI_BiDirectionalLineConfig(SPI2, SPI_Direction_Rx);
SPI_BiDirectionalLineConfig(SPI2, SPI_Direction_Tx);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource12, GPIO_AF_5); //SPI2_NSS PB12
GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_5); //SPI2_SCK PB13
GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_5); //SPI2_MISO PB14
GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_5); //SPI2_MOSI PB15
GPIO_StructInit(&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_15;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_High;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_14;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOB, &GPIO_InitStruct);
SPI_Cmd(SPI2, ENABLE);
//初始化LCD_DC、LCD_RST、LCD_LED
GPIO_StructInit(&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_10|GPIO_Pin_11;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_High;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStruct);
}
二、DMA设置
1、首先申请一个内存做为DMA的源地址:
之所以申请256*16个地址,是因为ST7735是一个128*128分辨率的LCD,一行128个点,由于是彩屏,每个点color值用2个字节,一行就是256个字节;另外一个汉字点阵是16*16,所以申请256*16这么一个空间,可以显示一行汉字。
#define DMABUFFERSIZE 256*16
uint8_t DMA_TxBuffer[DMABUFFERSIZE];
2、DMA向发送SPI2数据
1)DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&(SPI2->TXREG);
DMA_PeripheralBaseAddr外设地址要这么设置,可以从DMA_TxBuffer地址发送到SPI2
2)DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
外设地址是固定的
3)DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;源地址每次要增加,这样可以保障DMA_TxBuffer里的数据都发送给SPI2.
4)DMA_Cmd(DMA1_Channel4, ENABLE);
DMA_Cmd(DMA1_Channel5, ENABLE);
根据数据手册DAM channel要这么设置
void SPI_TxData_DMA_Polling(uint8_t *Buffer, uint16_t Length)
{
DMA_InitTypeDef DMA_InitStruct;
uint8_t DataCache = 0;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
DMA_DeInit(DMA1_Channel4);
DMA_DeInit(DMA1_Channel5);
DMA_StructInit(&DMA_InitStruct);
DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&(SPI2->RXREG);
DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)&DataCache;
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStruct.DMA_BufferSize = Length;
DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Disable;
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;
DMA_InitStruct.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;
DMA_InitStruct.DMA_Auto_Reload = DMA_Auto_Reload_Disable;
DMA_Init(DMA1_Channel4, &DMA_InitStruct);
DMA_StructInit(&DMA_InitStruct);
DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&(SPI2->TXREG);
DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)Buffer;
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStruct.DMA_BufferSize = Length;
DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;
DMA_InitStruct.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;
DMA_InitStruct.DMA_Auto_Reload = DMA_Auto_Reload_Disable;
DMA_Init(DMA1_Channel5, &DMA_InitStruct);
DMA_Cmd(DMA1_Channel4, ENABLE);
DMA_Cmd(DMA1_Channel5, ENABLE);
SPI_DMACmd(SPI2, ENABLE);
while (RESET == DMA_GetFlagStatus(DMA1_FLAG_TC4))
{
}
while (RESET == DMA_GetFlagStatus(DMA1_FLAG_TC5))
{
}
SPI_DMACmd(SPI2, DISABLE);
DMA_Cmd(DMA1_Channel4, DISABLE);
DMA_Cmd(DMA1_Channel5, DISABLE);
}
3、对源数据控制函数:
把DMA+SPI发送函数包装下:
void SPI_LCD_TxBuffer(uint8_t *Buffer, uint16_t Length)
{
if (Length)
{
SPI_TxData_DMA_Polling(Buffer, Length);
}
}
发送16行到LCD
//16行
void sendOneLineDataDMA(void)
{
LCD_CS_RESET();
LCD_DC_SET();
SPI_LCD_TxBuffer(DMA_TxBuffer,DMABUFFERSIZE);
LCD_CS_SET();
}
DMA方式清屏,
void GUI_Clear(uint16_t Color) //清屏
{
uint16_t i,j;
ST7735_SetWindow(0, 0, X_MAX_PIXEL, Y_MAX_PIXEL);
for(i=0;i<DMABUFFERSIZE/2;i++){
DMA_TxBuffer[i*2]=Color>>8;
DMA_TxBuffer[i*2+1]=Color&0xFF;
}
for(i=0;i<Y_MAX_PIXEL/16;i++)
{
sendOneLineDataDMA();
}
}
在DMA_TxBuffer上画点,相当于在128*16区域设置每个点的颜色值
void Gui_DrawPoint_DMA(uint16_t x,uint16_t y,uint16_t Data)
{
DMA_TxBuffer[2*x+y*256]=Data>>8;
DMA_TxBuffer[2*x+y*256+1]=Data;
}
用一个颜色值将整个源数据填满
void set_DMA_TxBuffer(uint16_t Data)
{
uint16_t i,j;
for(i=0;i<16;i++)
{
for(j=0;j<X_MAX_PIXEL;j++)
{
Gui_DrawPoint_DMA(j,i,Data);
}
}
}
4、DMA方式发送汉字、ASCIIvoid GUI_WriteCN16x16DMA(uint16_t x, uint16_t y,const uint8_t *cn, uint16_t wordColor, uint16_t backColor)
{
uint16_t i, j, mx,my,wordByte;
uint16_t zm;
uint16_t color;
uint8_t wordNum;
mx=x;
my=y;
while (*cn != '\0')
{
if(mx>119){
ST7735_SetWindow(0,my,X_MAX_PIXEL,16);
sendOneLineDataDMA();
mx=x;
my+=16;
memset(DMA_TxBuffer,0,sizeof(DMA_TxBuffer));
}
if(*cn<128){
wordNum = *cn - 32;
for (wordByte=0; wordByte<16; wordByte++)
{
color = Font_Data[wordNum].dat[wordByte];
for (j=0; j<8; j++)
{
if ((color&0x80) == 0x80)
{
Gui_DrawPoint_DMA(mx+j,(my+wordByte)%16,wordColor);
}
else
{
Gui_DrawPoint_DMA(mx+j,(my+wordByte)%16,backColor);
}
color <<= 1;
}
}
cn++;
mx +=8;
}
else
{
zm=*cn;
zm<<=8;
zm|=*(cn+1);
getMatrix(zm);
for(i=0; i<32; i++)
{ //MSK的位数
color=MatrixBuff[i];
for(j=0;j<8;j++)
{
if((color&0x80)==0x80)
{
Gui_DrawPoint_DMA(mx+j+(i%2)*8,i/2,wordColor);
}
else
{
Gui_DrawPoint_DMA(mx+j+(i%2)*8,i/2,backColor);
}
color<<=1;
}//for(j=0;j<8;j++)结束
}
cn += 2;
mx += 16;
}
}
ST7735_SetWindow(0,my,X_MAX_PIXEL, 16);
sendOneLineDataDMA();
set_DMA_TxBuffer(backColor);
my+=16;
while(my<(Y_MAX_PIXEL)){
ST7735_SetWindow(0,my,X_MAX_PIXEL, 16);
sendOneLineDataDMA();
my+=16;
}
}
5、实验:
void ST7735_Init(void)
{
char buf[16];
LCD_LED_SET();
LCD_SPI_Configure();
ST7735_HardReset();
ST7735_SendInitStr();
GUI_Clear(COLOR_Red);
sprintf(buf,"%d ",maxPage);
GUI_WriteCN16x16(20,20,buf,COLOR_Red,COLOR_Black);
PLATFORM_DelayMS(1000);
GUI_Clear(COLOR_Blue);
GUI_WriteCN16x16(20,20,buf,COLOR_Red,COLOR_Black);
PLATFORM_DelayMS(1000);
GUI_Clear(COLOR_Green);
GUI_WriteCN16x16(20,20,buf,COLOR_Red,COLOR_Black);
PLATFORM_DelayMS(1000);
}
三、演示效果
四、源码
mini-f53330_USART_Polling.rar
(188.6 KB)
|
此文章已获得独家原创/原创奖标签,著作权归21ic所有,未经允许禁止转载。
|