打印
[应用相关]

stm32驱动 ra8875电容屏

[复制链接]
3335|34
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
junpeng324|  楼主 | 2018-10-30 20:01 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
通用延时
void LCD_Delay(__IO uint32_t nCount)
{
  for(; nCount != 0; nCount--);
}

沙发
junpeng324|  楼主 | 2018-10-30 20:02 | 只看该作者
LCD 初始化
void LCD_GPIO_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
   
    /* 使能FSMC时钟*/
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);
   
    /* 使能FSMC对应相应管脚时钟*/
    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE
                                  | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOG
                                  | RCC_APB2Periph_GPIOF , ENABLE);
   
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
   
    /* 配置LCD复位控制管脚*/
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;               
    GPIO_Init(GPIOB, &GPIO_InitStructure);
   

   
    /* 配置FSMC相对应的数据线,FSMC-D0~D15: PD 14 15 0 1,PE 7 8 9 10 11 12 13 14 15,PD 8 9 10*/       
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_AF_PP;
   
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_8 | GPIO_Pin_9 |
                                  GPIO_Pin_10 | GPIO_Pin_14 | GPIO_Pin_15;
    GPIO_Init(GPIOD, &GPIO_InitStructure);
   
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 |
                                  GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 |
                                  GPIO_Pin_15;
    GPIO_Init(GPIOE, &GPIO_InitStructure);
   
                /* 配置FSMC相对应的控制线
                 * PD4-FSMC_NOE   :LCD-RD
                 * PD5-FSMC_NWE   :LCD-WR
                 * PG12-FSMC_NE4  :LCD-CS
                 * PE2-FSMC_A23   :LCD-DC
                */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    GPIO_Init(GPIOD, &GPIO_InitStructure);
   
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
    GPIO_Init(GPIOD, &GPIO_InitStructure);
   
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
    GPIO_Init(GPIOG, &GPIO_InitStructure);  
   
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_Init(GPIOE, &GPIO_InitStructure);  
   

    /* 配置LCD忙碌查询管脚*/
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 ;
    GPIO_Init(GPIOG, &GPIO_InitStructure);

}

使用特权

评论回复
板凳
junpeng324|  楼主 | 2018-10-30 20:02 | 只看该作者
LCD  FSMC 模式配置
void LCD_FSMC_Config(void)
{
    FSMC_NORSRAMInitTypeDef  FSMC_NORSRAMInitStructure;
    FSMC_NORSRAMTimingInitTypeDef  p;
   
   
    p.FSMC_AddressSetupTime = 0x02;         //地址建立时间
    p.FSMC_AddressHoldTime = 0x00;         //地址保持时间
    p.FSMC_DataSetupTime = 0x05;                 //数据建立时间
    p.FSMC_BusTurnAroundDuration = 0x00;
    p.FSMC_CLKDivision = 0x00;
    p.FSMC_DataLatency = 0x00;
    p.FSMC_AccessMode = FSMC_AccessMode_B;         // 一般使用模式B来控制LCD
   
    FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM4;
    FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
    FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM;
//        FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_NOR;
    FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
    FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
        FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable;        /* 注意旧库无这个成员 */
    FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
    FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
    FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
    FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
    FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
    FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
    FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
    FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p;
    FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p;  
   
    FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);
   
    /* 使能 FSMC Bank1_SRAM Bank */
    FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM4, ENABLE);  
}

使用特权

评论回复
地板
junpeng324|  楼主 | 2018-10-30 20:03 | 只看该作者
RA8875 写寄存器
void RA8875_WriteReg(uint8_t RegAddr, uint8_t RegValue)
{
  LCD_RA8875_REG (RegAddr);
  LCD_RA8875_WRITE_DATA(RegValue);
}

使用特权

评论回复
5
junpeng324|  楼主 | 2018-10-30 20:04 | 只看该作者
void RA8875_Config(void)
{

                /* 初始化PLL.  晶振频率为25M */
                LCD_RA8875_REG(0x88);
                LCD_Delay(10);                /* 短暂延迟 */
                LCD_RA8875_WRITE_DATA(12);        /* PLLDIVM [7] = 0 ;  PLLDIVN [4:0] = 10 */

          LCD_Delay(10000);
  

                LCD_RA8875_REG(0x89);
                LCD_Delay(10);                /* 延迟1us */
                LCD_RA8875_WRITE_DATA(2);        /* PLLDIVK[2:0] = 2, 除以4 */

  

                /* RA8875 的内部系统频率 (SYS_CLK) 是结合振荡电路及PLL 电路所产生,频率计算公式如下 :
                  SYS_CLK = FIN * ( PLLDIVN [4:0] +1 ) / ((PLLDIVM+1 ) * ( 2^PLLDIVK [2:0] ))
                          = 25M * (12 + 1) / ((0 + 1) * (2 ^ 2))
                                  = 81.25MHz
                */

                /* REG[88h]或REG[89h]被设定后,为保证PLL 输出稳定,须等待一段「锁频时间」(< 100us)。*/
            LCD_Delay(10000);
      
      /*
                        配置系统控制寄存器。 中文pdf 第18页:

                        bit3:2 色彩深度设定 (Color Depth Setting)
                                00b : 8-bpp 的通用TFT 接口, i.e. 256 色。
                                1xb : 16-bpp 的通用TFT 接口, i.e. 65K 色。         【选这个】

                        bit1:0 MCUIF 选择
                                00b : 8-位MCU 接口。
                                1xb : 16-位MCU 接口。 【选这个】
                */
   
    RA8875_WriteReg(0x10, (1 <<3 ) | (1 << 1));        /* 配置16位MCU并口,65K色 */
  
  

                /* REG[04h] Pixel Clock Setting Register (PCSR)
                        bit7  PCLK Inversion
                                0 : PDAT 是在PCLK 正缘上升 (Rising Edge) 时被取样。
                                1 : PDAT 是在PCLK 负缘下降 (Falling Edge) 时被取样。
                        bit1:0 PCLK 频率周期设定
                                Pixel Clock ,PCLK 频率周期设定。
                                00b: PCLK 频率周期= 系统频率周期。
                                01b: PCLK 频率周期= 2 倍的系统频率周期。
                                10b: PCLK 频率周期= 4 倍的系统频率周期。
                                11b: PCLK 频率周期= 8 倍的系统频率周期。
                */
            RA8875_WriteReg(0x04, 0x81);
            LCD_Delay(10000);
      
      
     
                /* OTD9960 & OTA7001 设置 */
                RA8875_WriteReg(0x14, 0x63);
                RA8875_WriteReg(0x15, 0x00);
                RA8875_WriteReg(0x16, 0x03);
                RA8875_WriteReg(0x17, 0x03);
                RA8875_WriteReg(0x18, 0x0B);
                RA8875_WriteReg(0x19, 0xDF);
                RA8875_WriteReg(0x1A, 0x01);
                RA8875_WriteReg(0x1B, 0x1F);
                RA8875_WriteReg(0x1C, 0x00);
                RA8875_WriteReg(0x1D, 0x16);
                RA8875_WriteReg(0x1E, 0x00);
                RA8875_WriteReg(0x1F, 0x01);
   
                       

   
    /* 设置TFT面板的 DISP  引脚为高,使能面板. 秉火TFT模块的DISP引脚连接到RA8875芯片的GP0X脚 */
    RA8875_WriteReg(0xC7, 0x01);        /* DISP = 1 */

    /* LCD 显示/关闭讯号 (LCD Display on) */
    RA8875_WriteReg(0x01, 0x80);

    /*         REG[40h] Memory Write Control Register 0 (MWCR0)

      Bit 7        显示模式设定
        0 : 绘图模式。
        1 : 文字模式。

      Bit 6        文字写入光标/内存写入光标设定
        0 : 设定文字/内存写入光标为不显示。
        1 : 设定文字/内存写入光标为显示。

      Bit 5        文字写入光标/内存写入光标闪烁设定
        0 : 游标不闪烁。
        1 : 游标闪烁。

      Bit 4   NA

      Bit 3-2  绘图模式时的内存写入方向
        00b : 左 -> 右,然后上 -> 下。
        01b : 右 -> 左,然后上 -> 下。
        10b : 上 -> 下,然后左 -> 右。
        11b : 下 -> 上,然后左 -> 右。

      Bit 1         内存写入光标自动增加功能设定
        0 : 当内存写入时光标位置自动加一。
        1 : 当内存写入时光标位置不会自动加一。

      Bit 0 内存读取光标自动增加功能设定
        0 : 当内存读取时光标位置自动加一。
        1 : 当内存读取时光标位置不会自动加一。
    */
    RA8875_WriteReg(0x40, 0x00);        /* 选择绘图模式 */
        //RA8875_WriteReg(0x20, 0x04);       

    /*         REG[41h] Memory Write Control Register1 (MWCR1)
      写入目的位置,选择图层1
    */
    RA8875_WriteReg(0x41, 0x01);        /* 选择绘图模式, 目的为CGRAM */
}

使用特权

评论回复
6
junpeng324|  楼主 | 2018-10-30 20:05 | 只看该作者
LCD 软件复位
void LCD_Rst(void)
{                       
        GPIO_ResetBits(GPIOB, GPIO_Pin_1);         //低电平复位
    LCD_Delay(0xAFFff);                                           
    GPIO_SetBits(GPIOB, GPIO_Pin_1);                          
    LCD_Delay(0xAFFff);        
}

使用特权

评论回复
7
junpeng324|  楼主 | 2018-10-30 20:14 | 只看该作者
lcd初始化,如果要用到lcd,一定要调用这个函数
void LCD_Init(void)
{
        LCD_GPIO_Config();
        LCD_FSMC_Config();
       
        LCD_Rst();
  
    RA8875_Config();  
}

使用特权

评论回复
8
junpeng324|  楼主 | 2018-10-30 20:16 | 只看该作者
关于触摸驱动函数
I2C_Delay I2C总线位延迟,最快400KHz
static void I2C_Delay(void)
{
        uint8_t i;

        /* 
    可使用逻辑分析仪来观察IIC通讯的频率
                CPU主频72MHz时,在内部Flash运行, MDK工程不优化
                循环次数为10时,SCL频率 = 205KHz
                循环次数为7时,SCL频率 = 347KHz, SCL高电平时间1.5us,SCL低电平时间2.87us
                 循环次数为5时,SCL频率 = 421KHz, SCL高电平时间1.25us,SCL低电平时间2.375us
        
        */
        for (i = 0; i < 10; i++);
}

使用特权

评论回复
9
junpeng324|  楼主 | 2018-10-30 20:17 | 只看该作者
Delay 复位触屏芯片使用的延迟函数
static void Delay(__IO uint32_t nCount)         //简单的延时函数
{
        for(; nCount != 0; nCount--);
}

使用特权

评论回复
10
junpeng324|  楼主 | 2018-10-30 20:17 | 只看该作者
I2C_Start CPU发起I2C总线启动信号
void I2C_Start(void)
{
        /* 当SCL高电平时,SDA出现一个下跳沿表示I2C总线启动信号 */
        I2C_SDA_1();
        I2C_SCL_1();
        I2C_Delay();
        I2C_SDA_0();
        I2C_Delay();
        I2C_SCL_0();
        I2C_Delay();
}

使用特权

评论回复
11
junpeng324|  楼主 | 2018-10-30 20:18 | 只看该作者
I2C_Stop CPU发起I2C总线停止信号
void I2C_Stop(void)
{
        /* 当SCL高电平时,SDA出现一个上跳沿表示I2C总线停止信号 */
        I2C_SDA_0();
        I2C_SCL_1();
        I2C_Delay();
        I2C_SDA_1();
}

使用特权

评论回复
12
junpeng324|  楼主 | 2018-10-30 20:19 | 只看该作者
I2C_Ack 产生一个ACK信号
static uint8_t I2C_WaitAck(void)
{
        uint8_t re;

        I2C_SDA_1();        /* CPU释放SDA总线 */
        I2C_Delay();
        I2C_SCL_1();        /* CPU驱动SCL = 1, 此时器件会返回ACK应答 */
        I2C_Delay();
        if (I2C_SDA_READ())        /* CPU读取SDA口线状态 */
        {
                re = 1;
        }
        else
        {
                re = 0;
        }
        I2C_SCL_0();
        I2C_Delay();
        return re;
}

使用特权

评论回复
13
junpeng324|  楼主 | 2018-10-30 20:19 | 只看该作者
I2C_Ack 产生一个ACK信号
static void I2C_Ack(void)
{
        I2C_SDA_0();        /* CPU驱动SDA = 0 */
        I2C_Delay();
        I2C_SCL_1();        /* CPU产生1个时钟 */
        I2C_Delay();
        I2C_SCL_0();
        I2C_Delay();
        I2C_SDA_1();        /* CPU释放SDA总线 */
}

使用特权

评论回复
14
junpeng324|  楼主 | 2018-10-30 20:20 | 只看该作者
I2C_NAck 产生1个NACK信号

static void I2C_NAck(void)
{
        I2C_SDA_1();        /* CPU驱动SDA = 1 */
        I2C_Delay();
        I2C_SCL_1();        /* CPU产生1个时钟 */
        I2C_Delay();
        I2C_SCL_0();
        I2C_Delay();       
}

使用特权

评论回复
15
junpeng324|  楼主 | 2018-10-30 20:20 | 只看该作者
I2C_SendByte CPU向总线设备发送8bit数据

static void I2C_SendByte(uint8_t ucByte)
{
        uint8_t i;

        /* 先发送字节的高位bit7 */
        for (i = 0; i < 8; i++)
        {               
                if (ucByte & 0x80)
                {
                        I2C_SDA_1();
                }
                else
                {
                        I2C_SDA_0();
                }
                I2C_Delay();
                I2C_SCL_1();
                I2C_Delay();       
                I2C_SCL_0();
                if (i == 7)
                {
                         I2C_SDA_1(); // 释放总线
                }
                ucByte <<= 1;        /* 左移一个bit */
                I2C_Delay();
        }
}

使用特权

评论回复
16
junpeng324|  楼主 | 2018-10-30 20:21 | 只看该作者
I2C_ReadByte CPU从I2C总线设备读取8bit数据

static uint8_t I2C_ReadByte(void)
{
        uint8_t i;
        uint8_t value;

        /* 读到第1个bit为数据的bit7 */
        value = 0;
        for (i = 0; i < 8; i++)
        {
                value <<= 1;
                I2C_SCL_1();
                I2C_Delay();
                if (I2C_SDA_READ())
                {
                        value++;
                }
                I2C_SCL_0();
                I2C_Delay();
        }
        return value;
}

使用特权

评论回复
17
junpeng324|  楼主 | 2018-10-30 20:22 | 只看该作者
I2C_CheckDevice 检测I2C总线设备,CPU向发送设备地址,然后读取设备应答来判断该设备是否存在

uint8_t I2C_CheckDevice(uint8_t Address)
{
        uint8_t ucAck;

        I2C_GPIO_Config();                /* 配置GPIO */
       
        I2C_Start();                /* 发送启动信号 */

        /* 发送设备地址+读写控制bit(0 = w, 1 = r) bit7 先传 */
        I2C_SendByte(Address | I2C_WR);
        ucAck = I2C_WaitAck();        /* 检测设备的ACK应答 */

        I2C_Stop();                        /* 发送停止信号 */

        return ucAck;
}

使用特权

评论回复
18
junpeng324|  楼主 | 2018-10-30 20:22 | 只看该作者
使用IIC读取数据
uint8_t I2C_ReadBytes( uint8_t ClientAddr,uint8_t* pBuffer, uint16_t NumByteToRead)
{
        uint16_t i;
       
       
        /* 第1步:发起I2C总线启动信号 */
        I2C_Start();

        /* 第2步:发送读设备地址,即将读取数据*/
        I2C_SendByte(ClientAddr|I2C_RD);
       
        /* 第3步:等待ACK */
        if (I2C_WaitAck() != 0)
        {
                goto cmd_fail;        /* 器件无应答 */
        }       
       
        /* 第4步:循环读取数据 */
        for (i = 0; i < NumByteToRead; i++)
        {
                pBuffer[i] = I2C_ReadByte();        /* 读1个字节 */     
               
                /* 每读完1个字节后,需要发送Ack, 最后一个字节不需要Ack,发Nack */
                if (i != NumByteToRead - 1)
                {
                        I2C_Ack();        /* 中间字节读完后,CPU产生ACK信号(驱动SDA = 0) */
                }
                else
                {
                        I2C_NAck();        /* 最后1个字节读完后,CPU产生NACK信号(驱动SDA = 1) */
                }  
        }
        /* 发送I2C总线停止信号 */
        I2C_Stop();
        return 0;        /* 执行成功 */

cmd_fail: /* 命令执行失败后,切记发送停止信号,避免影响I2C总线上其他设备 */
        /* 发送I2C总线停止信号 */
        I2C_Stop();

        return 0xff;
}

使用特权

评论回复
19
junpeng324|  楼主 | 2018-10-30 20:23 | 只看该作者
使用IIC写入数据

uint8_t I2C_WriteBytes(uint8_t ClientAddr,uint8_t* pBuffer,  uint8_t NumByteToWrite)
{
        uint16_t i;
  
  /* 第1步:发起I2C总线启动信号 */
  I2C_Start();

  /* 第2步:发送写设备地址,即将写入数据 */
  I2C_SendByte(ClientAddr);
  
  /* 第3步:等待ACK */
  if (I2C_WaitAck() != 0)
  {
    goto cmd_fail;        /*器件无应答 */
  }
  
        for (i = 0; i < NumByteToWrite; i++)
        {
       
                /* 第4步:开始写入数据 */
                I2C_SendByte(pBuffer[i]);
       
                /* 第5步:等待ACK */
                if (I2C_WaitAck() != 0)
                {
                        goto cmd_fail;        /* 器件无应答 */
                }

        }
       
        /* 命令执行成功,发送I2C总线停止信号 */
        I2C_Stop();
        return 0;

cmd_fail: /* 命令执行失败后,切记发送停止信号,避免影响I2C总线上其他设备 */
        /* 发送I2C总线停止信号 */
        I2C_Stop();
  
        return 0xff;
}

使用特权

评论回复
20
junpeng324|  楼主 | 2018-10-30 20:24 | 只看该作者
I2C_GPIO_Config 初始化控制触屏芯片的GPIO IIC RST INT
static void I2C_GPIO_Config(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;

        RCC_APB2PeriphClockCmd(GTP_I2C_GPIO_CLK|RCC_APB2Periph_AFIO, ENABLE);        /* 打开GPIO时钟 */

        GPIO_InitStructure.GPIO_Pin = GTP_I2C_SCL_PIN | GTP_I2C_SDA_PIN;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;          /* 开漏输出 */
        GPIO_Init(GTP_I2C_PORT, &GPIO_InitStructure);

        /* 给一个停止信号, 复位I2C总线上的所有设备到待机模式 */
        I2C_Stop();  
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

37

主题

1130

帖子

8

粉丝