最近在项目中要用到飞思卡尔的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重力加速度传感器相关推荐

  1. 最小二乘拟合二次曲线在STM32中的实现笔记

    传感器使用前要进行标定, 标定时必定需要进行曲线拟合.若用计算机处理很简单, 但实际中用微控制器中标定时, 只能进行一般的代数运算,无矩阵运算, 处理就显得非常不方便.最小二乘法推导了二次多项式曲线拟 ...

  2. STM32读取SHT3x系列温湿度传感器,标准库和HAL库

    STM32读取SHT3x系列(SHT30.SHT31.SHT35)温湿度传感器的数据并显示在0.96寸OLED屏上. 我下面提供两份代码,一份是标准库使用硬件I2C的,另一份是HAL库使用软件模拟II ...

  3. 深入浅出地理解STM32中的中断系统——从原理到简单工程示例——保姆级教程

    深入浅出地理解STM32中的中断系统 一.什么是中断?什么是异常? 二.如何管理中断? 三.NVIC 1 NVIC 特点 2 中断优先级 (1) 优先级分组 3 中断向量表 4 中断服务函数 (1)中 ...

  4. stm32中cubmx+keil+proteus+虚拟串口+串口助手的使用

    stm32中cubmx+keil+proteus+虚拟串口+串口助手的使用 stm32cubmx keil proteus 一个简单的实例 虚拟串口+串口调试 项目设计需要,以下为微控制器模块要用到的 ...

  5. K_A12_002 基于STM32等单片机采集光敏电阻传感器参数串口与OLED0.96双显示

    K_A12_002 基于STM32等单片机采集光敏电阻传感器参数串口与OLED0.96双显示 一.资源说明 二.基本参数 参数 引脚说明 三.驱动说明 IIC地址/采集通道选择/时序 对应程序: 四. ...

  6. STM32单片机(六). 传感器的使用

    传感器是单片机外围电路中最常见的模块,在搭配了各种形式的传感器电路后,就可以采集到的更多的环境信息.在本章节中,主要介绍呼吸灯.温度传感器.RTC实时时钟以及红外遥控模块的控制使用. 1.PWM实现呼 ...

  7. STM32中的通信协议

    STM32中的通信协议 通讯协议是指在嵌入式开发中,不同的硬件系统或者操作系统之间进行数据交换的方式,是一种数据通讯的规约. 通讯协议有很多种,而我今天要说的是串口通讯协议,而且是基于STM32来说的 ...

  8. STM32中GPIO的8种工作模式

    一.推挽输出:可以输出高.低电平,连接数字器件:推挽结构一般是指两个三极管分别受两个互补信号的控制,总是在一个三极管导通的时候另一个截止.高低电平由IC的电源决定.形象点解释:推挽,就是有推有拉,任何 ...

  9. Arduino处理STM32中的多个串口通讯问题

    简 介: 对于在Arduino下开发STM32的程序,对于STM32所具有的三个硬件USART进行测测试.结果显示可以使用这些串口完成相应的数据的输入与输出.但是涉及到以下两个问题,还没有得到解决:问 ...

  10. 超声波测距测速升压可调中周倒车雷达变频器传感器1:10

    简 介: 通过对于是用于超声波测速变压器的基本分析,为后面构成150kHz 放大节能信标组的感应信号打下基础. 关键词: 中周,电压器,超声波 ▌01 中周变压器   购买到这个周中变压器主要是为了构 ...

最新文章

  1. 孤军大作战!疯狂DIY 1U硬件防火墙实录(二)
  2. POI 使用替换字符方式进行模板生成word
  3. 第2.02节 下载源码
  4. 数学学习--最小二乘法案例剖析
  5. 利用协议代理实现导航控制器UINavigationController视图之间的正向传值和反向传值...
  6. java导出 elsx 文件,如何获取java导出的excel文件,发送请求导出excle文件
  7. python列表总结
  8. leetcode645. 错误的集合
  9. Oracle优化问题
  10. 如何调整标题字体大小_如何将「双代号网络图」调整清晰美观
  11. 各种系统架构图与详细说明
  12. 页面字体颜色的设置及常用颜色的RGB值
  13. 善于计划,善于总结,善于归纳
  14. mac 上格式化移动硬盘出现MediaKit报告设备上的空间不足以执行请求的解决办法
  15. Codeforces Round #835 (Div. 4) - D. Challenging Valleys
  16. 浙江大学计算机科学排名,2017浙江大学专业排名结果
  17. linux write文件,关于linux:write文件一个字节后何时发起写磁盘IO
  18. 小实操(3): 利用键盘事件实现小人快跑
  19. 1.前端笔记之html
  20. 2019c/c++校招100题

热门文章

  1. DDoS 攻击次数和流量峰值情况
  2. WRONGTYPE Operation against a key holding the wrong kind of value
  3. 网站打不开数据库错误等常见问题解决方法
  4. EasyDSS流媒体服务器如何解决5G超高清4k视频直播卡顿的问题解决方案
  5. 标签打印软件如何设置单排标签纸尺寸
  6. 8 升满壶和两个分别是 5 升、3 升的空壶 如何得到 4 升水?
  7. iOS——结构体指针
  8. DM6437的中断和事件
  9. php实现ps修图,ps皮肤处理精修方法
  10. linux服务器单向ping不通,Linux下的单向ping通问题