微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > AVR单片机对倾斜角传感器MMA8451操作实列之串口通信

AVR单片机对倾斜角传感器MMA8451操作实列之串口通信

时间:10-02 整理:3721RD 点击:
#include <iom16v.h>
#include <macros.h>
#define uchar unsigned char
#define uint unsigned int
#define ulint unsigned long int
//*********************************************************************************
//TWI状态定义
//MT 主方式传输  MR 主方式接收
#define START 0x08
#define RE_START 0x10
#define MT_SLA_ACK 0x18
#define MT_SLA_NOACK 0x20
#define MT_DATA_ACK  0x28
#define MT_DATA_NOACK 0x30
#define MR_SLA_ACK  0x40
#define MR_SLA_NOACK 0x48
#define MR_DATA_ACK 0x50
#define MR_DATA_NOACK 0x58
void delay_nus(unsigned int n);       //N us延时函数   
void delay_nms(unsigned int n);       //N ms延时函数
void conversion(uint temp_data);
uchar Single_Write_MMA8452(uchar REG_Address,uchar REG_data);   //单个写入数据
uchar Single_Read_MMA8452(uchar REG_Address);                   //单个读取内部寄存器数据
void Multiple_Read_MMA8452(uchar REG_Address);                //连续的读取内部寄存器数据
#define        wr_SlaveAddress   0x38        //定义器件在IIC总线中的从地址,根据SA0地址引脚不同修改
#define        rd_SlaveAddress   0x39        //定义器件在IIC总线中的从地址,根据SA0地址引脚不同修改
/*串口异步模式中断接收*/
#pragma interrupt_handler uart_rx:12
uchar BUF[8];                        //接收数据缓存区     
uchar ge,shi,bai,qian,wan;           //显示变量
int  dis_data;                       //变量
int x,y,z;
uchar  RX_DATA;
#define  mclk   8000000
uchar rdata,flag=0;
void uart_init(uint baud);                  //串口异步模式初始化
void uart_sendB(uchar data);                //串口异步发送
void uart_rx(void);                             //串口异步接收

//常用TWI操作(主模式写和主模式读)
/**************************************
起始信号,启动IIC
**************************************/
#define Start()              (TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN))//
/**************************************
停止信号,停止IIC
**************************************/
#define Stop()               (TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN))
/**************************************
等待中断发生
**************************************/
#define Wait()                     {while(!(TWCR&(1<<TWINT)));}
/**************************************
检验TWI状态寄存器,测试返回状态例:if(TestACK()!=MT_DATA_ACK)或if(TestACK()!=MT_SLA_ACK)
**************************************/
#define TestAck()           (TWSR&0xf8)
/**************************************
产生ACK,设置应答
**************************************/
#define SetAck()          (TWCR|=(1<<TWEA))
/**************************************
设置NOTACK
**************************************/
#define SetNoAck()    (TWCR&=~(1<<TWEA))
/**************************************
启动主I2C读方式
**************************************/
#define Twi()                    (TWCR=(1<<TWINT)|(1<<TWEN))
/**************************************
装入数据到TWDR寄存器,TWINT清零,启动发送数据;向TWDR写数据
**************************************/
#define Write8Bit(x)  {TWDR=(x);TWCR=(1<<TWINT)|(1<<TWEN);}  

//初始化MMA8452,根据需要请参考pdf进行修改************************
void Init_MMA8452(void)
{
   Single_Write_MMA8452(0x2A,0x01);   //切换到主动模式
   Single_Write_MMA8452(0x0E,0x12);   //切换到主动模式
   //Single_Write_MMA8452(0x2B,0x02);   //
}
//***********************************************************************

//初始化主机TWI,根据需要请参考pdf进行修改************************
void twi_init(void)
{
    TWBR=0X20;
        TWSR=0;
        TWCR=0X44;
}
//***********************************************************************
//******AVR MMA8452单字节写入*******************************************
uchar Single_Write_MMA8452(uchar REG_Address,uchar REG_data)
{
    uchar i;
    Start();                   //起始信号
    Wait();
    if(TestAck()!=START) return 1;//ACK
    Write8Bit(wr_SlaveAddress);  //发送设备地址+写信号
    Wait();
    if(TestAck()!=MT_SLA_ACK) return 1;//ACK
    Write8Bit(REG_Address);  //内部寄存器地址
    Wait();
        if(TestAck()!=MT_DATA_ACK) return 1;//ACK
    Write8Bit(REG_data);    //内部寄存器数据
    Wait();
    if(TestAck()!=MT_DATA_ACK) return 1;//ACK
        Stop();                //发送停止信号
    for(i=0;i<250;i++);
          return 0;
}
//***********************************************************************
//********AVR MMA8452单字节读取*****************************************

uchar Single_Read_MMA8452(uchar REG_Address)
{  
    uchar REG_data;
    Start();                                    //起始信号
    Wait();
    if (TestAck()!=START) return 0;             //ACK
    Write8Bit(wr_SlaveAddress);                     //发送设备地址+写信号
    Wait();  
    if (TestAck()!=MT_SLA_ACK) return 0;        //ACK /
    Write8Bit(REG_Address);                     //发送存储单元地址,从0开始       
    Wait();
    if (TestAck()!=MT_DATA_ACK) return 0;      //?
                                              //data1=TestAck();
    Start();                                  //起始信号
    Wait();
    if (TestAck()!=RE_START)  return 0;
    Write8Bit(rd_SlaveAddress);                //发送设备地址+读信号,每次地址加1
    Wait();
    if(TestAck()!=MR_SLA_ACK)  return 0;     //ACK
    Twi();//启动主机读方式
    Wait();
    if(TestAck()!=MR_DATA_NOACK) return 0;   //ACK   
    REG_data=TWDR;                           //读取MMA8451接收数据
    //SetAck()                                 //回应ACK
    Stop();                                 //停止信号
    //return 1;
        return REG_data;
}

//*********************************************************
//连续读出AVR MMA8452内部加速度数据,地址范围0x01~0x06
//
//*********************************************************
void Multiple_Read_MMA8452(uchar REG_Address)
{   
        uchar i;
        Start();                                     //起始信号
    Wait();
    if (TestAck()!=START) ;             //ACK
    Write8Bit(wr_SlaveAddress);                    //发送设备地址+写信号
    Wait();  
    if (TestAck()!=MT_SLA_ACK) ;
    Write8Bit(REG_Address);                    //发送存储单元地址,从0x01开始       
    Wait();
    if (TestAck()!=MT_DATA_ACK) ; //?
        Start();                                  //起始信号
    Wait();
    if (TestAck()!=RE_START)  ;
    Write8Bit(rd_SlaveAddress);               //发送设备地址+读信号 每次地址加1
    Wait();
    if(TestAck()!=MR_SLA_ACK)  ;     //ACK
    Twi();                                   //启动主机读方式
    Wait();
    if(TestAck()!=MR_DATA_NOACK) ;   //ACK   
    for (i=0; i<6; i++)                      //连续读取6个地址数据,存储中BUF
    {
        BUF[i] = TWDR;                       //BUF[0]存储0x32地址中的数据
        if (i == 5)
        {
         SetNoAck();                        //最后一个数据需要回NOACK
        }
        else
        {
          SetAck();                         //回应ACK
       }
   }
    //Stop();                                 //停止信号
           delay_nms(50);
       
}

//*****************************************************************
//*********************************************************
void conversion(uint temp_data)  
{  
    wan=temp_data/10000+0x30 ;
    temp_data=temp_data%10000;   //取余运算
        qian=temp_data/1000+0x30 ;
    temp_data=temp_data%1000;    //取余运算
    bai=temp_data/100+0x30   ;
    temp_data=temp_data%100;     //取余运算
    shi=temp_data/10+0x30    ;
    temp_data=temp_data%10;      //取余运算
    ge=temp_data+0x30;        
}
/*******************************/
//**********************************************************************
//显示x轴
void display_x(void)
{   float temp;
    uart_sendB('X');
    dis_data=(BUF[0]<<8)|BUF[1];  //合成数据   
        dis_data>>=4;
        x=dis_data;
        if(dis_data<0){
               dis_data=-dis_data;
             uart_sendB('-');
        }
        else uart_sendB('+');
    temp=(float)dis_data;      //计算数据和显示
    conversion(temp);          //转换出显示需要的数据
    uart_sendB(':');
    uart_sendB(qian);
    uart_sendB('.');
    uart_sendB(bai);
    uart_sendB(shi);
}
//***********************************************************************
//显示y轴
void display_y(void)
{   float temp;
    uart_sendB('Y');
    dis_data=(BUF[2]<<8)|BUF[3];  //合成数据   
        dis_data>>=4;
        y=dis_data;
        if(dis_data<0){
        dis_data=-dis_data;
    uart_sendB('-');
        }
        else uart_sendB('+');
    temp=(float)dis_data;      //计算数据和显示
    conversion(temp);          //转换出显示需要的数据
        uart_sendB(':');
        uart_sendB(qian);
        uart_sendB('.');
        uart_sendB(bai);
        uart_sendB(shi);
}
//***********************************************************************
//显示z轴
void display_z(void)
{   float temp;
    uart_sendB('Z');
    dis_data=(BUF[4]<<8)|BUF[5];    //合成数据  
    dis_data>>=4;
        z=dis_data;
        if(dis_data<0){
        dis_data=-dis_data;
    uart_sendB('-');
        }
        else uart_sendB('+');
    temp=(float)dis_data;      //计算数据和显示
    conversion(temp);          //转换出显示需要的数据
        uart_sendB(':');
        uart_sendB(qian);
        uart_sendB('.');
        uart_sendB(bai);
        uart_sendB(shi);
}
//*********************************************************
//******主程序********
//*********************************************************
void main(void)
{
    delay_nms(2);                    //上电延时       
    twi_init();                      //初始化主机
    Init_MMA8452();                 //初始化MMA8452
    RX_DATA=0;
    uart_init(9600);                //初始化串口速率
    Single_Read_MMA8452(0X1A);       //工厂程序。查阅加了没有显示
        while(1)                        //循环
{
    Init_MMA8452();                //初始化MMA8452
    Multiple_Read_MMA8452(0x01);       //连续读出数据,存储在BUF中
    uart_sendB(0x0d);
    uart_sendB(0x0a);
         
    display_x();                   //---------显示X轴
    display_y();                   //---------显示Y轴
    display_z();                   //---------显示Z轴
    RX_DATA=0;
    delay_nms(500);                                //延时50ms      
          
   }
}

/*-----------------------------------------------------------------------
延时函数
编译器:ICC-AVR v6.31A
日期: 2014-3-6
目标芯片 : M16
时钟:8.000000Mhz
-----------------------------------------------------------------------*/
void delay_nus(unsigned int n)       //N us延时函数
{
   unsigned int i=0;
   for (i=0;i<n;i++)
   asm("nop");
}
void delay_nms(unsigned int n)       //N ms延时函数
{
   unsigned int i=0,j=0;
   for (i=0;i<n;i++)
   for (j=0;j<1140;j++);
}

//*********************************************************
//******串口异步模式初始化********
//*********************************************************
void uart_init(uint baud)                  //串口异步模式初始化
{
   UCSRB=0x00;
   UCSRA=0x00;                                        //控制寄存器清零
   UCSRC=(1<<URSEL)|(0<<UPM0)|(3<<UCSZ0);   
                                           //选择UCSRC,异步模式,禁止                        
                                           //   校验,1位停止位,8位数据位
   baud=mclk/16/baud-1        ;                  //波特率最大为65K
   UBRRL=baud;                                                        
   UBRRH=baud>>8;                                    //设置波特率
   UCSRB=(1<<TXEN)|(1<<RXEN)|(1<<RXCIE);
                                           //接收、发送使能,接收中断使能
   SREG=BIT(7);                                   //全局中断开放
   DDRD|=0X02;                                   //配置TX为输出(很重要)
}
//*********************************************************

//*********************************************************
//******串口异步发送********
//*********************************************************
void uart_sendB(uchar data)
{
   while(!(UCSRA&(BIT(UDRE)))) ;
   UDR=data;
   while(!(UCSRA&(BIT(TXC))));
   UCSRA|=BIT(TXC);
}
//*********************************************************
//******串口异步接收********
//*********************************************************
void uart_rx(void)
{
    UCSRB&=~BIT(RXCIE);
        rdata=UDR;
        flag=1;
        UCSRB|=BIT(RXCIE);
}
//*********************************************************

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top