I2C通信和ADC

I2C接口

I2C接口只有两根线,SCL和SDA:

  • SCL:时钟线,传输时钟信号,由主设备向从设备传输时钟信号,
  • SDA:数据线,传输数据信号,主从设备之间相互传递数据的通道

I2C属于串行通信,数据以bit为单位在SDA线上串行依次传输,同步工作状态,主从设备工作在同一个时钟频率下,通过SCL线同步时钟,I2C传输电平信号,不需要很高的速度,通信双方距离很近,所以不需要差分信号来抗干扰,I2C通常用在同一块板子上的两个IC之间的通信,数据量不大且速度较低

I2C通信特征

I2C通信时双方是不对等的,分主从设备,通信由主设备主导,从设备被动的接收主设备的通信并及时响应主设备,I2C可以一对一,一对多的进行通信,主设备负责调度通信规则,决定某一时间和哪个从设备进行通信,主设备同一时间只能和一个从设备进行通信

每一个I2C的从设备在通信时都有一个地址来标记该设备芯片,主设备需要知道和自己通信的从设备的地址,通过地址判断是不是要通信的正确设备,I2C主要用于Soc和外设之间的通信

I2C通信时序

时序在实际上是通信线上按照时间发生的电平变化,以及变化对通信的意义,I2C总线有两种状态,空闲态和忙态,通信由周期组成,两个相邻周期之间是空闲态,每个周期有一个开始位和一个结束位,开始位和结束位之间是本次通信的数据,每个周期的发起和结束都是由主设备决定的,从设备只有被动等待和响应,没有权利决定,主设备每个周期会先发8位的从设备地址(7位地址,1位表示写入还是读出)广播到总线,总线上符合该地址的从设备会响应该广播,回复1bit的(ACK)数据到主设备,主设备从而就找到了要通信的设备,这个过程叫做片选

在某一个通信时刻,主从设备只能有一个占用总线写入数据发送,另外一个从总线读取,如果某个时刻主从设备都试图向总线写入,则会发生未知异常,在起始位以及其后的8个bit都是主设备在发送地址数据,第九个bit应该是主设备释放总线,由从设备发送ACK到总线回复主设备

S5PV210的I2C

I2C控制器

S5PV210内部内置了I2C的控制器来简化I2C设备的控制,在软件编程时只需要向控制器的寄存器中写入值即可,控制器就会产生适当的时序来控制I2C,I2C结构框图如下:
I2C框图
时钟来源PCLK_PSYS,经过内部分频最终得到I2C的CLK,该CLK通过SCL传送给从设备,I2CCON和I2CSTAT两个寄存器主要负责产生I2C时序,实际编程中要发送的起始位,停止位以及ACK都要通过这两个寄存器来实现,I2CDS移位寄存器将要发送的字节数据通过移位寄存器变成bit发送到SDA线上发送,Address寄存器和Comparator在I2C做从设备的时候用于放置和比较地址的

I2C时钟

I2CCON的bit6和bit0-3都是和时钟相关的,时钟来源于PCLK_PSYS,经过2级分频,bit6是第一级分频(PCLK/16或者PCLK/512),得到中间时钟之后经过bit0-3得到I2C的工作时钟I2CCLK/(I2CCON[0:3] + 1),分频系数是1-16

I2C主要寄存器

  • I2CCON和I2CSTAT主要配置I2C接口的主要配置以及产生I2C时序
  • I2CADD用于写自身的slave address
  • I2CCDS用于存储要发送或者接受的数据

S5PV210的G-Sensor

G-Sensor由PWMTOUT3引脚控制,当该引脚输出低电平时,G-Sensor不能工作,G-Sensor的SDA和SCL接的是I2C的0端口,在G-Sensor初始化的时候要初始化正确的GPIO引脚,配置为正确的模式和IO值

KXTE9型号的G-Sensor的I2C地址为固定的0b0001111(0x0ff),I2C的从设备地址,但是在通信中发送I2C从设备地址的时候需要再加上1bit表示读取写入,这样就是一个8bit的数据,也就是说主设备发送给G-Sensor数据时SAD的值应该是00011110,接收G-Sensor数据时SAD应该是00011111

I2C协议本身属于低俗协议,通信速度不能大于实际设备芯片的最大通信速率,一般来说只能做I2C从设备的芯片通信速度较低,像KXTE9只有400KHz

ADC数模转换

数字信号和模拟信号转换器ADC,称为数模转换器,CPU本身是数字的,但是外部的一些变量是模拟的,所以需要利用数字技术处理外部模拟的物理量

模拟信号,是一个连续的信号,现实生活中的时间,电压,高度等就是模拟信号,反应在数学里就是无限细分的值

数模转换就是把模拟信号按照一定精度进行采样,变成有限多个数字量,这个过程就是数模转换,数字化之后就可以在计算机中用数字来描述模拟量,是计算机技术的基础

计算机所有参与运算的都是数字量,如果参与计算的有模拟量,就需要使用数模转换器将模拟量转换为数字量来参与运算,同样,也可以通过使用有积分和微分效果的器件来将数字信号转换为模拟信号

AD转化的概念

量程

模拟量的输入范围,也就是说该AD转换器的转换范围,由于AD转换器是一个电子器件,只能输入电压信号,如果是别的信号一般是先把信号转换成电压信号,所以有的时候在AD转换器之前还有一个传感器将模拟信号转换模拟电压,再经过AD转换器转换为数字电压,AD的输入端要求的电压有一定的范围,这个范围就是量程

精度

数字量输出是有位数的,10位就表示输出的值是有10bit来表示的,位数越大表示精度越好

转换速率

AD转换是需要时间的,不同的AD转换器芯片需要的时间不一样的,甚至是同一个芯片配置不一样的时候需要的时间也是不一样的,转换速率的单位是MSPS,AD工作需要一个时钟,时钟有一定的范围,实际配置时不能超出这个范围,AD转换在该时钟操控下进行,该时钟的频率控制着AD转化的速率,成正比关系

ADC控制器

电阻式触摸屏工作时依赖于AD转换,在210Soc中ADC和电阻触摸屏是一起的,ADC时钟如下:
ADC时钟框图
其中ADCCLK就是ADC的时钟,是PCLK经过了一次分频后得到的,所以ADC初始化时必须要初始化分频器寄存器TSADCCONn的6-13位,210一共支持10个ADC通道AIN0-9,所以理论上可以同时进行10路AD转换,Soc有模拟引脚和数字引脚两种,例如GPIO属于数字引脚,ADC的Channel引脚就属于模拟引脚,模拟引脚专门用来输入输出模拟信号的,AD的10个通道中2-9都被触摸屏使用了,只有0和1通道可以用作ADC

ADC寄存器

  • TSCON0,触摸屏控制
  • TSACDCON0,ADC控制寄存器
  • TSDATX0,TSDATY0,转出来的AD值存储寄存器
  • CLRINTADC0
  • ADCMUX

ADC编程控制

头文件中的定义

#define TSADCCON0   0xE1700000
#define TSDATX0 0xE170000C
#define TSDATY0 0xE1700010
#define CLRINTADC0  0xE1700000
#define ADCMUX  0xE170001C
#define TSCON0  0xE1700000

#define rTSADCCON0  (*(volatile unsigned int *)TSADCCON0)
#define rTSDATX0    (*(volatile unsigned int *)TSDATX0)
#define rTSDATY0    (*(volatile unsigned int *)TSDATY0)
#define rCLRINTADC0 (*(volatile unsigned int *)CLRINTADC0)
#define rADCMUX (*(volatile unsigned int *)ADCMUX)

void adc_test();

ADC初始化和测试函数

#include "adc.h"

// 初始化adc
void adc_init(void) {
    rTSADCCON0 |= (1<<16); //分辨率设置为12
    rTSADCCON0 |= (1<<14); //启用分频器
    rTSADCCON0 &= ~(0xff<<6);
    rTSADCCON0 |= (65<<6);  //1Mhz
    rTSADCCON0 &= ~(1<<2); //正常操作模式
    rTSADCCON0 &= ~(1<<1); // 手动开启
    rADCMUX &= ~(0x0f<<0); // ADCIN0
}

// 测试adc,循环检测adc并得到adc的值并打印出来
void adc_test() {
    unsigned int valx = 0;
    unsigned int valy = 0;
    adc_init();
    while(1) {
        //开启adc转换
        rTSADCCON0 |= (1<<0);
        // 等待adc转换完毕
        while(!(rTSADCCON0 & (1<<15)));
        // 读取adc值 显示adc值
        valx = rTSDATX0;
        printf("xbit 14 = %d\r\n",(valx & (1<<14)));
        printf("adcx value = %d\r\n",(valx & (0xFFF<<0)));

        valy = rTSDATY0;
        printf("ybit 14 = %d\r\n",(valy & (1<<14)));
        printf("adcy value = %d\r\n",(valy & (0xFFF<<0)));
        sleep();
    }
}

static void sleep(){
    volatile unsigned int i,j;
    for(i = 0; i < 8000; i++) {
        for(j = 0; j < 1000; j++);
    }
}
  • 2
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值