Buscando un programa para usar el microcontrolador 51 para controlar ADXL345 para medir el ángulo. A través del sensor ADXL345, use el microcontrolador 51 para controlar el programa para medir el ángulo de inclinación.
//****************************************** * p>
// Programa de prueba GY-29 ADXL345 IIC
// Usando el microcontrolador STC89C51
// Oscilador de cristal: 11.0592M
// Pantalla: LCD1602
// Entorno de compilación Keil uVision2
// Consulte el programa de comunicación 24c04 del sitio web de Acer
// Hora: 1 de marzo de 2011
// QQ: 531389319
//****************************** **** ********
#include lt;REG51.Hgt;
#include lt;math.hgt; //Biblioteca Keil
# include lt; stdio.hgt; //Biblioteca Keil
#include lt; INTRINS.Hgt
#define uchar unsigned char
# define uint unsigned int
#define DataPort P0 //puerto de datos LCD1602
sbit SCL=P1^0 //definición del pin del reloj IIC
sbit SDA= P1^1 ; //definición del pin de datos IIC
sbit LCM_RS=P2^0; //puerto de comando LCD1602
sbit LCM_RW=P2^1; //puerto de comando LCD1602
p>
sbit LCM_EN=P2^2; //puerto de comando LCD1602
#define SlaveAddress 0xA6 //Definir la dirección esclava del dispositivo en el bus IIC, modificada según el pin de dirección ALT ADDRESS
//Cuando el pin ALT ADDRESS está conectado a tierra, la dirección es 0xA6, y cuando está conectado a la alimentación, la dirección es 0x3A
typedef unsigned char BYTE;
typedef unsigned short WORD;
BYTE BUF[8]; //Recibir área de búfer de datos
uchar ge, shi, bai, qian, wan //Mostrar variables
int dis_data; //Variable
int data_xyz[3];
retraso vacío(unsigned int k);
void InitLcd( ); //Inicializar lcd1602
void Init_ADXL345(void); //Inicializar ADXL345
<p>void WriteDataLCM(uchar dataW);
void WriteCommandLCM(uchar CMD, uchar Attribc);
void DisplayOneChar(uchar X, uchar Y, uchar DData);
void conversion(uint temp_data);
void Single_Write_ADXL345(uchar REG_Address, uchar REG_data); //datos de escritura única
uchar Single_Read_ADXL345(uchar REG_Address); //lectura única; datos de registro interno
void Multiple_Read_ADXL345(); //Leer continuamente datos de registro interno
//--------------- ---- -----------------
void Delay5us();
void Delay5ms();
void ADXL345_Start ();
void ADXL345_Stop();
void ADXL345_SendACK(bit ack);
bit ADXL345_RecvACK();
void ADXL345_SendByte (BYTE dat);
BYTE ADXL345_RecvByte();
void ADXL345_ReadPage();
void ADXL345_WritePage();
// ----------------------------------
//** ***** ********************************************** **** *
conversión nula (uint temp_data)
{
wan=temp_data/10000 0x30
temp_data=temp_data10000; operación
qian=temp_data/1000 0x30;
temp_data=temp_data1000; //Operación restante
bai=temp_data/100 0x30; > temp_data=temp_data100; //operación restante
shi=temp_data/10 0x30;
temp_data=temp_data10; //operación restante
ge=temp_data 0x30;
}
/****************************** *****/
retraso nulo(unsigned int k)
{
unsign
ed int i, j;
for(i=0;ilt;k;i)
{
for(j=0;jlt;121; j )
{;}}
}
/********************* *** **********/
void WaitForEnable(void)
{
DataPort=0xff
<; p>LCM_RS =0;LCM_RW=1;_nop_();LCM_EN=1;_nop_();_nop_();
mientras(DataPortamp;0x80
LCM_ES=0;
}
/*************************** **** **/
void WriteCommandLCM(uchar CMD, uchar Attribc)
{
if(Attribc)WaitForEnable()
LCM_RS =0; LCM_RW=0; _nop_();
Puerto de datos=CMD; =0;
}
/******************************* ***/
void WriteDataLCM(uchar dataW)
{
WaitForEnable()
LCM_RS=1; ; _nop_();
p>DataPort=datosW;
LCM_EN=1; _nop_(); p>}
/*************************************** */
void InitLcd()
{
WriteCommandLCM(0x38, 1);
WriteCommandLCM(0x08, 1); /p>
WriteCommandLCM(0x01, 1);
WriteCommandLCM(0x06, 1);
WriteCommandLCM(0x0c, 1); /p>
/******* ****************************/
void DisplayOneChar(uchar X, uchar Y, uchar DData) p>
{
Yamp;=1
Xamp;=15; >if(Y)X|=0x40;
X|=0x80;
WriteCommandLCM(X, 0);
WriteDataLCM(DData); p>
}
/ ************************************* ***
p>
Retraso de 5 microsegundos (STC90C52RC@12M)
Esta función debe ajustarse para diferentes entornos de trabajo. Tenga en cuenta que debe modificarse cuando el reloj es demasiado rápido.
Al cambiar a 1T Cuando utilice una MCU, ajuste esta función de retardo
****************************** ******** *****/
void Delay5us()
{
_nop_(); _nop_(); ; _nop_();
p>_nop_(); _nop_(); _nop_();
}
/****************************** ************ p>
Retraso de 5 milisegundos (STC90C52RC@12M)
Esta función debe ajustarse para diferentes entornos de trabajo
Al cambiar a una MCU 1T, ajuste esta función de retardo
****************************** ************/
void Delay5ms()
{
PALABRA n = 560
mientras (n--);
}
/*************************** ****************
Señal de inicio
****************** ************************ */
void ADXL345_Start()
{
SDA = 1; //Sube la línea de datos
SCL = 1; //Sube la línea de reloj
Delay5us(); //Retraso
SDA = 0; //Generar flanco descendente
Delay5us(); //Retraso cuando
SCL = 0 //Bajar la línea del reloj
}
/******************************************
Señal de parada
************ ********************** ******/
void ADXL345_Stop()
{
SDA = 0; // Baja la línea de datos
SCL = 1; // Lleva la línea del reloj hacia arriba
Delay5us(); //Retraso
SDA = 1 //Genera flanco ascendente
Delay5us; (); //Retraso
}
/******** ******************** **********
Enviar señal de respuesta
Parámetros de entrada: ack (0: ACK 1: NAK)
********************************* *** *******/
void ADXL345_SendACK(bit ack)
{
SDA = ack //Escribe señal de respuesta
p>SCL = 1; // Baja la línea del reloj
Delay5us(); //Delay
SCL = 0 // Baja la línea del reloj
p>Retraso5us(); //Retraso
}
/********************** ******** *************
Recibir señal de respuesta
************ ************ *******************/
bit ADXL345_RecvACK()
{
SCL = 1; // Levanta la línea del reloj
Delay5us(); //Retraso
CY = SDA //Leer señal de respuesta
p>
SCL = 0; //Tirar de la línea de reloj baja
Delay5us(); //Retraso
return CY;
}
/****** *************************************
Enviar un byte de datos al bus IIC
****************************** ***********/
void ADXL345_SendByte(BYTE dat)
{
BYTE i; > for (i=0; ilt; 8; i) // Contador de 8 bits p>
{
dat lt; = 1; data
SDA = CY; // Puerto de envío de datos
SCL = 1; // Tira de la línea del reloj hacia arriba
Delay5us() // Retraso
SCL = 0; // Baja la línea del reloj
Delay5us(); //Retraso
}
ADXL345_RecvACK();
}
/******* **************************** **
Recibir un byte de datos del bus IIC
*************************** *****
************/
BYTE ADXL345_RecvByte()
{
BYTE i;
BYTE dat = 0;
SDA = 1; //Habilitar pull-up interno, listo para leer datos,
for (i=0; ilt; 8; i) //8 Contador de bits
{
dat lt; = 1;
SCL = 1; //tirar la línea del reloj hacia arriba
Delay5us (); //Retraso
dat |= SDA; //Leer datos
SCL = 0; //Bajar la línea del reloj
Delay5us() ; //Retraso
}
return dat;
}
//******Escritura de un solo byte Enter* *****************************************
void Single_Write_ADXL345 (uchar REG_Address, uchar REG_data)
{
ADXL345_Start(); //Señal de inicio
ADXL345_SendByte(SlaveAddress); //Enviando señal de escritura de dirección del dispositivo
ADXL345_SendByte(REG_Address); //Dirección de registro interno, consulte la página 22 del pdf en chino
ADXL345_SendByte(REG_data); //Datos del registro interno, consulte la página 22 del pdf en chino
ADXL345_Stop(); //Enviar señal de parada
}
//*********Lectura de un solo byte***** ** ********************************
uchar Single_Read_ADXL345(uchar REG_Address)
{ uchar REG_data;
ADXL345_Start(); //Iniciar señal
ADXL345_SendByte(SlaveAddress); //Enviar señal de escritura de dirección del dispositivo
ADXL345_SendByte (REG_Address); //Envía la dirección de la unidad de memoria, comenzando desde 0
ADXL345_Start(); //Señal de inicio
ADXL345_SendByte(SlaveAddress 1);
//Enviar señal de lectura de dirección del dispositivo
REG_data=ADXL345_RecvByte(); //Leer datos de registro
ADXL345_SendACK(1);
ADXL345_Stop(); Señal de parada
return REG_data
}
//********************* * ************************************
//
//Lea continuamente los datos de aceleración interna de ADXL345, rango de direcciones 0x32~0x37
//
//************** *****************************************
void Multiple_read_ADXL345(void)
{ uchar i;
ADXL345_Start(); //Señal de inicio
ADXL345_SendByte(SlaveAddress); Signal
ADXL345_SendByte(0x32); //Enviar dirección de unidad de almacenamiento, comenzando desde 0x32
ADXL345_Start(); //Iniciar señal
ADXL345_SendByte(SlaveAddress 1 ) ; //Enviar señal de lectura de dirección del dispositivo
for (i=0; ilt; 6; i) //Leer continuamente 6 datos de dirección, almacenados en BUF
{
BUF[i] = ADXL345_RecvByte(); //BUF[0] almacena los datos en la dirección 0x32
if (i == 5)
{
ADXL345_SendACK(1); //Los últimos datos deben devolver NOACK
}
else
{
ADXL345_SendACK( 0); //Respuesta a ACK
}
}
ADXL345_Stop(); //Señal de parada
Delay5ms() ;
}
//********************************* * ********************************
//Inicialice ADXL345, consulte el pdf según sea necesario Realizar cambios************************
<p>void Init_ADXL345()
{
Single_Write_ADXL345(0x31, 0x0B); //Rango de medición, más o menos 16 g, modo de 13 bits
Single_Write_ADXL345 (0x2C, 0x08); //Establezca la velocidad en 12,5, consulte la página 13 del pdf
Single_Write_ADXL345(0x2D, 0x08); //Seleccione el modo de energía, consulte la página 24 del pdf
Single_Write_ADXL345(0x2E, 0x80); //Habilitar interrupción DATA_READY
Single_Write_ADXL345(0x1E, 0x00); //El desplazamiento X se escribe en la página pdf29 según el estado del sensor de prueba
Single_Write_ADXL345(0x1F, 0x00); / /El desplazamiento Y se escribe en la página 29 del pdf según el estado del sensor de prueba
Single_Write_ADXL345(0x20, 0x05); pdf página 29 según el estado del sensor de prueba
}
//************************ ******************* *******************************
//Mostrar eje x
void display_x()
{ float temp;
dis_data=(BUF[1]lt; lt;8) BUF[0]; //Datos sintéticos
if(dis_datalt; 0){
dis_data=-dis_data;
DisplayOneChar(2, 0, '-'); //Mostrar los bits de signo positivo y negativo
}
else DisplayOneChar(2, 0, ' ');
temp=(float)dis_data*3.9; //Calcule los datos y visualícelos, consulte la página de inicio rápido 4 de ADXL345
conversion(temp); p> DisplayOneChar(0, 0, 'X'); // Línea 0, no. La columna 0 muestra ,'.
DisplayOneChar(5, 0, bai); p> DisplayOneChar(6, 0, shi);
DisplayOneChar(7, 0 ,'g');
}
//**** ************************** ************************* *********************
>Mostrar eje y
void display_y()
{ temperatura flotante;
dis_data=(BUF[3]
lt;lt;8) BUF[2]; //Datos sintéticos
if(dis_datalt;0){
dis_data=-dis_data;
DisplayOneChar( 2, 1, '-'); //Mostrar bits de signo positivos y negativos
}
else DisplayOneChar(2, 1, ' '); >
temp=(float)dis_data*3.9; //Calcule los datos y visualícelos, consulte la página 4 del inicio rápido de ADXL345
conversion(temp); //Convierta los datos necesarios para la visualización
DisplayOneChar(0, 1, 'Y'); // Fila 1, columna 0 muestra y
DisplayOneChar(1, 1, ':'); (3, 1, qian);
DisplayOneChar(4, 1, '.');
DisplayOneChar(5, 1, bai
DisplayOneChar); (6, 1, shi);
DisplayOneChar(7, 1, 'g'
}
//****** *); ************************************************** ***************
//Mostrar eje z
void display_z()
{ float temp;
dis_data=(BUF[5]lt;lt;8) BUF[4]; //Datos sintéticos
if(dis_datalt;0){
dis_data =-dis_data;
DisplayOneChar(10, 1, '-'); //Mostrar bit de signo negativo
}
else DisplayOneChar(10, 1 , ' '); //Mostrar espacios
temp=(float)dis_data*3.9; //Calcular datos y mostrar, consulte la página 4 del inicio rápido de ADXL345
conversion(temp) ; //Convierte los datos necesarios para la visualización
/*
DisplayOneChar(10, 0, 'Z'); //Fila 0, columna 10 muestra Z
DisplayOneChar(11, 0, ':');
DisplayOneChar(11, 1, qian
DisplayOneChar(12, 1, '.'); > p>
DisplayOneChar(13, 1, bai);
DisplayOneChar(14, 1, shi
DisplayOneChar(15, 1, 'g'); /p>
p>
*/
}
//********************* ****** *******************************
<p>//******Programa principal************
//******************* *** *************************************
void main()
{
uchar devid;
float Roll, Pitch, Q, T, K
retardo(500); Retraso de encendido
InitLcd(); //Inicialización de LCD ADXL345
Init_ADXL345(); //Inicialización de ADXL345
devid=Single_Read_ADXL345(0X00); /Leer Los datos son 0XE5, lo que significa correcto
while(1) //Bucle
{
Init_ADXL345() //Inicializar ADXL345; p>
Multiple_Read_ADXL345(); //Leer datos continuamente y almacenarlos en BUF
data_xyz[0]=(BUF[1]lt;lt;8) BUF[0];
p>data_xyz[1]=(BUF[3]lt;lt;8) BUF[2] //Datos sintéticos
data_xyz[2]=(BUF[5 ]lt;lt ;8) BUF[4]; //Datos sintéticos
//Los datos originales de aceleración X, Y, Z respectivamente, 10 bits
Q=(float )data_xyz[ 0]*3.9;
T=(float)data_xyz[1]*3.9;
K=(float)data_xyz[2]*3.9;
Q=-Q;
Roll=(float)(((atan2(K, Q)*180)/3.14159265) 180); //Valor del ángulo del eje X
Pitch= (float)(((atan2(K, T)*180)/3.14159265) 180); //Valor del ángulo del eje Y
conversión(Roll); datos del eje necesarios para la visualización, o eje Y
DisplayOneChar(9, 1, 'A'
DisplayOneChar(10, 1, ':'); p> DisplayOneChar(11, 1, bai);
DisplayOneChar(12, 1, shi
DisplayOneChar(13, 1, ge); retraso(200); / /Retraso
}
}