加速度传感器驱动
mma8653
1.关于I2C (IIC)
1). I2C的定义
由飞利浦公司开发的两线式串行同步总线
通信使用两条线
一个时钟周期占一个bit位
SCL:时钟线 (区别于异步通信)
SDA:数据线
2). I2C的特点
a) 互联时只有两根线,硬件互联的成本低
b) 一条IIC总线上可以接多个IIC设备,
有主从之分, 每次通信的发起和结束都有主设备决定
c) 每个从设备都有特定的从设备地址 (7bit)
d) 总线上可以有多个主设备,支持总线冲突仲裁
3)IIC通信协议
辅助信号:
start信号
SCL处于高电平期间 SDA上出现一个下降沿
stop信号
SCL处于高电平期间 SDA上出现一个上升沿
ack信号
第九个周期 SCL处于高电平期间 接受方将SDA拉低
nak信号
第九个周期 SCL处于高电平期间 接受方未将SDA拉低
空闲状态 SCL和SDA处于高电平状态
发送数据时从高bit位开始发送
采取低送高取的方式
2.1 电路原理图
MCU_SCL_2 -----> GPIOD6
MCU_SDA_2 -----> GPIOD7
控制D6 D7管脚形成I2C通信时序有两种方式:
1) 纯软模拟
软件直接控制两个管脚上的电平变化
2) 软硬件结合
软件控制I2C控制器 I2C控制器控制以上两个管脚
I2C 控制器能做哪些工作 还需要软件完成哪些工作
以及如何配合工作
2.2 cpu datasheet
GPIOD6 D7 都需要选择功能一.
GPIODALTFN0
[15:14] 01 D7配置为功能1
[13:12] 01 D6 配置为功能1
CPU内部集成了3个I2C控制器
问mma 8653连接到了哪个I2C控制器上
根据电路原理图中mm8653芯片连接到了CPU GPIOD6 D7推断 连接到I2C2控制器上.
通信速率标准模式下: 100kbit/s
快速模式下:400kbit/s
可以配置成主设备或者从设备
I2CCON2 0xC00A6000
[3:0] 1111,发送时钟先设置成最慢 屏蔽硬件问题
[4] 读操作时,读到的是0,未出现中断未决. 1,出现了中断未决.
写操作时, 0,该位清0, 1,无效
轮询是否收发完成
[5] 1,使能收发中断
[6] 1, I2C CLOCK = PCLK / 256 (越慢越好)
[7] 0/1 禁止/使能ACK信号的产生
I2CSTAT2
[0] 是否收到ACK
[4] 0/1 禁止/使能输出
[5] 读操作
0/1 总线处于空闲/忙状态
写操作
0/1 产生STOP 产生START信号
[7:6] 10, 主设备接受模式
11,主设备发送模式
I2CDS2
[7:0] 收发数据
I2CLC2
[1:0] 01,SDA延时5个PCLK周期再跳变
[2] 1,使能滤波
I2CCLKENB2
[3] 1,给I2C控制器的时钟始终使能
2.3 从加速度传感器读取ID值并显示
问题1:从设备地址是多少?
0x1D
同一个I2C控制器的从设备地址只能挂载一个,从设备地址不可以重复.
问题2: 该芯片中有多少个特殊功能寄存器
大约有50个
问题3: ID值存在于哪个特殊功能寄存器中?
存在于WHO_AM_I 寄存器,
该寄存器的地址是0x0d,
ID值为 0x5A.
问题4: 如何读取mma8653芯片寄存器中的值
主设备:发start, 发0x1d<<1 | 0 收ACK 发0x0d 收ACK 发start 发0x1d<<1 | 1 收ACK 收数据 发NAK 发STOP
问题5: 如何才能向mma8653芯片寄存器中写入值
主设备:发start 发0x1d<<1 | W 收ACK 发0x0d 收ACK 发要写入寄存器的数据 收ACK 发数据 收ACK ... 发数据 不回ACK 发送stop
2.4 itoa 函数的实现
这里提供两种实现方式:
num = 0x123456bd buf= 0x123456bd
void itoa(char *buf, unsigned int num)
{
unsigned int tmp = 0;
int i;
i = 9;
buf[0] = '0';
buf[1] = 'x';
while (num)
{
tmp = num % 16;
if (tmp > 10)
{
buf[i] = tmp - 10 + 'A';
}
else {
buf[i] = tmp + '0';
}
i--;
num /= 16;
}
while (i>=2)
{
buf[i--] = '0';
}
buf[10] = 0;
}
void itoa (unsigned int num, char *buf)
{
int i = 0;
unsigned int tmp = 0;
int j = 0;
char buf1[11] = {
0};
if (num == 0)
{
buf1[i] = '0';
i++;
}
while (num) {
tmp = num % 16;
buf1[i] = (tmp > 9) ? (tmp - 10) + 'a' : tmp + '0';
num = num / 16;
i++;
}
i--;
for (i; i >= 0;i--)
{
buf[i] = buf1[j];
j++;
}
}
3.读加速度值
加速度值存在于哪些寄存器中?
地址为0x01~0x06的寄存器中
如何将该芯片切换为active模式?
地址为0x2a的寄存器CTRL_REG1
[0] 1/0 ACTIVE/STANDBY模式
iic.h
#ifndef __IIC_H_
#define __IIC_H_
extern void iic_init (