多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

ARM学习笔记(九)——SPI 与 GT9147

ARM学习笔记(九)——SPI 与 GT9147 一、SPI概述SPISerial Peripheral Interface串行外设接口是一种同步串行通信接口主要用于处理器与各种外设之间的数据通信。常见应用LCD显示屏Flash触摸屏控制器ADC/DAC传感器SD卡等SPI最大的特点是由主设备产生时钟通过时钟信号控制数据传输。二、SPI通信接口SPI通常使用4根信号线信号全称作用SCLKSerial Clock串行时钟MOSIMaster Out Slave In主机发送从机接收MISOMaster In Slave Out主机接收从机发送CS/SSChip Select片选信号例如i.MX6ULL 主设备 Master ┌──────────┐ SCLK ──┤ ├── SCLK MOSI ──┤ ├── MOSI MISO ──┤ SPI ├── MISO CS ──┤ ├── CS └──────────┘ │ │ ┌──────────┐ │ 从设备 │ │ Slave │ └──────────┘其中SCLK主设备产生时钟MOSI主设备向从设备发送数据MISO从设备向主设备发送数据CS选择具体的从设备三、SPI通信特点SPI属于1. 同步通信SPI具有专门的时钟线 SCLK。主设备通过SCLK控制通信节奏。SCLK ─┐ ┌─┐ ┌─┐ ┌─┐ └─┘ └─┘ └─┘ └─ ↑ ↑ ↑ 数据 数据 数据因此SPI属于同步串行通信。2. 全双工通信SPI可以同时进行发送和接收。Master ───── MOSI ─────→ Slave Master ←──── MISO ────── Slave因此SPI具有全双工通信的特点。3. 主从结构SPI通常采用Master │ ┌─────┼─────┐ │ │ │ CS0 CS1 CS2 │ │ │ Slave1 Slave2 Slave3一个主设备可以连接多个从设备。通过不同的CS片选信号选择不同的从设备。四、SPI数据传输过程假设主设备需要向从设备发送一个字节1010 0101主设备产生SCLK。每产生一个时钟周期就传输一位数据。SCLK ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ 1 2 3 4 5 6 7 8 MOSI 1 0 1 0 0 1 0 1经过8个时钟周期后10100101一个字节发送完成。五、SPI的四种工作模式SPI有4种工作模式模式CPOLCPHAMode 000Mode 101Mode 210Mode 311其中CPOLClock Polarity时钟极性CPHAClock Phase时钟相位1. CPOLCPOL决定SCLK在空闲状态下的电平。CPOL 0空闲状态SCLK 0CPOL 1空闲状态SCLK 12. CPHACPHA决定数据在哪一个时钟边沿采样。可以简单理解为CPOL决定时钟默认是高还是低CPHA决定在哪个边沿读取数据。因此CPOL CPHA ↓ 确定SPI具体通信模式使用某个SPI设备时主设备和从设备必须采用匹配的SPI模式。六、SPI与IIC的区别SPI和IIC都是常见的串行通信方式。对比SPIIIC时钟有有通信方式同步同步双工方式全双工通常半双工信号线通常4根2根速度通常较高相对较低地址方式CS片选设备地址多设备CS选择地址选择SPISCLK MOSI MISO CSIICSCL SDA七、GT9147简介GT9147是一款常见的电容式触摸屏控制器。它负责检测触摸屏上的触摸位置并将触摸坐标等信息提供给处理器。整体结构可以理解为手指 ↓ 触摸屏 ↓ GT9147 ↓ 通信接口 ↓ i.MX6ULL ↓ LCD显示GT9147本身主要负责检测触摸获取触摸坐标判断触摸状态向主控制器提供触摸数据八、电容式触摸基本原理电容式触摸屏利用人体与触摸屏之间的电容变化检测触摸。没有触摸时触摸屏 ↓ 电容状态基本稳定手指触摸后手指 ↓ 改变局部电场 ↓ 改变电容 ↓ GT9147检测变化 ↓ 计算触摸位置最终得到X坐标 Y坐标 触摸状态九、GT9147与LCD的关系LCD负责显示GT9147负责检测触摸两者功能不同。例如┌─────────────┐ │ i.MX6ULL │ └──────┬──────┘ │ ┌─────────┴─────────┐ ↓ ↓ LCD GT9147 ↓ ↓ 显示图像 检测触摸 ↓ X/Y坐标例如LCD分辨率为800 × 480那么触摸位置可能得到X 350 Y 200程序就可以根据这个坐标判断用户触摸了屏幕上的哪个区域。十、GT9147通信GT9147通常通过IIC接口与主控制器进行通信。因此i.MX6ULL │ │ IIC │ ├── SCL └── SDA │ ↓ GT9147这里需要注意GT9147主要使用IIC与主控制器交换触摸数据而不是SPI。所以学习GT9147时需要重点掌握IIC ↓ GT9147寄存器 ↓ 读取触摸状态 ↓ 读取X/Y坐标 ↓ LCD响应十一、GT9147触摸数据GT9147检测到触摸后主控制器需要读取相关寄存器。一般过程① 查询触摸状态 ↓ ② 判断是否有触摸 ↓ ③ 获取触摸点数量 ↓ ④ 读取X坐标 ↓ ⑤ 读取Y坐标 ↓ ⑥ 根据坐标执行相应操作例如触摸点 X 300 Y 150程序可以判断if(x 200 x 400 y 100 y 200) { /* 执行对应操作 */ }十二、X/Y坐标假设LCD分辨率为800 × 480通常可以理解为X → 0 ─────────────────── 799 │ │ │ 触摸点 │ ● │ (X,Y) │ │ ↓ Y 0 │ │ 479因此X范围0 ~ 799 Y范围0 ~ 479实际使用时还需要根据具体屏幕的安装方向和驱动配置进行坐标方向处理。十三、坐标高低字节触摸坐标通常需要使用两个字节保存。例如X_LX坐标低8位 X_HX坐标高8位组合成完整坐标x X_L | (X_H 8);Y坐标同理y Y_L | (Y_H 8);例如X_H 0x01 X_L 0x2C那么X 0x012C转换成十进制X 300十四、GT9147驱动基本结构实际开发时可以将GT9147驱动单独进行封装。例如bsp/ ├── gt9147.c ├── gt9147.h ├── i2c.c ├── i2c.h ├── lcd.c └── lcd.h其中gt9147.h保存GT9147寄存器定义函数声明数据结构例如#ifndef __GT9147_H #define __GT9147_H void gt9147_init(void); unsigned char gt9147_scan(void); #endif十五、GT9147初始化初始化的主要目的配置IIC ↓ 配置GT9147 ↓ 检测GT9147 ↓ 准备读取触摸数据程序结构可以设计成void gt9147_init(void) { /* IIC初始化 */ /* GT9147相关初始化 */ /* 检测GT9147 */ }十六、GT9147触摸扫描可以设计一个触摸扫描函数unsigned char gt9147_scan(void) { unsigned char touch_num; /* 读取GT9147触摸状态 */ /* 获取触摸点数量 */ return touch_num; }主函数中while(1) { if(gt9147_scan()) { /* 获取触摸坐标 */ /* 根据坐标执行操作 */ } }整体流程开始 ↓ GT9147初始化 ↓ LCD初始化 ↓ 进入循环 ↓ 读取触摸状态 ↓ 是否检测到触摸 ↙ ↘ 否 是 │ ↓ │ 读取X/Y坐标 │ ↓ │ 判断触摸区域 │ ↓ │ 执行操作 │ │ └──────←──────┘十七、GT9147实现触摸按键例如LCD上显示一个按钮┌────────────────────────┐ │ │ │ │ │ ┌────────┐ │ │ │ 按钮 │ │ │ └────────┘ │ │ │ └────────────────────────┘假设按钮区域X200 ~ 400 Y150 ~ 250读取触摸坐标if(x 200 x 400 y 150 y 250) { /* 按钮被按下 */ }这样就可以实现触摸屏 ↓ 获取坐标 ↓ 判断坐标区域 ↓ 执行功能例如触摸“LED ON” ↓ i.MX6ULL检测到坐标 ↓ 判断属于LED ON按钮区域 ↓ 点亮LED十八、LCD GT9147完整应用LCD和GT9147组合起来可以形成一个简单的触摸界面。i.MX6ULL │ ┌─────────┴─────────┐ │ │ ↓ ↓ LCD GT9147 │ │ ↓ ↓ 显示界面 读取触摸 │ ↓ X/Y坐标 │ ↓ 判断按钮区域 │ ↓ 执行对应功能例如LCD显示 ┌───────────────────────┐ │ LED控制 │ │ │ │ ┌──────────┐ │ │ │ LED ON │ │ │ └──────────┘ │ │ │ │ ┌──────────┐ │ │ │ LED OFF │ │ │ └──────────┘ │ └───────────────────────┘用户点击LED ON ↓ GT9147检测 ↓ 获得X/Y ↓ 判断区域 ↓ LED打开Mode 0CPOL0CPHA0 Mode 1CPOL0CPHA1 Mode 2CPOL1CPHA0 Mode 3CPOL1CPHA1
返回列表