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);
}
//*********************************************************
#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);
}
//*********************************************************