00. 目录
文章目录
01. FR801xH概述
FR801xH 系列芯片是面向SOC(片上系统),易于快速开发的低功耗蓝牙芯片。基于 Freqchip 的蓝牙智能固件和协议栈的支持,完全兼容蓝牙 V5.3(LE 模式)协议。同时用户可以基于芯片内置的 ARM CorteM3 嵌入式 32 位高性能单片机开发各种应用程序。
蓝牙智能固件包括 L2CAP 服务层协议、安全管理器 (SM)、属性协议(ATT)、通用属性配置文件 (GATT)和通用访问配置文件(GAP)。此外,还 支持应用程序配置文件,例如接近度、健康温度计、 心率、血压、血糖、人机界面设备(HID)和 SDK (包括驱动程序、OS-API 等)。SDK 还集成了用于网络应用程序的 SIG Mesh 协议。
采用 Freqchip 的创新技术,将 PMU(锂电池充电 器+LDO)、带 XIP 模式的 QSPI FLASH ROM、 I2C、UART、GPIO、ADC、PWM 集成在一块芯片中,为客户提供:
- 竞争力的功耗
- 稳定的蓝牙连接
- 极低的 BOM 成本
02. FR801xH功能框图
03. I2C相关类型
位于 components\driver\include\driver_iic.h
。
3.1 iic_channel_t
enum iic_channel_t
{
IIC_CHANNEL_0,
IIC_CHANNEL_1,
IIC_CHANNEL_MAX,
};
3.2 enum_iic_int_indx_t
typedef enum
{
INT_TRANS_DONE = 0x00000001,
INT_ARB_FAIL = 0x00000002,
INT_NO_ACK = 0x00000004,
INT_MS_DATA_REQ = 0x00000008,
INT_SLV_DATA_REQ = 0x00000010,
INT_RX_FFF = 0x00000020,
INT_RX_FFNE = 0x00000040,
INT_MS_TX_FFNF = 0x00000080,
INT_SW_RST = 0x00000100,
INT_ADD_TYPE_SEL = 0x00000200,
INT_SLV_TX_FFNF = 0x00000400,
}enum_iic_int_indx_t;
04. I2C相关API
4.1 iic_init
/*********************************************************************
* @fn iic_init
*
* @brief Initialize iic instance.
*
* @param channel - IIC_CHANNEL_0 or IIC_CHANNEL_1.
* speed - SCL speed when working as master, N * 1000
* slave_addr - local address when working as slave
*
* @return None.
*/
void iic_init(enum iic_channel_t channel, uint16_t speed, uint16_t slave_addr);
功能:
初始化 IIC 模块,默认配置为为 7 位地址模式
参数:
channel 初始化对象,可选 IIC_CHANNEL_0、IIC_CHANNEL_1
speed 配置总线时钟速率为 speed*1000
slave_addr 当本机工作在从机模式时的从机地址
返回值:
None
4.2 iic_write_byte
/*********************************************************************
* @fn iic_write_byte
*
* @brief write one byte to slave.
*
* @param channel - IIC_CHANNEL_0 or IIC_CHANNEL_1.
* slave_addr - slave address
* reg_addr - which register to be writen
* data - data to be writen
*
* @return None.
*/
uint8_t iic_write_byte(enum iic_channel_t channel, uint8_t slave_addr, uint8_t reg_addr, uint8_t data);
功能:
将一个字节数据发送给从机的特定地址
参数:
channel - 操作对象
slave_addr - 从机地址
reg_addr - 操作的从机寄存器地址
data - 待写入的数据
返回值:
None
4.3 iic_write_bytes
/*********************************************************************
* @fn iic_write_bytes
*
* @brief write multi-bytes to slave.
*
* @param channel - IIC_CHANNEL_0 or IIC_CHANNEL_1.
* slave_addr - slave address
* reg_addr - which register to be writen
* buffer - pointer to data buffer
* length - how many bytes to be written
*
* @return None.
*/
uint8_t iic_write_bytes(enum iic_channel_t channel, uint8_t slave_addr, uint8_t reg_addr, uint8_t *buffer, uint16_t length);
功能:
将多个字节数据发送给从机的特定地址
参数:
channel - 操作对象
slave_addr - 从机地址
reg_addr - 操作的从机寄存器起始地址
buffer - 待写入的数据
length - 待写入的数据长度
返回值:
true:写入成功;false:写入失败
4.4 iic_read_byte
/*********************************************************************
* @fn iic_read_byte
*
* @brief read one byte frome slave.
*
* @param channel - IIC_CHANNEL_0 or IIC_CHANNEL_1.
* slave_addr - slave address
* reg_addr - which register to be written
* buffer - store data to buffer
*
* @return None.
*/
uint8_t iic_read_byte(enum iic_channel_t channel, uint8_t slave_addr, uint8_t reg_addr, uint8_t *buffer);
功能:
从从机的特定地址读取一个字节数据
参数:
channel - 操作对象
slave_addr - 从机地址
reg_addr - 操作的从机寄存器地址
buffer - 读取数据的保存地址
返回值:
true:读取成功;false:读取失败
4.5 iic_read_bytes
/*********************************************************************
* @fn iic_read_bytes
*
* @brief read multi-bytes frome slave.
*
* @param channel - IIC_CHANNEL_0 or IIC_CHANNEL_1.
* slave_addr - slave address
* reg_addr - which register to be written
* buffer - buffer pointer to be written
* length - how many bytes to be read
*
* @return None.
*/
uint8_t iic_read_bytes(enum iic_channel_t channel, uint8_t slave_addr, uint8_t reg_addr, uint8_t *buffer, uint16_t length);
功能:
从从机的特定地址读取多个字节数据
参数:
channel - 操作对象
slave_addr - 从机地址
reg_addr - 操作的从机寄存器起始地址
buffer - 读取数据的保存地址
length - 待读取的数据长度
返回值:
true:读取成功;false:读取失败
05. I2C程序示例
mpu6050.h
#ifndef __MPU6050_H__
#define __MPU6050_H__
#include "mpu6050.h"
#include "driver_iic.h"
//0x68 默认左移1位
#define MPU6050_ADDRESS 0xD0
#define MPU6050_SMPLRT_DIV 0x19
#define MPU6050_CONFIG 0x1A
#define MPU6050_GYRO_CONFIG 0x1B
#define MPU6050_ACCEL_CONFIG 0x1C
#define MPU6050_ACCEL_XOUT_H 0x3B
#define MPU6050_ACCEL_XOUT_L 0x3C
#define MPU6050_ACCEL_YOUT_H 0x3D
#define MPU6050_ACCEL_YOUT_L 0x3E
#define MPU6050_ACCEL_ZOUT_H 0x3F
#define MPU6050_ACCEL_ZOUT_L 0x40
#define MPU6050_TEMP_OUT_H 0x41
#define MPU6050_TEMP_OUT_L 0x42
#define MPU6050_GYRO_XOUT_H 0x43
#define MPU6050_GYRO_XOUT_L 0x44
#define MPU6050_GYRO_YOUT_H 0x45
#define MPU6050_GYRO_YOUT_L 0x46
#define MPU6050_GYRO_ZOUT_H 0x47
#define MPU6050_GYRO_ZOUT_L 0x48
#define MPU6050_PWR_MGMT_1 0x6B
#define MPU6050_PWR_MGMT_2 0x6C
#define MPU6050_WHO_AM_I 0x75
void MPU6050_WriteReg(uint8_t regAddr, uint8_t data);
uint8_t MPU6050_ReadReg(uint8_t regAddr);
void MPU6050_init(void);
uint8_t MPU6050_getId(void);
void MPU6050_getData(int16_t *AccX, int16_t *AccY, int16_t *AccZ,
int16_t *GyroX, int16_t *GyroY, int16_t *GyroZ);
#endif /*__MPU6050_H__*/
mpu6050.c
#include "mpu6050.h"
#include "sys_utils.h"
#include "driver_system.h"
void MPU6050_WriteReg(uint8_t regAddr, uint8_t data)
{
iic_write_byte(IIC_CHANNEL_1, MPU6050_ADDRESS, regAddr, data);
}
uint8_t MPU6050_ReadReg(uint8_t regAddr)
{
uint8_t data = 0;
iic_read_byte(IIC_CHANNEL_1, MPU6050_ADDRESS, regAddr, &data);
return data;
}
void MPU6050_init(void)
{
// 设置引脚复用功能 SCL-- PA6 SDA -- PA7
system_set_port_mux(GPIO_PORT_A, GPIO_BIT_6, PORTA6_FUNC_I2C1_CLK);
system_set_port_mux(GPIO_PORT_A, GPIO_BIT_7, PORTA7_FUNC_I2C1_DAT);
system_set_port_pull((GPIO_PA6 | GPIO_PA7), true);
iic_init(IIC_CHANNEL_1, 1000, MPU6050_ADDRESS);
co_delay_100us(1);
// MPU6050初始化
MPU6050_WriteReg(MPU6050_PWR_MGMT_1, 0x01);
MPU6050_WriteReg(MPU6050_PWR_MGMT_2, 0x00);
MPU6050_WriteReg(MPU6050_SMPLRT_DIV, 0x09);
MPU6050_WriteReg(MPU6050_CONFIG, 0x06);
MPU6050_WriteReg(MPU6050_GYRO_CONFIG, 0x18);
MPU6050_WriteReg(MPU6050_ACCEL_CONFIG, 0x18);
}
uint8_t MPU6050_getId(void)
{
return MPU6050_ReadReg(MPU6050_WHO_AM_I);
}
void MPU6050_getData(int16_t *AccX, int16_t *AccY, int16_t *AccZ,
int16_t *GyroX, int16_t *GyroY, int16_t *GyroZ)
{
uint8_t DataH, DataL;
DataH = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_H);
DataL = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_L);
*AccX = (DataH << 8) | DataL;
DataH = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_H);
DataL = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_L);
*AccY = (DataH << 8) | DataL;
DataH = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_H);
DataL = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_L);
*AccZ = (DataH << 8) | DataL;
DataH = MPU6050_ReadReg(MPU6050_GYRO_XOUT_H);
DataL = MPU6050_ReadReg(MPU6050_GYRO_XOUT_L);
*GyroX = (DataH << 8) | DataL;
DataH = MPU6050_ReadReg(MPU6050_GYRO_YOUT_H);
DataL = MPU6050_ReadReg(MPU6050_GYRO_YOUT_L);
*GyroY = (DataH << 8) | DataL;
DataH = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_H);
DataL = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_L);
*GyroZ = (DataH << 8) | DataL;
}
demo.c
#include "sys_utils.h"
#include "driver_exti.h"
#include "mpu6050.h"
void peripheral_demo(void)
{
int16_t accx, accy, accz;
int16_t gyrox, gyroy, gyroz;
co_printf("MPU6050 Demo....\r\n");
MPU6050_init();
while(1)
{
co_printf("chipid: %x\r\n", MPU6050_getId());
MPU6050_getData(&accx, &accy, &accz, &gyrox, &gyroy, &gyroz);
co_printf("x: %d y: %d z: %d gx: %d gy: %d gz: %d\r\n", accx, accy, accz, gyrox, gyroy, gyroz);
co_delay_100us(10000);
}
}
程序运行结果
freqchipuser_entry_after_ble_init
MPU6050 Demo....
chipid: 68
x: -25 y: -1528 z: -1376 gx: -181 gy: 40 gz: -13
chipid: 68
x: -48 y: -1532 z: -1357 gx: -20 gy: -23 gz: 23
chipid: 68
x: -49 y: -1532 z: -1356 gx: -25 gy: -22 gz: 24
chipid: 68
x: -48 y: -1534 z: -1358 gx: -25 gy: -20 gz: 7
chipid: 68
x: -51 y: -1533 z: -1356 gx: -26 gy: -23 gz: 30
chipid: 68
x: -52 y: -1531 z: -1353 gx: -26 gy: -24 gz: 41