Github

从这里开始,整个RTT学习过程中对工程的完善和开发都记录在Github上的一个项目中,项目还会随着学习的深入进行更新
项目URL:https://github.com/HITLIVING/-RT-Thread-.git
读者可以通过Pull下来整个项目进一步了解
对LCD的驱动需要格外关注
drv_lil9341_lcd.c
drv_lil9341_lcd.h
这两个文件

外设配置

STM32F1RCT6芯片
野火MINI开发板自带显示屏(240*320)
显示屏控制芯片ILI9341
引脚已固定,设置使用8080时序控制显示屏

驱动程序

因为对LCD的驱动遵从野火MINI教程中使用GPIO口模拟8080时序,和RTT操作系统关系不大,
而且RTT暂时也未提供8080时序通信方式的支持
RTT默认将所有GPIO打开,PIN设备在使用时无需Cube配置
所以不需要用到Cube生成工程,和Env配置驱动
芯片ILI9341具体的时序内容,参照MINI开发板教程手册,或ILI9341芯片手册
这里仅对原例程中的宏定义,GPIO初始化等结合RTT做出修改
其它发送指令,读取指令等函数保持不变,当需要移植其它外设驱动时,可以采用相同的方法

宏定义

  1. /******控制信号线******/
  2. //片选
  3. #define ILI9341_CS GET_PIN(C, 4)
  4. //数据控制切换
  5. #define ILI9341_DC GET_PIN(C, 7)
  6. //写使能
  7. #define ILI9341_WR GET_PIN(C, 6)
  8. //读使能
  9. #define ILI9341_RD GET_PIN(C, 5)
  10. //背光
  11. #define ILI9341_BK GET_PIN(D, 2)

根据例程或手册,确定用到的控制信号线的引脚,并根据RTT中PIN设备的使用方法,获取设备号

  1. /********数据信号线***************/
  2. #define ILI9341_D0 GET_PIN(B, 0)
  3. ...
  4. #define ILI9341_D15 GET_PIN(B, 15)
  5. #define ILI9341_DATA_PORT GPIOB

数据信号线同理,因为历程中部分函数是直接操作GPIOB整个管脚,保留该定义
将B的每一个引脚都获取设备号是为了初始化引脚时使用

  1. ////控制线写入
  2. #define ILI9341_CS_SET rt_pin_write(ILI9341_CS, PIN_HIGH);
  3. #define ILI9341_DC_SET rt_pin_write(ILI9341_DC, PIN_HIGH);
  4. #define ILI9341_WR_SET rt_pin_write(ILI9341_WR, PIN_HIGH);
  5. #define ILI9341_RD_SET rt_pin_write(ILI9341_RD, PIN_HIGH);
  6. #define ILI9341_BK_SET rt_pin_write(ILI9341_BK, PIN_HIGH);
  7. //
  8. #define ILI9341_CS_CLR rt_pin_write(ILI9341_CS, PIN_LOW);
  9. #define ILI9341_DC_CLR rt_pin_write(ILI9341_DC, PIN_LOW);
  10. #define ILI9341_WR_CLR rt_pin_write(ILI9341_WR, PIN_LOW);
  11. #define ILI9341_RD_CLR rt_pin_write(ILI9341_RD, PIN_LOW);
  12. #define ILI9341_BK_CLR rt_pin_write(ILI9341_BK, PIN_LOW);

例程中对引脚的置高置低电平也进行了宏定义 ,例程通过直接操作寄存器实现,可以保留,但也可以用RTT提供的引脚操作函数实现,宏定义名保持不变,方便移植时,可以直接调用提供的函数

遇到其它宏定义时同样处理方法,如果直接操作寄存器的部分,可以保留而不影响移植

设备初始化

  1. /**
  2. * @brief 初始化ILI9341的pin引脚
  3. * @param 无
  4. * @retval 无
  5. */
  6. static void ILI9341_Pin_Config ( void )
  7. {
  8. rt_pin_mode(ILI9341_CS, PIN_MODE_OUTPUT);
  9. rt_pin_mode(ILI9341_DC, PIN_MODE_OUTPUT);
  10. rt_pin_mode(ILI9341_WR, PIN_MODE_OUTPUT);
  11. rt_pin_mode(ILI9341_RD, PIN_MODE_OUTPUT);
  12. rt_pin_mode(ILI9341_BK, PIN_MODE_OUTPUT);
  13. rt_pin_mode(ILI9341_D0, PIN_MODE_OUTPUT);
  14. ...
  15. rt_pin_mode(ILI9341_D15, PIN_MODE_OUTPUT);
  16. }

当宏定义部分处理好后,在所有的函数中唯一需要改动的就是引脚的初始化部分
例程中是使用STM函数库提供的GPIO初始化的函数进行初始化
而在RTT中,已将所有的GPIO口初始化完成,只是还需要对选用的引脚设置其模式

函数调用

在例程对于任何对显示屏操作的函数,都由调用三个内联函数来完成

  1. extern __inline void ILI9341_Write_Cmd ( uint16_t usCmd );
  2. extern __inline void ILI9341_Write_Data ( uint16_t usData );
  3. extern __inline uint16_t ILI9341_Read_Data ( void );

相当于是这三个函数对管脚的时序操作进行了封装,而且函数内部是通过调用宏定义完成的
其中当需要读取数据时,对引脚的模式切换也是通过直接操作寄存器实现的
因此,在移植时只需做好宏定义的同义转换,适配RTT,同时修改初始化函数,即可正常调用其已经准备好的函数

特殊注意

在C99编程模式下(RTT要求开启),对内联函数 __inline 有特殊要求
如果想要正常使用内联函数,其声明和定义需要在头文件下进行才不会报错
注:内联函数就像是函数的宏定义,在编译时,自动将函数内容插入被调用的部分,这样可以使程序在提升可读性的同时,避免嵌套太深而影响执行速度