[AT32M412] 【AT-START-M412测评】+硬件方式驱动TFT显示屏

[复制链接]
 楼主| jinglixixi 发表于 2025-6-2 00:40 | 显示全部楼层 |阅读模式
本帖最后由 jinglixixi 于 2025-6-2 09:42 编辑

#申请原创#

前面介绍了以硬件I2C驱动OLED的方法,这里再介绍一下以硬件SPI来驱动TFT显示屏的方法。
对于SPI的学习完全可以借鉴官方所提供的SPI例程,然后根据自身的需要予以相应的补充。
根据TFT屏的需要,对SPI及所用引脚的配置函数为:
  1. void tft_config(void)
  2. {
  3. gpio_init_type gpio_initstructure;
  4. spi_init_type spi_init_struct;
  5. crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
  6. crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE);
  7. crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);
  8. /* software cs, pb12 as a general io to control flash cs */
  9. gpio_initstructure.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  10. gpio_initstructure.gpio_pull = GPIO_PULL_NONE;
  11. gpio_initstructure.gpio_mode = GPIO_MODE_OUTPUT;
  12. gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  13. gpio_initstructure.gpio_pins = GPIO_PINS_12;
  14. gpio_init(GPIOB, &gpio_initstructure);

在进行TFT屏连接时,可充分利用J7接口来完成。
具体的连接关系为:
LCD-CS  --> PB12
LCD-RST --> PB11
LCD-DC  --> PB10
LCD-SDI --> PB15
LCD-SCK --> PB13
LCD-BK  --> PB9
02df483361ee2190d69c2448a5a9ab73
图1  引脚定义

0f528c434f742f5a7dae2f39674e8801
图2  所用接口

SPI发送字节数据的函数为:
  1. void lcd_spi2_write(uint8_t data)
  2. {
  3. uint32_t retry = 0;
  4. while (spi_i2s_flag_get(SPI2, SPI_I2S_TDBE_FLAG) == RESET)
  5. {
  6. retry++;
  7. if(retry > 10000)
  8. return;
  9. }
  10. spi_i2s_data_transmit(SPI2, data);
  11. retry = 0;
  12. while (spi_i2s_flag_get(SPI2, SPI_I2S_BF_FLAG) == SET)
  13. {
  14. retry++;
  15. if(retry > 0xFFFFF)
  16. return;
  17. }
  18. }

向寄存器发送内容的函数为:
  1. static void LCD_WR_REG(uint8_t reg)
  2. {
  3. LCD_DC_CLR;
  4. LCD_CS_CLR;
  5. lcd_spi2_write(reg);
  6. LCD_CS_SET;
  7. LCD_DC_SET;
  8. }

发送数据内容的函数为:
  1. static void LCD_WR_DATA(uint8_t data)
  2. {
  3. LCD_DC_SET;
  4. LCD_CS_CLR;
  5. lcd_spi2_write(data);
  6. LCD_CS_SET;
  7. }

向寄存器发送数据的函数为:
  1. static void LCD_WriteReg(uint8_t reg, uint16_t regdata)
  2. {
  3. LCD_WR_REG(reg);
  4. LCD_WR_DATA(regdata);
  5. }

这样就完成了以SPI进行TFT屏显示驱动的准备工作,随后就可利用TFT屏的相应功能函数。
该TFT显示屏的初始化函数为:
  1. void tft_Init(void)
  2. {
  3. // ili9220
  4. LCD_RESET();
  5. LCD_CS_CLR;
  6. LCD_WR_REG(0xCB);
  7. LCD_WR_DATA(0x39);
  8. LCD_WR_DATA(0x2C);
  9. LCD_WR_DATA(0x00);
  10. LCD_WR_DATA(0x34);
  11. LCD_WR_DATA(0x02);
  12. LCD_WR_REG(0xCF);
  13. LCD_WR_DATA(0x00);
  14. LCD_WR_DATA(0XC1);
  15. LCD_WR_DATA(0X30);
  16. LCD_WR_REG(0xE8);
  17. LCD_WR_DATA(0x85);
  18. LCD_WR_DATA(0x00);
  19. LCD_WR_DATA(0x78);
  20. LCD_WR_REG(0xEA);
  21. LCD_WR_DATA(0x00);
  22. LCD_WR_DATA(0x00);
  23. LCD_WR_REG(0xED);
  24. LCD_WR_DATA(0x64);
  25. LCD_WR_DATA(0x03);
  26. LCD_WR_DATA(0X12);
  27. LCD_WR_DATA(0X81);
  28. LCD_WR_REG(0xF7);
  29. LCD_WR_DATA(0x20);
  30. LCD_WR_REG(0xC0);
  31. LCD_WR_DATA(0x23);
  32. LCD_WR_REG(0xC1);
  33. LCD_WR_DATA(0x10);
  34. LCD_WR_REG(0xC5);
  35. LCD_WR_DATA(0x3e);
  36. LCD_WR_DATA(0x28);
  37. LCD_WR_REG(0xC7);
  38. LCD_WR_DATA(0x86);
  39. LCD_WR_REG(0x36);
  40. LCD_WR_DATA(0x48);
  41. LCD_WR_REG(0x3A);
  42. LCD_WR_DATA(0x55);
  43. LCD_WR_REG(0xB1);
  44. LCD_WR_DATA(0x00);
  45. LCD_WR_DATA(0x18);
  46. LCD_WR_REG(0xB6);
  47. LCD_WR_DATA(0x08);
  48. LCD_WR_DATA(0x82);
  49. LCD_WR_DATA(0x27);
  50. LCD_WR_REG(0xF2);
  51. LCD_WR_DATA(0x00);
  52. LCD_WR_REG(0x26);
  53. LCD_WR_DATA(0x01);
  54. LCD_WR_REG(0xE0);
  55. LCD_WR_DATA(0x0F);
  56. LCD_WR_DATA(0x31);
  57. LCD_WR_DATA(0x2B);
  58. LCD_WR_DATA(0x0C);
  59. LCD_WR_DATA(0x0E);
  60. LCD_WR_DATA(0x08);
  61. LCD_WR_DATA(0x4E);
  62. LCD_WR_DATA(0xF1);
  63. LCD_WR_DATA(0x37);
  64. LCD_WR_DATA(0x07);
  65. LCD_WR_DATA(0x10);
  66. LCD_WR_DATA(0x03);
  67. LCD_WR_DATA(0x0E);
  68. LCD_WR_DATA(0x09);
  69. LCD_WR_DATA(0x00);
  70. LCD_WR_REG(0XE1);
  71. LCD_WR_DATA(0x00);
  72. LCD_WR_DATA(0x0E);
  73. LCD_WR_DATA(0x14);
  74. LCD_WR_DATA(0x03);
  75. LCD_WR_DATA(0x11);
  76. LCD_WR_DATA(0x07);
  77. LCD_WR_DATA(0x31);
  78. LCD_WR_DATA(0xC1);
  79. LCD_WR_DATA(0x48);
  80. LCD_WR_DATA(0x08);
  81. LCD_WR_DATA(0x0F);
  82. LCD_WR_DATA(0x0C);
  83. LCD_WR_DATA(0x31);
  84. LCD_WR_DATA(0x36);
  85. LCD_WR_DATA(0x0F);
  86. LCD_WR_REG(0x11);
  87. delay_ms(120);
  88. LCD_WR_REG(0x29);
  89. LCD_WR_REG(0x2c);
  90. LCD_BK_SET;
  91. }

调整显示屏方向的函数为:
  1. void LCD_direction(uint8_t direction)
  2. {
  3. switch (direction)
  4. {
  5. case 0:
  6. LCD_W = 240;
  7. LCD_H = 320;
  8. LCD_WriteReg(0x36,0x48);
  9. break;
  10. case 1:
  11. LCD_W = 320;
  12. LCD_H = 240;
  13. LCD_WriteReg(0x36, 0x28);
  14. break;
  15. case 2:
  16. LCD_W = 240;
  17. LCD_H = 320;
  18. LCD_WriteReg(0x36, 0x88);
  19. break;
  20. case 3:
  21. LCD_W = 320;
  22. LCD_H = 240;
  23. LCD_WriteReg(0x36, 0x68);
  24. break;
  25. default:
  26. break;
  27. }
  28. }

实现字符显示的函数为:
  1. void LCD_ShowChar(unsigned int x,unsigned int y,char num,char mode)
  2. {
  3. char temp;
  4. char pos,t;
  5. unsigned int x0=x;
  6. unsigned int colortemp=POINT_COLOR;
  7. if(x>LCD_W-16||y>LCD_H-16) return;
  8. num=num-' ';
  9. LCD_SetWindows(x,y,x+8-1,y+16-1);
  10. if(!mode)
  11. {
  12. for(pos=0;pos<16;pos++)
  13. {
  14. temp=asc2_1608[(unsigned int)num*16+pos];
  15. for(t=0;t<8;t++)
  16. {
  17. if(temp&0x01) POINT_COLOR=colortemp;
  18. else
  19. POINT_COLOR=BACK_COLOR;
  20. LCD_WR_DATA(POINT_COLOR);
  21. temp>>=1;
  22. x++;
  23. }
  24. x=x0;
  25. y++;
  26. }
  27. }
  28. else
  29. {
  30. for(pos=0;pos<16;pos++)
  31. {
  32. temp=asc2_1608[(unsigned int)num*16+pos];
  33. for(t=0;t<8;t++)
  34. {
  35. if(temp&0x01) lcd_draw_point(x+t,y+pos,POINT_COLOR);
  36. temp>>=1;
  37. }
  38. }
  39. }
  40. POINT_COLOR=colortemp;
  41. }

实现字符串显示的函数为:
  1. void LCD_ShowString(unsigned int x,unsigned int y,const char *p)
  2. {
  3. while(*p!='\0')
  4. {
  5. if(x>LCD_W-16)
  6. {
  7. x=0;
  8. y+=16;
  9. }
  10. if(y>LCD_H-16)
  11. {
  12. y=x=0;
  13. }
  14. LCD_ShowChar(x,y,*p,1);
  15. x+=8;
  16. p++;
  17. }
  18. }

测试驱动效果的主程序为:
  1. int main(void)
  2. {
  3. system_clock_config();
  4. delay_init();
  5. tft_config();
  6. LCD_RESET();
  7. tft_Init();
  8. LCD_direction(2);
  9. lcd_spi_test();
  10. delay_ms(500);
  11. LCD_Clear(RED);
  12. BACK_COLOR=RED;
  13. POINT_COLOR=WHITE;
  14. LCD_ShowString(30,20,"AT32M413");
  15. LCD_ShowString(30,40,"LCD TEST");
  16. while(1);
  17. }

经程序的编译及下载,其测试效果如图3所示,说明驱动正常且有效。
a2e21e59bc48bb322c3bb19d8dba4d02
图3 测试效果




ZenithSeeker 发表于 2025-6-13 08:14 | 显示全部楼层
测试效果还行,楼主能不能出一期用DMA刷新的教程,期待。
szt1993 发表于 2025-6-16 00:02 | 显示全部楼层
SPI通讯还是非常稳定的
您需要登录后才可以回帖 登录 | 注册

本版积分规则

518

主题

2934

帖子

39

粉丝
快速回复 在线客服 返回列表 返回顶部

518

主题

2934

帖子

39

粉丝
快速回复 在线客服 返回列表 返回顶部