DMA简单介绍
DMA 直接内存搬运技术,使数据不经过cpu,直接从内存搬运到spi的发送的寄存器里面,这样做的好处是减少cpu的负担,而且能大大提升显示屏的刷新速率
使用spi直接驱动ST7789显示屏
最开始我是用spi直接驱动 显示屏幕,但我发现即使是使用spi的最大频率发送数据,刷屏的速率依旧很慢
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| #include "delay.h" #include "sys.h" #include "st7789.h" int main(void) { delay_init(); initlcd(); while(1){ fillScreen(0xf800); fillScreen(0); } }
|
<st7789.h>
1 2 3 4 5 6 7 8 9 10
| #include "sys.h" #define DC PBout(11) void initlcd(); void writeData(u8 data); void writeCommand(u8 data); void fillScreen(u16 color); void SPI1_Init(void); void SPI1_SetSpeed(u8 SpeedSet); u8 SPI1_ReadWriteByte(u8 TxData);
|
<st7789.c>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
| #include "st7789.h" #include "delay.h"
SPI_InitTypeDef SPI_InitStructure;
void SPI1_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA|RCC_APB2Periph_SPI1, ENABLE ); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(SPI1, &SPI_InitStructure); SPI_Cmd(SPI1, ENABLE); SPI1_ReadWriteByte(0xff); }
void SPI1_SetSpeed(u8 SpeedSet) { SPI_InitStructure.SPI_BaudRatePrescaler = SpeedSet ; SPI_Init(SPI1, &SPI_InitStructure); SPI_Cmd(SPI1,ENABLE); }
u8 SPI1_ReadWriteByte(u8 TxData) { u8 retry=0; while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET) { retry++; if(retry>200)return 0; } SPI_I2S_SendData(SPI1, TxData); retry=0;
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET) { retry++; if(retry>200)return 0; } return SPI_I2S_ReceiveData(SPI1); }
void initlcd(){ RCC->APB2ENR|=1<<3; GPIOB->CRH&=0XFFFF0FFF; GPIOB->CRH|=0X00003000; GPIOB->ODR|=1<11;
SPI1_Init(); SPI1_SetSpeed(SPI_BaudRatePrescaler_2); writeCommand(0x01); delay_us(150); writeCommand(0x11); delay_us(120); writeCommand(0x3A); writeData(0x55); writeCommand(0x36); writeData(0x00); writeCommand(0x21); writeCommand(0x13); writeCommand(0x29); } void writeData(u8 data){ DC = 1; SPI1_ReadWriteByte(data); }
void writeCommand(u8 cmd){ DC = 0; SPI1_ReadWriteByte(cmd); }
void fillScreen(u16 color){ u16 i ,j; writeCommand(0x2A); writeData(0); writeData(0); writeData(0); writeData(240); writeCommand(0X2B); writeData(0); writeData(0); writeData(0X01); writeData(0X40); writeCommand(0X2C); for(i = 0 ; i<240 ; i++){ for(j = 0 ; j<320 ; j++){ writeData(color>>8); writeData(color); } } }
|
结果
刷新频率约 1秒3帧
使用spi加dma驱动ST7789显示屏
在使dma搬运数据后刷新速率有了明显的提升
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| #include "delay.h" #include "sys.h" #include "st7789.h" int main(void) { delay_init(); initlcd(); while(1){ fillScreen(0xf800); fillScreen(0xffff); } }
|
<st7789.h>
1 2 3 4 5 6 7 8 9 10 11 12
| #include "sys.h" #define DC PBout(11) void initlcd(); void writeData(u8 data); void writeCommand(u8 data); void fillScreen(u16 color); void SPI1_Init(void); void SPI1_SetSpeed(u8 SpeedSet); u8 SPI1_ReadWriteByte(u8 TxData); void MYDMA_Config(DMA_Channel_TypeDef*DMA_CHx,u32 cpar,u32 cmar,u16 cndtr); void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx);
|
<st7789.c>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
| #include "st7789.h" #include "delay.h" #include "sys.h" u8 SendBuff[480]; DMA_InitTypeDef DMA_InitStructure; u16 DMA1_MEM_LEN;
void MYDMA_Config(DMA_Channel_TypeDef* DMA_CHx,u32 cpar,u32 cmar,u16 cndtr) { RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); DMA_DeInit(DMA_CHx); DMA1_MEM_LEN=cndtr; DMA_InitStructure.DMA_PeripheralBaseAddr = cpar; DMA_InitStructure.DMA_MemoryBaseAddr = cmar; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; 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_M2M = DMA_M2M_Disable; DMA_Init(DMA_CHx, &DMA_InitStructure); }
void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx) { DMA_Cmd(DMA_CHx, DISABLE ); DMA_SetCurrDataCounter(DMA1_Channel3,DMA1_MEM_LEN); DMA_Cmd(DMA_CHx, ENABLE); }
SPI_InitTypeDef SPI_InitStructure;
void SPI1_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA|RCC_APB2Periph_SPI1, ENABLE ); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(SPI1, &SPI_InitStructure); SPI_Cmd(SPI1, ENABLE); SPI1_ReadWriteByte(0xff); } void SPI1_SetSpeed(u8 SpeedSet) { SPI_InitStructure.SPI_BaudRatePrescaler = SpeedSet ; SPI_Init(SPI1, &SPI_InitStructure); SPI_Cmd(SPI1,ENABLE); }
u8 SPI1_ReadWriteByte(u8 TxData) { u8 retry=0; while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET) { retry++; if(retry>200)return 0; } SPI_I2S_SendData(SPI1, TxData); retry=0;
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET) { retry++; if(retry>200)return 0; } return SPI_I2S_ReceiveData(SPI1); }
void initlcd(){
RCC->APB2ENR|=1<<3; GPIOB->CRH&=0XFFFF0FFF; GPIOB->CRH|=0X00003000; GPIOB->ODR|=1<11; SPI1_Init(); SPI1_SetSpeed(SPI_BaudRatePrescaler_2); MYDMA_Config(DMA1_Channel3,(u32)&SPI1->DR,(u32)SendBuff,480); writeCommand(0x01); delay_us(150); writeCommand(0x11); delay_us(120); writeCommand(0x3A); writeData(0x55); writeCommand(0x36); writeData(0x00); writeCommand(0x21); writeCommand(0x13); writeCommand(0x29); } void writeData(u8 data){ DC = 1; SPI1_ReadWriteByte(data); }
void writeCommand(u8 cmd){ DC = 0; SPI1_ReadWriteByte(cmd); }
void fillScreen(u16 color){ u16 i ,j; writeCommand(0x2A); writeData(0); writeData(0); writeData(0); writeData(240); writeCommand(0X2B); writeData(0); writeData(0); writeData(0X01); writeData(0X40); writeCommand(0X2C); DC = 1; for(j=0 ;j<480;){ SendBuff[j] = color>>8; SendBuff[j+1] = color; j += 2; }
for(i = 0 ; i<320 ; i++){ SPI_I2S_DMACmd(SPI1,SPI_I2S_DMAReq_Tx,ENABLE); MYDMA_Enable(DMA1_Channel3); while(1){ if(DMA_GetFlagStatus(DMA1_FLAG_TC3)!=RESET) { DMA_ClearFlag(DMA1_FLAG_TC3); break; } } }
}
|
结果
刷新速率约一秒十多帧
连线
DC(A0)———— PB11
CLK———– PA5
MISO——— PA6
MOSI(SDA)——— PA7
CS———— GND
RESET———— VDD
BL———— VDD
引用
dma和spi部分参考正点原子代码,示例使用的主控芯片是stm32f103
相关链接(侵删)
- 基于stm32 标准库spi驱动st7789(使用DMA)
=================我是分割线=================
欢迎到公众号来唠嗑: