OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4855|回复: 4

JLX25664屏幕读回功能调试(IIC)

[复制链接]

5

主题

19

帖子

0

精华

初级会员

Rank: 2

积分
79
金钱
79
注册时间
2017-1-22
在线时间
20 小时
发表于 2022-8-31 10:53:16 | 显示全部楼层 |阅读模式
因为种种特殊原因,最终在F401的MCU上使用了IIC驱动这款液晶屏。首先要说明的是,这款屏幕支持三种通信方式,并口、SPI、IIC。其中SPI不支持读回功能,这部分说明在厂家的技术手册里是没有提及的,在ST75256的技术手册里才有相关说明。我们第一版硬件用的恰恰就是SPI...
其次,驱动这款屏幕,最优选肯定是并口方式。如果受限于IO,那么可以选择SPI、IIC。如果对读回没有要求,推荐SPI。最后才考虑IIC,因为速度真的慢了点。
最后附上代码。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

5

主题

19

帖子

0

精华

初级会员

Rank: 2

积分
79
金钱
79
注册时间
2017-1-22
在线时间
20 小时
 楼主| 发表于 2022-8-31 10:55:02 | 显示全部楼层
IO口初始化就不贴了。根据手册正确配置各引脚电平。

首先是iic部分代码
  1. #ifndef __MYIIC_LCD_H_
  2. #define __MYIIC_LCD_H_
  3. //#include "sys.h"
  4.                                

  5. #if defined STM32F4XX

  6. // 宏定义
  7. //工作模式
  8. #define LCD_IIC_NORMAL_MODE                0
  9. #define LCD_IIC_FAST_MODE                        1
  10. #define LCD_IIC_CLOCK                RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC
  11. #define LCD_SDA_GPIO                GPIOC
  12. #define LCD_SDA_PIN                        GPIO_Pin_3
  13. #define LCD_SCL_GPIO                GPIOB
  14. #define LCD_SCL_PIN                        GPIO_Pin_10

  15. #define LCD_IIC_SCL_L         GPIO_ResetBits(LCD_SCL_GPIO, LCD_SCL_PIN)//SCL_GPIO->BRR = SCL_PIN
  16. #define LCD_IIC_SCL_H         GPIO_SetBits(LCD_SCL_GPIO, LCD_SCL_PIN)//SCL_GPIO->BSRR = SCL_PIN
  17. #define LCD_IIC_SDA_L         GPIO_ResetBits(LCD_SDA_GPIO, LCD_SDA_PIN)//SDA_GPIO->BRR = SDA_PIN
  18. #define LCD_IIC_SDA_H         GPIO_SetBits(LCD_SDA_GPIO, LCD_SDA_PIN)//SDA_GPIO->BSRR = SDA_PIN
  19. #define LCD_IIC_SDA_STATE (GPIO_ReadInputDataBit(LCD_SDA_GPIO, LCD_SDA_PIN))//(SDA_GPIO->IDR&SDA_PIN)
  20. #define LCD_IIC_SCL_STATE (GPIO_ReadInputDataBit(LCD_SCL_GPIO, LCD_SCL_PIN) ? 1 : 0)//((SCL_GPIO->IDR&SCL_PIN)? 1 : 0)

  21. //#define LCD_IIC_NOP LCD_IIC_Delay()
  22. #define LCD_IIC_NOP_1 delay_us(1)//---ZX
  23. #define LCD_IIC_NOP_2 delay_us(1)//---ZX
  24. #define LCD_IIC_NOP_4 delay_us(2)//---ZX

  25. //IO方向设置
  26. #define LCD_SDA_IN   {LCD_SDA_GPIO->MODER&=~(3<<(3*2));LCD_SDA_GPIO->MODER|=(0<<(3*2));}        //{SDA_GPIO->MODER&=~(3<<(7*2));SDA_GPIO->MODER|=(0<<(7*2));}        //Px0输入模式
  27. #define LCD_SDA_OUT {LCD_SDA_GPIO->MODER&=~(3<<(3*2));LCD_SDA_GPIO->MODER|=(1<<(3*2));}//{SDA_GPIO->MODER&=~(3<<(7*2));SDA_GPIO->MODER|=(1<<(7*2));} //Px0输出模式
  28. //#define SDA_IN  {;}        //PA7输入模式
  29. //#define SDA_OUT {;} //PA7输出模式

  30. #else
  31. // 宏定义
  32. //工作模式
  33. #define LCD_IIC_NORMAL_MODE                0
  34. #define LCD_IIC_FAST_MODE                        1
  35. #define LCD_IIC_CLOCK                RCU_GPIOB//RCC_AHBPeriph_GPIOB
  36. #define LCD_SDA_GPIO                GPIOB
  37. #define LCD_SDA_PIN                        GPIO_PIN_7
  38. #define LCD_SCL_GPIO                GPIOB
  39. #define LCD_SCL_PIN                        GPIO_PIN_6

  40. #define LCD_IIC_SCL_L         GPIO_BC(LCD_SCL_GPIO) = (uint32_t)LCD_SCL_PIN//SCL_GPIO->BRR = SCL_PIN
  41. #define LCD_IIC_SCL_H         GPIO_BOP(LCD_SCL_GPIO) = (uint32_t)LCD_SCL_PIN//SCL_GPIO->BSRR = SCL_PIN
  42. #define LCD_IIC_SDA_L         GPIO_BC(LCD_SDA_GPIO) = (uint32_t)LCD_SDA_PIN//SDA_GPIO->BRR = SDA_PIN
  43. #define LCD_IIC_SDA_H         GPIO_BOP(LCD_SDA_GPIO) = (uint32_t)LCD_SDA_PIN//SDA_GPIO->BSRR = SDA_PIN
  44. #define LCD_IIC_SDA_STATE (GPIO_ISTAT(LCD_SDA_GPIO)&(LCD_SDA_PIN))//(SDA_GPIO->IDR&SDA_PIN)
  45. #define LCD_IIC_SCL_STATE ((GPIO_ISTAT(LCD_SCL_GPIO)&(LCD_SCL_PIN)) ? 1 : 0)//((SCL_GPIO->IDR&SCL_PIN)? 1 : 0)

  46. //#define LCD_IIC_NOP LCD_IIC_Delay()
  47. #define LCD_IIC_NOP_1 delay_us(1)//---ZX
  48. #define LCD_IIC_NOP_2 delay_us(1)//---ZX
  49. #define LCD_IIC_NOP_4 delay_us(2)//---ZX

  50. //IO方向设置
  51. #define LCD_SDA_IN  {GPIO_CTL0(LCD_SDA_GPIO) &= ~(3<<28); GPIO_CTL0(LCD_SDA_GPIO) |= (0<<28);}//{SDA_GPIO->MODER&=~(3<<(7*2));SDA_GPIO->MODER|=(0<<(7*2));}        //Px0输入模式
  52. #define LCD_SDA_OUT {GPIO_CTL0(LCD_SDA_GPIO) &= ~(3<<28); GPIO_CTL0(LCD_SDA_GPIO) |= (3<<28);}//{SDA_GPIO->MODER&=~(3<<(7*2));SDA_GPIO->MODER|=(1<<(7*2));} //Px0输出模式
  53. //#define SDA_IN  {;}        //PA7输入模式
  54. //#define SDA_OUT {;} //PA7输出模式
  55. #endif

  56. enum ENUM_LCD_IIC_REPLY
  57. {
  58. LCD_IIC_NACK=0
  59. ,LCD_IIC_ACK=1
  60. };

  61. typedef enum
  62. {
  63. LCD_IIC_READY=0
  64. ,LCD_IIC_BUS_BUSY=1
  65. ,LCD_IIC_BUS_ERROR=2
  66. }ENUM_LCD_IIC_BUS_STATE;



  67. #define LCD_IIC_BUS

  68. //extern u8 ack;         //应答标志位

  69. //IIC所有操作函数
  70. void LCD_IIC_Init(void);                //初始化IIC的IO口                                 
  71. void LCD_Start_I2C(unsigned char mode);
  72. void LCD_Stop_I2C(unsigned char mode);
  73. unsigned char LCD_SendByte_I2C(unsigned char c,unsigned char mode);
  74. unsigned char LCD_RcvByte_I2C(unsigned char mode);
  75. void LCD_ack_I2C(unsigned char a,unsigned char mode);

  76. void LCD_IIC_Write_One_Byte(unsigned char daddr,unsigned char addr,unsigned char data);
  77. unsigned char LCD_IIC_Read_One_Byte(unsigned char daddr,unsigned char addr);
  78. unsigned char LCD_IIC_Status(void);
  79. #endif

复制代码
  1. #if defined STM32F4XX
  2. #include "stm32f4xx.h"
  3. #else
  4. #include "gd32f30x.h"
  5. #endif
  6. #include "myiic_lcd.h"
  7. #include "delay.h"
  8. #include "dataHandler.h"
  9. //////////////////////////////////////////////////////////////////////////////////         
  10. //本程序只供学习使用,未经作者许可,不得用于其它任何用途
  11. //ALIENTEK STM32F429开发板
  12. //IIC驱动代码          
  13. //正点原子@ALIENTEK
  14. //技术论坛:www.openedv.com
  15. //创建日期:2016/1/13
  16. //版本:V1.0
  17. //版权所有,盗版必究。
  18. //Copyright(C) 广州市星翼电子科技有限公司 2014-2024
  19. //All rights reserved                                                                          
  20. //////////////////////////////////////////////////////////////////////////////////        
  21. u8 LCD_ack;         //应答标志位

  22. #define LCD_SCL_IDLE_TIMEOUT        3000
  23. void LCD_IIC_Delay(unsigned char mode)
  24. {
  25.         if(mode == LCD_IIC_NORMAL_MODE)
  26.                 delay_us(5);
  27.         else
  28.                 delay_us(1);     
  29. }
  30. //IIC初始化
  31. void LCD_IIC_Init(void)
  32. {
  33.         #if defined STM32F4XX
  34.         GPIO_InitTypeDef  GPIO_InitStructure;

  35.   RCC_AHB1PeriphClockCmd(LCD_IIC_CLOCK, ENABLE);

  36.        
  37.   //GPIO
  38.   GPIO_InitStructure.GPIO_Pin = LCD_SCL_PIN;
  39.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
  40.   GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;// 开漏  //推挽输出
  41.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//100MHz
  42.   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//上拉
  43.   GPIO_Init(LCD_SCL_GPIO, &GPIO_InitStructure);//初始化

  44.         //GPIO
  45.   GPIO_InitStructure.GPIO_Pin = LCD_SDA_PIN;
  46.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
  47.   GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;// 开漏  //推挽输出
  48.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//100MHz
  49.   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//上拉
  50.   GPIO_Init(LCD_SDA_GPIO, &GPIO_InitStructure);//初始化
  51.         #else
  52.         rcu_periph_clock_enable(LCD_IIC_CLOCK);
  53.         gpio_init(SCL_GPIO, GPIO_MODE_OUT_OD, GPIO_OSPEED_50MHZ, SCL_PIN);
  54.         gpio_init(SDA_GPIO, GPIO_MODE_OUT_OD, GPIO_OSPEED_50MHZ, SDA_PIN);
  55. #endif

  56.         LCD_IIC_SDA_H;
  57.         LCD_IIC_SCL_H;
  58. }

  59. u8 LCD_Judge_SCL_Idle(void)
  60. {
  61.         u16 errTime = 0;
  62.         while(LCD_IIC_SCL_STATE == 0)
  63.         {
  64.                 delay_us(1);
  65.                 errTime++;
  66.                 if(errTime > LCD_SCL_IDLE_TIMEOUT)//if(errTime > 1000)
  67.                 {
  68.                         return 0;
  69.                 }
  70.         }
  71.         return 1;
  72. }

  73. /*******************************************************************
  74.                      起动总线函数               
  75. 函数原型: void  Start_I2C();  
  76. 功能:     启动I2C总线,即发送I2C起始条件.  
  77. A HIGH-to-LOW transition of the data line, while the
  78. clock is HIGH is defined as the start condition (S).
  79. ********************************************************************/
  80. void LCD_Start_I2C(unsigned char mode)
  81. {
  82.     LCD_SDA_OUT;
  83.     LCD_IIC_SDA_H;   /*发送起始条件的数据信号*/
  84.     delay_us(1);
  85.     LCD_IIC_SCL_H;
  86.     LCD_IIC_Delay(mode);
  87.     LCD_Judge_SCL_Idle();
  88.     LCD_IIC_SDA_L;   /*发送起始信号*/  
  89.     delay_us(1);
  90.     LCD_IIC_SCL_L;   /*钳住I2C总线,准备发送或接收数据 */
  91.     LCD_IIC_Delay(mode);
  92. }
  93. /*******************************************************************
  94.                       结束总线函数               
  95. 函数原型: void  Stop_I2C();  
  96. 功能:     结束I2C总线,即发送I2C结束条件.
  97. A LOW-to-HIGH transition of the data line while the clock is HIGH is
  98. defined as the stop condition (P).  
  99. ********************************************************************/
  100. void LCD_Stop_I2C(unsigned char mode)
  101. {
  102.     LCD_SDA_OUT;
  103.     LCD_IIC_SDA_L;  /*发送结束条件的数据信号*/
  104.     __nop();__nop();//delay_us(1);
  105.     LCD_IIC_SCL_H;  /*结束条件建立时间大于4μs*/
  106.     LCD_IIC_Delay(mode);
  107.     LCD_Judge_SCL_Idle();
  108.     LCD_IIC_SDA_H;  /*发送I2C总线结束信号*/
  109.     LCD_IIC_Delay(mode);
  110. }

  111. /*******************************************************************
  112.                  字节数据传送函数               
  113. 函数原型: void  SendByte(unsigned char c);
  114. 功能:  将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
  115.      此状态位进行操作.(不应答或非应答都使ack=0 假)     
  116.      发送数据正常,ack=1; ack=0表示被控器无应答或损坏。
  117. ********************************************************************/
  118. unsigned char LCD_SendByte_I2C(unsigned char c,unsigned char mode)
  119. {
  120.         unsigned char BitCnt;
  121.         LCD_SDA_OUT;
  122.         for(BitCnt=0;BitCnt<8;BitCnt++)  /*要传送的数据长度为8位*/
  123.   {
  124.                 if((c<<BitCnt)&0x80)LCD_IIC_SDA_H;   /*判断发送位*/
  125.     else  LCD_IIC_SDA_L;               
  126.     __nop();__nop();//delay_us(1);
  127.     LCD_IIC_SCL_H;               /*置时钟线为高,通知被控器开始接收数据位*/
  128.                 //delay_us(2);
  129.                 LCD_IIC_Delay(mode);   
  130.                 LCD_Judge_SCL_Idle();
  131.     LCD_IIC_SCL_L;
  132.                 LCD_IIC_Delay(mode);
  133.                 //delay_us(2);
  134.                
  135.         }
  136.         //delay_us(2);
  137.   LCD_IIC_SDA_H;               /*8位发送完后释放数据线,准备接收应答位*/
  138.         __nop();__nop();//delay_us(1);
  139.         LCD_SDA_IN;
  140.         //delay_us(2);
  141.   LCD_IIC_SCL_H;
  142.         LCD_IIC_Delay(mode);
  143.         LCD_Judge_SCL_Idle();
  144.   if(LCD_IIC_SDA_STATE)
  145.       LCD_ack=0;     
  146.   else
  147.       LCD_ack=1;        /*判断是否接收到应答信号*/
  148.        
  149.   LCD_IIC_SCL_L;
  150.         LCD_IIC_Delay(mode);//delay_us(2);
  151.         return LCD_ack;
  152. }
  153. /*******************************************************************
  154.                  字节数据接收函数               
  155. 函数原型: unsigned char  RcvByte();
  156. 功能:  用来接收从器件传来的数据,并判断总线错误(不发应答信号),
  157.      发完后请用应答函数。  
  158. ********************************************************************/
  159. unsigned char LCD_RcvByte_I2C(unsigned char mode)
  160. {
  161.         unsigned char BitCnt;
  162.         unsigned char retc=0;   
  163.         LCD_SDA_OUT;
  164.         LCD_IIC_SDA_H;
  165.         LCD_SDA_IN;                                        /*置数据线为输入方式*/
  166.         //delay_us(2);
  167.         for(BitCnt=0;BitCnt<8;BitCnt++)
  168.         {  
  169.                
  170.                 //delay_us(2);
  171.                 LCD_IIC_SCL_L;       /*置时钟线为低,准备接收数据位*/
  172.                 LCD_IIC_Delay(mode);
  173.                 LCD_IIC_SCL_H;       /*置时钟线为高使数据线上数据有效*/
  174.                 LCD_IIC_Delay(mode);
  175.                 LCD_Judge_SCL_Idle();
  176.                 retc=retc<<1;
  177.                 if(LCD_IIC_SDA_STATE)retc=retc+1; /*读数据位,接收的数据位放入retc中 */
  178.                 //delay_us(2);
  179.         //LCD_IIC_SCL_L;
  180.         //LCD_IIC_Delay(mode);
  181.         }
  182.    
  183. //    LCD_SDA_OUT;
  184. //    LCD_IIC_SDA_H;
  185. //    __nop();__nop();//delay_us(1);
  186. //        LCD_SDA_IN;
  187. //        LCD_IIC_SCL_H;
  188. //        LCD_IIC_Delay(mode);
  189. //        LCD_Judge_SCL_Idle();
  190. //      if(LCD_IIC_SDA_STATE)
  191. //          LCD_ack=0;     
  192. //      else
  193. //          LCD_ack=1;        /*判断是否接收到应答信号*/
  194. //        
  195.       LCD_IIC_SCL_L;
  196.         LCD_IIC_Delay(mode);
  197.         return(retc);
  198. }
  199. /********************************************************************
  200.                      应答子函数
  201. 原型:  void ack_I2C(bit a);

  202. 功能:主控器进行应答信号,(可以是应答或非应答信号)
  203. ********************************************************************/
  204. void LCD_ack_I2C(unsigned char a,unsigned char mode)
  205. {
  206.         LCD_SDA_OUT;
  207.         if(a==0)LCD_IIC_SDA_L;     /*在此发出应答或非应答信号 */
  208.         else LCD_IIC_SDA_H;
  209.         __nop();__nop();//LCD_IIC_Delay(mode);      
  210.         LCD_IIC_SCL_H;
  211.         LCD_IIC_Delay(mode);
  212.         LCD_Judge_SCL_Idle();
  213.         LCD_IIC_SCL_L;                /*清时钟线,钳住I2C总线以便继续接收*/
  214.         LCD_IIC_Delay(mode);//delay_us(2);
  215. }

复制代码

回复 支持 反对

使用道具 举报

5

主题

19

帖子

0

精华

初级会员

Rank: 2

积分
79
金钱
79
注册时间
2017-1-22
在线时间
20 小时
 楼主| 发表于 2022-8-31 10:58:24 | 显示全部楼层
然后是lcd屏幕的驱动
  1. #ifndef __LCD_256_64_H_
  2. #define __LCD_256_64_H_

  3. #if defined STM32F4XX
  4. #include "stm32f4xx.h"
  5. #else
  6. #include "gd32f30x.h"
  7. #endif
  8. #include "dataType.h"

  9. //LCD分辨率
  10. #define LCD_WIDTH        256
  11. #define LCD_HEIGHT        64

  12. //IO管脚定义
  13. //lcd_rd  PE10
  14. //lcd_wr  PE11
  15. //lcd_rst  PE12
  16. //lcd_light  PE13

  17. #define LCD_COMM_SERIAL 0
  18. #define LCD_COMM_SPI    1
  19. #define LCD_COMM_IIC    2
  20. #define LCD_COMM        LCD_COMM_IIC

  21. #if defined STM32F4XX
  22.     #if LCD_COMM == LCD_COMM_SPI
  23.     #define  LCD_CS_PIN        GPIO_Pin_12   //pB12
  24.     #define  LCD_RS_PIN        GPIO_Pin_11  //pa11
  25.     #define  LCD_RD_PIN        GPIO_Pin_15  //pb15
  26.     #define  LCD_WR_PIN        GPIO_Pin_9    //pc9
  27.     #define  LCD_RESET_PIN     GPIO_Pin_12   //pa12
  28.     #define  LCD_BLK_PIN       GPIO_Pin_8   //pa8
  29.     #elif LCD_COMM == LCD_COMM_IIC
  30.     //IF0 割线,焊接到3.3
  31.     //CS -- 焊接R12(PB12)           不焊接R13
  32.     //RD WR 焊接R14 R15直接拉高, 不焊接R17 R21
  33.     //D0 --  焊接R6(PB10), 不焊接R18
  34.     //D1~D3 - 焊接R23 R24 R25(PC3) 不焊接R22 R27 R31
  35.     //D4-D5 -- 不焊接R43 R45,悬空
  36.     //D6-D7 -- 不焊接R35 R36, 并短接到地
  37.     #define  LCD_CS_PIN        GPIO_Pin_12   //pb12   片选,接地. 焊接R12,不焊接R13
  38.     #define  LCD_RS_PIN        GPIO_Pin_11  //pa11  使用IIC时,此引脚不使用,拉高
  39.    
  40.     //RD WR不需要接到MCU,直接修改电阻
  41.     //#define  LCD_RD_PIN        GPIO_Pin_15  //pb15  使用IIC时,此引脚不使用,拉高。焊接R15,不焊接R17
  42.     //#define  LCD_WR_PIN        GPIO_Pin_9   //pc9   使用IIC时,此引脚不使用,拉高。焊接R14,不焊接R21
  43.     #define  LCD_RESET_PIN     GPIO_Pin_12  //pa12
  44.     #define  LCD_BLK_PIN       GPIO_Pin_8   //pa8
  45.     #else
  46.    
  47.     #endif
  48. #else
  49. #define  LCD_CS_PIN        GPIO_PIN_8   //pc8
  50. #define  LCD_RS_PIN        GPIO_PIN_11  //pa11
  51. #define  LCD_RD_PIN        GPIO_PIN_15  //pb15
  52. #define  LCD_WR_PIN        GPIO_PIN_9   //pc9
  53. #define  LCD_RESET_PIN     GPIO_PIN_12  //pa12
  54. #define  LCD_BLK_PIN       GPIO_PIN_8   //pa8

  55. #endif
  56. //lcd D0-D7  PC0-PC7
  57. #define  LCD_D0_D7_PIN      ((uint16_t)0x00ff)//0x00ff  //GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7





  58. #if defined STM32F4XX
  59. #if LCD_COMM == LCD_COMM_SPI
  60.     #define   LCD_CS_HIGH       GPIO_WriteBit(GPIOB,LCD_CS_PIN,Bit_SET)
  61.     #define   LCD_CS_LOW                    GPIO_WriteBit(GPIOB,LCD_CS_PIN,Bit_RESET)

  62.     #define   LCD_RS_HIGH       GPIO_WriteBit(GPIOA,LCD_RS_PIN,Bit_SET)
  63.     #define   LCD_RS_LOW                    GPIO_WriteBit(GPIOA,LCD_RS_PIN,Bit_RESET)

  64.     #define   LCD_RD_HIGH       GPIO_WriteBit(GPIOB,LCD_RD_PIN,Bit_SET)
  65.     #define   LCD_RD_LOW                    GPIO_WriteBit(GPIOB,LCD_RD_PIN,Bit_RESET)

  66.     #define   LCD_WR_HIGH       GPIO_WriteBit(GPIOC,LCD_WR_PIN,Bit_SET)
  67.     #define   LCD_WR_LOW                           GPIO_WriteBit(GPIOC,LCD_WR_PIN,Bit_RESET)
  68. #elif LCD_COMM == LCD_COMM_IIC
  69.     #define   LCD_CS_HIGH       GPIO_WriteBit(GPIOB,LCD_CS_PIN,Bit_SET)
  70.     #define   LCD_CS_LOW                    GPIO_WriteBit(GPIOB,LCD_CS_PIN,Bit_RESET)
  71.    
  72.     #define   LCD_RS_HIGH       GPIO_WriteBit(GPIOA,LCD_RS_PIN,Bit_SET)
  73.     #define   LCD_RS_LOW                    GPIO_WriteBit(GPIOA,LCD_RS_PIN,Bit_RESET)
  74. #endif

  75. #define   LCD_RESET_HIGH    GPIO_WriteBit(GPIOA,LCD_RESET_PIN,Bit_SET)
  76. #define   LCD_RESET_LOW            GPIO_WriteBit(GPIOA,LCD_RESET_PIN,Bit_RESET)


  77. #define   LCD_BLK_HIGH      GPIO_WriteBit(GPIOA,LCD_BLK_PIN,Bit_SET)
  78. #define   LCD_BLK_LOW                    GPIO_WriteBit(GPIOA,LCD_BLK_PIN,Bit_RESET)
  79. #define         LCD_BLK_STATUS                GPIO_ReadInputDataBit(GPIOA, LCD_BLK_PIN)//(GPIOA->IDR        &         (1<<8))

  80. #else
  81. #define   LCD_CS_HIGH       gpio_bit_set(GPIOC,LCD_CS_PIN)
  82. #define   LCD_CS_LOW            gpio_bit_reset(GPIOC,LCD_CS_PIN)

  83. #define   LCD_RS_HIGH       gpio_bit_set(GPIOA,LCD_RS_PIN)
  84. #define   LCD_RS_LOW            gpio_bit_reset(GPIOA,LCD_RS_PIN)

  85. #define   LCD_RD_HIGH       gpio_bit_set(GPIOB,LCD_RD_PIN)
  86. #define   LCD_RD_LOW            gpio_bit_reset(GPIOB,LCD_RD_PIN)

  87. #define   LCD_WR_HIGH       gpio_bit_set(GPIOC,LCD_WR_PIN)
  88. #define   LCD_WR_LOW            gpio_bit_reset(GPIOC,LCD_WR_PIN)


  89. #define   LCD_RESET_HIGH    gpio_bit_set(GPIOA,LCD_RESET_PIN)
  90. #define   LCD_RESET_LOW            gpio_bit_reset(GPIOA,LCD_RESET_PIN)

  91. #define   LCD_BLK_HIGH      gpio_bit_set(GPIOA,LCD_BLK_PIN)
  92. #define   LCD_BLK_LOW            gpio_bit_reset(GPIOA,LCD_BLK_PIN)
  93. #define         LCD_BLK_STATUS                                (GPIO_ISTAT(GPIOA)&(LCD_BLK_PIN))//(GPIOA->IDR        &         (1<<8))
  94. #endif
  95. void transfer_data_lcd(u8 data, u8 data_type);//data_type: 0-CMD data  1-Display data.  
  96. #if LCD_COMM == LCD_COMM_SPI
  97. void transfer_command_lcd(u8 data1);
  98. //void transfer_data_lcd(u8 data1);
  99. #elif LCD_COMM == LCD_COMM_IIC
  100. void iic_comm_lcd(u8 start, u8 stop, u8 addr, u8 ctrl, u16 len, u8 data, u8* buf);
  101. #endif
  102. u8 transfer_data_lcd_read(void);
  103. void initial_lcd25664_gpio(void);
  104. void initial_lcd25664(void);
  105. void lcd_address(int x,int y,int x_total,int y_total);
  106. void lcd_address_read(int x,int y,int x_total,int y_total);
  107. void clear_screen(void);
  108. void lcd_disp_readback(void);
  109. #endif

复制代码
  1. #include "delay.h"
  2. #include "lcd25664.h"

  3. #include "spi.h"
  4. #include "myiic_lcd.h"
  5. #include "string.h"
  6. #define KEY_VALUE        (u16)(1 << 10)


  7. #define LCD_IIC_SA0     0
  8. #define LCD_IIC_SA1     0
  9. #define LCD_IIC_ADDR_R     (0x78 | (LCD_IIC_SA1 << 2) | (LCD_IIC_SA0 << 1) | 1)
  10. #define LCD_IIC_ADDR_W     (0x78 | (LCD_IIC_SA1 << 2) | (LCD_IIC_SA0 << 1) | 0)
  11. #define LCD_IIC_CTRL_REGDATA_LAST   (0x40)    //01000000b A0:H-Data Register  L-CMD Register
  12. #define LCD_IIC_CTRL_REGCMD_LAST    (0x00)    //01000000b A0:H-Data Register  L-CMD Register
  13. #define LCD_IIC_CTRL_REGDATA_ANOTHER   (0xC0)    //01000000b A0:H-Data Register  L-CMD Register
  14. #define LCD_IIC_CTRL_REGCMD_ANOTHER    (0x80)    //01000000b A0:H-Data Register  L-CMD Register
  15. u8 lcd_iic_cmddata_buf[256];

  16. u8 lcd_iic_disp_buf[8][256];
  17. u8 lcd_iic_disp_buf_w[8][256];

  18. int lcd_disp_pos = 0;
  19. int lcd_disp_posX = 0, lcd_disp_posY = 0, lcd_disp_minX = 0, lcd_disp_minY = 0, lcd_disp_maxX = 0, lcd_disp_maxY = 0, lcd_disp_w = 0;

  20. void iic_comm_lcd(u8 start, u8 stop, u8 addr, u8 ctrl, u16 len, u8 data, u8* buf)
  21. {
  22.     if(start)
  23.     {
  24.         LCD_Start_I2C(LCD_IIC_FAST_MODE);                /*启动总线*/
  25.         LCD_SendByte_I2C(addr, LCD_IIC_FAST_MODE);//01111000b -- SA0-0 SA1-0 RW-0(Write is 0)
  26.         //LCD_ack_I2C(1,LCD_IIC_FAST_MODE);
  27.     }
  28.     LCD_SendByte_I2C(ctrl, LCD_IIC_FAST_MODE);//10000000b 1-Co
  29.     //LCD_ack_I2C(1,LCD_IIC_FAST_MODE);
  30.     if(len == 1)
  31.     {
  32.         LCD_SendByte_I2C(data, LCD_IIC_FAST_MODE);//10000000b 1-Co
  33.         //LCD_ack_I2C(1,LCD_IIC_FAST_MODE);
  34.     }
  35.     else
  36.     {
  37.         for(u16 i = 0; i < len; i++)
  38.         {
  39.             LCD_SendByte_I2C(buf[i], LCD_IIC_FAST_MODE);//10000000b 1-Co
  40.             //LCD_ack_I2C(1,LCD_IIC_FAST_MODE);
  41.         }
  42.     }
  43.     if(stop)
  44.         LCD_Stop_I2C(LCD_IIC_FAST_MODE);
  45. }
  46. /**
  47. * @brief       写指令到 LCD 模块
  48. * @param[in]   data1:命令参数
  49. * @return      None
  50. */  
  51. void transfer_command_lcd(u8 data1)
  52. {
  53. #if defined STM32F4XX
  54.     #if LCD_COMM == LCD_COMM_SPI
  55.         LCD_CS_LOW;//lcd_cs1=0;
  56.         LCD_RS_LOW;//lcd_rs=0;
  57.         LCD_RD_LOW;//lcd_rd=0;
  58.         LCD_WR_LOW;//lcd_wr=0;
  59.         SPI_ReadWriteByte_to_lcd(data1);
  60.         LCD_RD_HIGH;//lcd_rd=1;
  61.         LCD_CS_HIGH;//lcd_cs1=1;
  62.         LCD_RD_LOW;//lcd_rd=0;
  63.     #elif LCD_COMM == LCD_COMM_IIC
  64.     //iic_comm_lcd(1, 1, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGCMD_LAST, 1, data1, 0);
  65.     LCD_Start_I2C(LCD_IIC_FAST_MODE);                /*启动总线*/
  66.     LCD_SendByte_I2C(0x78, LCD_IIC_FAST_MODE);//01111000b -- SA0-0 SA1-0 RW-0(Write is 0)
  67.     LCD_SendByte_I2C(0x80, LCD_IIC_FAST_MODE);//10000000b 1-Co
  68.     LCD_SendByte_I2C(data1, LCD_IIC_FAST_MODE);//10000000b 1-Co
  69.     LCD_Stop_I2C(LCD_IIC_FAST_MODE);
  70.     #endif
  71. #else
  72.   u16 regTemp = 0;
  73.         LCD_CS_LOW;//lcd_cs1=0;
  74.         LCD_RS_LOW;//lcd_rs=0;
  75.         LCD_RD_LOW;//lcd_rd=0;
  76.         LCD_WR_LOW;//lcd_wr=0;

  77.         regTemp = gpio_output_port_get(GPIOC);//GPIO_ReadOutputData(GPIOC);
  78.         regTemp = regTemp & 0xFF00;
  79.         gpio_port_write(GPIOC,regTemp | data1);//GPIO_Write(GPIOC,regTemp | data1);//P1=data1;
  80.         LCD_RD_HIGH;//lcd_rd=1;
  81.         LCD_CS_HIGH;//lcd_cs1=1;
  82.         LCD_RD_LOW;//lcd_rd=0;
  83. #endif
  84. }

  85. /**
  86. * @brief       写数据到 LCD 模块
  87. * @param[in]   data1:数据参数
  88. * @return      None
  89. */  
  90. void transfer_data_lcd(u8 data, u8 data_type)//void transfer_data_lcd(u8 data1)
  91. {
  92. #if defined STM32F4XX
  93.     #if LCD_COMM == LCD_COMM_SPI
  94.         LCD_CS_LOW;//lcd_cs1=0;
  95.         LCD_RS_HIGH;//lcd_rs=1;
  96.         LCD_RD_LOW;//lcd_rd=0;
  97.         LCD_WR_LOW;//lcd_wr=0;
  98.     SPI_ReadWriteByte_to_lcd(data);

  99.         LCD_RD_HIGH;//lcd_rd=1;
  100.         LCD_CS_HIGH;//lcd_cs1=1;
  101.         LCD_RD_LOW;//lcd_rd=0;
  102.     #elif LCD_COMM == LCD_COMM_IIC
  103.     LCD_SendByte_I2C(data, LCD_IIC_FAST_MODE);//
  104.     if(data_type && lcd_disp_w)
  105.     {
  106.         lcd_iic_disp_buf_w[lcd_disp_posY][lcd_disp_posX] = data;
  107.         
  108.         lcd_disp_posX++;
  109.         if(lcd_disp_posX > lcd_disp_maxX)
  110.         {
  111.             lcd_disp_posX = lcd_disp_minX;
  112.             lcd_disp_posY++;
  113.             if(lcd_disp_posY > lcd_disp_maxY)
  114.                 lcd_disp_posY = lcd_disp_minY;
  115.         }
  116.     }
  117.     else
  118.        lcd_disp_w = 0;
  119.     //LCD_Start_I2C(LCD_IIC_FAST_MODE);                /*启动总线*/
  120.     //LCD_SendByte_I2C(0x78, LCD_IIC_FAST_MODE);//01111000b -- SA0-0 SA1-0 RW-0(Write is 0)
  121.     //LCD_SendByte_I2C(0xC0, LCD_IIC_FAST_MODE);//10000000b 1-Co
  122.     //LCD_SendByte_I2C(data1, LCD_IIC_FAST_MODE);//10000000b 1-Co
  123.     //LCD_Stop_I2C(LCD_IIC_FAST_MODE);
  124.     #endif
  125. #else
  126.         u16 regTemp = 0;

  127.         LCD_CS_LOW;//lcd_cs1=0;
  128.         LCD_RS_HIGH;//lcd_rs=1;
  129.         LCD_RD_LOW;//lcd_rd=0;
  130.         LCD_WR_LOW;//lcd_wr=0;
  131.         regTemp = gpio_output_port_get(GPIOC);//GPIO_ReadOutputData(GPIOC);
  132.         regTemp = regTemp & 0xFF00;
  133.         gpio_port_write(GPIOC,regTemp | data1);//GPIO_Write(GPIOC,regTemp | data1);//P1=data1;
  134.         LCD_RD_HIGH;//lcd_rd=1;
  135.         LCD_CS_HIGH;//lcd_cs1=1;
  136.         LCD_RD_LOW;//lcd_rd=0;
  137. #endif
  138. }

  139. u8 transfer_data_lcd_read(void)
  140. {
  141.     u16 regTemp = 0;
  142.     #if defined STM32F4XX
  143.         #if LCD_COMM == LCD_COMM_SPI
  144.    
  145.         #elif LCD_COMM == LCD_COMM_IIC
  146.         regTemp = LCD_RcvByte_I2C(LCD_IIC_FAST_MODE);
  147.         #endif
  148.     #else
  149.    
  150.     #endif
  151.         return (u8)regTemp;
  152. }

  153. void read_data_lcd(u8* buf, u8 len)
  154. {
  155.        
  156. }
  157. //u8 disp_change_flag = 0;
  158. void lcd_disp_readback(void)
  159. {
  160.     lcd_address_read(0, 0, LCD_WIDTH, LCD_HEIGHT/8);
  161.     for(int i=0;i<LCD_HEIGHT/8;i++)
  162.     {               
  163.         for (int j=0; j< LCD_WIDTH; j++)
  164.         {
  165.             //iic_comm_lcd(1, 0, 0x79, 0xC0, 0, 0, 0);
  166.             lcd_iic_disp_buf[i][j] = transfer_data_lcd_read();
  167.             LCD_ack_I2C((i == LCD_HEIGHT/8 - 1 && j == LCD_WIDTH - 1) ? 1 : 0, LCD_IIC_FAST_MODE);
  168.             //LCD_Stop_I2C(LCD_IIC_FAST_MODE);
  169.         }
  170.     }
  171.     #if LCD_COMM == LCD_COMM_IIC
  172.     LCD_Stop_I2C(LCD_IIC_FAST_MODE);
  173.     #endif
  174.    
  175. //    if(disp_change_flag)
  176. //    {
  177. //        disp_change_flag = 0;
  178. //        memset(lcd_iic_disp_buf, 0, sizeof(lcd_iic_disp_buf));
  179. //    }
  180.    
  181.     if(memcmp(lcd_iic_disp_buf, lcd_iic_disp_buf_w, sizeof(lcd_iic_disp_buf_w)))//与显示内容不一致
  182.     {
  183.         memcpy(lcd_iic_disp_buf, lcd_iic_disp_buf_w, sizeof(lcd_iic_disp_buf_w));
  184.         initial_lcd25664();
  185.         #if defined STM32F4XX
  186.                 IWDG_ReloadCounter();
  187.                 #else
  188.                 fwdgt_counter_reload();//IWDG_ReloadCounter();
  189.                 #endif
  190.         //LCD_BLK_HIGH;
  191.         
  192.         lcd_address(0, 0, LCD_WIDTH, LCD_HEIGHT/8);
  193.         for(int i=0;i<LCD_HEIGHT/8;i++)
  194.         {               
  195.             for (int j=0; j< LCD_WIDTH; j++)
  196.             {
  197.                 transfer_data_lcd(lcd_iic_disp_buf[i][j], 1);
  198.             }
  199.         }
  200.         #if LCD_COMM == LCD_COMM_IIC
  201.         LCD_Stop_I2C(LCD_IIC_FAST_MODE);
  202.         #endif
  203.     }
  204.    
  205. }
  206. /**
  207. * @brief       LCD引脚初始化
  208. * @param[in]   None
  209. * @return      None
  210. */  
  211. void initial_lcd25664_gpio(void)
  212. {
  213.     GPIO_InitTypeDef GPIO_InitStructure;
  214.         #if defined STM32F4XX
  215.        
  216.         #if LCD_COMM == LCD_COMM_SPI
  217.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);
  218.         RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC,ENABLE);
  219.          
  220.         
  221.         GPIO_InitStructure.GPIO_Pin = (1U << 10) ;
  222.         GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  223.         GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
  224.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  225.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  226.         GPIO_Init(GPIOB, &GPIO_InitStructure);
  227.             
  228.         GPIO_InitStructure.GPIO_Pin = (1U << 3) ;
  229.         GPIO_Init(GPIOC, &GPIO_InitStructure);
  230.          
  231.          
  232.         GPIO_PinAFConfig(GPIOB,10,GPIO_AF_SPI2);
  233.         GPIO_PinAFConfig(GPIOC,3,GPIO_AF_SPI2);

  234.          
  235.          
  236.         uint16_t tempreg = 0;
  237.         SPI_DeInit(SPI2);
  238.          
  239.         tempreg = SPI2->CR1;
  240.         tempreg &= 0x3040;
  241.         tempreg |= (uint16_t)((uint32_t)SPI_Direction_2Lines_FullDuplex | SPI_Mode_Master |
  242.                                                                                                                                         SPI_DataSize_8b | SPI_CPOL_High |  
  243.                                                                                                                                         SPI_CPHA_2Edge| SPI_NSS_Soft |  
  244.                                                                                                                                         SPI_BaudRatePrescaler_128 | SPI_FirstBit_MSB);
  245.         SPI2->CR1 = tempreg;
  246.         SPI2->I2SCFGR &= (uint16_t)~((uint16_t)SPI_I2SCFGR_I2SMOD);
  247.         SPI2->CRCPR = 7;
  248.         SPI2->CR1 |= SPI_CR1_SPE;
  249.          
  250.          

  251.         GPIO_InitStructure.GPIO_Pin = (1U << 12) ;
  252.         GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  253.         GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  254.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  255.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
  256.         GPIO_Init(GPIOB, &GPIO_InitStructure);

  257.         GPIOB->BSRRL |= (1U << 12); //PB12 写高电平
  258.         #elif LCD_COMM == LCD_COMM_IIC
  259.         RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC,ENABLE);
  260.         LCD_IIC_Init();
  261.         
  262.         GPIO_InitStructure.GPIO_Pin = LCD_CS_PIN;
  263.       GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
  264.       GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;// 开漏  //推挽输出
  265.       GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//100MHz
  266.       GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//上拉
  267.       GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
  268.       
  269.       GPIO_InitStructure.GPIO_Pin = LCD_RS_PIN;
  270.       GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化
  271.       
  272.       GPIO_InitStructure.GPIO_Pin = LCD_RESET_PIN;
  273.       GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化
  274.       
  275.       GPIO_InitStructure.GPIO_Pin = LCD_BLK_PIN;
  276.       GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化
  277.       
  278.       LCD_CS_LOW;
  279.       LCD_RS_HIGH;
  280.       LCD_BLK_LOW;
  281.       LCD_RESET_LOW;
  282.         #else
  283.         
  284.         #endif
  285.         #else
  286.         rcu_periph_clock_enable(RCU_GPIOA);
  287.         rcu_periph_clock_enable(RCU_GPIOB);
  288.         rcu_periph_clock_enable(RCU_GPIOC);
  289.         gpio_init(GPIOC, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, LCD_D0_D7_PIN | LCD_CS_PIN | LCD_WR_PIN);
  290.         gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, LCD_RS_PIN | LCD_RESET_PIN | LCD_BLK_PIN);
  291.         gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, LCD_RD_PIN);
  292.         #endif
  293. }
  294. /**
  295. * @brief       LCD初始化
  296. * @param[in]   None
  297. * @return      None
  298. */  
  299. void initial_lcd25664(void)
  300. {
  301.     //初始化液晶屏IO
  302.     //initial_lcd25664_gpio();

  303.         LCD_RESET_LOW;//reset=0;
  304.         delay_ms(10);
  305.         LCD_RESET_HIGH;//reset=1;
  306.         delay_ms(10);
  307.     #if LCD_COMM == LCD_COMM_SPI
  308.         transfer_command_lcd(0x30); //EXT=0
  309.         transfer_command_lcd(0x94); //Sleep out
  310.         transfer_command_lcd(0x31); //EXT=1
  311.         transfer_command_lcd(0xD7); //Autoread disable
  312.         transfer_data_lcd(0X9F, 0); //
  313.         transfer_command_lcd(0x32); //Analog SET
  314.         transfer_data_lcd(0x00, 0); //OSC Frequency adjustment
  315.         transfer_data_lcd(0x01, 0); //Frequency on booster capacitors->6KHz
  316.         transfer_data_lcd(0x05, 0); //Bias=1/9
  317.         transfer_command_lcd(0x20); // Gray Level
  318.         transfer_data_lcd(0x01, 0);
  319.         transfer_data_lcd(0x03, 0);
  320.         transfer_data_lcd(0x05, 0);
  321.         transfer_data_lcd(0x07, 0);
  322.         transfer_data_lcd(0x09, 0);
  323.         transfer_data_lcd(0x0b, 0);
  324.         transfer_data_lcd(0x0d, 0);
  325.         transfer_data_lcd(0x10, 0);
  326.         transfer_data_lcd(0x11, 0);
  327.         transfer_data_lcd(0x13, 0);
  328.         transfer_data_lcd(0x15, 0);
  329.         transfer_data_lcd(0x17, 0);
  330.         transfer_data_lcd(0x19, 0);
  331.         transfer_data_lcd(0x1b, 0);
  332.         transfer_data_lcd(0x1d, 0);
  333.         transfer_data_lcd(0x1f, 0);
  334.    
  335.         transfer_command_lcd(0x30); //EXT1=0,EXT0=0,表示选择了“扩展指令表 1”
  336.         transfer_command_lcd(0x75); //页地址设置
  337.         transfer_data_lcd(0X00, 0); //起始页地址:YS=0X00
  338.         transfer_data_lcd(0X1f, 0); //结束页地址:YE=0x1F 每 4 行为一页,第 0~3 行为第 0 页,第 124~127 行为第 31页
  339.         transfer_command_lcd(0x15); //列地址设置
  340.         transfer_data_lcd(0X00, 0); //起始列地址:XS=0
  341.         transfer_data_lcd(0Xff, 0); // 结束列地址:XE=256(0xff)
  342.         transfer_command_lcd(0xBC); //Data scan direction
  343.         transfer_data_lcd(0x00, 0); //MX.MY=Normal
  344.         transfer_data_lcd(0xA6, 0);
  345.         transfer_data_lcd(0x0c, 0); //数据格式,如果设为 0x0C:表示选择 LSB(DB0)在顶,如果设为 0x08:表示选择LSB(DB0)在底

  346.         transfer_command_lcd(0xCA); //显示控制
  347.         transfer_data_lcd(0X00, 0); //设置 CL 驱动频率:CLD=0
  348.         transfer_data_lcd(0X3F, 0); //占空比:Duty=64
  349.         transfer_data_lcd(0X20, 0); //N 行反显:Nline=off
  350.         transfer_command_lcd(0xF0); //显示模式
  351.         transfer_data_lcd(0X10, 0); //如果设为 0x11:表示选择 4 灰度级模式,如果设为 0x10:表示选择黑白模式
  352.         transfer_command_lcd(0x81); //设置对比度, “0x81”不可改动,紧跟着的 2 个数据是可改的,但“先微调后粗调”这个顺序别乱了
  353.         transfer_data_lcd(0x12, 0); //对比度微调,可调范围 0x00~0x3f,共 64 级
  354.         transfer_data_lcd(0x02, 0); //对比度粗调,可调范围 0x00~0x07,共 8 级
  355.         transfer_command_lcd(0x20); //Power control
  356.         transfer_data_lcd(0x0B, 0); //D0=regulator ; D1=follower ; D3=booste, on:1 off:0
  357.         delay_us(1);
  358.         transfer_command_lcd(0xAF); //打开显示
  359.     #elif LCD_COMM == LCD_COMM_IIC
  360.     iic_comm_lcd(1, 1, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGCMD_LAST, 1, 0x30, 0);//EXT=0
  361.     iic_comm_lcd(1, 1, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGCMD_LAST, 1, 0x94, 0);//Sleep out
  362.     iic_comm_lcd(1, 1, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGCMD_LAST, 1, 0x31, 0);//EXT=1
  363.     iic_comm_lcd(1, 0, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGCMD_ANOTHER, 1, 0xD7, 0);//Autoread disable
  364.         iic_comm_lcd(0, 1, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGDATA_LAST, 1, 0x9F, lcd_iic_cmddata_buf);//Set to disable
  365.     iic_comm_lcd(1, 0, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGCMD_ANOTHER, 1, 0x32, 0);//Analog SET. 偏压比设置
  366.         lcd_iic_cmddata_buf[0] = 0x00;  lcd_iic_cmddata_buf[1] = 0x01;  lcd_iic_cmddata_buf[2] = 0x05;
  367.         iic_comm_lcd(0, 1, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGDATA_LAST, 3, 0x00, lcd_iic_cmddata_buf);
  368.     iic_comm_lcd(1, 0, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGCMD_ANOTHER, 1, 0x20, 0);// Gray Level
  369.         lcd_iic_cmddata_buf[0] = 0x01;  lcd_iic_cmddata_buf[1] = 0x03;  lcd_iic_cmddata_buf[2] = 0x05;
  370.         lcd_iic_cmddata_buf[3] = 0x07;  lcd_iic_cmddata_buf[4] = 0x09;  lcd_iic_cmddata_buf[5] = 0x0b;
  371.         lcd_iic_cmddata_buf[6] = 0x0d;  lcd_iic_cmddata_buf[7] = 0x10;  lcd_iic_cmddata_buf[8] = 0x11;
  372.         lcd_iic_cmddata_buf[9] = 0x13;  lcd_iic_cmddata_buf[10] = 0x15;  lcd_iic_cmddata_buf[11] = 0x17;
  373.         lcd_iic_cmddata_buf[12] = 0x19;  lcd_iic_cmddata_buf[13] = 0x1b;  lcd_iic_cmddata_buf[14] = 0x1d;
  374.         lcd_iic_cmddata_buf[15] = 0x1f;
  375.         iic_comm_lcd(0, 1, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGDATA_LAST, 16, 0x00, lcd_iic_cmddata_buf);

  376.     iic_comm_lcd(1, 1, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGCMD_LAST, 1, 0x30, 0);    //EXT1=0,EXT0=0,表示选择了“扩展指令表 1”
  377.     iic_comm_lcd(1, 0, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGCMD_ANOTHER, 1, 0x75, 0);    //页地址设置
  378.         lcd_iic_cmddata_buf[0] = 0x00;  lcd_iic_cmddata_buf[1] = 0x1f;
  379.         iic_comm_lcd(0, 1, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGDATA_LAST, 2, 0x00, lcd_iic_cmddata_buf);
  380.     iic_comm_lcd(1, 0, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGCMD_ANOTHER, 1, 0x15, 0);    //列地址设置
  381.         lcd_iic_cmddata_buf[0] = 0x00;  lcd_iic_cmddata_buf[1] = 0xff;
  382.         iic_comm_lcd(0, 1, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGDATA_LAST, 2, 0x00, lcd_iic_cmddata_buf);
  383.     iic_comm_lcd(1, 0, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGCMD_ANOTHER, 1, 0xBC, 0);//Data scan direction
  384.         lcd_iic_cmddata_buf[0] = 0x00;  lcd_iic_cmddata_buf[1] = 0xA6;  lcd_iic_cmddata_buf[2] = 0x0C;
  385.         iic_comm_lcd(0, 1, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGDATA_LAST, 3, 0x00, lcd_iic_cmddata_buf);
  386.     iic_comm_lcd(1, 0, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGCMD_ANOTHER, 1, 0xCA, 0);//显示控制
  387.         lcd_iic_cmddata_buf[0] = 0x00;  lcd_iic_cmddata_buf[1] = 0x3F;  lcd_iic_cmddata_buf[2] = 0x20;
  388.         iic_comm_lcd(0, 1, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGDATA_LAST, 3, 0x00, lcd_iic_cmddata_buf);
  389.     iic_comm_lcd(1, 0, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGCMD_ANOTHER, 1, 0xF0, 0);//显示模式
  390.         iic_comm_lcd(0, 1, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGDATA_LAST, 1, 0x10, lcd_iic_cmddata_buf);//如果设为 0x11:表示选择 4 灰度级模式,如果设为 0x10:表示选择黑白模式
  391.     iic_comm_lcd(1, 0, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGCMD_ANOTHER, 1, 0x81, 0);//设置对比度, “0x81”不可改动,紧跟着的 2 个数据是可改的,但“先微调后粗调”这个顺序别乱
  392.         lcd_iic_cmddata_buf[0] = 0x12;  lcd_iic_cmddata_buf[1] = 0x02;
  393.         iic_comm_lcd(0, 1, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGDATA_LAST, 2, 0x00, lcd_iic_cmddata_buf);
  394.     iic_comm_lcd(1, 0, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGCMD_ANOTHER, 1, 0x20, 0);//Power control
  395.         iic_comm_lcd(0, 1, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGDATA_LAST, 1, 0x0B, lcd_iic_cmddata_buf);//D0=regulator ; D1=follower ; D3=booste, on:1 off:0
  396.     delay_us(1);
  397.     iic_comm_lcd(1, 1, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGCMD_LAST, 1, 0xAF, 0);
  398.     #endif
  399.         //LCD_BLK_LOW;//LCD_BLK_HIGH;
  400.         clear_screen();
  401. }

  402. /**
  403. * @brief       设置LCD页地址&列地址
  404. * @param[in]   x:列起始地址 0 ~ (LCD_WIDTH-1)
  405. * @param[in]   y:页起始地址 0 ~ (LCD_HEIGHT/8 -1)
  406. * @param[in]   x_total:总列数
  407. * @param[in]   y_total:总页数
  408. * @return      None
  409. */  
  410. void lcd_address(int x,int y,int x_total,int y_total)
  411. {
  412.         x = x % LCD_WIDTH;
  413.     y = y % (LCD_HEIGHT/8);
  414.    
  415.     #if LCD_COMM == LCD_COMM_SPI
  416.         transfer_command_lcd(0x15); //Set Column Address
  417.         transfer_data_lcd(x, 0);
  418.         transfer_data_lcd(x+x_total-1, 0);
  419.    
  420.         transfer_command_lcd(0x75); //Set Page Address
  421.         transfer_data_lcd(y, 0);
  422.         transfer_data_lcd(y+y_total-1, 0);
  423.    
  424.         transfer_command_lcd(0x30);
  425.         transfer_command_lcd(0x5c);
  426.     #elif LCD_COMM == LCD_COMM_IIC//当使用IIC方式时,此函数后只能跟显示数据
  427.     iic_comm_lcd(1, 1, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGCMD_LAST, 1, 0x30, 0);//EXT=0
  428.    
  429.     iic_comm_lcd(1, 0, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGCMD_ANOTHER, 1, 0x15, 0);    //列地址设置
  430.     lcd_iic_cmddata_buf[0] = x;  lcd_iic_cmddata_buf[1] = x+x_total-1;
  431.     iic_comm_lcd(0, 1, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGDATA_LAST, 2, 0x00, lcd_iic_cmddata_buf);
  432.    
  433.     iic_comm_lcd(1, 0, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGCMD_ANOTHER, 1, 0x75, 0);    //页地址设置
  434.         lcd_iic_cmddata_buf[0] = y;  lcd_iic_cmddata_buf[1] = y+y_total-1;
  435.     iic_comm_lcd(0, 1, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGDATA_LAST, 2, 0x00, lcd_iic_cmddata_buf);
  436.    
  437.     iic_comm_lcd(1, 1, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGCMD_LAST, 1, 0x30, 0);//EXT=0
  438.     iic_comm_lcd(1, 0, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGCMD_ANOTHER, 1, 0x5C, 0);//写数据
  439.     iic_comm_lcd(0, 0, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGDATA_LAST, 0, 0, 0);
  440.     #endif
  441.    
  442.     lcd_disp_posX = x;
  443.     lcd_disp_posY = y;
  444.     lcd_disp_minX = x;
  445.     lcd_disp_minY = y;
  446.     lcd_disp_maxX = x+x_total-1;
  447.     lcd_disp_maxY = y+y_total-1;
  448.     if(lcd_disp_maxX >= LCD_WIDTH)
  449.         lcd_disp_maxX = LCD_WIDTH - 1;
  450.     if(lcd_disp_maxY >= LCD_HEIGHT/8)
  451.         lcd_disp_maxY = LCD_HEIGHT/8 - 1;
  452.     lcd_disp_w = 1;
  453. }
  454. /**
  455. * @brief       从LCD中读出显示数据
  456. * @param[in]   x:列起始地址 0 ~ (LCD_WIDTH-1)
  457. * @param[in]   y:页起始地址 0 ~ (LCD_HEIGHT/8 -1)
  458. * @param[in]   x_total:总列数
  459. * @param[in]   y_total:总页数
  460. * @return      None
  461. */  
  462. void lcd_address_read(int x,int y,int x_total,int y_total)
  463. {
  464.         //x=x-1;
  465.         //y=y-1;
  466.     x = x % LCD_WIDTH;
  467.     y = y % (LCD_HEIGHT/8);
  468.     #if LCD_COMM == LCD_COMM_SPI//SPI方式不支持读回
  469.         transfer_command_lcd(0x15); //Set Column Address
  470.         transfer_data_lcd(x, 0);
  471.         transfer_data_lcd(x+x_total-1, 0);
  472.         transfer_command_lcd(0x75); //Set Page Address
  473.         transfer_data_lcd(y, 0);
  474.         transfer_data_lcd(y+y_total-1, 0);
  475.         transfer_command_lcd(0x30);
  476.         transfer_command_lcd(0x5d);
  477.     #elif LCD_COMM == LCD_COMM_IIC//
  478.     //iic_comm_lcd(1, 1, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGCMD_LAST, 1, 0x30, 0);//EXT=0
  479.    
  480.      iic_comm_lcd(1, 0, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGCMD_ANOTHER, 1, 0x15, 0);    //列地址设置
  481.     lcd_iic_cmddata_buf[0] = x;  lcd_iic_cmddata_buf[1] = x+x_total-1;
  482.     iic_comm_lcd(0, 1, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGDATA_LAST, 2, 0x00, lcd_iic_cmddata_buf);
  483.    
  484.     iic_comm_lcd(1, 0, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGCMD_ANOTHER, 1, 0x75, 0);    //页地址设置
  485.         lcd_iic_cmddata_buf[0] = y;  lcd_iic_cmddata_buf[1] = y+y_total-1;
  486.     iic_comm_lcd(0, 1, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGDATA_LAST, 2, 0x00, lcd_iic_cmddata_buf);
  487.    
  488.     iic_comm_lcd(1, 1, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGCMD_LAST, 1, 0x30, 0);//EXT=0
  489.     iic_comm_lcd(1, 1, LCD_IIC_ADDR_W, LCD_IIC_CTRL_REGCMD_ANOTHER, 1, 0x5D, 0);//读数据
  490.     iic_comm_lcd(1, 0, LCD_IIC_ADDR_R, LCD_IIC_CTRL_REGDATA_LAST, 0, 0, 0);
  491.     LCD_RcvByte_I2C(LCD_IIC_FAST_MODE);//不知为何,直接读取会从设置的结束地址开始读。所以此处先空出1个字节的读取。
  492.     LCD_ack_I2C(0, LCD_IIC_FAST_MODE);
  493.     #endif
  494. }
  495. /**
  496. * @brief       清屏
  497. * @param[in]   None
  498. * @return      None
  499. */
  500. void clear_screen(void)
  501. {
  502.         int i,j;
  503.         lcd_address(0,0,256,8);
  504.         for(i=0;i<LCD_HEIGHT/8;i++)
  505.         {
  506.                 for(j=0;j<LCD_WIDTH;j++)
  507.                 {
  508.             transfer_data_lcd(0x00, 1);
  509.                 }
  510.         }
  511.      #if LCD_COMM == LCD_COMM_IIC
  512.     LCD_Stop_I2C(LCD_IIC_FAST_MODE);
  513.     #endif
  514. }

  515. void disp_read(int x, int y, int width, int height, u8* dp, u16 max_len)
  516. {
  517.         if(max_len < width * height / 8)
  518.                 return;
  519.         lcd_address_read(x,y,width,height/8);
  520.         for(u8 i = 0; i < 64; i++)
  521.                 dp[i] = transfer_data_lcd_read();
  522.         //read_data_lcd(dp, width * height / 8);
  523.      #if LCD_COMM == LCD_COMM_IIC
  524.     LCD_Stop_I2C(LCD_IIC_FAST_MODE);
  525.     #endif
  526. }
复制代码
回复 支持 反对

使用道具 举报

5

主题

19

帖子

0

精华

初级会员

Rank: 2

积分
79
金钱
79
注册时间
2017-1-22
在线时间
20 小时
 楼主| 发表于 2022-8-31 11:02:05 | 显示全部楼层
最后是应用举例。
显示时
  1. /**
  2. * @brief       图形写入函数,高度需为8像素的整数倍
  3. * @param[in]   x:列起始地址(像素) 0 ~ (LCD_WIDTH-1)
  4. * @param[in]   y:页起始地址 0 ~ (LCD_HEIGHT/8 -1)
  5. * @param[in]   bmpAddr:数据地址
  6. * @param[in]   style:0:正常显示,1-反显
  7. * @return      图片高度(像素)
  8. */
  9. static unsigned char bmp[LCD_WIDTH*LCD_HEIGHT/8];
  10. u8 ShowBMP(unsigned char x,unsigned char y,u32 bmpAddr, unsigned char style)
  11. {
  12.         unsigned int p;
  13.         unsigned char width,high,page;
  14.         unsigned char i,j;

  15.         Chip_Spi_FastRead_nByte(bmpAddr, bmp, 2);
  16.         if((bmp[0] == 0xFF && bmp[1] == 0xFF) || (((bmp[0] * bmp[1]) / 8) > LCD_WIDTH*LCD_HEIGHT/8))
  17.                 return 0;
  18.         Chip_Spi_FastRead_nByte(bmpAddr + 2, bmp + 2, ((bmp[0] * bmp[1]) / 8));

  19.         high = bmp[0];
  20.         width = bmp[1];
  21.     page = high/8;
  22.    
  23.     lcd_address(x,y,width,page);
  24.        
  25.         p=2;
  26.     if(style)
  27.     {
  28.         for(i=0;i<page;i++)
  29.         {               
  30.             for ( j=0;j<width;j++)
  31.             {
  32.                 transfer_data_lcd(~bmp[p++], 1);
  33.             }
  34.         }
  35.     }
  36.     else
  37.     {
  38.         for(i=0;i<page;i++)
  39.         {               
  40.             for ( j=0;j<width;j++)
  41.             {
  42.                 transfer_data_lcd(bmp[p++], 1);
  43.             }
  44.         }
  45.     }
  46.         return high;
  47. }
复制代码


读回时调用lcd_disp_readback函数就可以了。
写在最后:代码是我在SPI方式基础上修改的。我简单测试了一下读写一屏的时间差不多,都是在100ms左右
回复 支持 反对

使用道具 举报

12

主题

3387

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8627
金钱
8627
注册时间
2020-5-11
在线时间
4059 小时
发表于 2022-8-31 11:25:30 | 显示全部楼层
IIC确实麻烦.
这种单色屏或四级灰度屏,由于数据量不大,单色屏就只需要2048字节RAM(灰度屏加倍)就可以在内存中进行显示,然后复制到屏幕显示,回读就在RAM中读取,就可以不需要在显示屏中读取了.我曾用过SPI接口的JLX12864,就是用单片机RAM来进行映射的.
专治疑难杂症
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-8 18:24

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表