【STM32F1】——9轴姿态传感器JY901与IIC通信
一、简介
本篇主要对9轴姿态传感器JY901的调试过程进行总结,实现了以下功能。
- IIC通信采集+串口收发:使用STM32F103C8T6的GPIO口模拟IIC,从JY901读取数据,并通过USART1串口发送到PC。
二、JY901介绍
- 电压:3.3-5V
- 量程:X/Z轴 ±180°, Y轴 ±90°
- 通信方式:IIC、UART(默认9600波特率)
- 型号区别:JY901S(带温补),JY901B(带气压)
- 帧头格式:以角度输出为例,回传数据为11位。格式为:0x55 0x53 RollL RollH PitchL PitchH YawL YawH TL TH SUM
- JY901的IIC通信协议:
1)模块的IIC协议采用寄存器地址访问的方式。每个地址内的数据均为16位数据,寄存器地址和含义详见用户手册。
2)JY901-IIC的写入:主机向JY901发送开始信号,写入JY901的设备地址dev(即0x50)。再写入目标寄存器的地址reg。随后写入第一个数据的低字节、高字节。当最后一个数据写完后,主机向JY901发送停止信号。
3)JY901-IIC的读取:主机向JY901发送开始信号,写入JY901的设备地址dev(即0x50)。再写入目标寄存器的地址reg。主机再向JY901发送一个读信号(dev<<1)+1。JY901按先低字节,后高字节的顺序输出数据。主机在接收每一个字节后,拉低SDA总线,并向JY901发送应答信号,待接收到length长度的数据后,主机不再反馈应答信号,数据传输停止。主机发送停止信号,结束读取。
三、IIC通信的相关知识点
-
IIC通信的总线:分为时钟线SCL和信号线SDA,其中:
1)SCL:由主设备提供时钟信号,用来同步数据传输;
2)SDA:用来传输数据 -
IIC的通信协议:
1)由SCL和SDA通过逻辑电平的配合,产生三种信号,构成基本的时序单元:
① 开始信号:SCL高电平期间,SDA由高电平变为低电平,意味着总线被占用
② 结束信号:SCL高电平期间,SDA由低电平变为高电平,意味着总线空闲
③ 应答信号:发送设备每发送完一个字节(8位)后,在第9位释放数据线,由接收设备反馈一个信号。当应答信号为低电平时,表示接收设备成功接收,规定为有效应答ACK;反之为无效应答。 -
IIC通信的数据传输原则:
1)先发送高位数据,再发送低位数据(高位先行)
2)IIC总线进行数据传输时,在SCL=1时,SDA上的不允许由电平变化。只有在SCL=0时,SDA上的电平才可以变化。数据的传输是边沿触发。
3)当SCL=SDA=1时,总线处于空闲状态。 -
IIC写操作的通信过程:依靠地址进行通信
1)主机在IIC总线上发送起始信号,总线上的所有从机等待主机的数据;
2)主机发送“从机地址+0(代表写数据)”得到8位数据帧,从机检测是否为对应地址,产生应答信号。
3)主机接收应答信号,向从机发送真正的数据信号。
- IIC读操作的通信过程:
1)主机在IIC总线上发送起始信号,总线上的所有从机等待主机的数据;
2)主机发送 “从机地址+1(代表读操作)”组成的8位数据帧,从机检测是否为对应地址,产生应答信号,同时向主机返回8位数据帧,随后等待主机的应答信号;
3)主机发出应答信号,从机发送数据,直到主机发送非应答信号,从机停止发送
-
模拟IIC和硬件IIC
1)硬件IIC:对应芯片上的IIC外设,有相应IIC驱动电路。通信较为稳定,但需要直接调用内部寄存器进行配置,编程相对繁琐;
2)软件IIC:使用GPIO管脚,用软件控制SCL,SDA线输出高低电平,模拟i2c协议的时序,通信稳定,编程相对简单; -
注意事项IIC外接上拉电阻:
1)在使用模拟IIC通信时,需要外接上拉电阻,一般使用4.7kΩ!因为GPIO口一般配置的是开漏输出,这意味着内部电路可以吸收电流,但无法提供电流,即GPIO可以被设置为低电平,但不能被设置为高电平。而上拉电阻可以保证在没有设备驱动时总线SCL和SDA被保持在高电平状态。2)这里的GPIO口不能使用推挽输出,因为一个设备输出高电平,一个设备输出低电平时会导致短路烧毁设备。
四、JY901的模拟IIC通信
-
接线:
-
程序简介:使用STM32F103C8T6的GPIO口模拟IIC通信,实现9轴姿态模块JY901数据的读取,并利用USART1发送到PC。
-
实现思路:
1)配置GPIO口,拉高电平进行初始化;
2)编写模拟IIC通信的子函数;
3)配置串口USART1,打开发送中断;
4)IIC读取JY901的数据,通过USART1发送到PC的串口助手。 -
代码解析:
1)模拟IIC对应的GPIO口初始化:一定配置成开漏输出!
void IIC_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //配置PB10-SCL PB11-SDL 为开漏输出 刷新频率为10Mhz GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //应用配置到GPIOB GPIO_Init(GPIOB, &GPIO_InitStructure); SDA_OUT(); //sda线输出 IIC_SDA=1; IIC_SCL=1; }
2)模拟IIC通信的一些子函数:
#include "sys.h" #define SDA_IN() { GPIOB->CRL&=0x0FFFFFFF;GPIOB->CRL|=(u32)8<<28;} #define SDA_OUT() { GPIOB->CRL&=0x0FFFFFFF;GPIOB->CRL|=(u32)3<<28;} #define IIC_SCL PBout(10) #define IIC_SDA PBout(11) #define READ_SDA PBin(11) void IIC_Start(void) { SDA_OUT(); IIC_SDA = 1; IIC_SCL = 1; delay_us(5); IIC_SDA = 0; delay_us(5); IIC_SCL = 0; } void IIC_Stop(void) { SDA_OUT</