STM32中使用MMA7660重力加速度传感器
最近在项目中要用到飞思卡尔的MMA7660这一款传感器,我在STM32中使用的是模拟I2C来读写它的寄存器,闲话不多说,代码如下:
1、IO引脚配置和模拟I2C的方法
/******************** (C) COPYRIGHT 2015 ASTO **************************@* 文件名 :mma7660.c@* 描述 :飞思卡尔的MMA7660系列重力加速度传感器 @* 开发平台:STM32F103CBT6系列处理器@* 通信方式:I2C@* 硬件连接: ------------------------------* | PB1 : 中断引脚 |* | PB10 : SCL数据线 |* | PB11 : SDA数据线 |* ------------------------------@* 库版本 :ST3.5.0@* 开发者 :POWER
************************************************************************/#include "stm32f10x.h"
#include "mma7660.h"
#include "delay.h"/**=========================================================* 函数功能:MMA7660中断向量表配置* 参数: 无* * 函数返回值:无 *========================================================= */
static void MMA7660_NVIC_Config(void)
{NVIC_InitTypeDef NVIC_InitStructure;/* Enable the EXTI1 Interrupt */NVIC_InitStructure.NVIC_IRQChannel = MMA7660_INT_IRQ; //中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //抢占优先级NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;//次优先级NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //通道中断使能NVIC_Init(&NVIC_InitStructure);//初始化中断
}/**=========================================================* 函数功能:MMA7660中断线配置* 参数: 无* * 函数返回值:无 *========================================================= */
static void MMA7660_ExtiInit(void)
{EXTI_InitTypeDef EXTI_InitStructure;MMA7660_NVIC_Config();RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);//配置MMA7660模块发生相应的事件后中断配置GPIO_EXTILineConfig(MMA7660_INT_PORT_SRC, MMA7660_INT_SOURCE); EXTI_InitStructure.EXTI_Line = MMA7660_INT_LINE; //中断线EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//使用中断方式触发模式(另外还有事件方式触发模式)EXTI_InitStructure.EXTI_Trigger = MMA7660_INT_MODE; //中断信号触发边沿EXTI_InitStructure.EXTI_LineCmd = ENABLE; //中断线使能EXTI_Init(&EXTI_InitStructure); //初始化中断
}/************************************************************* IIC总线模拟程序************************************************************//**=========================================================* 函数功能:MMA7660端口状态配置* 参数: 无* * 函数返回值:无 *========================================================= */
void MMA7660_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//中断引脚配置GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入GPIO_Init(GPIOB, &GPIO_InitStructure); // 选择B端口//SCL数据线配置GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 ; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 普通推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 最高输出速率50MHzGPIO_Init(GPIOB, &GPIO_InitStructure); // 选择B端口//SDA数据线配置GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 ; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; // 开漏输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 最高输出速率50MHzGPIO_Init(GPIOB, &GPIO_InitStructure); // 选择B端口MMA7660_ExtiInit(); //中断配置MMA7660_Begin(); //MMA7660寄存器配置
}/**=========================================================* 函数功能:MMA7660的SDA数据线配置,这里作为输出用* 参数: 无* * 函数返回值:无 *========================================================= */
void MMA_SDA_IOOUT(void)
{ GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 ; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; // 开漏输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 最高输出速率50MHzGPIO_Init(GPIOB, &GPIO_InitStructure); // 选择B端口
}/**=========================================================* 函数功能:MMA7660的SDA数据线配置,这里作为输入用* 参数: 无* * 函数返回值:无 *========================================================= */
void MMA_SDA_IOIN(void)
{ GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 ; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入GPIO_Init(GPIOB, &GPIO_InitStructure); // 选择B端口
}/**=========================================================* 函数功能:IIC总线初始化信号* 参数:无* 函数返回值:无 * SDA ---* |________* SCL ----------* |____ *========================================================= */
void I2C_Start(void)
{MMA7660_SCL_H;MMA7660_SDA_H;Delayus(1);MMA7660_SDA_L;Delayus(1);
}/**=========================================================* 函数功能:IIC总线停止信号* 参数:无* 函数返回值:无 * SDA ---------* ______|* SCL ---------* |___*========================================================= */
void I2C_Stop(void)
{MMA7660_SCL_H;MMA7660_SDA_L;Delayus(1);MMA7660_SDA_H;Delayus(1);
}/**=========================================================* 函数功能:接收由从机向主机发起的ACK信号。* 参数: ACKBIT* * 函数返回值:MMA_ERROR/MMA_OK *========================================================= */
uint8_t I2C_SlaveAck(void)
{uint8_t ts=0;MMA7660_SCL_L;MMA7660_SDA_H;MMA_SDA_IOIN(); //SDA设为输入Delayus(1);MMA7660_SCL_H;while(MMA7660_SDA_D!=0) {ts++;if(ts>200) {MMA_SDA_IOOUT(); //SDA设为输出MMA7660_SCL_L;return MMA_ERROR; //返回错误 }}MMA7660_SCL_L;MMA_SDA_IOOUT(); //SDA设为输出//MMA7660_SDA_H;Delayus(1);return MMA_OK; //返回错误
}/**=========================================================* 函数功能:IIC写一个字节数据* 参数: a:需要写入的一个字节数据* 函数返回值:无*========================================================= */
void I2C_WriteByte(uint8_t a)
{uint8_t i; for(i=0; i<8; i++){ MMA7660_SCL_L;if((a&0x80)!=0) MMA7660_SDA_H;else MMA7660_SDA_L;a <<= 1;Delayus(1);MMA7660_SCL_H;Delayus(1);}MMA7660_SCL_L; if(I2C_SlaveAck()==MMA_ERROR) { //等待从机的ACK信号return ;}
}/**=========================================================* 函数功能:IIC读一个字节数据* 参数:无* 函数返回值:返回读出的一个字节数据*========================================================= */
uint8_t I2C_ReadByte(void)
{uint8_t a =0;uint8_t i;MMA_SDA_IOIN(); //SDA设为输入 for(i=0; i<8; i++) {a <<= 1; MMA7660_SCL_H;Delayus(1);if(MMA7660_SDA_D==1) a |= 0x01;Delayus(1);MMA7660_SCL_L;Delayus(2); }return a;
}
2、MMA相关的代码
/************************************************************* MMA7660相关函数************************************************************/
/**=========================================================* 函数功能:写MAA7660寄存器* 参数: * Regs_Addr - 寄存器地址* Regs_Data - 寄存器值* 函数返回值:*========================================================= */
void MMA7660_WriteReg(uint8_t Regs_Addr,uint8_t Regs_Data)
{ I2C_Start();I2C_WriteByte(MMA7660_DEV_WRITE); //先写Slave地址,并配置成写模式I2C_WriteByte(Regs_Addr); //写寄存器地址I2C_WriteByte(Regs_Data); //写寄存器内容I2C_Stop(); //结束本段IIC进程
}/**=========================================================* 函数功能:读MAA7660单字节* 参数* Regs_Addr - 寄存器地址* 函数返回值:寄存器值*========================================================= */
uint8_t MMA7660_ReadReg(uint8_t Regs_Addr)
{uint8_t ret;I2C_Start();I2C_WriteByte(MMA7660_DEV_WRITE); //先写Slave地址,并配置成写模式I2C_WriteByte(Regs_Addr); //写寄存器地址I2C_Start();I2C_WriteByte(MMA7660_DEV_READ); //写Slave地址,并配置成读模式ret=I2C_ReadByte(); //从传感器中读出数据I2C_SlaveAck();I2C_Stop(); //结束本段IIC进程 return ret;} /**=========================================================* 函数功能:读MAA7660加速度输出* 参数 :* Regs_Addr - 加速度寄存器地址* 函数返回值:加速度值*========================================================= */
uint8_t MMA7660_GetResult(uint8_t Regs_Addr)
{uint8_t ret;// 等待转换完成并取出值 ret=MMA7660_ReadReg(Regs_Addr);while(ret&0x40) {ret=MMA7660_ReadReg(Regs_Addr); //数据更新,重新读}return ret;
}/**=========================================================* 函数功能:MAA7660寄存器配置,决定MMA7660工作方式* 参数 :* * 函数返回值:无*========================================================= */
void MMA7660_Begin(void)
{MMA7660_WriteReg(MMA7660_MODE,0x00); //standby mode //首先必须进入standby模式才能更改寄存器MMA7660_WriteReg(MMA7660_SPCNT,0x00); //No Sleep CountMMA7660_WriteReg(MMA7660_INTSU,0xE3);//0xE0 will be OK //original value: 0x03 //Configure GINT InterruptMMA7660_WriteReg(MMA7660_PDET,0xE0); //orginal value: 0xE0 //No tap detection enabledMMA7660_WriteReg(MMA7660_SR,0x02); //orginal value: 0x34 //8 samples/s,TILT debounce filter=2MMA7660_WriteReg(MMA7660_PD,0x00); //original value: 0x00 //No tap detection debounce count enabledMMA7660_WriteReg(MMA7660_MODE,0x41);//original value: 0x41 //Active Mode,INT= push-pull and active low
}
3、头文件定义
#ifndef _MMA7660_H_
#define _MMA7660_H_//硬件定义
#define MM_INT GPIO_Pin_1 // PB1
#define MM_SCL GPIO_Pin_10 // PB10
#define MM_SDA GPIO_Pin_11 // PB11/************************************************************* 中断线配置,低电平触发************************************************************/
#define MMA7660_INT_GPIO_SRC GPIOB //外设组
#define MMA7660_INT_PORT_SRC GPIO_PortSourceGPIOB //中断引脚组
#define MMA7660_INT_IRQ EXTI1_IRQn //中断号
#define MMA7660_INT_SOURCE GPIO_PinSource1 //中断源
#define MMA7660_INT_LINE EXTI_Line1 //中断线
#define MMA7660_INT_MODE EXTI_Trigger_Falling //中断触发方式/************************************************************* 相关宏定义************************************************************/
//==========模拟IIC==================//
#define MMA_ERROR 0
#define MMA_OK 1
#define I2C_NOACK 0
#define I2C_ACK 1
#define MMA7660_SDA GPIO_Pin_10 // PB10 //IIC数据线接口
#define MMA7660_SCL GPIO_Pin_11 // PB11 //IIC时钟线接口
#define MMA7660_INT GPIO_Pin_1 // PB1 //中断线接口 #define MMA7660_INT_D GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) //PB1读数据#define MMA7660_SDA_D GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) //PB11读数据
#define MMA7660_SDA_H GPIO_SetBits(GPIOB, GPIO_Pin_11) // PB11 高电平
#define MMA7660_SDA_L GPIO_ResetBits(GPIOB, GPIO_Pin_11) // PB11 低电平#define MMA7660_SCL_H GPIO_SetBits(GPIOB, GPIO_Pin_10) // PB10 高电平
#define MMA7660_SCL_L GPIO_ResetBits(GPIOB, GPIO_Pin_10) // PB10 低电平//==========MMA7660 寄存器地址==================//
#define MMA7660_XOUT 0x00 // 6-bit output value X
#define MMA7660_YOUT 0x01 // 6-bit output value Y
#define MMA7660_ZOUT 0x02 // 6-bit output value Z
#define MMA7660_TILT 0x03 // Tilt Status
#define MMA7660_SRST 0x04 // Sampling Rate Status
#define MMA7660_SPCNT 0x05 // Sleep Count
#define MMA7660_INTSU 0x06 // Interrupt Setup
#define MMA7660_MODE 0x07 // Mode
#define MMA7660_SR 0x08 // Auto-Wake/Sleep and // Portrait/Landscape samples // per seconds and Debounce Filter
#define MMA7660_PDET 0x09 // Tap Detection
#define MMA7660_PD 0x0A // Tap Debounce Count//=========MMA7660 功能参数==================//
#define MMA7660_DEV_ADDR 0x4C //Normally,can range 0x08 to 0xEF
#define MMA7660_DEV_WRITE MMA7660_DEV_ADDR<<1 | 0x00
#define MMA7660_DEV_READ MMA7660_DEV_ADDR<<1 | 0x01/************************************************************* 全局函数声明************************************************************/
void MMA7660_Init(void); //SCL,INT端口输出配置
void MMA_SDA_IOOUT(void); //SDA端口配置为输出
void MMA_SDA_IOIN(void); //SDA端口配置为输入
void I2C_Start(void); //开始信号
void I2C_Stop(void); //结束信号
uint8_t I2C_SlaveAck(void); //应答信号
void I2C_WriteByte(uint8_t a); //写一字节
uint8_t I2C_ReadByte(void); //读一字节
void MMA7660_WriteReg(uint8_t Regs_Addr,uint8_t Regs_Data); //写寄存器
uint8_t MMA7660_ReadReg(uint8_t Regs_Addr); //读寄存器
uint8_t MMA7660_GetResult(uint8_t Regs_Addr); //读加速度
void MMA7660_Begin(void); //开始传送前的寄存器值设置/************************************************************* 全局定义************************************************************/#endif /* _MMA7660_H_ */
4、中断处理函数
#if MMA7660_EN > 0u
#include "mma7660.h"
/*******************************************************************************
* Function Name : EXTI1_IRQHandler
* Description : This function handles External lines 1 interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void EXTI1_IRQHandler(void)
{OSIntEnter(); //用于统计中断的嵌套层数,对嵌套层数+1,请注意:这适用于有内核参与的中断if(EXTI_GetITStatus(MMA7660_INT_LINE) != RESET) //如果检测到状态位置位{ EXTI_ClearITPendingBit(MMA7660_INT_LINE); //清除中断标志位//发送信号量给相应的MMA7660任务控制块if (!GPIO_ReadInputDataBit(MMA7660_INT_GPIO_SRC, GPIO_Pin_1)) { //如果读取到的是低电平,则表明产生了重力传感器事件OS_ERR err;MMA7660_ReadReg(MMA7660_TILT);//读取TILT寄存器,清除中断,以便下次再进入中断 //使用发送信号量的方式//第二个参数:1. OS_OPT_POST_NONE表明在发布任务信号量之后调用任务调度程序// 2. OS_OPT_POST_NO_SCHED则OSTaskSemPost后不会调用调度程序OSTaskSemPost(&MMA7660_TCB,OS_OPT_POST_NONE,&err); } }OSIntExit();//对嵌套层数减1,在退出中断前启动任务调度(适用于有u/COS-III内核参与的中断)
}
#endif
5、主函数调用
在main函数中调用如下代码即可:
#if MMA7660_EN > 0u /* MMA7660重力传感器初始化 */MMA7660_Init(); #endif
STM32中使用MMA7660重力加速度传感器相关推荐
- 最小二乘拟合二次曲线在STM32中的实现笔记
传感器使用前要进行标定, 标定时必定需要进行曲线拟合.若用计算机处理很简单, 但实际中用微控制器中标定时, 只能进行一般的代数运算,无矩阵运算, 处理就显得非常不方便.最小二乘法推导了二次多项式曲线拟 ...
- STM32读取SHT3x系列温湿度传感器,标准库和HAL库
STM32读取SHT3x系列(SHT30.SHT31.SHT35)温湿度传感器的数据并显示在0.96寸OLED屏上. 我下面提供两份代码,一份是标准库使用硬件I2C的,另一份是HAL库使用软件模拟II ...
- 深入浅出地理解STM32中的中断系统——从原理到简单工程示例——保姆级教程
深入浅出地理解STM32中的中断系统 一.什么是中断?什么是异常? 二.如何管理中断? 三.NVIC 1 NVIC 特点 2 中断优先级 (1) 优先级分组 3 中断向量表 4 中断服务函数 (1)中 ...
- stm32中cubmx+keil+proteus+虚拟串口+串口助手的使用
stm32中cubmx+keil+proteus+虚拟串口+串口助手的使用 stm32cubmx keil proteus 一个简单的实例 虚拟串口+串口调试 项目设计需要,以下为微控制器模块要用到的 ...
- K_A12_002 基于STM32等单片机采集光敏电阻传感器参数串口与OLED0.96双显示
K_A12_002 基于STM32等单片机采集光敏电阻传感器参数串口与OLED0.96双显示 一.资源说明 二.基本参数 参数 引脚说明 三.驱动说明 IIC地址/采集通道选择/时序 对应程序: 四. ...
- STM32单片机(六). 传感器的使用
传感器是单片机外围电路中最常见的模块,在搭配了各种形式的传感器电路后,就可以采集到的更多的环境信息.在本章节中,主要介绍呼吸灯.温度传感器.RTC实时时钟以及红外遥控模块的控制使用. 1.PWM实现呼 ...
- STM32中的通信协议
STM32中的通信协议 通讯协议是指在嵌入式开发中,不同的硬件系统或者操作系统之间进行数据交换的方式,是一种数据通讯的规约. 通讯协议有很多种,而我今天要说的是串口通讯协议,而且是基于STM32来说的 ...
- STM32中GPIO的8种工作模式
一.推挽输出:可以输出高.低电平,连接数字器件:推挽结构一般是指两个三极管分别受两个互补信号的控制,总是在一个三极管导通的时候另一个截止.高低电平由IC的电源决定.形象点解释:推挽,就是有推有拉,任何 ...
- Arduino处理STM32中的多个串口通讯问题
简 介: 对于在Arduino下开发STM32的程序,对于STM32所具有的三个硬件USART进行测测试.结果显示可以使用这些串口完成相应的数据的输入与输出.但是涉及到以下两个问题,还没有得到解决:问 ...
- 超声波测距测速升压可调中周倒车雷达变频器传感器1:10
简 介: 通过对于是用于超声波测速变压器的基本分析,为后面构成150kHz 放大节能信标组的感应信号打下基础. 关键词: 中周,电压器,超声波 ▌01 中周变压器 购买到这个周中变压器主要是为了构 ...
最新文章
- 孤军大作战!疯狂DIY 1U硬件防火墙实录(二)
- POI 使用替换字符方式进行模板生成word
- 第2.02节 下载源码
- 数学学习--最小二乘法案例剖析
- 利用协议代理实现导航控制器UINavigationController视图之间的正向传值和反向传值...
- java导出 elsx 文件,如何获取java导出的excel文件,发送请求导出excle文件
- python列表总结
- leetcode645. 错误的集合
- Oracle优化问题
- 如何调整标题字体大小_如何将「双代号网络图」调整清晰美观
- 各种系统架构图与详细说明
- 页面字体颜色的设置及常用颜色的RGB值
- 善于计划,善于总结,善于归纳
- mac 上格式化移动硬盘出现MediaKit报告设备上的空间不足以执行请求的解决办法
- Codeforces Round #835 (Div. 4) - D. Challenging Valleys
- 浙江大学计算机科学排名,2017浙江大学专业排名结果
- linux write文件,关于linux:write文件一个字节后何时发起写磁盘IO
- 小实操(3): 利用键盘事件实现小人快跑
- 1.前端笔记之html
- 2019c/c++校招100题