21160|19

356

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

STM32F767 FMC驱动TFT屏幕并成功移植EMWIN(记录一下)) [复制链接]

 
本帖最后由 ihalin 于 2016-8-12 00:19 编辑


经过一段时间琢磨stm32F767用fmc来驱动屏幕发现老是不成功,后来发现原来是 F7直接用FSMC驱动MCU接口的屏会有问题的!因为Cache在搞鬼!使用MPU(内存保护单元)对SRAM区做保护才可以驱动MCU屏还有一个原因是我是用杜邦线连接屏幕的干扰大,要在读数据的时候延时2到10us就可以。还有USART3的引脚 PD9 PD8和FMC的数据引脚有冲突,要断开桥接



下面是介绍FMC
FMC是FSMC的基础上支持SDRAM的升级版本
可变存储控制器 (FMC) 包括以下 3 个存储控制器:
 NOR/PSRAM 存储控制器
 NAND 存储控制器
 同步 DRAM (SDRAM/Mobile LPSDR SDRAM) 控制器

FMC  主要特性
FMC 功能块可连接:同步/异步静态存储器、SDRAM 存储器和 NAND Flash。其主要用途有:
 将 AHB 数据通信事务转换为适当的外部器件协议
 满足外部存储器器件的访问时间要求
所有外部存储器共享地址、数据和控制信号, 但有各自的片选信号。FMC 一次只能访问一
个外部器件。
FMC 控制器的主要特性如下:
 连接静态存储器映射的器件:
– 静态随机访问存储器 (SRAM)
– NOR Flash/OneNAND Flash
– PSRAM(4 个存储区域)
– 带有硬件 ECC 的 NAND Flash 存储器,可检查多达 8 KB 的数据
 连接同步 DRAM (SDRAM/Mobile LPSDR SDRAM) 存储器
 支持突发模式,能够更快速地访问同步器件(如 NOR Flash、PSRAM 和 SDRAM)
 可编程连续时钟输出以支持异步和同步访问
 具有 8 位、16 位或 32 位宽的数据总线
 每个存储区域有独立的片选控制
 每个存储区域可独立配置
 写使能和字节通道选择输出,可配合 PSRAM、SRAM 和 SDRAM 器件使用
 外部异步等待控制
 16 x 32 位深度写 FIFO
 SDRAM 控制器具有可缓存的 6 x 32 位深度读 FIFO(6 x 14 位地址标记)。
写 FIFO 由所有存储控制器所共用,包括:
 写数据 FIFO,用于存储要写入存储器的 AHB 数据(最多 32 位)以及 AHB 传输的一个
控制位(突发或非连续模式)。
 写地址 FIFO,用于存储 AHB 地址(最多 28 位)以及 AHB 数据大小(最多 2 位)。
在突发模式下工作时,将仅存储起始地址,但越过页边界时除外(适用于 PSRAM 和
SDRAM)。在此情况下,AHB 突发传输将分成两个 FIFO 条目。

通过将 FMC_BCR1 寄存器中的 WFDIS 位置 1 可禁止写 FIFO。
启动时,必须通过用户应用程序对 FMC 引脚进行配置。应用程序未使用的 FMC I/O 引脚可
用于其它用途。
定义外部器件类型和其特性的 FMC 寄存器通常在启动时进行设置,并且在下次上电或复位
前保持不变。但是,可随时更改设置。





下面是自己用的是 TFT ILI9341


fmc 接口
FMC_D15——>PD10
FMC_D14——>PD9
FMC_D13——>PD8
FMC_D12——>PE15
FMC_D11——>PE14
FMC_D10——>PE13
FMC_D9  ——>PE12
FMC_D8  ——>PE11
FMC_D7  ——>PE10
FMC_D6  ——>PE9
FMC_D5  ——>PE8
FMC_D4  ——>PE7
FMC_D3  ——>PD1
FMC_D2  ——>PD0
FMC_D1  ——>PD15
FMC_D0  ——>PD14
LCD(背光)---->PB5
LCD_CS——>FMC_NE4
LCD_RS——>FMC_A21(这里A21作为数据命令区分线,在16位数据总线时STM32内部地址会右移一位对齐  A21的偏移量计算:
Bank(x).region(y) + 2 * (2^n)     
Bank(x).region(y)为控制块的首地址
n为你所接的地址管脚号)
0x60000000 + 2 * (2的21次方) = 0x6000 0000 + 0x0040 0000
通过A21 = 0 作为RS=0; 0x6000 0000+0x003F FFFE
通过A21 =1 作为 RS=1; 0x6000 0000+0x0040 0000
0011 FFFF FFFF FFFF FFFF FFFF  对应 A21=0 ---->RS=0
0100 0000 0000 0000 0000 0000  对应 A21=1 ---->RS=1
RS的高低电平,决定了是数据还是命令
所以定义//LCD地址结构体
typedef struct
{
        vu16 LCD_REG;
        vu16 LCD_RAM;
} LCD_TypeDef;
//使用NOR/SRAM的 Bank1.sector1,地址位HADDR[27,26]=00 A21作为数据命令区分线
//注意设置时STM32内部会右移一位对其!                              
#define LCD_BASE        ((u32)(0x60000000 | 0x003FFFFE))
#define LCD             ((LCD_TypeDef *) LCD_BASE)






还要注意的是:
F7直接用FSMC驱动MCU接口的屏会有问题的!因为Cache在搞鬼!使用MPU(内存保护单元)对SRAM区做保护才可以驱动MCU屏
不初始化Cache
MPU设置:
  1. void MPU_Config(void)
  2. {
  3.   MPU_Region_InitTypeDef MPU_InitStruct;
  4.   
  5.   /* Disable the MPU */
  6.   HAL_MPU_Disable();

  7.   /* Configure the MPU attributes as WT for SRAM */
  8.   MPU_InitStruct.Enable = MPU_REGION_ENABLE;
  9.   MPU_InitStruct.BaseAddress = 0x20010000;
  10.   MPU_InitStruct.Size = MPU_REGION_SIZE_4GB;
  11.   MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
  12.   MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
  13.   MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
  14.   MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
  15.   MPU_InitStruct.Number = MPU_REGION_NUMBER0;
  16.   MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
  17.   MPU_InitStruct.SubRegionDisable = 0x00;
  18.   MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;

  19.   HAL_MPU_ConfigRegion(&MPU_InitStruct);

  20.   /* Enable the MPU */
  21.   HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
  22. }
复制代码



下面是LCD的驱动:
LCD.H
  1. #ifndef __LCD_H
  2. #define __LCD_H               
  3. #include "sys.h"         
  4. #include "stdlib.h"


  5. //LCD重要参数集
  6. typedef struct  
  7. {                          
  8.         u16 width;                        //LCD 宽度
  9.         u16 height;                        //LCD 高度
  10.         u16 id;                                //LCD ID
  11.         u8  dir;                        //横屏还是竖屏控制:0,竖屏;1,横屏。        
  12.         u16        wramcmd;                //开始写gram指令
  13.         u16 setxcmd;                //设置x坐标指令
  14.         u16 setycmd;                //设置y坐标指令
  15. }_lcd_dev;           

  16. //LCD参数2
  17. extern _lcd_dev lcddev;        //管理LCD重要参数
  18. //LCD的画笔颜色和背景色           
  19. extern u32  POINT_COLOR;//默认红色   
  20. extern u32  BACK_COLOR; //背景颜色.默认为白色


  21. //////////////////////////////////////////////////////////////////////////////////         
  22. //-----------------MCU屏 LCD端口定义----------------
  23.   
  24. //LCD地址结构体
  25. typedef struct
  26. {
  27.         vu16 LCD_REG;
  28.         vu16 LCD_RAM;
  29. } LCD_TypeDef;
  30. //使用NOR/SRAM的 Bank1.sector1,地址位HADDR[27,26]=00 A18作为数据命令区分线
  31. //注意设置时STM32内部会右移一位对其!                              
  32. //#define LCD_BASE        ((u32)(0x60000000 | 0x0007FFFE))
  33. //#define LCD_BASE        ((u32)(0x60000000 | 0x00000000))
  34. //#define LCD_BASE        ((u32)(0x60000000 | 0x0000007E))
  35. #define LCD_BASE        ((u32)(0x60000000 | 0x003FFFFE))
  36. #define LCD             ((LCD_TypeDef *) LCD_BASE)
  37. //////////////////////////////////////////////////////////////////////////////////
  38.          
  39. //扫描方向定义
  40. #define L2R_U2D  0                 //从左到右,从上到下
  41. #define L2R_D2U  1                 //从左到右,从下到上
  42. #define R2L_U2D  2                 //从右到左,从上到下
  43. #define R2L_D2U  3                 //从右到左,从下到上

  44. #define U2D_L2R  4                 //从上到下,从左到右
  45. #define U2D_R2L  5                 //从上到下,从右到左
  46. #define D2U_L2R  6                 //从下到上,从左到右
  47. #define D2U_R2L  7                //从下到上,从右到左         

  48. #define DFT_SCAN_DIR  L2R_U2D  //默认的扫描方向

  49. //画笔颜色
  50. #define WHITE                  0xFFFF
  51. #define BLACK                  0x0000         
  52. #define BLUE                  0x001F  
  53. #define BRED             0XF81F
  54. #define GRED                          0XFFE0
  55. #define GBLUE                         0X07FF
  56. #define RED                    0xF800
  57. #define MAGENTA                0xF81F
  58. #define GREEN                  0x07E0
  59. #define CYAN                   0x7FFF
  60. #define YELLOW                 0xFFE0
  61. #define BROWN                          0XBC40 //棕色
  62. #define BRRED                          0XFC07 //棕红色
  63. #define GRAY                           0X8430 //灰色
  64. //GUI颜色

  65. #define DARKBLUE               0X01CF        //深蓝色
  66. #define LIGHTBLUE               0X7D7C        //浅蓝色  
  67. #define GRAYBLUE                0X5458 //灰蓝色
  68. //以上三色为PANEL的颜色

  69. #define LIGHTGREEN              0X841F //浅绿色
  70. //#define LIGHTGRAY        0XEF5B //浅灰色(PANNEL)
  71. #define LGRAY                          0XC618 //浅灰色(PANNEL),窗体背景色

  72. #define LGRAYBLUE        0XA651 //浅灰蓝色(中间层颜色)
  73. #define LBBLUE           0X2B12 //浅棕蓝色(选择条目的反色)
  74.                                                                                                                                       
  75. void LCD_Init(void);                                                                                                                   //初始化
  76. void LCD_DisplayOn(void);                                                                                                        //开显示
  77. void LCD_DisplayOff(void);                                                                                                        //关显示
  78. void LCD_Clear(u32 Color);                                                                                                         //清屏
  79. void LCD_SetCursor(u16 Xpos, u16 Ypos);                                                                                //设置光标
  80. void LCD_DrawPoint(u16 x,u16 y);                                                                                        //画点
  81. void LCD_Fast_DrawPoint(u16 x,u16 y,u32 color);                                                                //快速画点
  82. u32  LCD_ReadPoint(u16 x,u16 y);                                                                                         //读点
  83. void LCD_Draw_Circle(u16 x0,u16 y0,u8 r);                                                                         //画圆
  84. void LCD_DrawLine(u16 x1, u16 y1, u16 x2, u16 y2);                                                        //画线
  85. void LCD_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2);                                                   //画矩形
  86. void LCD_Fill(u16 sx,u16 sy,u16 ex,u16 ey,u32 color);                                                   //填充单色
  87. void LCD_Color_Fill(u16 sx,u16 sy,u16 ex,u16 ey,u16 *color);                                //填充指定颜色
  88. void LCD_ShowChar(u16 x,u16 y,u8 num,u8 size,u8 mode);                                                //显示一个字符
  89. void LCD_ShowNum(u16 x,u16 y,u32 num,u8 len,u8 size);                                                  //显示一个数字
  90. void LCD_ShowxNum(u16 x,u16 y,u32 num,u8 len,u8 size,u8 mode);                                //显示 数字
  91. void LCD_ShowString(u16 x,u16 y,u16 width,u16 height,u8 size,u8 *p);                //显示一个字符串,12/16字体

  92. void LCD_WriteReg(u16 LCD_Reg, u16 LCD_RegValue);
  93. u16 LCD_ReadReg(u16 LCD_Reg);
  94. void LCD_WriteRAM_Prepare(void);
  95. void LCD_WriteRAM(u16 RGB_Code);
  96. void LCD_SSD_BackLightSet(u8 pwm);                                                        //SSD1963 背光控制
  97. void LCD_Scan_Dir(u8 dir);                                                                        //设置屏扫描方向
  98. void LCD_Display_Dir(u8 dir);                                                                //设置屏幕显示方向
  99. void LCD_Set_Window(u16 sx,u16 sy,u16 width,u16 height);        //设置窗口                                                                                                                                                                                                                                                      
  100. //LCD分辨率设置
  101. #define SSD_HOR_RESOLUTION                320                //LCD水平分辨率
  102. #define SSD_VER_RESOLUTION                240                //LCD垂直分辨率
  103. //LCD驱动参数设置
  104. #define SSD_HOR_PULSE_WIDTH                1                //水平脉宽
  105. #define SSD_HOR_BACK_PORCH                46                //水平前廊
  106. #define SSD_HOR_FRONT_PORCH                210                //水平后廊

  107. #define SSD_VER_PULSE_WIDTH                1                //垂直脉宽
  108. #define SSD_VER_BACK_PORCH                23                //垂直前廊
  109. #define SSD_VER_FRONT_PORCH                22                //垂直前廊
  110. //如下几个参数,自动计算
  111. #define SSD_HT        (SSD_HOR_RESOLUTION+SSD_HOR_BACK_PORCH+SSD_HOR_FRONT_PORCH)
  112. #define SSD_HPS        (SSD_HOR_BACK_PORCH)
  113. #define SSD_VT         (SSD_VER_RESOLUTION+SSD_VER_BACK_PORCH+SSD_VER_FRONT_PORCH)
  114. #define SSD_VPS (SSD_VER_BACK_PORCH)

  115. #endif  
  116.          
  117.          


复制代码
LCD.C
  1. #include "lcd.h"
  2. #include "stdlib.h"
  3. #include "font.h"
  4. #include "uart.h"         
  5. #include "delay.h"         


  6. SRAM_HandleTypeDef SRAM_Handler;    //SRAM句柄(用于控制LCD)

  7. //LCD的画笔颜色和背景色           
  8. u32 POINT_COLOR=0xFF000000;                //画笔颜色
  9. u32 BACK_COLOR =0xFFFFFFFF;          //背景色
  10. int t=0;
  11. //管理LCD重要参数
  12. //默认为竖屏
  13. _lcd_dev lcddev;
  14.            
  15. //写寄存器函数
  16. //regval:寄存器值
  17. void LCD_WR_REG(vu16 regval)
  18. {
  19.         regval=regval;                //使用-O2优化的时候,必须插入的延时
  20.         LCD->LCD_REG=regval;//写入要写的寄存器序号         
  21. }
  22. //写LCD数据
  23. //data:要写入的值
  24. void LCD_WR_DATA(vu16 data)
  25. {         
  26.         data=data;                        //使用-O2优化的时候,必须插入的延时
  27.         LCD->LCD_RAM=data;                 
  28. }
  29. //读LCD数据
  30. //返回值:读到的值
  31. u16 LCD_RD_DATA(void)
  32. {
  33.         delay_us(2);
  34.         vu16 ram;                        //防止被优化
  35.         ram=LCD->LCD_RAM;        
  36.         return ram;         
  37. }                                          
  38. //写寄存器
  39. //LCD_Reg:寄存器地址
  40. //LCD_RegValue:要写入的数据
  41. void LCD_WriteReg(u16 LCD_Reg,u16 LCD_RegValue)
  42. {        

  43.         LCD->LCD_REG = LCD_Reg;                //写入要写的寄存器序号         
  44.         LCD->LCD_RAM = LCD_RegValue;//写入数据                             
  45. }           
  46. //读寄存器
  47. //LCD_Reg:寄存器地址
  48. //返回值:读到的数据
  49. u16 LCD_ReadReg(u16 LCD_Reg)
  50. {                                                                                   
  51.         LCD_WR_REG(LCD_Reg);                //写入要读的寄存器序号
  52.         delay_us(10);
  53.         return LCD_RD_DATA();                //返回读到的值
  54. }   
  55. //开始写GRAM
  56. void LCD_WriteRAM_Prepare(void)
  57. {
  58.          LCD->LCD_REG=lcddev.wramcmd;         
  59. }         
  60. //LCD写GRAM
  61. //RGB_Code:颜色值
  62. void LCD_WriteRAM(u16 RGB_Code)
  63. {                                                            
  64.         LCD->LCD_RAM = RGB_Code;//写十六位GRAM
  65. }
  66. //从ILI93xx读出的数据为GBR格式,而我们写入的时候为RGB格式。
  67. //通过该函数转换
  68. //c:GBR格式的颜色值
  69. //返回值:RGB格式的颜色值
  70. u16 LCD_BGR2RGB(u16 c)
  71. {
  72.         u16  r,g,b,rgb;   
  73.         b=(c>>0)&0x1f;
  74.         g=(c>>5)&0x3f;
  75.         r=(c>>11)&0x1f;         
  76.         rgb=(b<<11)+(g<<5)+(r<<0);                 
  77.         return(rgb);
  78. }
  79. //当mdk -O1时间优化时需要设置
  80. //延时i
  81. void opt_delay(u8 i)
  82. {
  83.         while(i--);
  84. }
  85. //读取个某点的颜色值         
  86. //x,y:坐标
  87. //返回值:此点的颜色
  88. u32 LCD_ReadPoint(u16 x,u16 y)
  89. {
  90.          u16 r=0,g=0,b=0;
  91.         if(x>=lcddev.width||y>=lcddev.height)return 0;        //超过了范围,直接返回
  92.         LCD_SetCursor(x,y);            
  93.         if(lcddev.id==0X9341||lcddev.id==0X5310||lcddev.id==0X1963)LCD_WR_REG(0X2E);//9341/3510/1963 发送读GRAM指令
  94.         else if(lcddev.id==0X5510)LCD_WR_REG(0X2E00);        //5510 发送读GRAM指令
  95.          r=LCD_RD_DATA();                                                                //dummy Read           
  96.         if(lcddev.id==0X1963)return r;                                        //1963直接读就可以
  97.         opt_delay(2);         
  98.          r=LCD_RD_DATA();                                                                    //实际坐标颜色
  99.         //9341/NT35310/NT35510要分2次读出
  100.         opt_delay(2);                                            
  101.         b=LCD_RD_DATA();
  102.         g=r&0XFF;                //对于9341/5310/5510,第一次读取的是RG的值,R在前,G在后,各占8位
  103.         g<<=8;
  104.         return (((r>>11)<<11)|((g>>10)<<5)|(b>>11));        //ILI9341/NT35310/NT35510需要公式转换一下
  105. }                        
  106. //LCD开启显示
  107. void LCD_DisplayOn(void)
  108. {                                          
  109.         if(lcddev.id==0X9341||lcddev.id==0X5310||lcddev.id==0X1963)LCD_WR_REG(0X29);        //开启显示
  110.         else if(lcddev.id==0X5510)LCD_WR_REG(0X2900);        //开启显示
  111. }         
  112. //LCD关闭显示
  113. void LCD_DisplayOff(void)
  114. {           
  115.         if(lcddev.id==0X9341||lcddev.id==0X5310||lcddev.id==0X1963)LCD_WR_REG(0X28);        //关闭显示
  116.         else if(lcddev.id==0X5510)LCD_WR_REG(0X2800);        //关闭显示
  117. }   
  118. //设置光标位置(对RGB屏无效)
  119. //Xpos:横坐标
  120. //Ypos:纵坐标
  121. void LCD_SetCursor(u16 Xpos, u16 Ypos)
  122. {         
  123.          if(lcddev.id==0X9341||lcddev.id==0X5310)
  124.         {                    
  125.                 LCD_WR_REG(lcddev.setxcmd);
  126.                 LCD_WR_DATA(Xpos>>8);LCD_WR_DATA(Xpos&0XFF);                          
  127.                 LCD_WR_REG(lcddev.setycmd);
  128.                 LCD_WR_DATA(Ypos>>8);LCD_WR_DATA(Ypos&0XFF);                 
  129.         }else if(lcddev.id==0X1963)
  130.         {                                          
  131.                 if(lcddev.dir==0)//x坐标需要变换
  132.                 {
  133.                         Xpos=lcddev.width-1-Xpos;
  134.                         LCD_WR_REG(lcddev.setxcmd);
  135.                         LCD_WR_DATA(0);LCD_WR_DATA(0);                 
  136.                         LCD_WR_DATA(Xpos>>8);LCD_WR_DATA(Xpos&0XFF);                          
  137.                 }else
  138.                 {
  139.                         LCD_WR_REG(lcddev.setxcmd);
  140.                         LCD_WR_DATA(Xpos>>8);LCD_WR_DATA(Xpos&0XFF);                 
  141.                         LCD_WR_DATA((lcddev.width-1)>>8);LCD_WR_DATA((lcddev.width-1)&0XFF);                                                  
  142.                 }        
  143.                 LCD_WR_REG(lcddev.setycmd);
  144.                 LCD_WR_DATA(Ypos>>8);LCD_WR_DATA(Ypos&0XFF);                 
  145.                 LCD_WR_DATA((lcddev.height-1)>>8);LCD_WR_DATA((lcddev.height-1)&0XFF);                                          
  146.                
  147.         }else if(lcddev.id==0X5510)
  148.         {
  149.                 LCD_WR_REG(lcddev.setxcmd);LCD_WR_DATA(Xpos>>8);                 
  150.                 LCD_WR_REG(lcddev.setxcmd+1);LCD_WR_DATA(Xpos&0XFF);                        
  151.                 LCD_WR_REG(lcddev.setycmd);LCD_WR_DATA(Ypos>>8);                  
  152.                 LCD_WR_REG(lcddev.setycmd+1);LCD_WR_DATA(Ypos&0XFF);                        
  153.         }
  154. }                  
  155. //设置LCD的自动扫描方向(对RGB屏无效)
  156. //注意:其他函数可能会受到此函数设置的影响(尤其是9341),
  157. //所以,一般设置为L2R_U2D即可,如果设置为其他扫描方式,可能导致显示不正常.
  158. //dir:0~7,代表8个方向(具体定义见lcd.h)
  159. //9341/5310/5510/1963等IC已经实际测试                     
  160. void LCD_Scan_Dir(u8 dir)
  161. {
  162.         u16 regval=0;
  163.         u16 dirreg=0;
  164.         u16 temp;  
  165.         if((lcddev.dir==1&&lcddev.id!=0X1963)||(lcddev.dir==0&&lcddev.id==0X1963))//横屏时,对1963不改变扫描方向!竖屏时1963改变方向
  166.         {                           
  167.                 switch(dir)//方向转换
  168.                 {
  169.                         case 0:dir=6;break;
  170.                         case 1:dir=7;break;
  171.                         case 2:dir=4;break;
  172.                         case 3:dir=5;break;
  173.                         case 4:dir=1;break;
  174.                         case 5:dir=0;break;
  175.                         case 6:dir=3;break;
  176.                         case 7:dir=2;break;            
  177.                 }
  178.         }
  179.         if(lcddev.id==0x9341||lcddev.id==0X5310||lcddev.id==0X5510||lcddev.id==0X1963)//9341/5310/5510/1963,特殊处理
  180.         {
  181.                 switch(dir)
  182.                 {
  183.                         case L2R_U2D://从左到右,从上到下
  184.                                 regval|=(0<<7)|(0<<6)|(0<<5);
  185.                                 break;
  186.                         case L2R_D2U://从左到右,从下到上
  187.                                 regval|=(1<<7)|(0<<6)|(0<<5);
  188.                                 break;
  189.                         case R2L_U2D://从右到左,从上到下
  190.                                 regval|=(0<<7)|(1<<6)|(0<<5);
  191.                                 break;
  192.                         case R2L_D2U://从右到左,从下到上
  193.                                 regval|=(1<<7)|(1<<6)|(0<<5);
  194.                                 break;         
  195.                         case U2D_L2R://从上到下,从左到右
  196.                                 regval|=(0<<7)|(0<<6)|(1<<5);
  197.                                 break;
  198.                         case U2D_R2L://从上到下,从右到左
  199.                                 regval|=(0<<7)|(1<<6)|(1<<5);
  200.                                 break;
  201.                         case D2U_L2R://从下到上,从左到右
  202.                                 regval|=(1<<7)|(0<<6)|(1<<5);
  203.                                 break;
  204.                         case D2U_R2L://从下到上,从右到左
  205.                                 regval|=(1<<7)|(1<<6)|(1<<5);
  206.                                 break;         
  207.                 }
  208.                 if(lcddev.id==0X5510)dirreg=0X3600;
  209.                 else dirreg=0X36;
  210.                  if((lcddev.id!=0X5310)&&(lcddev.id!=0X5510)&&(lcddev.id!=0X1963))regval|=0X08;//5310/5510/1963不需要BGR   
  211.                  LCD_WriteReg(dirreg,regval);
  212.                 if(lcddev.id!=0X1963)//1963不做坐标处理
  213.                 {
  214.                         if(regval&0X20)
  215.                         {
  216.                                 if(lcddev.width<lcddev.height)//交换X,Y
  217.                                 {
  218.                                         temp=lcddev.width;
  219.                                         lcddev.width=lcddev.height;
  220.                                         lcddev.height=temp;
  221.                                 }
  222.                         }else  
  223.                         {
  224.                                 if(lcddev.width>lcddev.height)//交换X,Y
  225.                                 {
  226.                                         temp=lcddev.width;
  227.                                         lcddev.width=lcddev.height;
  228.                                         lcddev.height=temp;
  229.                                 }
  230.                         }  
  231.                 }
  232.                 if(lcddev.id==0X5510)
  233.                 {
  234.                         LCD_WR_REG(lcddev.setxcmd);LCD_WR_DATA(0);
  235.                         LCD_WR_REG(lcddev.setxcmd+1);LCD_WR_DATA(0);
  236.                         LCD_WR_REG(lcddev.setxcmd+2);LCD_WR_DATA((lcddev.width-1)>>8);
  237.                         LCD_WR_REG(lcddev.setxcmd+3);LCD_WR_DATA((lcddev.width-1)&0XFF);
  238.                         LCD_WR_REG(lcddev.setycmd);LCD_WR_DATA(0);
  239.                         LCD_WR_REG(lcddev.setycmd+1);LCD_WR_DATA(0);
  240.                         LCD_WR_REG(lcddev.setycmd+2);LCD_WR_DATA((lcddev.height-1)>>8);
  241.                         LCD_WR_REG(lcddev.setycmd+3);LCD_WR_DATA((lcddev.height-1)&0XFF);
  242.                 }else
  243.                 {
  244.                         LCD_WR_REG(lcddev.setxcmd);
  245.                         LCD_WR_DATA(0);LCD_WR_DATA(0);
  246.                         LCD_WR_DATA((lcddev.width-1)>>8);LCD_WR_DATA((lcddev.width-1)&0XFF);
  247.                         LCD_WR_REG(lcddev.setycmd);
  248.                         LCD_WR_DATA(0);LCD_WR_DATA(0);
  249.                         LCD_WR_DATA((lcddev.height-1)>>8);LCD_WR_DATA((lcddev.height-1)&0XFF);  
  250.                 }
  251.           }
  252. }     
  253. //画点
  254. //x,y:坐标
  255. //POINT_COLOR:此点的颜色
  256. void LCD_DrawPoint(u16 x,u16 y)
  257. {
  258.         LCD_SetCursor(x,y);                //设置光标位置
  259.         LCD_WriteRAM_Prepare();        //开始写入GRAM
  260.         LCD->LCD_RAM=POINT_COLOR;  
  261. }
  262. //快速画点
  263. //x,y:坐标
  264. //color:颜色
  265. void LCD_Fast_DrawPoint(u16 x,u16 y,u32 color)
  266. {           
  267.         if(lcddev.id==0X9341||lcddev.id==0X5310)
  268.         {
  269.                 LCD_WR_REG(lcddev.setxcmd);
  270.                 LCD_WR_DATA(x>>8);LCD_WR_DATA(x&0XFF);                           
  271.                 LCD_WR_REG(lcddev.setycmd);
  272.                 LCD_WR_DATA(y>>8);LCD_WR_DATA(y&0XFF);                           
  273.         }else if(lcddev.id==0X5510)
  274.         {
  275.                 LCD_WR_REG(lcddev.setxcmd);LCD_WR_DATA(x>>8);  
  276.                 LCD_WR_REG(lcddev.setxcmd+1);LCD_WR_DATA(x&0XFF);         
  277.                 LCD_WR_REG(lcddev.setycmd);LCD_WR_DATA(y>>8);  
  278.                 LCD_WR_REG(lcddev.setycmd+1);LCD_WR_DATA(y&0XFF);
  279.         }else if(lcddev.id==0X1963)
  280.         {
  281.                 if(lcddev.dir==0)x=lcddev.width-1-x;
  282.                 LCD_WR_REG(lcddev.setxcmd);
  283.                 LCD_WR_DATA(x>>8);LCD_WR_DATA(x&0XFF);                 
  284.                 LCD_WR_DATA(x>>8);LCD_WR_DATA(x&0XFF);                 
  285.                 LCD_WR_REG(lcddev.setycmd);
  286.                 LCD_WR_DATA(y>>8);LCD_WR_DATA(y&0XFF);                 
  287.                 LCD_WR_DATA(y>>8);LCD_WR_DATA(y&0XFF);                 
  288.         }                 
  289.         LCD->LCD_REG=lcddev.wramcmd;
  290.         LCD->LCD_RAM=color;
  291. }         
  292. //SSD1963 背光设置
  293. //pwm:背光等级,0~100.越大越亮.
  294. void LCD_SSD_BackLightSet(u8 pwm)
  295. {        
  296.         LCD_WR_REG(0xBE);        //配置PWM输出
  297.         LCD_WR_DATA(0x05);        //1设置PWM频率
  298.         LCD_WR_DATA(pwm*2.55);//2设置PWM占空比
  299.         LCD_WR_DATA(0x01);        //3设置C
  300.         LCD_WR_DATA(0xFF);        //4设置D
  301.         LCD_WR_DATA(0x00);        //5设置E
  302.         LCD_WR_DATA(0x00);        //6设置F
  303. }

  304. //设置LCD显示方向
  305. //dir:0,竖屏;1,横屏
  306. void LCD_Display_Dir(u8 dir)
  307. {
  308.         lcddev.dir=dir;                //竖屏/横屏
  309.         if(dir==0)                        //竖屏
  310.         {
  311.                 lcddev.width=240;
  312.                 lcddev.height=320;
  313.                 if(lcddev.id==0X9341||lcddev.id==0X5310)
  314.                 {
  315.                         lcddev.wramcmd=0X2C;
  316.                          lcddev.setxcmd=0X2A;
  317.                         lcddev.setycmd=0X2B;           
  318.                         if(lcddev.id==0X5310)
  319.                         {
  320.                                 lcddev.width=320;
  321.                                 lcddev.height=480;
  322.                         }
  323.                 }else if(lcddev.id==0x5510)
  324.                 {
  325.                         lcddev.wramcmd=0X2C00;
  326.                          lcddev.setxcmd=0X2A00;
  327.                         lcddev.setycmd=0X2B00;
  328.                         lcddev.width=480;
  329.                         lcddev.height=800;
  330.                 }else if(lcddev.id==0X1963)
  331.                 {
  332.                         lcddev.wramcmd=0X2C;        //设置写入GRAM的指令
  333.                         lcddev.setxcmd=0X2B;        //设置写X坐标指令
  334.                         lcddev.setycmd=0X2A;        //设置写Y坐标指令
  335.                         lcddev.width=480;                //设置宽度480
  336.                         lcddev.height=800;                //设置高度800  
  337.                 }
  338.         }else                                 //横屏
  339.         {                                          
  340.                 lcddev.width=320;
  341.                 lcddev.height=240;
  342.                 if(lcddev.id==0X9341||lcddev.id==0X5310)
  343.                 {
  344.                         lcddev.wramcmd=0X2C;
  345.                          lcddev.setxcmd=0X2A;
  346.                         lcddev.setycmd=0X2B;           
  347.                 }else if(lcddev.id==0x5510)
  348.                 {
  349.                         lcddev.wramcmd=0X2C00;
  350.                          lcddev.setxcmd=0X2A00;
  351.                         lcddev.setycmd=0X2B00;
  352.                         lcddev.width=800;
  353.                         lcddev.height=480;
  354.                 }else if(lcddev.id==0X1963)
  355.                 {
  356.                         lcddev.wramcmd=0X2C;        //设置写入GRAM的指令
  357.                         lcddev.setxcmd=0X2A;        //设置写X坐标指令
  358.                         lcddev.setycmd=0X2B;        //设置写Y坐标指令
  359.                         lcddev.width=800;                //设置宽度800
  360.                         lcddev.height=480;                //设置高度480  
  361.                 }
  362.                 if(lcddev.id==0X5310)
  363.                 {         
  364.                         lcddev.width=480;
  365.                         lcddev.height=320;                        
  366.                 }
  367.         }
  368.         LCD_Scan_Dir(DFT_SCAN_DIR);        //默认扫描方向
  369. }         
  370. //设置窗口(对RGB屏无效),并自动设置画点坐标到窗口左上角(sx,sy).
  371. //sx,sy:窗口起始坐标(左上角)
  372. //width,height:窗口宽度和高度,必须大于0!!
  373. //窗体大小:width*height.
  374. void LCD_Set_Window(u16 sx,u16 sy,u16 width,u16 height)
  375. {     
  376.         u16 twidth,theight;
  377.         twidth=sx+width-1;
  378.         theight=sy+height-1;
  379.         if(lcddev.id==0X9341||lcddev.id==0X5310||(lcddev.dir==1&&lcddev.id==0X1963))
  380.         {
  381.                 LCD_WR_REG(lcddev.setxcmd);
  382.                 LCD_WR_DATA(sx>>8);
  383.                 LCD_WR_DATA(sx&0XFF);         
  384.                 LCD_WR_DATA(twidth>>8);
  385.                 LCD_WR_DATA(twidth&0XFF);  
  386.                 LCD_WR_REG(lcddev.setycmd);
  387.                 LCD_WR_DATA(sy>>8);
  388.                 LCD_WR_DATA(sy&0XFF);
  389.                 LCD_WR_DATA(theight>>8);
  390.                 LCD_WR_DATA(theight&0XFF);
  391.         }else if(lcddev.id==0X1963)//1963竖屏特殊处理
  392.         {
  393.                 sx=lcddev.width-width-sx;
  394.                 height=sy+height-1;
  395.                 LCD_WR_REG(lcddev.setxcmd);
  396.                 LCD_WR_DATA(sx>>8);
  397.                 LCD_WR_DATA(sx&0XFF);         
  398.                 LCD_WR_DATA((sx+width-1)>>8);
  399.                 LCD_WR_DATA((sx+width-1)&0XFF);  
  400.                 LCD_WR_REG(lcddev.setycmd);
  401.                 LCD_WR_DATA(sy>>8);
  402.                 LCD_WR_DATA(sy&0XFF);
  403.                 LCD_WR_DATA(height>>8);
  404.                 LCD_WR_DATA(height&0XFF);                 
  405.         }else if(lcddev.id==0X5510)
  406.         {
  407.                 LCD_WR_REG(lcddev.setxcmd);LCD_WR_DATA(sx>>8);  
  408.                 LCD_WR_REG(lcddev.setxcmd+1);LCD_WR_DATA(sx&0XFF);         
  409.                 LCD_WR_REG(lcddev.setxcmd+2);LCD_WR_DATA(twidth>>8);   
  410.                 LCD_WR_REG(lcddev.setxcmd+3);LCD_WR_DATA(twidth&0XFF);   
  411.                 LCD_WR_REG(lcddev.setycmd);LCD_WR_DATA(sy>>8);   
  412.                 LCD_WR_REG(lcddev.setycmd+1);LCD_WR_DATA(sy&0XFF);  
  413.                 LCD_WR_REG(lcddev.setycmd+2);LCD_WR_DATA(theight>>8);   
  414.                 LCD_WR_REG(lcddev.setycmd+3);LCD_WR_DATA(theight&0XFF);  
  415.         }
  416. }
  417. //SRAM底层驱动,时钟使能,引脚分配
  418. //此函数会被HAL_SRAM_Init()调用
  419. //hsram:SRAM句柄
  420. void HAL_SRAM_MspInit(SRAM_HandleTypeDef *hsram)
  421. {        
  422.         GPIO_InitTypeDef GPIO_Initure;
  423.         
  424.         __HAL_RCC_FMC_CLK_ENABLE();                                //使能FMC时钟
  425.         __HAL_RCC_GPIOD_CLK_ENABLE();                        //使能GPIOD时钟
  426.         __HAL_RCC_GPIOE_CLK_ENABLE();                        //使能GPIOE时钟
  427.         
  428.         //初始化PD0,1,4,5,7,8,9,10,13,14,15
  429.         GPIO_Initure.Pin=GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_7|GPIO_PIN_8|\
  430.                      GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
  431.         GPIO_Initure.Mode=GPIO_MODE_AF_PP;                 //推挽复用
  432.         GPIO_Initure.Pull=GPIO_PULLUP;                        //上拉
  433.         GPIO_Initure.Speed=GPIO_SPEED_HIGH;                //高速
  434.         GPIO_Initure.Alternate=GPIO_AF12_FMC;        //复用为FMC
  435.         HAL_GPIO_Init(GPIOD,&GPIO_Initure);     //初始化
  436.         
  437.         //初始化PE7,8,9,10,11,12,13,14,15
  438.         GPIO_Initure.Pin=GPIO_PIN_5|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|\
  439.                      GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
  440.         HAL_GPIO_Init(GPIOE,&GPIO_Initure);
  441.         GPIO_Initure.Pin=GPIO_PIN_0|GPIO_PIN_12;
  442.         HAL_GPIO_Init(GPIOF,&GPIO_Initure);
  443. }
  444.         
  445. //初始化lcd
  446. void LCD_Init(void)
  447. {           
  448.         GPIO_InitTypeDef GPIO_Initure;
  449.         FMC_NORSRAM_TimingTypeDef FMC_ReadWriteTim;
  450.         FMC_NORSRAM_TimingTypeDef FMC_WriteTim;
  451.    
  452.         __HAL_RCC_GPIOB_CLK_ENABLE();                        //开启GPIOB时钟
  453.         GPIO_Initure.Pin=GPIO_PIN_5|GPIO_PIN_6;            //PB5,背光控制
  454.         GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;  //推挽输出
  455.         GPIO_Initure.Pull=GPIO_PULLUP;          //上拉
  456.         GPIO_Initure.Speed=GPIO_SPEED_HIGH;     //高速
  457.         HAL_GPIO_Init(GPIOB,&GPIO_Initure);
  458.    
  459.         SRAM_Handler.Instance=FMC_NORSRAM_DEVICE;               
  460.         SRAM_Handler.Extended=FMC_NORSRAM_EXTENDED_DEVICE;   
  461.    
  462.         SRAM_Handler.Init.NSBank=FMC_NORSRAM_BANK1;     //使用NE1
  463.         SRAM_Handler.Init.DataAddressMux=FMC_DATA_ADDRESS_MUX_DISABLE; //地址/数据线不复用
  464.         SRAM_Handler.Init.MemoryType=FMC_MEMORY_TYPE_SRAM;   //SRAM
  465.         SRAM_Handler.Init.MemoryDataWidth=FMC_NORSRAM_MEM_BUS_WIDTH_16; //16位数据宽度
  466.         SRAM_Handler.Init.BurstAccessMode=FMC_BURST_ACCESS_MODE_DISABLE; //是否使能突发访问,仅对同步突发存储器有效,此处未用到
  467.         SRAM_Handler.Init.WaitSignalPolarity=FMC_WAIT_SIGNAL_POLARITY_LOW;//等待信号的极性,仅在突发模式访问下有用
  468.         SRAM_Handler.Init.WaitSignalActive=FMC_WAIT_TIMING_BEFORE_WS;   //存储器是在等待周期之前的一个时钟周期还是等待周期期间使能NWAIT
  469.         SRAM_Handler.Init.WriteOperation=FMC_WRITE_OPERATION_ENABLE;    //存储器写使能
  470.         SRAM_Handler.Init.WaitSignal=FMC_WAIT_SIGNAL_DISABLE;           //等待使能位,此处未用到
  471.         SRAM_Handler.Init.ExtendedMode=FMC_EXTENDED_MODE_ENABLE;        //读写使用不同的时序
  472.         SRAM_Handler.Init.AsynchronousWait=FMC_ASYNCHRONOUS_WAIT_DISABLE;//是否使能同步传输模式下的等待信号,此处未用到
  473.         SRAM_Handler.Init.WriteBurst=FMC_WRITE_BURST_DISABLE;           //禁止突发写
  474.         SRAM_Handler.Init.ContinuousClock=FMC_CONTINUOUS_CLOCK_SYNC_ASYNC;
  475.         SRAM_Handler.Init.WriteFifo = FMC_WRITE_FIFO_ENABLE;
  476.   SRAM_Handler.Init.PageSize = FMC_PAGE_SIZE_NONE;
  477.         
  478.         
  479. //        //FMC读时序控制寄存器
  480.         FMC_ReadWriteTim.AddressSetupTime=15;        //地址建立时间(ADDSET)为15个HCLK 1/216M*15=4.6ns*15
  481.         FMC_ReadWriteTim.AddressHoldTime=15;
  482.         FMC_ReadWriteTim.DataSetupTime=255;           //数据保存时间(DATAST)为255个HCLK        =4.6*255
  483.         FMC_ReadWriteTim.BusTurnAroundDuration = 15;
  484.         FMC_ReadWriteTim.CLKDivision=16;
  485.         FMC_ReadWriteTim.DataLatency =17;
  486.         FMC_ReadWriteTim.AccessMode=FMC_ACCESS_MODE_A; //模式A
  487.         //FMC写时序控制寄存器
  488.         FMC_WriteTim.AddressSetupTime=15;            //地址建立时间(ADDSET)为17个HCLK=82.5ns
  489.         FMC_WriteTim.AddressHoldTime=15;
  490.         FMC_WriteTim.DataSetupTime=255;               //数据保存时间(DATAST)为5.5ns*17个HCLK=82.5ns
  491.         FMC_WriteTim.BusTurnAroundDuration = 15;
  492.         FMC_WriteTim.CLKDivision=16;
  493.         FMC_WriteTim.DataLatency =17;
  494.         FMC_WriteTim.AccessMode=FMC_ACCESS_MODE_A;     //模式A
  495.         
  496.         HAL_SRAM_Init(&SRAM_Handler,&FMC_ReadWriteTim,&FMC_WriteTim);        
  497.         HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_RESET);        //RST
  498.         delay_ms(100); // delay 50 ms  
  499.         HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_SET);        //RST
  500.         delay_ms(50);
  501.         delay_ms(50); // delay 50 ms
  502.         //尝试9341 ID的读取               
  503.         LCD_WR_REG(0XD3);                                   
  504.         lcddev.id=LCD_RD_DATA();        //dummy read         
  505.         lcddev.id=LCD_RD_DATA();        //读到0X00
  506.         lcddev.id=LCD_RD_DATA();           //读取93               
  507.         lcddev.id<<=8;
  508.         lcddev.id|=LCD_RD_DATA();          //读取41                                       
  509.    
  510.                 LCD_WR_REG(0xCF);  
  511.                 LCD_WR_DATA(0x00);
  512.                 LCD_WR_DATA(0xC1);
  513.                 LCD_WR_DATA(0X30);
  514.                 LCD_WR_REG(0xED);  
  515.                 LCD_WR_DATA(0x64);
  516.                 LCD_WR_DATA(0x03);
  517.                 LCD_WR_DATA(0X12);
  518.                 LCD_WR_DATA(0X81);
  519.                 LCD_WR_REG(0xE8);  
  520.                 LCD_WR_DATA(0x85);
  521.                 LCD_WR_DATA(0x10);
  522.                 LCD_WR_DATA(0x7A);
  523.                 LCD_WR_REG(0xCB);  
  524.                 LCD_WR_DATA(0x39);
  525.                 LCD_WR_DATA(0x2C);
  526.                 LCD_WR_DATA(0x00);
  527.                 LCD_WR_DATA(0x34);
  528.                 LCD_WR_DATA(0x02);
  529.                 LCD_WR_REG(0xF7);  
  530.                 LCD_WR_DATA(0x20);
  531.                 LCD_WR_REG(0xEA);  
  532.                 LCD_WR_DATA(0x00);
  533.                 LCD_WR_DATA(0x00);
  534.                 LCD_WR_REG(0xC0);    //Power control
  535.                 LCD_WR_DATA(0x1B);   //VRH[5:0]
  536.                 LCD_WR_REG(0xC1);    //Power control
  537.                 LCD_WR_DATA(0x01);   //SAP[2:0];BT[3:0]
  538.                 LCD_WR_REG(0xC5);    //VCM control
  539.                 LCD_WR_DATA(0x30);          //3F
  540.                 LCD_WR_DATA(0x30);          //3C
  541.                 LCD_WR_REG(0xC7);    //VCM control2
  542.                 LCD_WR_DATA(0XB7);
  543.                 LCD_WR_REG(0x36);    // Memory Access Control
  544.                 LCD_WR_DATA(0x48);
  545.                 LCD_WR_REG(0x3A);   
  546.                 LCD_WR_DATA(0x55);
  547.                 LCD_WR_REG(0xB1);   
  548.                 LCD_WR_DATA(0x00);   
  549.                 LCD_WR_DATA(0x1A);
  550.                 LCD_WR_REG(0xB6);    // Display Function Control
  551.                 LCD_WR_DATA(0x0A);
  552.                 LCD_WR_DATA(0xA2);
  553.                 LCD_WR_REG(0xF2);    // 3Gamma Function Disable
  554.                 LCD_WR_DATA(0x00);
  555.                 LCD_WR_REG(0x26);    //Gamma curve selected
  556.                 LCD_WR_DATA(0x01);
  557.                 LCD_WR_REG(0xE0);    //Set Gamma
  558.                 LCD_WR_DATA(0x0F);
  559.                 LCD_WR_DATA(0x2A);
  560.                 LCD_WR_DATA(0x28);
  561.                 LCD_WR_DATA(0x08);
  562.                 LCD_WR_DATA(0x0E);
  563.                 LCD_WR_DATA(0x08);
  564.                 LCD_WR_DATA(0x54);
  565.                 LCD_WR_DATA(0XA9);
  566.                 LCD_WR_DATA(0x43);
  567.                 LCD_WR_DATA(0x0A);
  568.                 LCD_WR_DATA(0x0F);
  569.                 LCD_WR_DATA(0x00);
  570.                 LCD_WR_DATA(0x00);
  571.                 LCD_WR_DATA(0x00);
  572.                 LCD_WR_DATA(0x00);                  
  573.                 LCD_WR_REG(0XE1);    //Set Gamma
  574.                 LCD_WR_DATA(0x00);
  575.                 LCD_WR_DATA(0x15);
  576.                 LCD_WR_DATA(0x17);
  577.                 LCD_WR_DATA(0x07);
  578.                 LCD_WR_DATA(0x11);
  579.                 LCD_WR_DATA(0x06);
  580.                 LCD_WR_DATA(0x2B);
  581.                 LCD_WR_DATA(0x56);
  582.                 LCD_WR_DATA(0x3C);
  583.                 LCD_WR_DATA(0x05);
  584.                 LCD_WR_DATA(0x10);
  585.                 LCD_WR_DATA(0x0F);
  586.                 LCD_WR_DATA(0x3F);
  587.                 LCD_WR_DATA(0x3F);
  588.                 LCD_WR_DATA(0x0F);
  589.                 LCD_WR_REG(0x2B);
  590.                 LCD_WR_DATA(0x00);
  591.                 LCD_WR_DATA(0x00);
  592.                 LCD_WR_DATA(0x01);
  593.                 LCD_WR_DATA(0x3f);
  594.                 LCD_WR_REG(0x2A);
  595.                 LCD_WR_DATA(0x00);
  596.                 LCD_WR_DATA(0x00);
  597.                 LCD_WR_DATA(0x00);
  598.                 LCD_WR_DATA(0xef);         
  599.                 LCD_WR_REG(0x11); //Exit Sleep
  600.                 delay_ms(120);
  601.                 LCD_WR_REG(0x29); //display on        

  602.         //初始化完成以后,提速

  603.                 //重新配置写时序控制寄存器的时序                                                                        
  604.                 FMC_Bank1E->BWTR[0]&=~(0XF<<0);        //地址建立时间(ADDSET)清零         
  605.                 FMC_Bank1E->BWTR[0]&=~(0XF<<8);        //数据保存时间清零
  606.                 FMC_Bank1E->BWTR[0]|=4<<0;                 //地址建立时间(ADDSET)为4个HCLK =21ns           
  607.                 FMC_Bank1E->BWTR[0]|=4<<8;                 //数据保存时间(DATAST)为5.2ns*4个HCLK=21ns
  608.         
  609.         LCD_Display_Dir(0);                //默认为竖屏
  610.         HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET);        //PB5点亮背光
  611.         LCD_Clear(WHITE);
  612. }  
  613. //清屏函数
  614. //color:要清屏的填充色
  615. void LCD_Clear(u32 color)
  616. {
  617.         u32 index=0;      
  618.         u32 totalpoint=lcddev.width;
  619.         totalpoint*=lcddev.height;                         //得到总点数
  620.         LCD_SetCursor(0x00,0x0000);                        //设置光标位置
  621.         LCD_WriteRAM_Prepare();                     //开始写入GRAM                  
  622.         for(index=0;index<totalpoint;index++)
  623.         {
  624.                 LCD->LCD_RAM=color;        
  625.         }
  626. }  
  627. //在指定区域内填充单个颜色
  628. //(sx,sy),(ex,ey):填充矩形对角坐标,区域大小为:(ex-sx+1)*(ey-sy+1)   
  629. //color:要填充的颜色
  630. void LCD_Fill(u16 sx,u16 sy,u16 ex,u16 ey,u32 color)
  631. {         
  632.         u16 i,j;
  633.         u16 xlen=0;
  634.         xlen=ex-sx+1;         
  635.         for(i=sy;i<=ey;i++)
  636.         {
  637.                 LCD_SetCursor(sx,i);                                      //设置光标位置
  638.                 LCD_WriteRAM_Prepare();                             //开始写入GRAM         
  639.                 for(j=0;j<xlen;j++)LCD->LCD_RAM=color;        //显示颜色            
  640.         }  
  641. }  
  642. //在指定区域内填充指定颜色块                        
  643. //(sx,sy),(ex,ey):填充矩形对角坐标,区域大小为:(ex-sx+1)*(ey-sy+1)   
  644. //color:要填充的颜色
  645. void LCD_Color_Fill(u16 sx,u16 sy,u16 ex,u16 ey,u16 *color)
  646. {  
  647.         u16 height,width;
  648.         u16 i,j;
  649.         width=ex-sx+1;                         //得到填充的宽度
  650.         height=ey-sy+1;                        //高度
  651.         for(i=0;i<height;i++)
  652.         {
  653.                 LCD_SetCursor(sx,sy+i);           //设置光标位置
  654.                 LCD_WriteRAM_Prepare();     //开始写入GRAM
  655.                 for(j=0;j<width;j++)LCD->LCD_RAM=color[i*width+j];//写入数据
  656.         }
  657. }  
  658. //画线
  659. //x1,y1:起点坐标
  660. //x2,y2:终点坐标  
  661. void LCD_DrawLine(u16 x1, u16 y1, u16 x2, u16 y2)
  662. {
  663.         u16 t;
  664.         int xerr=0,yerr=0,delta_x,delta_y,distance;
  665.         int incx,incy,uRow,uCol;
  666.         delta_x=x2-x1; //计算坐标增量
  667.         delta_y=y2-y1;
  668.         uRow=x1;
  669.         uCol=y1;
  670.         if(delta_x>0)incx=1; //设置单步方向
  671.         else if(delta_x==0)incx=0;//垂直线
  672.         else {incx=-1;delta_x=-delta_x;}
  673.         if(delta_y>0)incy=1;
  674.         else if(delta_y==0)incy=0;//水平线
  675.         else{incy=-1;delta_y=-delta_y;}
  676.         if( delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴
  677.         else distance=delta_y;
  678.         for(t=0;t<=distance+1;t++ )//画线输出
  679.         {  
  680.                 LCD_DrawPoint(uRow,uCol);//画点
  681.                 xerr+=delta_x ;
  682.                 yerr+=delta_y ;
  683.                 if(xerr>distance)
  684.                 {
  685.                         xerr-=distance;
  686.                         uRow+=incx;
  687.                 }
  688.                 if(yerr>distance)
  689.                 {
  690.                         yerr-=distance;
  691.                         uCol+=incy;
  692.                 }
  693.         }  
  694. }   
  695. //画矩形         
  696. //(x1,y1),(x2,y2):矩形的对角坐标
  697. void LCD_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2)
  698. {
  699.         LCD_DrawLine(x1,y1,x2,y1);
  700.         LCD_DrawLine(x1,y1,x1,y2);
  701.         LCD_DrawLine(x1,y2,x2,y2);
  702.         LCD_DrawLine(x2,y1,x2,y2);
  703. }
  704. //在指定位置画一个指定大小的圆
  705. //(x,y):中心点
  706. //r    :半径
  707. void LCD_Draw_Circle(u16 x0,u16 y0,u8 r)
  708. {
  709.         int a,b;
  710.         int di;
  711.         a=0;b=r;         
  712.         di=3-(r<<1);             //判断下个点位置的标志
  713.         while(a<=b)
  714.         {
  715.                 LCD_DrawPoint(x0+a,y0-b);             //5
  716.                  LCD_DrawPoint(x0+b,y0-a);             //0           
  717.                 LCD_DrawPoint(x0+b,y0+a);             //4               
  718.                 LCD_DrawPoint(x0+a,y0+b);             //6
  719.                 LCD_DrawPoint(x0-a,y0+b);             //1      
  720.                  LCD_DrawPoint(x0-b,y0+a);            
  721.                 LCD_DrawPoint(x0-a,y0-b);             //2            
  722.                   LCD_DrawPoint(x0-b,y0-a);             //7                     
  723.                 a++;
  724.                 //使用Bresenham算法画圆     
  725.                 if(di<0)di +=4*a+6;         
  726.                 else
  727.                 {
  728.                         di+=10+4*(a-b);   
  729.                         b--;
  730.                 }                                                     
  731.         }
  732. }                                                                           
  733. //在指定位置显示一个字符
  734. //x,y:起始坐标
  735. //num:要显示的字符:" "--->"~"
  736. //size:字体大小 12/16/24/32
  737. //mode:叠加方式(1)还是非叠加方式(0)
  738. void LCD_ShowChar(u16 x,u16 y,u8 num,u8 size,u8 mode)
  739. {                                                            
  740.     u8 temp,t1,t;
  741.         u16 y0=y;
  742.         u8 csize=(size/8+((size%8)?1:0))*(size/2);                //得到字体一个字符对应点阵集所占的字节数        
  743.          num=num-' ';//得到偏移后的值(ASCII字库是从空格开始取模,所以-' '就是对应字符的字库)
  744.         for(t=0;t<csize;t++)
  745.         {   
  746.                 if(size==12)temp=asc2_1206[num][t];                  //调用1206字体
  747.                 else if(size==16)temp=asc2_1608[num][t];        //调用1608字体
  748.                 else if(size==24)temp=asc2_2412[num][t];        //调用2412字体
  749.                 else if(size==32)temp=asc2_3216[num][t];        //调用3216字体
  750.                 else return;                                                                //没有的字库
  751.                 for(t1=0;t1<8;t1++)
  752.                 {                           
  753.                         if(temp&0x80)LCD_Fast_DrawPoint(x,y,POINT_COLOR);
  754.                         else if(mode==0)LCD_Fast_DrawPoint(x,y,BACK_COLOR);
  755.                         temp<<=1;
  756.                         y++;
  757.                         if(y>=lcddev.height)return;                //超区域了
  758.                         if((y-y0)==size)
  759.                         {
  760.                                 y=y0;
  761.                                 x++;
  762.                                 if(x>=lcddev.width)return;        //超区域了
  763.                                 break;
  764.                         }
  765.                 }           
  766.         }                                            
  767. }   
  768. //m^n函数
  769. //返回值:m^n次方.
  770. u32 LCD_Pow(u8 m,u8 n)
  771. {
  772.         u32 result=1;         
  773.         while(n--)result*=m;   
  774.         return result;
  775. }                        
  776. //显示数字,高位为0,则不显示
  777. //x,y :起点坐标         
  778. //len :数字的位数
  779. //size:字体大小
  780. //color:颜色
  781. //num:数值(0~4294967295);         
  782. void LCD_ShowNum(u16 x,u16 y,u32 num,u8 len,u8 size)
  783. {                 
  784.         u8 t,temp;
  785.         u8 enshow=0;                                                   
  786.         for(t=0;t<len;t++)
  787.         {
  788.                 temp=(num/LCD_Pow(10,len-t-1))%10;
  789.                 if(enshow==0&&t<(len-1))
  790.                 {
  791.                         if(temp==0)
  792.                         {
  793.                                 LCD_ShowChar(x+(size/2)*t,y,' ',size,0);
  794.                                 continue;
  795.                         }else enshow=1;
  796.                           
  797.                 }
  798.                  LCD_ShowChar(x+(size/2)*t,y,temp+'0',size,0);
  799.         }
  800. }
  801. //显示数字,高位为0,还是显示
  802. //x,y:起点坐标
  803. //num:数值(0~999999999);         
  804. //len:长度(即要显示的位数)
  805. //size:字体大小
  806. //mode:
  807. //[7]:0,不填充;1,填充0.
  808. //[6:1]:保留
  809. //[0]:0,非叠加显示;1,叠加显示.
  810. void LCD_ShowxNum(u16 x,u16 y,u32 num,u8 len,u8 size,u8 mode)
  811. {  
  812.         u8 t,temp;
  813.         u8 enshow=0;                                                   
  814.         for(t=0;t<len;t++)
  815.         {
  816.                 temp=(num/LCD_Pow(10,len-t-1))%10;
  817.                 if(enshow==0&&t<(len-1))
  818.                 {
  819.                         if(temp==0)
  820.                         {
  821.                                 if(mode&0X80)LCD_ShowChar(x+(size/2)*t,y,'0',size,mode&0X01);  
  822.                                 else LCD_ShowChar(x+(size/2)*t,y,' ',size,mode&0X01);  
  823.                                  continue;
  824.                         }else enshow=1;
  825.                           
  826.                 }
  827.                  LCD_ShowChar(x+(size/2)*t,y,temp+'0',size,mode&0X01);
  828.         }
  829. }
  830. //显示字符串
  831. //x,y:起点坐标
  832. //width,height:区域大小  
  833. //size:字体大小
  834. //*p:字符串起始地址                  
  835. void LCD_ShowString(u16 x,u16 y,u16 width,u16 height,u8 size,u8 *p)
  836. {         
  837.         u8 x0=x;
  838.         width+=x;
  839.         height+=y;
  840.     while((*p<='~')&&(*p>=' '))//判断是不是非法字符!
  841.     {      
  842.         if(x>=width){x=x0;y+=size;}
  843.         if(y>=height)break;//退出
  844.         LCD_ShowChar(x,y,*p,size,0);
  845.         x+=size/2;
  846.         p++;
  847.     }  
  848. }
复制代码
下面是main.c
  1. #include "sys.h"
  2. #include "led.h"
  3. #include "uart.h"
  4. #include "adc.h"
  5. #include "delay.h"
  6. #include "lcd.h"
  7. #include "GUI.h"
  8. #include "WM.h"
  9. #include "dso.h"
  10. extern UART_HandleTypeDef UART3_Handler;
  11. extern ADC_HandleTypeDef ADC1_Handler ;
  12. extern ADC_HandleTypeDef ADC2_Handler ;
  13. extern ADC_HandleTypeDef ADC3_Handler ;
  14. uint32_t ADC123_Buff[1024];
  15. int main(void)
  16. {
  17.         
  18.         int x=0;
  19.         u8 lcd_id[12];
  20.         double data;
  21.   int len,i=0;
  22.   MPU_Config();
  23.   //CPU_CACHE_Enable();
  24.   HAL_Init();
  25.   SystemClock_Config();
  26.         delay_init(216);
  27.         Led_Init();
  28.   //uart_init(9600);
  29.         LCD_Init();
  30.         ADC123_Config();
  31.   HAL_ADC_Start(&ADC3_Handler);
  32.         HAL_ADC_Start(&ADC2_Handler);
  33.         HAL_ADCEx_MultiModeStart_DMA(&ADC1_Handler, (uint32_t *)ADC123_Buff, 1024);
  34.   POINT_COLOR=RED;
  35.     while(1)
  36.    {
  37.     POINT_COLOR=RED;         
  38.                 LCD_ShowString(10,40,240,32,32,"    EEWORLD");
  39.                 LCD_ShowString(10,80,240,32,32,"    ihalin");
  40.                 LCD_ShowString(10,120,240,32,32,"   STM32F767");
  41.                 LCD_ShowString(160                                                                                                                                                                                                                                                                                                                  ,300,240,16,16,"2016/8/8");                                                   
  42.         }
  43. }
复制代码





过几天写一下EMWIN的移植

此帖出自stm32/stm8论坛

最新回复

谢谢分享  详情 回复 发表于 2017-8-31 16:35
点赞(1) 关注(4)
 

回复
举报

360

帖子

0

TA的资源

纯净的硅(初级)

沙发
 
讚 謝謝你的分享 。
此帖出自stm32/stm8论坛
 
 

回复

565

帖子

0

TA的资源

一粒金砂(高级)

板凳
 
此帖出自stm32/stm8论坛
 
个人签名stm32/LoRa物联网:304350312
 

回复

4

帖子

0

TA的资源

一粒金砂(初级)

4
 
触摸不用校准吗?
此帖出自stm32/stm8论坛

点评

没移植触摸屏  详情 回复 发表于 2016-8-29 20:20
 
 
 

回复

356

帖子

0

TA的资源

一粒金砂(中级)

5
 
dingmu 发表于 2016-8-26 11:29
触摸不用校准吗?

没移植触摸屏
此帖出自stm32/stm8论坛
 
 
 

回复

180

帖子

0

TA的资源

一粒金砂(中级)

6
 
有没有人觉得浪费
此帖出自stm32/stm8论坛
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

7
 
版主威武
此帖出自stm32/stm8论坛
 
 
 

回复

9

帖子

0

TA的资源

一粒金砂(中级)

8
 
我的怎么RD LCD ID都不正确,好郁闷,感觉WRITE 了什么就READ 了什么,屏幕就像个ECHO什么都没正确回复。
此帖出自stm32/stm8论坛

点评

ID 没读出来看看程序的LCd的读或写寄存器函数加个10Us-2us的延时试试。可能是速度太快了  详情 回复 发表于 2017-3-7 07:54
 
 
 

回复

9

帖子

0

TA的资源

一粒金砂(中级)

9
 
有工程文件提供参考就好了
此帖出自stm32/stm8论坛
 
 
 

回复

356

帖子

0

TA的资源

一粒金砂(中级)

10
 
trion 发表于 2017-3-6 12:04
我的怎么RD LCD ID都不正确,好郁闷,感觉WRITE 了什么就READ 了什么,屏幕就像个ECHO什么都没正确回复。

ID 没读出来看看程序的LCd的读或写寄存器函数加个10Us-2us的延时试试。可能是速度太快了
此帖出自stm32/stm8论坛
 
 
 

回复

9

帖子

0

TA的资源

一粒金砂(中级)

11
 
ihalin 发表于 2017-3-7 07:54
ID 没读出来看看程序的LCd的读或写寄存器函数加个10Us-2us的延时试试。可能是速度太快了

        LCD_WR_REG(0XD3);                                  
        lcddev_id=LCD_RD_DATA();               
        lcddev_id=LCD_RD_DATA();       
        lcddev_id=LCD_RD_DATA();                                                                             
        lcddev_id<<=8;
        lcddev_id|=LCD_RD_DATA();                 
HAL_Delay(50);

每个读写内部还有延迟依然不给。
此帖出自stm32/stm8论坛
 
 
 

回复

9

帖子

0

TA的资源

一粒金砂(中级)

12
 
写0xd3返回0xd3d3.写0xd5返回0xd5d5哪怕主频只有10M
此帖出自stm32/stm8论坛

点评

肯定的,因为D14不能读,他连接到STLINK的串口了,可以写,那个IO好像被强上拉了。  详情 回复 发表于 2017-3-12 16:41
 
 
 

回复

695

帖子

0

TA的资源

一粒金砂(高级)

13
 
trion 发表于 2017-3-12 15:13
写0xd3返回0xd3d3.写0xd5返回0xd5d5哪怕主频只有10M

肯定的,因为D14不能读,他连接到STLINK的串口了,可以写,那个IO好像被强上拉了。
此帖出自stm32/stm8论坛
 
 
 

回复

13

帖子

0

TA的资源

一粒金砂(中级)

14
 
本身这种MCU接口屏的速度比F7的RGB接口屏速度是大大的慢了,而又不用CACHE那太浪费F7,MPU设置中试试:
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE   改为MPU_ACCESS_BUFFERABLE,

然后MPU设置函数的最后加上SCB_EnableICache();SCB_EnableDCache();启动缓存。

最后在你的液晶读写命令里,读前加上:SCB_InvalidateDCache();  写前加上: SCB_CleanDCache();

这样就和DMA不冲突了
此帖出自stm32/stm8论坛
 
 
 

回复

13

帖子

0

TA的资源

一粒金砂(中级)

15
 
考虑到只需保护FMSC屏幕使用地址,可以把最后两个函数改为: SCB_InvalidateDCache_by_Addr 和SCB_CleanDCache_by_Addr ,具体地址参数按你实际的填写.
此帖出自stm32/stm8论坛
 
 
 

回复

13

帖子

0

TA的资源

一粒金砂(中级)

16
 
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;改为MPU_ACCESS_CACHEABLE;
此帖出自stm32/stm8论坛
 
 
 

回复

13

帖子

0

TA的资源

一粒金砂(中级)

17
 

此帖出自stm32/stm8论坛
 
 
 

回复

13

帖子

0

TA的资源

一粒金砂(中级)

18
 
工欲善其事,必先利其器
此帖出自stm32/stm8论坛
 
 
 

回复

4

帖子

0

TA的资源

一粒金砂(初级)

19
 
实在搞不懂,你连接的片选信号是NE4,为什么说HADDR[27:26]=00; BASE=0X6000 0000+XXX;NE4不应该是HADDR[27:26]=11; BASE=0XC00 0000+XXX吗属于BANK1-第四区,你干嘛选第一区啊
此帖出自stm32/stm8论坛
 
 
 

回复

98

帖子

0

TA的资源

一粒金砂(中级)

20
 
谢谢分享
此帖出自stm32/stm8论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/6 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表