[APM32F4] 【APM32F402R Micro-EVB开发板测评】+TFT屏显示驱动及信息显示

[复制链接]
 楼主| jinglixixi 发表于 2025-7-23 11:33 | 显示全部楼层 |阅读模式

APM32F402R Micro-EVB开发板是一款近于最小系统的开发板,为其添加相应的外设,可用起到丰富其羽翼的作用。这里是利用闲置SPI接口为其配置一个TFT显示屏,该闲置的SPI电路如图1所示。
25ab6605fb5adec688a0c3c20c684dd5
图1  闲置SPI电路

该闲置SPI电路所使用的引脚为PA4~PA7,这里就用它与TFT屏的对应引脚连接。此外,还需为其分配一些辅助引脚。
在使用SPI进行硬件驱动前,先以模拟的方式来驱动该显示屏。
对TFT屏所用引脚的配置函数为:
  1. void BOARD_TFT_Config()
  2. {
  3.     GPIO_Config_T GPIO_ConfigStruct = {0U};
  4.     RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOA);
  5.     GPIO_ConfigStruct.pin = GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
  6.     GPIO_ConfigStruct.mode = GPIO_MODE_OUT_PP;
  7.     GPIO_ConfigStruct.speed = GPIO_SPEED_50MHz;
  8.     GPIO_Config(GPIOA, &GPIO_ConfigStruct);
  9.                
  10.     RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOB);
  11.     GPIO_ConfigStruct.pin = GPIO_PIN_8|GPIO_PIN_9;
  12.     GPIO_Config(GPIOB, &GPIO_ConfigStruct);
  13. }

实现高低电平输出的语句定义为:
#define LCD_CS_High()   GPIOA->BSC = GPIO_PIN_4
#define LCD_CS_Low()    GPIOA->BC = GPIO_PIN_4

#define LCD_REST_High() GPIOB->BSC = GPIO_PIN_8
#define LCD_REST_Low()  GPIOB->BC = GPIO_PIN_8

#define LCD_DC_High()   GPIOB->BSC = GPIO_PIN_9
#define LCD_DC_Low()    GPIOB->BC = GPIO_PIN_9

#define LCD_SDI_High()  GPIOA->BSC = GPIO_PIN_7
#define LCD_SDI_Low()   GPIOA->BC = GPIO_PIN_7

#define LCD_SCK_High()  GPIOA->BSC = GPIO_PIN_5
#define LCD_SCK_Low()   GPIOA->BC = GPIO_PIN_5

#define LCD_LED_High()  GPIOA->BSC = GPIO_PIN_6
#define LCD_LED_Low()   GPIOA->BC = GPIO_PIN_6

此外,为较好地控制时序关系,还使用SysTick配置了一个起短延时作用的函数,其内容为:
  1. void delay_u(uint32_t delay)
  2. {
  3. delay = 0xf*delay ;
  4. while(delay--);
  5. }

模拟SPI发送字节数据的函数为:
  1. void LCD_Writ_Bus(unsigned char com)   
  2. {       
  3.         unsigned char uci;
  4.         for(uci=0;uci<8;uci++)
  5.         {
  6.                 if(com & 0x80)
  7.                 {
  8.                         LCD_SDI_High();
  9.                 }
  10.                 else
  11.                 {
  12.                         LCD_SDI_Low();
  13.                 }
  14.                 com = com << 1;
  15.                 delay_u(1);
  16.                
  17.                 LCD_SCK_Low();
  18.                 LCD_SCK_High();
  19.         }        
  20. }

对显示屏的初始化函数为:
  1. void tft_Init(void)
  2. {   
  3.     // ili9220B
  4.     LCD_REST_Low();
  5.     Delay();
  6.     LCD_REST_High();
  7.     Delay();
  8.     LCD_CS_Low();
  9.     LCD_WR_REG(0xCB);   
  10.     LCD_WR_DATA8(0x39);
  11.     LCD_WR_DATA8(0x2C);
  12.     LCD_WR_DATA8(0x00);
  13.     LCD_WR_DATA8(0x34);
  14.     LCD_WR_DATA8(0x02);
  15.     LCD_WR_REG(0xCF);  
  16.     LCD_WR_DATA8(0x00);
  17.     LCD_WR_DATA8(0XC1);
  18.     LCD_WR_DATA8(0X30);  
  19.     LCD_WR_REG(0xE8);  
  20.     LCD_WR_DATA8(0x85);
  21.     LCD_WR_DATA8(0x00);
  22.     LCD_WR_DATA8(0x78);  
  23.     LCD_WR_REG(0xEA);  
  24.     LCD_WR_DATA8(0x00);
  25.     LCD_WR_DATA8(0x00);  
  26.     LCD_WR_REG(0xED);  
  27.     LCD_WR_DATA8(0x64);
  28.     LCD_WR_DATA8(0x03);
  29.     LCD_WR_DATA8(0X12);
  30.     LCD_WR_DATA8(0X81);
  31.     LCD_WR_REG(0xF7);  
  32.     LCD_WR_DATA8(0x20);   
  33.     LCD_WR_REG(0xC0);
  34.     LCD_WR_DATA8(0x23);
  35.     LCD_WR_REG(0xC1);  
  36.     LCD_WR_DATA8(0x10);
  37.     LCD_WR_REG(0xC5);  
  38.     LCD_WR_DATA8(0x3e);
  39.     LCD_WR_DATA8(0x28);
  40.     LCD_WR_REG(0xC7);  
  41.     LCD_WR_DATA8(0x86);
  42.     LCD_WR_REG(0x36);
  43.     LCD_WR_DATA8(0xE8);
  44.     LCD_WR_REG(0x3A);   
  45.     LCD_WR_DATA8(0x55);
  46.     LCD_WR_REG(0xB1);   
  47.     LCD_WR_DATA8(0x00);  
  48.     LCD_WR_DATA8(0x18);  
  49.     LCD_WR_REG(0xB6);
  50.     LCD_WR_DATA8(0x08);
  51.     LCD_WR_DATA8(0x82);
  52.     LCD_WR_DATA8(0x27);  
  53.     LCD_WR_REG(0xF2);  
  54.     LCD_WR_DATA8(0x00);  
  55.     LCD_WR_REG(0x26);  
  56.     LCD_WR_DATA8(0x01);  
  57.     LCD_WR_REG(0xE0);
  58.     LCD_WR_DATA8(0x0F);
  59.     LCD_WR_DATA8(0x31);
  60.     LCD_WR_DATA8(0x2B);
  61.     LCD_WR_DATA8(0x0C);
  62.     LCD_WR_DATA8(0x0E);
  63.     LCD_WR_DATA8(0x08);
  64.     LCD_WR_DATA8(0x4E);
  65.     LCD_WR_DATA8(0xF1);
  66.     LCD_WR_DATA8(0x37);
  67.     LCD_WR_DATA8(0x07);
  68.     LCD_WR_DATA8(0x10);
  69.     LCD_WR_DATA8(0x03);
  70.     LCD_WR_DATA8(0x0E);
  71.     LCD_WR_DATA8(0x09);
  72.     LCD_WR_DATA8(0x00);
  73.     LCD_WR_REG(0XE1);
  74.     LCD_WR_DATA8(0x00);
  75.     LCD_WR_DATA8(0x0E);
  76.     LCD_WR_DATA8(0x14);
  77.     LCD_WR_DATA8(0x03);
  78.     LCD_WR_DATA8(0x11);
  79.     LCD_WR_DATA8(0x07);
  80.     LCD_WR_DATA8(0x31);
  81.     LCD_WR_DATA8(0xC1);
  82.     LCD_WR_DATA8(0x48);
  83.     LCD_WR_DATA8(0x08);
  84.     LCD_WR_DATA8(0x0F);
  85.     LCD_WR_DATA8(0x0C);
  86.     LCD_WR_DATA8(0x31);
  87.     LCD_WR_DATA8(0x36);
  88.     LCD_WR_DATA8(0x0F);  
  89.     LCD_WR_REG(0x11);
  90.     Delay();                               
  91.     LCD_WR_REG(0x29);
  92.     LCD_WR_REG(0x2c);
  93.     LCD_LED_High();
  94. }

实现清除屏幕的函数为:
  1. void LCD_Clear(unsigned int Color)
  2. {
  3.           char VH,VL;
  4.           unsigned int i,j;
  5.           VH=Color>>8;
  6.           VL=Color;       
  7.           LCD_W= 320;
  8.           LCD_H =240;
  9.           Address_set(0,0,LCD_W-1,LCD_H-1);
  10.           for(i=0;i<LCD_W;i++)
  11.           {
  12.                for (j=0;j<LCD_H;j++)
  13.                {
  14.                       LCD_WR_DATA8(VH);
  15.                       LCD_WR_DATA8(VL);       
  16.                }
  17.           }
  18. }

发送字符的函数为:
  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.         Address_set(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 POINT_COLOR=BACK_COLOR;
  19.                                 LCD_WR_DATA(POINT_COLOR);       
  20.                                 temp>>=1;
  21.                                 x++;
  22.                         }
  23.                         x=x0;
  24.                         y++;
  25.                 }       
  26.         }
  27.         else
  28.         {
  29.                 for(pos=0;pos<16;pos++)
  30.                 {
  31.                         temp=asc2_1608[(unsigned int)num*16+pos];
  32.                         for(t=0;t<8;t++)
  33.                         {                 
  34.                              if(temp&0x01)LCD_DrawPoint(x+t,y+pos);     
  35.                              temp>>=1;
  36.                         }
  37.                 }
  38.         }
  39.         POINT_COLOR=colortemp;                                          
  40. }

显示字符串的函数为:
  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){x=0;y+=16;}
  6.         if(y>LCD_H-16){y=x=0;}
  7.         LCD_ShowChar(x,y,*p,0);
  8.         x+=8;
  9.         p++;
  10.     }  
  11. }

实现显示测试的主程序为:
  1. int main(void)
  2. {
  3.         BOARD_LED_Config(LED2);
  4.         BOARD_LED_Config(LED3);
  5.         BOARD_TFT_Config();
  6.         tft_Init();
  7.         LCD_Clear(RED);
  8.         BACK_COLOR=RED;
  9.         POINT_COLOR=YELLOW;
  10.         LCD_ShowString(120,10,"APM32F402");
  11.         while (1)
  12.         {
  13.                 Delay();       
  14.                 BOARD_LED_Toggle(LED2);
  15.                 BOARD_LED_Toggle(LED3);
  16.         }
  17. }


经程序的编译和下载,其显示效果如图2和图3所示,说明功能正常。
f3f7c6b70783204f707d5d5fb81df42f
图2 器件连接

255080cb50ad6fe83e01e13fbd250b02
图3 显示效果


阳光爆裂 发表于 2025-7-24 11:24 | 显示全部楼层
楼主这是使用GPIO来模拟的SPI时序吗?
 楼主| jinglixixi 发表于 2025-7-24 15:25 | 显示全部楼层
阳光爆裂 发表于 2025-7-24 11:24
楼主这是使用GPIO来模拟的SPI时序吗?

是的,只要能显示后面改为SPI驱动就有保障了。
暖茶轻语 发表于 2025-7-24 21:04 | 显示全部楼层
这个开发板测评很详细,特别是TFT屏的驱动部分,代码注释也很清晰,对初学者来说很有帮助。
阳光爆裂 发表于 2025-7-25 10:15 | 显示全部楼层
也是,也要先确定一下LCD屏的接收是否正常。
调试了半天,LCD屏有bug,这事就有点xx了
 楼主| jinglixixi 发表于 2025-7-25 12:23 | 显示全部楼层
暖茶轻语 发表于 2025-7-24 21:04
这个开发板测评很详细,特别是TFT屏的驱动部分,代码注释也很清晰,对初学者来说很有帮助。
...

感谢支持!!!
 楼主| jinglixixi 发表于 2025-7-25 12:25 | 显示全部楼层
阳光爆裂 发表于 2025-7-25 10:15
也是,也要先确定一下LCD屏的接收是否正常。
调试了半天,LCD屏有bug,这事就有点xx了 ...

实践中稳步迈进是最可靠的,虽然有时会慢一点。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

517

主题

2932

帖子

39

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