msp430单片机模拟IIC总线读取MMA7660三轴加速度传感器

发布者:EnchantedDreams最新更新时间:2015-09-17 来源: eefocus关键字:msp430  单片机  模拟IIC总线  MMA7660  三轴加速度传感器 手机看文章 扫描二维码
随时随地手机看文章
搞了几天的msp430单片机,发现它的硬件IIC并不是很好用(没调出来,嘿嘿),所以就弃之不用了,改用模拟IIC总线的协议。用来读取MMA7660三轴加速度按传感器的X,Y,Z的值,并通过串口显示出来,串口也是通过定时器TimerA模拟来的,只是为了练习一下单片机的编程所以都用了模拟。测试结果如下:
[转载]msp430单片机模拟IIC总线读取MMA7660三轴加速度传感器
代码如下:
file1 : main.c
#include "msp430G2452.h"
#include "g2452uart.h"                
#include "MMA7660FC.h"
#define SDA_DirOut  P2DIR |= BIT0
#define SDA_DirIn  P2DIR &=~ BIT0
 
#define SDA_0   P2OUT &=~ BIT0
#define SDA_1   P2OUT |= BIT0
 
#define SCL_1   P2OUT |= BIT1
#define SCL_0   P2OUT &=~ BIT1
 
#define Get_Bit( x,y)  ((x&(1<
#define SDA_in    Get_Bit(P2IN,0)
 
 char X_value=0 ;
 char Y_value=0 ;
 char Z_value=0 ;
 signed char  X_value_final,Y_value_final,Z_value_final;   //三轴加速度的最终值,有正负
 
void OSC_Init()
{
WDTCTL=WDTPW+WDTHOLD;//close whatchdog
 
if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF)
 {
   while(1);                               // If calibration constants erased
                                           // do not load, trap CPU!!
 }
//1Mhz
 BCSCTL1 = CALBC1_1MHZ;                    // Set range
 DCOCTL = CALDCO_1MHZ;                     // Set DCO step + modulation */
 
 
 
}
 
 void Port_Init()
 {
P2DIR |= BIT0+BIT1;
SDA_1;
SCL_1;
 }
 void delay_us( unsigned int k )
 {
while(k--)
_nop();
 
 }
 
 void IIC_Start()
 {
SDA_1;
SCL_1;
delay_us(5);
SDA_0;                 //产生下降沿
delay_us(5);
 
SCL_0;                 //拉低时钟线,准备发送或者接收数据
 
 }
 
 void IIC_Stop()
 {
SCL_1;
SDA_0;
delay_us(5);
SDA_1;               //产生一个上升沿
delay_us(5);
 
 }
 
 void IIC_SendAck()
 {
SDA_0;
SCL_1;
delay_us(5);
SCL_0;
delay_us(5);
 
 }
 
 void IIC_SendNAck()
 {
    SDA_1;
SCL_1;
delay_us(5);
SCL_0;
delay_us(5);
 }
 
 unsigned char  IIC_RecAck()
 {
unsigned char CY ;
SDA_DirIn;                //在接收模式下,设置SDA的方向为输入
     SCL_1;                    //拉高时钟线
    delay_us(5);                 //延时
    CY = SDA_in;                   //读应答信号
    SCL_0 ;                    //拉低时钟线
    delay_us(5);                 //延时
    SDA_DirOut;                //接收结束的时候还要吧SDA的方向切换过来
    return CY;
 
 
 
 }
 
void IIC_WriteByte(unsigned int  data)
{
  unsigned char i ;
  for (i=0;i<8;i++)
  {
 
 if((data&0x80)?1:0)  //分别发送每一位二进制数据
 SDA_1;
 else
 SDA_0 ;
 
 SCL_1;
 data<<=1;           //移位传送下一位
delay_us(5);
SCL_0;               //在SCL上升沿的时候加载一位的数据
delay_us (5);
  }
  SDA_1; //8位数据位发送完释放数据总线,同时SDA拉高
 // IIC_Recevie();  //接收答信号
 
}
unsigned char  IIC_Read(void )
{
 
unsigned char i ,data=0;
SDA_DirIn;                //在接收模式下,设置SDA的方向为输入
for (i=0;i<8;i++)
{
SCL_0;
delay_us(5);
SCL_1 ;                //SCL下降沿期间有数据,当SCL为高时数据线上的数据才有效
data<<=1;
data|=SDA_in;
delay_us(3);
}
SDA_DirOut;                //接收结束的时候还要吧SDA的方向切换过来
return data;
 
}
 
void WriteToAddr(unsigned char REG_addr, unsigned char REG_data )
{
 
IIC_Start();
  IIC_WriteByte(SlaveAddress+0);           //发送从机地址+写入操作0
  IIC_RecAck();                  //应答
 
  IIC_WriteByte(REG_addr);        //写入内部寄存器地址
  IIC_WriteByte(REG_data);        //写入内部寄存器数据
  IIC_RecAck();
  IIC_Stop();
  delay_us(5);
}
 unsigned char ReadFromAddr(unsigned char REG_addr)
{
 
 unsigned char RecData ;
 IIC_Start();                  //启动IIC总线
 IIC_WriteByte(SlaveAddress+0);   //写入从机地址+写命令0
 IIC_WriteByte(REG_addr);     //写入要读的内部寄存器地址
 
 IIC_Start();
 IIC_WriteByte(SlaveAddress+1);   //写入从机地址+读命令1
 RecData=IIC_Read();
 IIC_SendNAck();
 IIC_Stop();
 return RecData;
 
}
void MMA7660_Init()
{
WriteToAddr(MMA7660_MODE,0x01);
 
}
void Read3axle(void)
{
 
X_value=ReadFromAddr(X_outAddr);
Y_value=ReadFromAddr(Y_outAddr);
Z_value=ReadFromAddr(X_outAddr);
 
//将采集到的数据转换到-32~31之间
     X_value_final=(char)(X_value<<2);
     X_value_final =(char)(X_value_final /4);
 
     Y_value_final= (char)(Y_value<<2);
     Y_value_final = (char)(Y_value_final /4);
 
     Z_value_final= (char)(Z_value<<2);
     Z_value_final = (char)(Z_value_final /4);
 
}
[page]
//-----------主函数-----------------------------------------------------------
void main(void)
{
OSC_Init();
Port_Init();
TimerA_UART_init();
MMA7660_Init();
__enable_interrupt();
 
TimerA_UART_print("All Initialization is OK!rn");
 
for (;;)
{
//__bis_SR_register(LPM0_bits);
Read3axle();
if (X_value_final>0)
P1OUT|= BIT0;
else if(X_value_final<0)
P1OUT&=~ BIT0;
else _nop();
 
//------------------------------
TimerA_UART_print("X_value---->");
output((unsigned int )X_value,4);
TimerA_UART_print("    ");
//------------------------------
    TimerA_UART_print("Y_value---->");
output((unsigned int )Y_value,4);
TimerA_UART_print("    ");
//------------------------------
TimerA_UART_print("Z_value---->");
output((unsigned int )Z_value,4);
TimerA_UART_print("rn");
//------------------------------
 
 
P1OUT ^= BIT6 ;
//delay_us(20000);
 
}
 
}
//-------------------华丽的分割线-----------------------------------------------------------------
//file2 : g2452uart.h
 
#include "msp430g2452.h"
 
//------------------------------------------------------------------------------
// Hardware-related definitions
//------------------------------------------------------------------------------
#define UART_TXD   0x02                     // TXD on P1.1 (Timer0_A.OUT0)
#define UART_RXD   0x04                     // RXD on P1.2 (Timer0_A.CCI1A)
 
//------------------------------------------------------------------------------
// Conditions for 9600 Baud SW UART, SMCLK = 1MHz
//------------------------------------------------------------------------------
#define UART_TBIT_DIV_2     (1000000 / (9600 * 2))
#define UART_TBIT           (1000000 / 9600)
 
//------------------------------------------------------------------------------
// Global variables used for full-duplex UART communication
//------------------------------------------------------------------------------
unsigned int txData;                        // UART internal variable for TX
unsigned char rxBuffer;                     // Received UART character
 
//------------------------------------------------------------------------------
 
// 串口通信的接口函数说明:
//------------------------------------------------------------------------------
void TimerA_UART_init(void);
//TimerA_UART_init()模拟串口通信初始化函数,在main()函数中调用此函数就可以使用一下两个函数了
 
void TimerA_UART_tx(unsigned char byte);
//TimerA_UART_tx( byte ) 通过串口发送一字节的数据
 
void TimerA_UART_print(char *string);
//TimerA_UART_print(*string) 通过串口发送任意字节的字符穿
 
void output(unsigned int num , int n );
//输出一个数字
 
//注:接收的一字节数据存在rxBuffer变量里。
 
void Port1_Init()
{
    P1OUT = 0x00;                           // Initialize all GPIO
    P1SEL = UART_TXD + UART_RXD;            // Timer function for TXD/RXD pins
  //  P1DIR = 0xFF & ~UART_RXD;               // Set all pins but RXD to output
    //设置TXD为输出模式,P1.1和P1.2两个调试小灯也为输出模式。RXD为输入模式。
    P1DIR |= UART_TXD+BIT0+BIT6;
    P1DIR &=~ UART_RXD;
 
    P1OUT &=~ BIT0+BIT6 ; //初始化让两个灯都灭。
 
  
}
//------------------------------------------------------------------------------
// Function configures Timer_A for full-duplex UART operation
//------------------------------------------------------------------------------
void TimerA_UART_init(void)
{
Port1_Init();                           //P1端口初始化!
    TACCTL0 = OUT;                          // Set TXD Idle as Mark = '1'
    TACCTL1 = SCS + CM1 + CAP + CCIE;       // Sync, Neg Edge, Capture, Int
    TACTL = TASSEL_2 + MC_2;                // SMCLK, start in continuous mode
}
//------------------------------------------------------------------------------
// Outputs one byte using the Timer_A UART
//------------------------------------------------------------------------------
void TimerA_UART_tx(unsigned char byte)
{
    while (TACCTL0 & CCIE);                 // Ensure last char got TX'd
    TACCR0 = TAR;                           // Current state of TA counter
    TACCR0 += UART_TBIT;                    // One bit time till first bit
    TACCTL0 = OUTMOD0 + CCIE;               // Set TXD on EQU0, Int
    txData = byte;                          // Load global variable
    txData |= 0x100;                        // Add mark stop bit to TXData
    txData <<= 1;                           // Add space start bit
}
 
//------------------------------------------------------------------------------
// Prints a string over using the Timer_A UART
//------------------------------------------------------------------------------
void TimerA_UART_print(char *string)
{
    while (*string) {
        TimerA_UART_tx(*string++);
    }
}
 
void output(unsigned int num , int n )
{
char *p,pd[4];
  p=pd;
 
    pd[0]=num/1000 +48 ;  //千位
    pd[1]=num/100 +48 ;// 百位
    pd[2]=num0/10  +48 ; //十位
    pd[3]=num   +48;//个位
 
while (n--)
TimerA_UART_tx((*p++));
 
}
//------------------------------------------------------------------------------
// Timer_A UART - Transmit Interrupt Handler
//------------------------------------------------------------------------------
#pragma vector = TIMER0_A0_VECTOR
__interrupt void Timer_A0_ISR(void)
{
    static unsigned char txBitCnt = 10;
 
    TACCR0 += UART_TBIT;                    // Add Offset to CCRx
    if (txBitCnt == 0) {                    // All bits TXed?
        TACCTL0 &= ~CCIE;                   // All bits TXed, disable interrupt
        txBitCnt = 10;                      // Re-load bit counter
    }
    else {
        if (txData & 0x01) {
          TACCTL0 &= ~OUTMOD2;              // TX Mark '1'
        }
        else {
          TACCTL0 |= OUTMOD2;               // TX Space '0'
        }
        txData >>= 1;
        txBitCnt--;
    }
}      
//------------------------------------------------------------------------------
// Timer_A UART - Receive Interrupt Handler
//------------------------------------------------------------------------------
#pragma vector = TIMER0_A1_VECTOR
__interrupt void Timer_A1_ISR(void)
{
    static unsigned char rxBitCnt = 8;
    static unsigned char rxData = 0;
 
    switch (__even_in_range(TA0IV, TA0IV_TAIFG)) { // Use calculated branching
        case TA0IV_TACCR1:                        // TACCR1 CCIFG - UART RX
            TACCR1 += UART_TBIT;                 // Add Offset to CCRx
            if (TACCTL1 & CAP) {                 // Capture mode = start bit edge
                TACCTL1 &= ~CAP;                 // Switch capture to compare mode
                TACCR1 += UART_TBIT_DIV_2;       // Point CCRx to middle of D0
            }
            else {
                rxData >>= 1;
                if (TACCTL1 & SCCI) {            // Get bit waiting in receive latch
                    rxData |= 0x80;
                }
                rxBitCnt--;
                if (rxBitCnt == 0) {             // All bits RXed?
                    rxBuffer = rxData;           // Store in global variable
                    rxBitCnt = 8;                // Re-load bit counter
                    TACCTL1 |= CAP;              // Switch compare to capture mode
                    //__bic_SR_register_on_exit(LPM0_bits);  // Clear LPM0 bits from 0(SR)
                }
            }
            break;
    }
}
//----------------------华丽的分割线2--------------------------------------------------------
//file :MMA7660FC.h
 
#ifndef _MMA7660FC_H
#define _MMA7660FC_H
 
#define MMA7660FC_ADD   0x4C    //Please contact the factory to request a different IIC address
 
#define MMA7660FC_MW_ADD 0x98       //master write address
#define MMA7660FC_MR_ADD 0x99       //master read address
 
#define SlaveAddress 0x98    //从机地址
#define X_outAddr  0x00
#define Y_outAddr   0x01
#define Z_outAddr   0x02
 
 
 
// IIC Register Address
#define MMA7660_XOUT    0x00
#define MMA7660_YOUT    0x01
#define MMA7660_ZOUT    0x02
#define MMA7660_TILT    0x03
#define MMA7660_SRST    0x04
#define MMA7660_SPCNT   0x05
#define MMA7660_INTSU   0x06
#define MMA7660_MODE    0x07
#define MMA7660_SR      0x08
#define MMA7660_PDET    0x09
#define MMA7660_PD      0x0A
 
#endif
////////////////////////////////////////////////////////////////////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\
//以上为所有程序源码!编译工具CCS V5.0

关键字:msp430  单片机  模拟IIC总线  MMA7660  三轴加速度传感器 引用地址:msp430单片机模拟IIC总线读取MMA7660三轴加速度传感器

上一篇:ZLG7290矩阵键盘控制forMSP40
下一篇:spi协议及工作原理分析

推荐阅读最新更新时间:2024-03-16 14:32

基于51单片机的直流数字电压表(0-5V)
利用串行A/D转换器TLC549对输入信号电压源进行采集转换成数字信号给 51单片机 ,经单片机进行数据处理后给1602液晶显示。 误差小于1%. #include reg52.h #include intrins.h #define uint unsigned int #define uchar unsigned char uchar LCD ; //电压数据转换成LCD1602液晶字符显示 uint Volt; sbit DO = P1^0; //时钟 sbit CS = P1^1; //片选 sbit CLK = P1^2; //数据输出 sbit RS = P2^0; //160
[单片机]
基于51<font color='red'>单片机</font>的直流数字电压表(0-5V)
MSP430 USB JTAG安装"INF找不到所需的段落" 的解方法
先前做过实验就发现自己的电脑上出现这款仿真器的INF错误,猜到可能是系统的原因,因为自己曾经将仿真器拿到同样一台非精简版的系统的电脑上就没有任何问题,今天终于找到解决方法: 1、首先按如下操作 这是你系统装的是精简版的问题 a.打开 控制面板 管理工具 服务 ,查看 smart card是否启用 ,没有的话,请手动启动。如果 smart card 服务也无法启用,可检查 scardsvr 服务是否存在,且已经启动,如果没有启动请手动启动,然后设为 自动 。 b.如果该服务不存在,则按以下步骤操作,单击 开始 运行 输入cmd 打开命令提示符窗口,先执行命令 scardsvr reinstall ,接着在执行命令 regsvr32
[单片机]
单片机中进制转换知识
1.如何把一个四字节的十六进制数转换为十进制数,十六进制数的格式低位在前,假设第一个字节位hex_buf ,hex_buf ,hex_buf ,hex_buf 。 方法: uint64 add_sum =0; sum += hex_buf ; sum += hex_buf 8; sum += hex_buf 16; sum += hex_buf 24; 即可得到四个字节十六进制数的十进制数。 2.如何把一个十进制数转换为一个十六进制数。 比如:123456789 首先确认这个数需要用几个字节的十六进制数表示,比如一个字节可以表示的最大数ff也就255,两个字节0xff
[单片机]
基于MSP430的舵机控制系统设计
0引 言 无人机是一种由动力驱动、机上无人驾驶、可重复使用的航空器的简称。在无人机系统中,采用PWM波信号控制的舵机是重要的执行机构,它是无人机控制动作的动力来源。为便于系统扩展和升级 ,在飞控系统中往往采用分布式策略,将舵机的控制部分作为一个独立单元进行设计,称为舵机控制系统。 传统产生PWM波的方法是通过大量的分立原件来实现的.所产生的脉冲频率和宽度往往不是很准确,很难做到对舵机的精确控制。另外,利用CPLD或FPGA产生PWM波已在很多场合得到应用,依靠CPLD或FPGA特有的并行处理能力和大量的1/0接口,可以同时控制几十甚至上百个舵机同时工作,但CPLD或FPGA生成PWM波时,并不具备事务处理能力,实际应用中还需要
[单片机]
基于<font color='red'>MSP430</font>的舵机控制系统设计
PIC单片机的各种汇编语言指令详解
pic单片机为最常用单片机之一,许多程序均基于pic单片机进行开发。因此,熟练pic单片机编程尤为重要。为保证大家能准确、熟练掌握pic单片机的使用,本文特带来pic单片机的各种汇编语言指令的讲解。 一、pic的指令系统 pic8位单片机共有三个级别,有相对应的指令集。基本级pic系列芯片共有指令33条,每条指令是12位字长;中级pic系列芯片共有指令35条,每条指令是14位字长;高级pic系列芯片共有指令58条,每条指令是16位字长。其指令向下兼容。 二、pic汇编语言指令格式 pic系列微控制器汇编语言指令与MCS-51系列单片机汇编语言一样,每条汇编语言指令由4个部分组成,其书写格式如下: 标号 操作码助记符 操作数
[单片机]
PIC<font color='red'>单片机</font>的各种汇编语言指令详解
认识单片机-单片机最小系统
现在很火的STC类51单片机的最小系统,其中分几部分: 1.电源部分为图右上解的电源开头,5V输入给单片机进行供,常用的单片机系统电源电压有5V,3.3V,STC单片机也是有这两种不同电压的片子的,大家在做设计时需先确认系统电压后来进行选择。 2.晶振部分,在图的左下角连接到单片机中的X1,晶振是什么作用哪?对单片机来讲,他就是心脏,没了晶振就单片机就没了心跳,就不可能正常运行了,晶振是提供单片机进行正常运行的脉搏,他跳一下或几下,单片机走一条指令,这里就有了指令周期与时钟周期的概念,原AT的单片机是12个时间一个指令周期,STC比AT的会快很多,具体多少记不太清了,大家自己看一下数据手册吧。 3.复位电路部分,C
[单片机]
认识<font color='red'>单片机</font>-<font color='red'>单片机</font>最小系统
基于AVR单片机的医用臭氧治疗仪的设计与实现
  概述   臭氧作为一种高效冷杀菌手段,目前已经被广泛应用在各行各业中。具有高效、迅速杀菌作用的臭氧在医院环境消毒、术前消毒等方面应用广泛,其治疗效果优于其它传统杀菌治疗仪。因此研制一种运行稳定、使用方便、便携的臭氧治疗仪产品,为妇科疾病患者提供一种方便有效的在家治疗方式,具有实际意义。   目前市面上的同类型产品都是采用80C51单片机为控制核心的, 虽然也能实现它所需求的功能,但执行速度慢,在长期工作环境中,特别在臭氧治疗仪的内部大功率气泵模块和臭氧发生器的干扰下,系统功耗高和抗干扰性能差,系统性能不稳定等问题便凸现出来。对此本文采用了ATMEL公司的一款AVR高档单片机,对控制系统作了改进,提高了整机的性能。   臭
[单片机]
基于AVR<font color='red'>单片机</font>的医用臭氧治疗仪的设计与实现
基于80C51单片机和AD526运放实现防腐电源监控节点的设计
金属发生腐蚀的现象随处可见。腐蚀给金属材料造成的直接和间接损失是巨大的,以至造成灾难性的破坏事故,引起严重的环境污染。研究表明,因腐蚀造成的损失一般占国民生产总值的3%~4%,其中约有15%是可以通过现有的防腐技术避免的,而阴极保护技术的发展又是与防腐技术的进步分不开的。 防腐电源是阴极保护技术中最为关键的设备。由于易腐蚀的金属构件大部分分布在野外或者地下,并且分布范围广,如石油管道、输电线路、海上平台等,所以必然要求发展可靠性高、智能化的新型防腐电源,并且要求通过工业网远程采集现场数据,进行计算分析,实现远程控制,从而提高现场设备的可靠性,实现无人管理。 1、防腐电源系统的结构组成 阴极保护技术简单地说就是测量被保护金属
[单片机]
基于80C51<font color='red'>单片机</font>和AD526运放实现防腐电源监控节点的设计
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved