• 3线硬件SPI+DMA驱动 HX8347 TFT屏


    3线硬件SPI+DMA驱动 HX8347 TFT屏,实现用DMA清屏。

    a81c5161c51b4678bbb7adaeaebc35ee.jpg

    参考:基于stm32 标准库spi驱动st7789彩屏TFT(使用DMA)-技术天地-深圳市修德电子有限公司

    一、源码

    HX8347.h

    1. #ifndef USER_HX8347_H_
    2. #define USER_HX8347_H_
    3. #define SPI_hardware
    4. #define SPI_hardware_dma
    5. #define Buf_Size 480
    6. #define X_MAX_PIXEL 240
    7. #define Y_MAX_PIXEL 320
    8. #define RED 0xf800
    9. #define GREEN 0x07e0
    10. #define BLUE 0x001f
    11. #define WHITE 0xffff
    12. #define BLACK 0x0000
    13. #define YELLOW 0xFFE0
    14. #define GRAY0 0xEF7D //灰色0 3165 00110 001011 00101
    15. #define GRAY1 0x8410 //灰色1 00000 000000 00000
    16. #define GRAY2 0x4208 //灰色2 1111111111011111
    17. #ifdef SPI_hardware
    18. #define LCD_CS GPIO_Pin_0 // CS:PA0
    19. #define LCD_SDA GPIO_Pin_7 // SDA:PA7 SPI1 //硬件SPI实现,不用人工处理
    20. #define LCD_SCL GPIO_Pin_5 // SCL:PA5 SPI1 //硬件SPI实现,不用人工处理
    21. #define LCD_RST GPIO_Pin_4 // RST:PA4
    22. #else
    23. #define LCD_CS GPIO_Pin_0 // CS:PA0
    24. #define LCD_SDA GPIO_Pin_1 // SDA:PA1
    25. #define LCD_SCL GPIO_Pin_3 // SCL:PA3
    26. #define LCD_RST GPIO_Pin_4 // RST:PA4
    27. #endif
    28. #define LCD_SCL_SET GPIO_WriteBit(GPIOA, LCD_SCL,Bit_SET)
    29. #define LCD_SDA_SET GPIO_WriteBit(GPIOA, LCD_SDA,Bit_SET)
    30. #define LCD_CS_SET GPIO_WriteBit(GPIOA, LCD_CS,Bit_SET)
    31. #define LCD_RST_SET GPIO_WriteBit(GPIOA, LCD_RST,Bit_SET)
    32. #define LCD_SCL_CLR GPIO_WriteBit(GPIOA, LCD_SCL,Bit_RESET)
    33. #define LCD_SDA_CLR GPIO_WriteBit(GPIOA, LCD_SDA,Bit_RESET)
    34. #define LCD_CS_CLR GPIO_WriteBit(GPIOA, LCD_CS,Bit_RESET)
    35. #define LCD_RST_CLR GPIO_WriteBit(GPIOA, LCD_RST,Bit_RESET)
    36. void LCD_GPIO_Init(void);
    37. void Lcd_WriteIndex(unsigned char Index);
    38. void Lcd_WriteData(unsigned char Data);
    39. void LCD_WriteData_16Bit(unsigned int Data);
    40. void Lcd_Write_REG(unsigned char Index,unsigned char Data);
    41. void LCD_Init(void);
    42. void Lcd_Clear(unsigned int Color);
    43. void FillRect(u16 x1, u16 y1, u16 x2, u16 y2, u16 color);
    44. void FillRect_DMA(u16 color);
    45. void Gui_DrawFont_GBK16(unsigned int x, unsigned int y, unsigned int fc, unsigned int bc, unsigned char *s);
    46. #endif /* USER_HX8347_H_ */

    HX8347.c

    1. #include "debug.h"
    2. #include "HX8347.h"
    3. #include "font.h"
    4. extern unsigned char TxData[];
    5. extern void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx);
    6. void LCD_GPIO_Init(void)
    7. {
    8. GPIO_InitTypeDef GPIO_InitStructure = {0};
    9. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    10. #ifdef SPI_hardware
    11. GPIO_InitStructure.GPIO_Pin = LCD_CS|LCD_RST;
    12. #else
    13. GPIO_InitStructure.GPIO_Pin = LCD_SCL|LCD_SDA|LCD_CS|LCD_RST;
    14. #endif
    15. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    16. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    17. GPIO_Init(GPIOA, &GPIO_InitStructure);
    18. }
    19. //向SPI总线传输一个8位数据
    20. void SPI_WriteData(unsigned char Data)
    21. {
    22. #ifdef SPI_hardware
    23. SPI_I2S_SendData( SPI1, Data);
    24. while( SPI_I2S_GetFlagStatus( SPI1, SPI_I2S_FLAG_TXE ) == RESET );
    25. //Delay_Us(1);
    26. uint32_t i;
    27. SysTick->SR &= ~(1 << 0);
    28. i = 8;
    29. SysTick->CMP = i;
    30. SysTick->CTLR |= (1 << 4);
    31. SysTick->CTLR |= (1 << 5) | (1 << 0);
    32. while((SysTick->SR & (1 << 0)) != (1 << 0))
    33. ;
    34. SysTick->CTLR &= ~(1 << 0);
    35. #else
    36. unsigned char i=0;
    37. for(i=8;i>0;i--)
    38. {
    39. if(Data&0x80)
    40. LCD_SDA_SET; //输出数据
    41. else LCD_SDA_CLR;
    42. LCD_SCL_CLR;
    43. LCD_SCL_SET;
    44. Data<<=1;
    45. }
    46. #endif
    47. }
    48. //向液晶屏写一个8位指令
    49. void Lcd_WriteIndex(unsigned char Index)
    50. {
    51. //SPI 写命令时序开始
    52. LCD_CS_CLR;
    53. SPI_WriteData(0x70);
    54. SPI_WriteData(Index);
    55. LCD_CS_SET;
    56. }
    57. //向液晶屏写一个8位数据
    58. void Lcd_WriteData(unsigned char Data)
    59. {
    60. LCD_CS_CLR;
    61. SPI_WriteData(0x72);
    62. SPI_WriteData(Data);
    63. LCD_CS_SET;
    64. }
    65. //向液晶屏写一个16位数据
    66. void LCD_WriteData_16Bit(unsigned int Data)
    67. {
    68. LCD_CS_CLR;
    69. SPI_WriteData(0x72);
    70. SPI_WriteData(Data>>8);
    71. SPI_WriteData(Data);
    72. LCD_CS_SET;
    73. }
    74. void Lcd_Write_REG(unsigned char Index,unsigned char Data)
    75. {
    76. Lcd_WriteIndex(Index);
    77. Lcd_WriteData(Data);
    78. }
    79. void Lcd_Reset(void)
    80. {
    81. LCD_RST_CLR;
    82. Delay_Ms(50);
    83. LCD_RST_SET;
    84. Delay_Ms(50);
    85. }
    86. // set region to paint
    87. void LCD_SetWindow(unsigned int x1,unsigned int y1,unsigned int x2,unsigned int y2)
    88. {
    89. //SC
    90. Lcd_Write_REG(0x02,x1>>8); // Column address start2
    91. Lcd_Write_REG(0x03,(u8)x1); // Column address start1
    92. //EC
    93. Lcd_Write_REG(0x04,x2>>8); // Column address end2
    94. Lcd_Write_REG(0x05,(u8)x2); // Column address end1
    95. //SP
    96. Lcd_Write_REG(0x06,y1>>8); // Row address start2
    97. Lcd_Write_REG(0x07,(u8)y1); // Row address start1
    98. //EP
    99. Lcd_Write_REG(0x08,y2>>8); // Row address end2
    100. Lcd_Write_REG(0x09,(u8)y2); // Row address end1
    101. //写0x22到index register,那么下次send data就会直接被写到graphic ram
    102. Lcd_WriteIndex(0x22);
    103. }
    104. void FillRect(u16 x1, u16 y1, u16 x2, u16 y2, u16 color)
    105. {
    106. LCD_SetWindow(x1, y1,x2,y2);
    107. x2 = x2 - x1 + 1;
    108. y2 = y2 - y1 + 1;
    109. LCD_CS_CLR;
    110. SPI_WriteData(0x72);
    111. for(x1 = x2; x1 != 0 ; x1--)
    112. {
    113. for (y1 = y2;y1 != 0 ;y1--)
    114. {
    115. SPI_WriteData(color>>8);
    116. SPI_WriteData(color);
    117. }
    118. }
    119. LCD_CS_SET;
    120. }
    121. void FillRect_DMA(u16 color)
    122. {
    123. int16_t j;
    124. LCD_SetWindow(0, 0,239,319);
    125. LCD_CS_CLR;
    126. SPI_WriteData(0x72);
    127. for(j=0 ;j<480;){
    128. TxData[j] = color>>8;
    129. TxData[j+1] = color;
    130. j += 2;
    131. }
    132. for(j = 0 ; j<320 ; j++){
    133. SPI_I2S_DMACmd(SPI1,SPI_I2S_DMAReq_Tx,ENABLE);
    134. MYDMA_Enable(DMA1_Channel3);
    135. while(1){
    136. if(DMA_GetFlagStatus(DMA1_FLAG_TC3)!=RESET)
    137. {
    138. DMA_ClearFlag(DMA1_FLAG_TC3);
    139. break;
    140. }
    141. }
    142. }
    143. LCD_CS_SET;
    144. }
    145. void LCD_Init(void)
    146. {
    147. //LCD_GPIO_Init();
    148. Lcd_Reset();
    149. Lcd_Write_REG(0x18,0x88); //UADJ 75Hz
    150. Lcd_Write_REG(0x19,0x01); //OSC_EN='1', start Osc
    151. //Power Voltage Setting
    152. Lcd_Write_REG(0x1B,0x1e); //VRH=4.60V 0x1e
    153. Lcd_Write_REG(0x1C,0x04); //AP Crosstalk 04
    154. Lcd_Write_REG(0x1A,0x01); //BT (VGH~15V,VGL~-10V,DDVDH~5V) 0x01
    155. Lcd_Write_REG(0x24,0x21); //VMH 27 0x38
    156. Lcd_Write_REG(0x25,0x5F); //VML
    157. //VCOM offset
    158. Lcd_Write_REG(0x23,0x8C); //for Flicker adjust
    159. Lcd_Write_REG(0x1F,0x88);// GAS=1, VOMG=00, PON=0, DK=1, XDK=0, DVDH_TRI=0, STB=0
    160. Delay_Ms(50);
    161. Lcd_Write_REG(0x1F,0x80);// GAS=1, VOMG=00, PON=0, DK=0, XDK=0, DVDH_TRI=0, STB=0
    162. Delay_Ms(50);
    163. Lcd_Write_REG(0x1F,0x90);// GAS=1, VOMG=00, PON=1, DK=0, XDK=0, DVDH_TRI=0, STB=0
    164. Delay_Ms(50);
    165. Lcd_Write_REG(0x1F,0xD0);// GAS=1, VOMG=10, PON=1, DK=0, XDK=0, DDVDH_TRI=0, STB=0
    166. Delay_Ms(50);
    167. //Display ON Setting
    168. Lcd_Write_REG(0x28,0x38); //GON=1, DTE=1, D=1000
    169. Delay_Ms(50);
    170. Lcd_Write_REG(0x28,0x3C); //GON=1, DTE=1, D=1100
    171. Lcd_Write_REG(0x36,0x09); //REV, BGR
    172. Lcd_Write_REG(0x17,0x05); //16BIT/PIXEL
    173. //Gamma 2.2 Setting
    174. Lcd_Write_REG(0x40,0x00); //
    175. Lcd_Write_REG(0x41,0x00); //
    176. Lcd_Write_REG(0x42,0x00); //
    177. Lcd_Write_REG(0x43,0x11); //
    178. Lcd_Write_REG(0x44,0x0e); //
    179. Lcd_Write_REG(0x45,0x23); //
    180. Lcd_Write_REG(0x46,0x08); //
    181. Lcd_Write_REG(0x47,0x53); //
    182. Lcd_Write_REG(0x48,0x03); //
    183. Lcd_Write_REG(0x49,0x11); //
    184. Lcd_Write_REG(0x4A,0x18); //
    185. Lcd_Write_REG(0x4B,0x1a); //
    186. Lcd_Write_REG(0x4C,0x16); //
    187. Lcd_Write_REG(0x50,0x1c); //
    188. Lcd_Write_REG(0x51,0x31); //
    189. Lcd_Write_REG(0x52,0x2e); //
    190. Lcd_Write_REG(0x53,0x3f); //
    191. Lcd_Write_REG(0x54,0x3f); //
    192. Lcd_Write_REG(0x55,0x3f); //
    193. Lcd_Write_REG(0x56,0x2c); //
    194. Lcd_Write_REG(0x57,0x77); //
    195. Lcd_Write_REG(0x58,0x09); //
    196. Lcd_Write_REG(0x59,0x05); //
    197. Lcd_Write_REG(0x5A,0x07); //
    198. Lcd_Write_REG(0x5B,0x0e); //
    199. Lcd_Write_REG(0x5C,0x1c); //
    200. Lcd_Write_REG(0x5D,0x88); //
    201. Delay_Ms(100);
    202. FillRect(0, 0, 239, 319, RED );
    203. }
    204. /*************************************************
    205. 函数名:LCD_DrawPoint
    206. 功能:画一个点
    207. 入口参数:无
    208. 返回值:无
    209. *************************************************/
    210. void Gui_DrawPoint(unsigned int x,unsigned int y,unsigned int Data)
    211. {
    212. LCD_SetWindow(x,y,x+1,y+1);
    213. LCD_WriteData_16Bit(Data);
    214. }
    215. void Gui_DrawFont_GBK16(unsigned int x, unsigned int y, unsigned int fc, unsigned int bc,unsigned char *s)
    216. {
    217. unsigned char i,j;
    218. unsigned short k,x0;
    219. x0=x;
    220. while(*s)
    221. {
    222. if((*s) < 128)
    223. {
    224. k=*s;
    225. if (k==13)
    226. {
    227. x=x0;
    228. y+=16;
    229. }
    230. else
    231. {
    232. if (k>32) k-=32; else k=0;
    233. for(i=0;i<16;i++)
    234. for(j=0;j<8;j++)
    235. {
    236. if(asc16[k*16+i]&(0x80>>j)) Gui_DrawPoint(x+j,y+i,fc);
    237. else
    238. {
    239. if (fc!=bc) Gui_DrawPoint(x+j,y+i,bc);
    240. }
    241. }
    242. x+=8;
    243. }
    244. s++;
    245. }
    246. else
    247. {
    248. for (k=0;k
    249. {
    250. if ((hz16[k].Index[0]==*(s))&&(hz16[k].Index[1]==*(s+1)))
    251. {
    252. for(i=0;i<16;i++)
    253. {
    254. for(j=0;j<8;j++)
    255. {
    256. if(hz16[k].Msk[i*2]&(0x80>>j)) Gui_DrawPoint(x+j,y+i,fc);
    257. else {
    258. if (fc!=bc) Gui_DrawPoint(x+j,y+i,bc);
    259. }
    260. }
    261. for(j=0;j<8;j++)
    262. {
    263. if(hz16[k].Msk[i*2+1]&(0x80>>j)) Gui_DrawPoint(x+j+8,y+i,fc);
    264. else
    265. {
    266. if (fc!=bc) Gui_DrawPoint(x+j+8,y+i,bc);
    267. }
    268. }
    269. }
    270. }
    271. }
    272. s+=2;x+=16;
    273. }
    274. }
    275. }

    main.c

    1. /********************************** (C) COPYRIGHT *******************************
    2. * File Name : main.c
    3. * Author : WCH
    4. * Version : V1.0.0
    5. * Date : 2021/06/06
    6. * Description : Main program body.
    7. *********************************************************************************
    8. * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
    9. * Attention: This software (modified or not) and binary are used for
    10. * microcontroller manufactured by Nanjing Qinheng Microelectronics.
    11. *******************************************************************************/
    12. /*
    13. *@Note
    14. GPIO routine:
    15. PA0 push-pull output.
    16. */
    17. #include "debug.h"
    18. #include "HX8347.h"
    19. /* Global define */
    20. /* Global Variable */
    21. unsigned char TxData[Buf_Size]={0};
    22. u16 DMA1_MEM_LEN;
    23. /*********************************************************************
    24. * @fn GPIO_Toggle_INIT
    25. *
    26. * @brief Initializes GPIOA.0
    27. *
    28. * @return none
    29. */
    30. void GPIO_Toggle_INIT(void)
    31. {
    32. GPIO_InitTypeDef GPIO_InitStructure = {0};
    33. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    34. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
    35. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    36. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    37. GPIO_Init(GPIOB, &GPIO_InitStructure);
    38. }
    39. void SPI_1Lines_HalfDuplex_Init(void)
    40. {
    41. GPIO_InitTypeDef GPIO_InitStructure={0};
    42. SPI_InitTypeDef SPI_InitStructure={0};
    43. RCC_APB2PeriphClockCmd( RCC_APB2Periph_SPI1|RCC_APB2Periph_GPIOA, ENABLE );
    44. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
    45. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    46. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    47. GPIO_Init( GPIOA, &GPIO_InitStructure );
    48. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
    49. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    50. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    51. GPIO_Init( GPIOA, &GPIO_InitStructure );
    52. SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx;
    53. SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
    54. SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
    55. SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //在空闲状态下,时钟线保持低电平
    56. SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //数据在时钟的上升沿被传输。
    57. SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
    58. SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
    59. SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
    60. SPI_InitStructure.SPI_CRCPolynomial = 7;
    61. SPI_Init( SPI1, &SPI_InitStructure );
    62. SPI_Cmd( SPI1, ENABLE );
    63. }
    64. //使能dma1的通道3,因为spi输出对应的是此通道
    65. void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx)
    66. {
    67. DMA_Cmd(DMA_CHx, DISABLE );
    68. DMA_SetCurrDataCounter(DMA1_Channel3,DMA1_MEM_LEN);
    69. DMA_Cmd(DMA_CHx, ENABLE);
    70. }
    71. /*********************************************************************
    72. * @fn DMA_Tx_Init
    73. *
    74. * @brief Initializes the DMAy Channelx configuration.
    75. *
    76. * @param DMA_CHx - x can be 1 to 7.
    77. * ppadr - Peripheral base address.
    78. * memadr - Memory base address.
    79. * bufsize - DMA channel buffer size.
    80. *
    81. * @return none
    82. */
    83. void DMA_Tx_Init( DMA_Channel_TypeDef* DMA_CHx, u32 ppadr, u32 memadr, u16 bufsize)
    84. {
    85. DMA_InitTypeDef DMA_InitStructure={0};
    86. RCC_AHBPeriphClockCmd( RCC_AHBPeriph_DMA1, ENABLE );
    87. DMA_DeInit(DMA_CHx);
    88. DMA1_MEM_LEN=bufsize;
    89. DMA_InitStructure.DMA_PeripheralBaseAddr = ppadr;
    90. DMA_InitStructure.DMA_MemoryBaseAddr = memadr;
    91. DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
    92. DMA_InitStructure.DMA_BufferSize = bufsize;
    93. DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    94. DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    95. DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    96. DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    97. DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
    98. DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
    99. DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    100. DMA_Init( DMA_CHx, &DMA_InitStructure );
    101. }
    102. /*********************************************************************
    103. * @fn main
    104. *
    105. * @brief Main program.
    106. *
    107. * @return none
    108. */
    109. int main(void)
    110. {
    111. u8 i = 0;
    112. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    113. SystemCoreClockUpdate();
    114. Delay_Init();
    115. USART_Printf_Init(115200);
    116. printf("SystemClk:%d\r\n", SystemCoreClock);
    117. printf( "ChipID:%08x\r\n", DBGMCU_GetCHIPID() );
    118. printf("GPIO Toggle TEST\r\n");
    119. GPIO_Toggle_INIT();
    120. LCD_GPIO_Init();
    121. #ifdef SPI_hardware
    122. printf("SPI_HARDWARE");
    123. SPI_1Lines_HalfDuplex_Init();
    124. #ifdef SPI_hardware_dma
    125. printf("SPI_HARDWARE_DMA");
    126. DMA_Tx_Init( DMA1_Channel3, (u32)&SPI1->DATAR, (u32)TxData, Buf_Size );
    127. DMA_Cmd( DMA1_Channel3, ENABLE );
    128. #endif
    129. #else
    130. printf("SPI_SOFTWARE");
    131. #endif
    132. LCD_Init();
    133. GPIO_WriteBit(GPIOB, GPIO_Pin_13,Bit_RESET);
    134. while(1)
    135. {
    136. //下面用的是SPI+DMA
    137. Delay_Ms(1000);
    138. FillRect_DMA(GREEN);
    139. Delay_Ms(1000);
    140. FillRect_DMA(GREEN);
    141. Delay_Ms(1000);
    142. FillRect_DMA(BLUE);
    143. Delay_Ms(1000);
    144. FillRect_DMA(YELLOW);
    145. Delay_Ms(1000);
    146. FillRect(0, 0, 239, 63, RED );
    147. //下面用的硬件SPI
    148. Gui_DrawFont_GBK16(15,5,BLACK,GRAY0,"HELLO world");
    149. Gui_DrawFont_GBK16(15,25,RED,GRAY0,"LCD OK DISPLAY");
    150. Gui_DrawFont_GBK16(15,45,RED,GRAY0,"智能物联红外测温系统通过人数");
    151. Gui_DrawFont_GBK16(15,65,RED,GRAY0,"报警人数人体温度环境表面距离");
    152. Gui_DrawFont_GBK16(15,85,RED,GRAY0,"网络连接中.温度气象站雨量风速");
    153. Gui_DrawFont_GBK16(15,105,RED,GRAY0,"创新实验平台℃");
    154. Delay_Ms(1000);
    155. GPIO_WriteBit(GPIOB, GPIO_Pin_13, (i == 0) ? (i = Bit_SET) : (i = Bit_RESET));
    156. printf( "GPIOB:%d\r\n", i);
    157. FillRect(0, 0, 239, 319, RED );
    158. Delay_Ms(1000);
    159. FillRect(0, 0, 239, 319, GREEN );
    160. Delay_Ms(1000);
    161. FillRect(0, 0, 239, 319, BLUE );
    162. FillRect(50, 50, 100, 100, RED );
    163. }
    164. }

    二、说明

    1、DMA初始化:

    void DMA_Tx_Init( DMA_Channel_TypeDef* DMA_CHx, u32 ppadr, u32 memadr, u16 bufsize)
    {
        DMA_InitTypeDef DMA_InitStructure={0};

        RCC_AHBPeriphClockCmd( RCC_AHBPeriph_DMA1, ENABLE );

        DMA_DeInit(DMA_CHx);
        DMA1_MEM_LEN=bufsize;

        DMA_InitStructure.DMA_PeripheralBaseAddr = ppadr;
        DMA_InitStructure.DMA_MemoryBaseAddr = memadr;
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
        DMA_InitStructure.DMA_BufferSize = bufsize;
        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 );
    }

    2、用DMA主要是清屏:

    void FillRect_DMA(u16 color)
    {
        int16_t j;
        LCD_SetWindow(0, 0,239,319);

        LCD_CS_CLR;
        SPI_WriteData(0x72);

        for(j=0 ;j<480;){
            TxData[j] = color>>8;
            TxData[j+1] = color;
         j += 2;
        }

        for(j = 0 ; j<320 ; j++){
            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;
                }
            }

        }
        LCD_CS_SET;
    }
     

    为了使用DMA申请了一个480字节的空间,就是屏幕上一行所需空间(240*2):

    unsigned char TxData[Buf_Size]={0}; 

    清屏过程就是每次DMA发送480个字节清一行,然后循环320次清掉整个屏幕。

    如果改变 TxData的值,可以向屏幕发送一些字符、图画什么的。需要写一个改变TxData内容的函数。

    3、可以考虑为DMA申请更大的内存空间,那样就可以一次传更多的数据。但是240*320*2=153600=150KB空间,一般单片机没有这么大的SRAM,怎么都需要分屏传输。

    SPI+DMA

  • 相关阅读:
    Jenkins cron定时构建触发器
    完美!字节3-1级别大佬把《数据结构与算法》讲透了,带源码笔记
    vue js中使用typeof和Object.prototype.toString.call()判断类型(超详细),浅析call()和apply()的区别
    可视化容器管理工具-portainer.io使用
    Node.js 实战 第1章 欢迎进入Node.js 的世界 1.4 Node 自带的工具 1.4.1 npm
    文本输入编辑框 EditText
    数据库系统与应用复习——第六章关系数据理论
    我大抵是卷上瘾了,横竖睡不着!竟让一个Bug,搞我两次!
    【HDLBits 刷题 6】Circuits(2)Sequential Logic---Latches and Filp Flops
    buuctf web [极客大挑战 2019]Upload
  • 原文地址:https://blog.csdn.net/weixin_44067125/article/details/134330542