请大家帮帮我,调试了几天,通过串口打印读出来的ADXL345三轴的加速度只是-1,拜托大牛们帮帮我
IIC程序如下:
#include "iic.h"
/*
函数名称 : IIC_Config
功 能 : 基本配置
参 数 : 无
返 回 值 : 无
作 者 :
库 版 本 : V2.3.0
文件版本 : V1.0
日 期 :
*/
void IIC_Config(void)
{
I2C->CR1 &=~(1<<0);//禁用I2C模块
CLK->PCKENR1 &=~(0X1<<0);
CLK->PCKENR1 |=(0X1<<0);//使能IIC外设时钟
SCL_OUT();
SDA_OUT();
IIC_SCL(1);
IIC_SDA(1);
/*
I2C->FREQR &=~(1<<5); //输入时钟频率16M
I2C->FREQR |= (1<<5);
I2C->TRISER &=~(0X1F<<0); //0x10 + 1
I2C->TRISER |= (0X11<<0);
I2C->CCRL &=~( 0xFF<<0); //16M / 100K / 2
I2C->CCRL |=(0X50<<0);
I2C->CCRH = 0x00;
I2C->CR1 &=~(0X01<<0); //开启I2C外设
I2C->CR1 |=(0X01<<0);
I2C->CR2 &=~(0X4<<0); //应答使能
I2C->CR2 |=(0X4<<0);
I2C->OARL = 0x50; //自身地址
I2C->OARH = 0x00;
SCL_H();//ODR4置位--发送1
SDA_H();//ODR5置位--发送1
*/
}
/****************************
*函数名:IIC_start
*函数功能:模拟 iic 启动信号
*函数参数:无
*函数返回值:无
*作者:
*时间:
*版本:v1.0
*****************************/
//产生IIC起始信号
void IIC_Start(void)
{
SDA_OUT(); //sda线输出
IIC_SDA(1);
IIC_SCL(1);
Delay_nus(4);
IIC_SDA(0);//START:when CLK is high,DATA change form high to low
Delay_nus(4);
IIC_SCL(0);//钳住I2C总线,准备发送或接收数据
}
/****************************
*函数名:IIC_stop
*函数功能:模拟 iic 停止信号
*函数参数:无
*函数返回值:无
*版本:v1.0
*****************************/
//产生IIC停止信号
void IIC_Stop(void)
{
SDA_OUT();//sda线输出
IIC_SDA(0);
IIC_SCL(1);//STOP:when CLK is high DATA change form low to high
Delay_nus(4);
//IIC_SCL(1);
IIC_SDA(1);//发送I2C总线结束信号
Delay_nus(4);
}
/**********************************
*函数名:IIC_waitAck
*函数功能:IIC master 等待应答信号
*函数参数:无
*函数返回值:无
*作者:
*版本:v1.0
**********************************/
//等待应答信号到来
//返回值:1,接收应答失败
// 0,接收应答成功
u8 IIC_WaitAck(void)
{
u8 ucErrTime=0;
SDA_IN(); //SDA设置为输入
IIC_SDA(1);Delay_nus(1);
IIC_SCL(1);Delay_nus(1);
while(READ_SDA())
{
ucErrTime++;
if(ucErrTime>250)
{
IIC_Stop();
return 1;
}
}
IIC_SCL(0);//时钟输出0
return 0;
}
/****************************
*函数名:IIC_ack
*函数功能:给应答信号
*函数参数:无
*函数返回值:无
*作者:
*版本:v1.0
*****************************/
//产生ACK应答
void IIC_Ack(void)
{
IIC_SCL(0);
SDA_OUT();
IIC_SDA(1);
Delay_nus(2);
IIC_SDA(0);//拉低应答
Delay_nus(3);
IIC_SCL(1);
Delay_nus(4);
IIC_SCL(0);
Delay_nus(2);
IIC_SDA(1);
}
/****************************
*函数名:IIC_nAck
*函数功能:不给应答信号
*函数参数:无
*函数返回值:无
*作者:
*时间:
*版本:v1.0
*****************************/
//不产生ACK应答
void IIC_NAck(void)
{
IIC_SCL(0);
SDA_OUT();
IIC_SDA(1);
Delay_nus(2);
IIC_SDA(1);
Delay_nus(3);
IIC_SCL(1);
Delay_nus(4);
IIC_SCL(0);
Delay_nus(2);
IIC_SDA(1);
}
/****************************
*函数名:IIC_sendByte
*函数功能:发送一个字节
*函数参数:txd
*函数返回值:无
*作者:
*版本:v1.0
*****************************/
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答
void IIC_SendByte(u8 txd)
{
u8 t;
SDA_OUT();
IIC_SCL(0);//拉低时钟开始数据传输
for(t=0;t<8;t++)
{
IIC_SDA((txd&0x80)>>7);//从高位到地位发
txd<<=1;
Delay_nus(2); //对TEA5767这三个延时都是必须的
IIC_SCL(1);
Delay_nus(2);
IIC_SCL(0);
Delay_nus(2);
}
}
/*
*函数名:IIC_readByte
*函数功能:读取一个字节
*函数参数:ack=0 时,发送 ACK,ack=1,发送 nACK
*函数返回值:返回读取到的数据
*作者:
*版本:v1.0
*/
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK
u8 IIC_ReadByte(unsigned char ack)
{
u8 i,receive=0;
SDA_IN();//SDA设置为输入
for(i=0;i<8;i++)
{
IIC_SCL(0);
Delay_nus(2);
IIC_SCL(1);
receive<<=1;
if(READ_SDA())receive++;
Delay_nus(1);
}
if (!ack)
IIC_NAck();//发送nACK
else
IIC_Ack(); //发送ACK
return receive;
}
#ifndef _IIC_H_
#define _IIC_H_
#include "stm8s.h"
#include "delay.h"
#include "stdio.h"
#include "string.h"
//IO 方向
#define SCL_OUT(){GPIOB->DDR |=(1<<4);GPIOB->CR1 |=(1<<4);GPIOB->CR2 &=~(1<<4);}
#define SDA_IN() {GPIOB->DDR &=~(1<<5);GPIOB->CR1 &=~(1<<5);GPIOB->CR1 |=(1<<5);GPIOB->CR2 &=~(1<<5);}
#define SDA_OUT() {GPIOB->DDR &=~(1<<5);GPIOB->DDR |=(1<<5);GPIOB->CR1 &=~(1<<5);GPIOB->CR1 |=(1<<5);GPIOB->CR2 &=~(1<<5);}
#define IIC_SCL(x) x?(GPIOB->ODR &= ~(1<<4)):(GPIOB->ODR |= (1<<4))
#define IIC_SDA(x) x?(GPIOB->ODR &= ~(1<<5)):(GPIOB->ODR |= (1<<5))
#define READ_SDA() (GPIOB->IDR & (1<<5))
//IIC所有操作函数
void IIC_Config(void); //初始化IIC的IO口
void IIC_Start(void); //发送IIC开始信号
void IIC_Stop(void); //发送IIC停止信号
void IIC_SendByte(u8 txd); //IIC发送一个字节
u8 IIC_ReadByte(unsigned char ack);//IIC读取一个字节
u8 IIC_WaitAck(void); //IIC等待ACK信号
void IIC_Ack(void);//IIC发送ACK信号
void IIC_NAck(void);//IIC不发送ACK信号
#endif
串口程序如下:
#include "uart.h"
void UART1_Config(void) //串口1初始化配置
{
//PD5--UATI1_TX--推挽输出,PD6--UART1_RX--浮空输入
//输出模式,推挽输出TXD
GPIOD->DDR &= ~(1<<5);
GPIOD->CR1 |= (1<<5);
//输入模式,浮空输入 RX
GPIOD->DDR &= ~(1<<6);
GPIOD->CR1 &= ~(1<<6);
u16 Uart1_DIV;
Uart1_DIV = 16000000/115200; //串口分频值
UART1->BRR2 = (u8)((Uart1_DIV & 0xf000) >> 8)|(u8)((Uart1_DIV & 0x000f));
UART1->BRR1 = (u8)((Uart1_DIV & 0x0ff0) >> 4);
UART1->CR1 = 0; //使能串口1,禁用奇偶校验
UART1->CR2 &=~(0X7F<<2); //接收终端使能,接受使能,发送使能
UART1->CR2 |= (0XB<<2);
UART1->CR3 &=~(0X3<<4);//一个停止位
}
/*
函数名称 : UART1_SendByte
功 能 : UART1发送一个字符
参 数 : Data --- 数据
返 回 值 : 无
作 者 :
时 间 :2018年10月27日10:18:35
*/
void UART1_SendByte(uint8_t Data)
{
while((UART1_GetFlagStatus(UART1_FLAG_TXE)==RESET));
UART1_SendData8(Data);
while((UART1_GetFlagStatus(UART1_FLAG_TC)==RESET));
}
/*
函数名称 : UART1_SendNByte
功 能 : 串口1发送N个字符
参 数 : pData ---- 字符串
Length --- 长度
返 回 值 : 无
作 者 :
时 间 :2018年10月27日10:18:35
*/
void UART1_SendNByte(uint8_t *pData, uint16_t Length)
{
while(Length--)
{
UART1_SendByte(*pData);
pData++;
}
}
/*
函数名:fputc
描述 :重定向c库函数printf到USART1
输入 :无
输出 :无
调用 :由printf调用
*/
int fputc(int ch, FILE *f)
{
/*将Printf内容发往串口*/
UART1->DR=(unsigned char)ch;
while (!(UART1->SR & UART1_FLAG_TXE));
return (ch);
}
/*
函数名称 : UART1_Printf
功 能 : 串口1打印输出
参 数 : String --- 字符串
返 回 值 : 无
作 者 :
时 间 :2018年10月27日10:18:35
*/
void UART1_Printf(float *String)
{
while((*String) != '\0')
{
UART1_SendByte((int)*String);
String++;
}
}
#ifndef _UART_H_
#define _UART_H_
#include "stm8s.h"
#include "stdio.h"
#include "string.h"
void UART1_Config(void);
void UART1_SendByte(uint8_t Data);
void UART1_SendNByte(uint8_t *pData, uint16_t Length);
//int fputc(int ch, FILE *f);
void UART1_Printf(float *String);
#endif
ADXL345与main函数程序如下:
#include "adxl345.h"
//初始化ADXL345.
//返回值:0,初始化成功;1,初始化失败.
u8 ADXL345_Config(void)
{
IIC_Config();//初始化IIC总线
if(ADXL345_RD_Reg(DEVICE_ID)==0XE5) //读取器件ID
{
ADXL345_WR_Reg(DATA_FORMAT,0X2B); //低电平中断输出,13位全分辨率,输出数据右对齐,16g量程
ADXL345_WR_Reg(BW_RATE,0x0A); //数据输出速度为100Hz
ADXL345_WR_Reg(POWER_CTL,0x28); //链接使能,测量模式
ADXL345_WR_Reg(INT_ENABLE,0x00); //不使用中断
ADXL345_WR_Reg(OFSX,0x00);
ADXL345_WR_Reg(OFSY,0x00);
ADXL345_WR_Reg(OFSZ,0x00);
return 0;
}
return 1;
}
//写ADXL345寄存器
//addr:寄存器地址
//val:要写入的值
//返回值:无
void ADXL345_WR_Reg(u8 addr,u8 val)
{
IIC_Start();
IIC_SendByte(ADXL_WRITE); //发送写器件指令
IIC_WaitAck();
IIC_SendByte(addr); //发送寄存器地址
IIC_WaitAck();
IIC_SendByte(val); //发送值
IIC_WaitAck();
IIC_Stop(); //产生一个停止条件
}
//读ADXL345寄存器
//addr:寄存器地址
//返回值:读到的值
u8 ADXL345_RD_Reg(u8 addr)
{
u8 temp=0;
IIC_Start();
IIC_SendByte(ADXL_WRITE); //发送写器件指令
temp=IIC_WaitAck();
IIC_SendByte(addr); //发送寄存器地址
temp=IIC_WaitAck();
IIC_Start(); //重新启动
IIC_SendByte(ADXL_READ); //发送读器件指令
temp=IIC_WaitAck();
temp=IIC_ReadByte(0); //读取一个字节,不继续再读,发送NAK
IIC_Stop(); //产生一个停止条件
return temp; //返回读到的值
}
//读取ADXL的平均值
//x,y,z:读取10次后取平均值
void ADXL345_RD_Avval(short *x,short *y,short *z)
{
short tx=0,ty=0,tz=0;
u8 i;
for(i=0;i<10;i++)
{
ADXL345_RD_XYZ(x,y,z);
Delay_nms(10);
tx+=(short)*x;
ty+=(short)*y;
tz+=(short)*z;
}
*x=tx/10;
*y=ty/10;
*z=tz/10;
}
//自动校准
//xval,yval,zval:x,y,z轴的校准值
void ADXL345_AUTO_Adjust(char *xval,char *yval,char *zval)
{
short tx,ty,tz;
u8 i;
short offx=0,offy=0,offz=0;
ADXL345_WR_Reg(POWER_CTL,0x00); //先进入休眠模式.
Delay_nms(100);
ADXL345_WR_Reg(DATA_FORMAT,0X2B); //低电平中断输出,13位全分辨率,输出数据右对齐,16g量程
ADXL345_WR_Reg(BW_RATE,0x0A); //数据输出速度为100Hz
ADXL345_WR_Reg(POWER_CTL,0x28); //链接使能,测量模式
ADXL345_WR_Reg(INT_ENABLE,0x00); //不使用中断
ADXL345_WR_Reg(OFSX,0x00);
ADXL345_WR_Reg(OFSY,0x00);
ADXL345_WR_Reg(OFSZ,0x00);
Delay_nms(12);
for(i=0;i<10;i++)
{
ADXL345_RD_Avval(&tx,&ty,&tz);
offx+=tx;
offy+=ty;
offz+=tz;
}
offx/=10;
offy/=10;
offz/=10;
*xval=-offx/4;
*yval=-offy/4;
*zval=-(offz-256)/4;
ADXL345_WR_Reg(OFSX,*xval);
ADXL345_WR_Reg(OFSY,*yval);
ADXL345_WR_Reg(OFSZ,*zval);
}
//读取3个轴的数据
//x,y,z:读取到的数据
void ADXL345_RD_XYZ(short *x,short *y,short *z)
{
u8 buf[6];
u8 i;
IIC_Start();
IIC_SendByte(ADXL_WRITE); //发送写器件指令
IIC_WaitAck();
IIC_SendByte(0x32); //发送寄存器地址(数据缓存的起始地址为0X32)
IIC_WaitAck();
IIC_Start(); //重新启动
IIC_SendByte(ADXL_READ); //发送读器件指令
IIC_WaitAck();
for(i=0;i<6;i++)
{
if(i==5)buf[i]=IIC_ReadByte(0);//读取一个字节,不继续再读,发送NACK
else buf[i]=IIC_ReadByte(1); //读取一个字节,继续读,发送ACK
}
IIC_Stop(); //产生一个停止条件
*x=(short)(((u16)buf[1]<<8)+buf[0]);
*y=(short)(((u16)buf[3]<<8)+buf[2]);
*z=(short)(((u16)buf[5]<<8)+buf[4]);
}
//读取ADXL345的数据times次,再取平均
//x,y,z:读到的数据
//times:读取多少次
void ADXL345_Read_Average(short *x,short *y,short *z,u8 times)
{
u8 i;
short tx,ty,tz;
*x=0;
*y=0;
*z=0;
if(times)//读取次数不为0
{
for(i=0;i