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做出修改
其它发送指令,读取指令等函数保持不变,当需要移植其它外设驱动时,可以采用相同的方法
宏定义
/******控制信号线******/
//片选
#define ILI9341_CS GET_PIN(C, 4)
//数据控制切换
#define ILI9341_DC GET_PIN(C, 7)
//写使能
#define ILI9341_WR GET_PIN(C, 6)
//读使能
#define ILI9341_RD GET_PIN(C, 5)
//背光
#define ILI9341_BK GET_PIN(D, 2)
根据例程或手册,确定用到的控制信号线的引脚,并根据RTT中PIN设备的使用方法,获取设备号
/********数据信号线***************/
#define ILI9341_D0 GET_PIN(B, 0)
...
#define ILI9341_D15 GET_PIN(B, 15)
#define ILI9341_DATA_PORT GPIOB
数据信号线同理,因为历程中部分函数是直接操作GPIOB整个管脚,保留该定义
将B的每一个引脚都获取设备号是为了初始化引脚时使用
////控制线写入
#define ILI9341_CS_SET rt_pin_write(ILI9341_CS, PIN_HIGH);
#define ILI9341_DC_SET rt_pin_write(ILI9341_DC, PIN_HIGH);
#define ILI9341_WR_SET rt_pin_write(ILI9341_WR, PIN_HIGH);
#define ILI9341_RD_SET rt_pin_write(ILI9341_RD, PIN_HIGH);
#define ILI9341_BK_SET rt_pin_write(ILI9341_BK, PIN_HIGH);
//
#define ILI9341_CS_CLR rt_pin_write(ILI9341_CS, PIN_LOW);
#define ILI9341_DC_CLR rt_pin_write(ILI9341_DC, PIN_LOW);
#define ILI9341_WR_CLR rt_pin_write(ILI9341_WR, PIN_LOW);
#define ILI9341_RD_CLR rt_pin_write(ILI9341_RD, PIN_LOW);
#define ILI9341_BK_CLR rt_pin_write(ILI9341_BK, PIN_LOW);
例程中对引脚的置高置低电平也进行了宏定义 ,例程通过直接操作寄存器实现,可以保留,但也可以用RTT提供的引脚操作函数实现,宏定义名保持不变,方便移植时,可以直接调用提供的函数
遇到其它宏定义时同样处理方法,如果直接操作寄存器的部分,可以保留而不影响移植
设备初始化
/**
* @brief 初始化ILI9341的pin引脚
* @param 无
* @retval 无
*/
static void ILI9341_Pin_Config ( void )
{
rt_pin_mode(ILI9341_CS, PIN_MODE_OUTPUT);
rt_pin_mode(ILI9341_DC, PIN_MODE_OUTPUT);
rt_pin_mode(ILI9341_WR, PIN_MODE_OUTPUT);
rt_pin_mode(ILI9341_RD, PIN_MODE_OUTPUT);
rt_pin_mode(ILI9341_BK, PIN_MODE_OUTPUT);
rt_pin_mode(ILI9341_D0, PIN_MODE_OUTPUT);
...
rt_pin_mode(ILI9341_D15, PIN_MODE_OUTPUT);
}
当宏定义部分处理好后,在所有的函数中唯一需要改动的就是引脚的初始化部分
例程中是使用STM函数库提供的GPIO初始化的函数进行初始化
而在RTT中,已将所有的GPIO口初始化完成,只是还需要对选用的引脚设置其模式
函数调用
在例程对于任何对显示屏操作的函数,都由调用三个内联函数来完成
extern __inline void ILI9341_Write_Cmd ( uint16_t usCmd );
extern __inline void ILI9341_Write_Data ( uint16_t usData );
extern __inline uint16_t ILI9341_Read_Data ( void );
相当于是这三个函数对管脚的时序操作进行了封装,而且函数内部是通过调用宏定义完成的
其中当需要读取数据时,对引脚的模式切换也是通过直接操作寄存器实现的
因此,在移植时只需做好宏定义的同义转换,适配RTT,同时修改初始化函数,即可正常调用其已经准备好的函数
特殊注意
在C99编程模式下(RTT要求开启),对内联函数 __inline
有特殊要求
如果想要正常使用内联函数,其声明和定义需要在头文件下进行才不会报错
注:内联函数就像是函数的宏定义,在编译时,自动将函数内容插入被调用的部分,这样可以使程序在提升可读性的同时,避免嵌套太深而影响执行速度