• 3线硬件SPI+DMA驱动 HX8347 TFT屏-快速显示文字


     本文实现DMA快速显示文字

    汉字点阵通常是16*16点阵,那么用DMA一次性显示汉字,应该至少申请480*16个字节的空间,用于显示一行文字,其中480是屏幕一行用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*16
    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. void Gui_DrawFont_GBK16_DMA(unsigned int x, unsigned int y, unsigned int fc, unsigned int bc,unsigned char *s);
    47. void showimage(const unsigned char *p);
    48. #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
    128. TxData[j] = color>>8;
    129. TxData[j+1] = color;
    130. j += 2;
    131. }
    132. for(j = 0 ; j<320/(Buf_Size/480) ; 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_DrawPoint_DMA(unsigned int x,unsigned int y,unsigned int Data)
    216. {
    217. //LCD_SetWindow(x,y,x+1,y+1);
    218. //LCD_WriteData_16Bit(Data);
    219. TxData[2*x+y*480]=Data>>8;
    220. TxData[2*x+y*480+1]=Data;
    221. }
    222. void DMA_BUFFER_RESET(unsigned int bc)
    223. {
    224. unsigned int j;
    225. for(j=0 ;j
    226. TxData[j] = bc>>8;
    227. TxData[j+1] = bc;
    228. j += 2;
    229. }
    230. }
    231. void Gui_DrawFont_GBK16(unsigned int x, unsigned int y, unsigned int fc, unsigned int bc,unsigned char *s)
    232. {
    233. unsigned char i,j;
    234. unsigned short k,x0;
    235. x0=x;
    236. while(*s)
    237. {
    238. if((*s) < 128)
    239. {
    240. k=*s;
    241. if (k==13)
    242. {
    243. x=x0;
    244. y+=16;
    245. }
    246. else
    247. {
    248. if (k>32) k-=32; else k=0;
    249. for(i=0;i<16;i++)
    250. for(j=0;j<8;j++)
    251. {
    252. if(asc16[k*16+i]&(0x80>>j)) Gui_DrawPoint(x+j,y+i,fc);
    253. else
    254. {
    255. if (fc!=bc) Gui_DrawPoint(x+j,y+i,bc);
    256. }
    257. }
    258. x+=8;
    259. }
    260. s++;
    261. }
    262. else
    263. {
    264. for (k=0;k
    265. {
    266. if ((hz16[k].Index[0]==*(s))&&(hz16[k].Index[1]==*(s+1)))
    267. {
    268. for(i=0;i<16;i++)
    269. {
    270. for(j=0;j<8;j++)
    271. {
    272. if(hz16[k].Msk[i*2]&(0x80>>j)) Gui_DrawPoint(x+j,y+i,fc);
    273. else {
    274. if (fc!=bc) Gui_DrawPoint(x+j,y+i,bc);
    275. }
    276. }
    277. for(j=0;j<8;j++)
    278. {
    279. if(hz16[k].Msk[i*2+1]&(0x80>>j)) Gui_DrawPoint(x+j+8,y+i,fc);
    280. else
    281. {
    282. if (fc!=bc) Gui_DrawPoint(x+j+8,y+i,bc);
    283. }
    284. }
    285. }
    286. }
    287. }
    288. s+=2;x+=16;
    289. }
    290. }
    291. }
    292. void Gui_DrawFont_GBK16_DMA(unsigned int x, unsigned int y, unsigned int fc, unsigned int bc,unsigned char *s)
    293. {
    294. unsigned char i,j;
    295. unsigned short k,x0,y0;
    296. x0=x;
    297. y0=y;
    298. x=0;
    299. y=0;
    300. DMA_BUFFER_RESET(bc); //清缓存
    301. while(*s)
    302. {
    303. if((*s) < 128)
    304. {
    305. k=*s;
    306. if (k==13)
    307. {
    308. x=x0;
    309. y+=16;
    310. }
    311. else
    312. {
    313. if (k>32) k-=32; else k=0;
    314. for(i=0;i<16;i++)
    315. for(j=0;j<8;j++)
    316. {
    317. if(asc16[k*16+i]&(0x80>>j)) Gui_DrawPoint_DMA(x+j,y+i,fc);
    318. else
    319. {
    320. if (fc!=bc) Gui_DrawPoint_DMA(x+j,y+i,bc);
    321. }
    322. }
    323. x+=8;
    324. }
    325. s++;
    326. }
    327. else
    328. {
    329. for (k=0;k
    330. {
    331. if ((hz16[k].Index[0]==*(s))&&(hz16[k].Index[1]==*(s+1)))
    332. {
    333. for(i=0;i<16;i++)
    334. {
    335. for(j=0;j<8;j++)
    336. {
    337. if(hz16[k].Msk[i*2]&(0x80>>j)) Gui_DrawPoint_DMA(x+j,y+i,fc);
    338. else {
    339. if (fc!=bc) Gui_DrawPoint_DMA(x+j,y+i,bc);
    340. }
    341. }
    342. for(j=0;j<8;j++)
    343. {
    344. if(hz16[k].Msk[i*2+1]&(0x80>>j)) Gui_DrawPoint_DMA(x+j+8,y+i,fc);
    345. else
    346. {
    347. if (fc!=bc) Gui_DrawPoint_DMA(x+j+8,y+i,bc);
    348. }
    349. }
    350. }
    351. }
    352. }
    353. s+=2;x+=16;
    354. }
    355. }
    356. LCD_SetWindow(0,y0,239,y0+16);
    357. LCD_CS_CLR;
    358. SPI_WriteData(0x72);
    359. SPI_I2S_DMACmd(SPI1,SPI_I2S_DMAReq_Tx,ENABLE);
    360. MYDMA_Enable(DMA1_Channel3);
    361. while(1){
    362. if(DMA_GetFlagStatus(DMA1_FLAG_TC3)!=RESET)
    363. {
    364. DMA_ClearFlag(DMA1_FLAG_TC3);
    365. break;
    366. }
    367. }
    368. LCD_CS_SET;
    369. }
    370. //Image2LCD取模方式 水平扫描 从左到右 字节顺序
    371. void showimage(const unsigned char *p) //显示图片
    372. {
    373. int i,x,y;
    374. for(i=0;i<20;i++)
    375. {
    376. for(y=0;y<16;y++)
    377. for(x=0;x<240;x++)
    378. {
    379. TxData[2*x+y*480]=p[i*16*480+y*480+x*2];
    380. TxData[2*x+y*480+1]=p[i*16*480+y*480+x*2+1];
    381. }
    382. LCD_SetWindow(0,i*16,239,i*16+16);
    383. LCD_CS_CLR;
    384. SPI_WriteData(0x72);
    385. SPI_I2S_DMACmd(SPI1,SPI_I2S_DMAReq_Tx,ENABLE);
    386. MYDMA_Enable(DMA1_Channel3);
    387. while(1){
    388. if(DMA_GetFlagStatus(DMA1_FLAG_TC3)!=RESET)
    389. {
    390. DMA_ClearFlag(DMA1_FLAG_TC3);
    391. break;
    392. }
    393. }
    394. LCD_CS_SET;
    395. }
    396. }

    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. Delay_Ms(1000);
    137. FillRect_DMA(GREEN);
    138. Gui_DrawFont_GBK16_DMA(0,5,BLACK,GREEN,"HELLO world");
    139. Gui_DrawFont_GBK16_DMA(0,25,RED,GREEN,"LCD OK DISPLAY");
    140. Gui_DrawFont_GBK16_DMA(0,45,RED,GREEN,"智能物联红外测温系统通过人数");
    141. Gui_DrawFont_GBK16_DMA(0,65,RED,GREEN,"报警人数人体温度环境表面距离");
    142. Gui_DrawFont_GBK16_DMA(0,85,RED,GREEN,"网络连接中.温度气象站雨量风速");
    143. Gui_DrawFont_GBK16_DMA(0,105,RED,GREEN,"创新实验平台℃");
    144. Delay_Ms(2000);
    145. FillRect_DMA(RED);
    146. Delay_Ms(1000);
    147. FillRect_DMA(BLUE);
    148. Gui_DrawFont_GBK16_DMA(0,5,WHITE,BLUE,"HELLO world");
    149. Gui_DrawFont_GBK16_DMA(0,25,WHITE,BLUE,"LCD OK DISPLAY");
    150. Gui_DrawFont_GBK16_DMA(0,45,WHITE,BLUE,"智能物联红外测温系统通过人数");
    151. Gui_DrawFont_GBK16_DMA(0,65,WHITE,BLUE,"报警人数人体温度环境表面距离");
    152. Gui_DrawFont_GBK16_DMA(0,85,WHITE,BLUE,"网络连接中.温度气象站雨量风速");
    153. Gui_DrawFont_GBK16_DMA(0,105,WHITE,BLUE,"创新实验平台℃");
    154. Delay_Ms(1000);
    155. FillRect_DMA(YELLOW);
    156. Delay_Ms(1000);
    157. FillRect(0, 0, 239, 63, RED );
    158. Gui_DrawFont_GBK16(15,5,BLACK,GRAY0,"HELLO world");
    159. Gui_DrawFont_GBK16(15,25,RED,GRAY0,"LCD OK DISPLAY");
    160. Gui_DrawFont_GBK16(15,45,RED,GRAY0,"智能物联红外测温系统通过人数");
    161. Gui_DrawFont_GBK16(15,65,RED,GRAY0,"报警人数人体温度环境表面距离");
    162. Gui_DrawFont_GBK16(15,85,RED,GRAY0,"网络连接中.温度气象站雨量风速");
    163. Gui_DrawFont_GBK16(15,105,RED,GRAY0,"创新实验平台℃");
    164. Delay_Ms(1000);
    165. GPIO_WriteBit(GPIOB, GPIO_Pin_13, (i == 0) ? (i = Bit_SET) : (i = Bit_RESET));
    166. printf( "GPIOB:%d\r\n", i);
    167. FillRect(0, 0, 239, 319, RED );
    168. Delay_Ms(1000);
    169. FillRect(0, 0, 239, 319, GREEN );
    170. Delay_Ms(1000);
    171. FillRect(0, 0, 239, 319, BLUE );
    172. FillRect(50, 50, 100, 100, RED );
    173. }
    174. }

    二、说明

     1、增加了 Gui_DrawPoint_DMA(unsigned int x,unsigned int y,unsigned int Data)向DMA内存画点的功能

    void Gui_DrawPoint_DMA(unsigned int x,unsigned int y,unsigned int Data)
    {
        TxData[2*x+y*480]=Data>>8;
        TxData[2*x+y*480+1]=Data;

    }

    2、增加了void DMA_BUFFER_RESET(unsigned int bc),用于清空DMA内存

    void DMA_BUFFER_RESET(unsigned int bc)
    {
        unsigned int j;
        for(j=0 ;j         TxData[j] = bc>>8;
            TxData[j+1] = bc;
         j += 2;
        }

    3、增加了Gui_DrawFont_GBK16_DMA(unsigned int x, unsigned int y, unsigned int fc, unsigned int bc,unsigned char *s)。用于处理字符串并以DMA方式输出到屏幕。

    void Gui_DrawFont_GBK16_DMA(unsigned int x, unsigned int y, unsigned int fc, unsigned int bc,unsigned char *s)
    {
        unsigned char i,j;
        unsigned short k,x0,y0;
        x0=x;
        y0=y;
        x=0;
        y=0;

        DMA_BUFFER_RESET(bc);       //清缓存
        while(*s)
        {

            if((*s) < 128)
            {
                k=*s;
                if (k==13)
                {
                    x=x0;
                    y+=16;
                }
                else
                {
                    if (k>32) k-=32; else k=0;

                    for(i=0;i<16;i++)
                    for(j=0;j<8;j++)
                        {
                            if(asc16[k*16+i]&(0x80>>j)) Gui_DrawPoint_DMA(x+j,y+i,fc);
                            else
                            {
                                if (fc!=bc) Gui_DrawPoint_DMA(x+j,y+i,bc);
                            }
                        }
                    x+=8;
                }
                s++;
            }

            else
            {


                for (k=0;k             {
                  if ((hz16[k].Index[0]==*(s))&&(hz16[k].Index[1]==*(s+1)))
                  {

                        for(i=0;i<16;i++)
                        {
                            for(j=0;j<8;j++)
                                {
                                    if(hz16[k].Msk[i*2]&(0x80>>j))  Gui_DrawPoint_DMA(x+j,y+i,fc);
                                    else {
                                        if (fc!=bc) Gui_DrawPoint_DMA(x+j,y+i,bc);
                                    }
                                }
                            for(j=0;j<8;j++)
                                {
                                    if(hz16[k].Msk[i*2+1]&(0x80>>j))   Gui_DrawPoint_DMA(x+j+8,y+i,fc);
                                    else
                                    {
                                        if (fc!=bc) Gui_DrawPoint_DMA(x+j+8,y+i,bc);
                                    }
                                }
                        }
                    }
                  }
                s+=2;x+=16;
            }

        }

        LCD_SetWindow(0,y0,239,y0+16);
        LCD_CS_CLR;
        SPI_WriteData(0x72);


        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;

    }

    4、增加了void showimage(const unsigned char *p);可以显示图片。

    三、总结

    1、申请的DMA空间为480*16,对应于屏幕是一个240*16的长条空间。也就是每次向屏幕刷一个 240*16范围,对应文字就是一行。改变起始位置,就可以在其他地方再刷一行。

    DMA快速显示文字

  • 相关阅读:
    Ubuntu 切换输入法
    瑞芯微开发板资料收集
    分位数回归的求解
    Go 包操作之如何拉取私有的Go Module
    Redis-01基本数据结构
    [附源码]SSM计算机毕业设计学生互评的在线作业管理系统JAVA
    RabbitMq大纲
    url后面直接拼接参数
    在Spring Boot应用中实现阿里云短信功能的整合
    MySQL 高级SQL语句 (二)
  • 原文地址:https://blog.csdn.net/weixin_44067125/article/details/134339670