|
![](static/image/common/ico_lz.png)
楼主 |
发表于 2008-12-1 12:01:45
|
显示全部楼层
【2楼】 lnc361 :
SMB380 读写子程序
我将你给的改了一下,用于在ICCAVR 6。31A中编译。
加入了用串口发送到串口调试软件。
读出的几个寄存器全是0,是不是传感器SMB380 没响应,还是我的程序改的有问题?请帮忙看一下。谢谢!
/*******************************
*程序名称:功能函数集
*设 计:
*功能:IO口模拟I2C总线
*数据线:IO----PC1 时钟线:SCK----PC0
*单片机:ATmega16
*编译:ICC AVR 6.31A
*晶 振:8.000000Mhz
*日 期:2008-12-01
****************************/
#include <iom16v.h>
#include <macros.h>
/*双向数据*/
#define IO_CLR PORTC &= ~(1 << PC1) /*电平置低*/
#define IO_SET PORTC |= (1 << PC1) /*电平置高*/
#define IO_R PINC & (1 << PC1) /*电平读取*/
#define IO_IN DDRC &= ~(1 << PC1) /*方向输入*/
#define IO_OUT DDRC |= (1 << PC1) /*方向输出*/
/*时钟信号*/
#define SCK_CLR PORTC &= ~(1 << PC0) /*时钟信号*/
#define SCK_SET PORTC |= (1 << PC0) /*电平置高*/
#define SCK_IN DDRC &= ~(1 << PC0) /*方向输入*/
#define SCK_OUT DDRC |= (1 << PC0) /*方向输出*/
#define uchar unsigned char
#define uint unsigned int
#define mclk 8000000
uint Axis[6];
//uint ReadData; 加入 6个数据的数组
//sbit IO_R = P1^3;
//sbit I2C_SCL = P1^4;
#define SMB380_ADDR_WRITE 0x70
#define SMB380_ADDR_READ 0x71
//Registers address
#define OPER_REG 0x15 //Wake_up(bit 0),Wake_up_pause(bit1,bit2),Shadow_dis(bit3),
//latch_int(bit4),new_data_int(bit5),enable_adv_int(bit6)
#define OPER_SET 0x14 //rang(bit4'3),bandwith(bit2'1'0)
#define DUR_HYST 0x11 //any_motion_dur(bit6'7),hg_hyst(bit5'4'3),lg_hyst(bit5'4'3)
#define ANY_MOTION_TRES 0x10
#define HG_DUR 0x0F
#define HG_THRES 0x0E
#define LG_DUR 0x0D
#define LG_THRES 0X0C
#define INTERRUPT_SET 0x0B //enable_lg(bit0),enble_hg(bit1),counter_lg(bit2'3),
//counter_hg(bit4'5),any_motion(bit6),alert(bit7)
#define CONTROL_REG 0x0A //sleep(bit0),soft_reset(bit1),self_test0(bit2),self_test1(bit3),
//ee_w(bit4),updata_image(bit5),reset_int(bit6),
#define STATUS_REG 0x09 //status_hg(bit0),status_lg(bit1),hg_latch(bit2),lg_latch(bit3),
//alert(bit4),st_result(bit7)
#define ACC_Z_MSB 0x07
#define ACC_Z_LSB 0x06 //ACC_Z_BIT0'1(bit6'7),new_data_z(bit0)
#define ACC_Y_MSB 0x05
#define ACC_Y_LSB 0x04 //ACC_Y_BIT0'1(bit6'7),new_data_y(bit0)
#define ACC_X_MSB 0x03
#define ACC_X_LSB 0x02 //ACC_X_BIT0'1(bit6'7),new_data_x(bit0)
//延时n个ms子程序
void delay_ms(uint ms)
{
uint i,j;
for(i=0;i<ms;i++)
{
for(j=0;j<1141;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);
}
/******************************************************************************
函数:I2C_Delay( void )
功能:模拟I2C总线延时
说明:请根据具体情况调整延时值
******************************************************************************/
void I2C_Delay( void )
{
NOP();NOP();NOP();NOP();
NOP();NOP();NOP();NOP();
NOP();NOP();NOP();NOP();
NOP();NOP();NOP();NOP();
}
/******************************************************************************
函数:I2C_Start()
功能:产生I2C总线的起始条件
说明:SCL处于高电平期间,当SDA出现下降沿时启动I2C总线
本函数也用来产生重复起始条件
******************************************************************************/
void I2C_Start()
{
IO_SET; NOP();
SCK_SET; I2C_Delay();
IO_CLR; I2C_Delay();
SCK_CLR; NOP();NOP();
}
/******************************************************************************
函数:I2C_Write()
功能:向I2C总线写1个字节的数据
参数:dat是要写到总线上的数据
******************************************************************************/
void I2C_Write( uchar dat )
{
uchar t = 8;
for( ; t>0; t-- )
{
if( dat & 0x80 )
IO_SET;
else
IO_CLR;
NOP();
dat <<= 1;
SCK_SET;
I2C_Delay();
I2C_Delay();
SCK_CLR;
I2C_Delay();
}
}
/******************************************************************************
函数:I2C_Read()
功能:从从机读取1个字节的数据
返回:读取的1个字节数据
******************************************************************************/
uchar I2C_Read( )
{
uint dat=0;
uchar t = 8;
//P1M |= 0x08; //加入 bit3 置1
PORTC |= 0x01; //加入 SDA PC0 置1
IO_SET; //在读取数据之前,要把SDA拉高,使之处于输入状态
for( ; t>0; t-- )
{
SCK_SET;
I2C_Delay();
dat <<= 1;
if ( IO_R )
dat++;
SCK_CLR;
I2C_Delay();
}
IO_CLR;
//P1M &= 0xF7; //加入 bit3 清0
PORTC &= 0x01; //加入 SDA PC0 清0
return dat;
}
/******************************************************************************
函数:I2C_GetAck()
功能:读取从机应答位(应答或非应答),用于判断:从机是否成功接收主机数据
返回:0-从机应答
1-从机非应答
说明:从机在收到每一个字节后都要产生应答位,主机如果收到非应答则应当终止传输
******************************************************************************/
uchar I2C_GetAck( void )
{
uchar Ack;
//P1M |= 0x08;
PORTC |= 0x01; //加入 SDA PC0 置1
IO_SET;
I2C_Delay();
SCK_SET;
Ack = IO_R;
I2C_Delay();
IO_CLR;
//P1M &= 0xF7;
PORTC &= 0x01; //加入 SDA PC0 清0
SCK_CLR;
I2C_Delay();
return Ack;
}
/****************************************************************************
函数:I2C_PutAck()
功能:主机产生应答位(应答或非应答),用于通知从机:主机是否成功接收从机数据
参数:Ack = 0:主机应答
Ack = 1:主机非应答
说明:主机在收到每一个字节后都要产生应答,在收到最后一个字节时,应当产生非应答
******************************************************************************/
void I2C_PutAck( uchar Ack )
{
//I2C_SDA = Ack;
if(Ack) //加入
IO_SET; //Ack = 1:主机非应答
else
IO_CLR; //Ack = 0:主机应答
I2C_Delay();
SCK_SET;
I2C_Delay();
SCK_CLR;
I2C_Delay();
IO_CLR;
}
/******************************************************************************
函数:I2C_Stop()
功能:产生I2C总线的停止条件
说明:SCL处于高电平期间,当SDA出现上升沿时停止I2C总线
******************************************************************************/
void I2C_Stop()
{
IO_CLR; NOP();NOP();
SCK_SET; I2C_Delay();
IO_SET; I2C_Delay();
}
/******************************************************************************
函数:void I2C_Send()
功能:启动I2C总线发数据
返回:0-正常,1-异常(无应答)
******************************************************************************/
//从机地址, 子地址, 写数据缓冲区
uchar I2C_Send( uchar SLA, uchar Addr, uchar WriteBuf )
{
I2C_Start( );
if ( !(SLA&0x01) )
{
I2C_Write( SLA );
if ( I2C_GetAck() )
{
I2C_Stop();
return 1;
}
I2C_Write( Addr );
if ( I2C_GetAck() )
{
I2C_Stop();
return 1;
}
I2C_Write( WriteBuf );//发送数据
if ( I2C_GetAck() )
{
I2C_Stop();
return 1;
}
I2C_Stop( );
return 0;
}
I2C_Stop( );
return 1;
}
/******************************************************************************
函数:void I2C_Rev()
功能:启动I2C总线收数据
返回:0-正常,1-异常(无应答)
******************************************************************************/
//从机地址, 子地址, 读数据缓冲区, 读数据长度
uchar I2C_Rev( uchar SLA, uchar Addr, uint *ReadBuf, uchar Size )
{
I2C_Start( );
I2C_Write( SLA&0xFE );
if ( I2C_GetAck() )
{
I2C_Stop();
return 1;
}
I2C_Write( Addr );
if ( I2C_GetAck() )
return 1;
I2C_Stop();
I2C_Start( );
I2C_Write( SLA );
if ( I2C_GetAck() )
{
I2C_Stop();
return 1;
}
for( ; ; )
{
*ReadBuf++ = I2C_Read( );
if ( (--Size) == 0 )
{
I2C_PutAck(1); //接收完最后一个数据时发送NAK
break;
}
I2C_PutAck(0);
}
I2C_Stop();
return 0;
}
void main( )
{
uchar i;
uart_init(19200); //串口初始化
I2C_Send( SMB380_ADDR_WRITE, 0x15, 0x22 ); //加入new_data_INT bit5 置1
//Wake_up_pause bit2,1 0x01 每80ms自动唤醒
//从机地址, 子地址, 读数据缓冲区, 读数据长度
I2C_Rev( SMB380_ADDR_READ, 0x14, Axis, 0x0A );
I2C_Send( SMB380_ADDR_WRITE, 0x14, ((Axis[0]&0xE0)|0x02) ); //先读取0x14寄存器的值,
//再写入使保留位不变的设定值。
I2C_Send( SMB380_ADDR_WRITE, 0x0B, 0x00 ); //加入 关闭其它所有中断
I2C_Rev( SMB380_ADDR_READ, 0x0A, Axis, 0x01 );
I2C_Send( SMB380_ADDR_WRITE, 0x0A, ((Axis[0]&0x80)|0x20) );
//加入你要的其它程序
delay_ms(40);
while(1)
{
I2C_Rev( SMB380_ADDR_READ, 0x00, Axis, 0x06 ); //指定地址读一个字节数据
for(i=0;i<6;i++)
{
uart_sendB(Axis);
}
}
} |
|