STM32中使用MMA7660重力加速度传感器

来源:互联网 发布:unity3d点击播放动画 编辑:程序博客网 时间:2024/04/29 01:09


最近在项目中要用到飞思卡尔的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/* ********************************************************** * * 中断线配置,低电平触发 * ********************************************************** */#defineMMA7660_INT_GPIO_SRCGPIOB//外设组#defineMMA7660_INT_PORT_SRC    GPIO_PortSourceGPIOB//中断引脚组#defineMMA7660_INT_IRQ       EXTI1_IRQn//中断号#defineMMA7660_INT_SOURCE   GPIO_PinSource1//中断源  #defineMMA7660_INT_LINE    EXTI_Line1//中断线#defineMMA7660_INT_MODE      EXTI_Trigger_Falling//中断触发方式/* ********************************************************** * * 相关宏定义 * ********************************************************** *///==========模拟IIC==================//#define MMA_ERROR0#define MMA_OK1#define I2C_NOACK0#define I2C_ACK1#define MMA7660_SDAGPIO_Pin_10//PB10 //IIC数据线接口#define MMA7660_SCLGPIO_Pin_11//PB11 //IIC时钟线接口#define MMA7660_INTGPIO_Pin_1//PB1  //中断线接口 #defineMMA7660_INT_DGPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1)//PB1读数据#defineMMA7660_SDA_DGPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11)//PB11读数据#defineMMA7660_SDA_H   GPIO_SetBits(GPIOB, GPIO_Pin_11) // PB11 高电平#defineMMA7660_SDA_L   GPIO_ResetBits(GPIOB, GPIO_Pin_11) // PB11 低电平#defineMMA7660_SCL_H   GPIO_SetBits(GPIOB, GPIO_Pin_10) // PB10 高电平#defineMMA7660_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





0 0
原创粉丝点击