基于f103zet6单片机,使用adxl345检测电机振动频率,串口打印,程序模板为正点原子
1、项目简介
2、实现逻辑
#对adxl345初始化 #检测电机振动(加速度),串口打印
3、应用场景
#检测电机或其他物品的振动
4.梳理核心代码
#define SlaveAddress 0xA6 //定义器件在IIC根据总线的地址ALT ADDRESS不同修改地址引脚 //ALT ADDRESS引脚接地时地址为0xA6.接电源时地址为0x3A unsigned char BUF[8]; //接收数据缓存区 unsigned char ge,shi,bai,qian,wan; //显示变量 unsigned char err; float temp_X,temp_Y,temp_Z; float Acc_X,Acc_Y,Acc_Z,q; short Frequency; void SCL_Set_Output(void) { GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = SCL_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(SCL_GPIO, &GPIO_InitStructure); } void SDA_Set_Output(void) { GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = SDA_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(SDA_GPIO, &GPIO_InitStructure); } void SDA_Set_Input(void) { GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = SDA_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(SDA_GPIO, &GPIO_InitStructure); } /************************************** 起始信号 **************************************/ void ADXL345_Start(void) { SCL_OUT(); SDA_OUT(); SET_SDA();//SDA = 1; //拉高数据线 SET_SCL();//SCL = 1; //拉高时钟线 delay_us(2);//Delay5us(); //延时 CLE_SDA();//SDA = 0; //拉低数据线 delay_us(2);//Delay5us(); //延时 CLE_SCL();//SCL = 0; //拉低时钟线 } /************************************** 停止信号 **************************************/ void ADXL345_Stop(void) { SCL_OUT(); SDA_OUT(); CLE_SDA();//SDA = 0; //拉低数据线 SET_SCL();//SCL = 1; //拉高时钟线 delay_us(2);//Delay5us(); //延时 SET_SDA();//SDA = 1; //产生上升沿 delay_us(2);//Delay5us(); //延时 CLE_SCL(); } /************************************** 发送应答信号 入口参数:ack (0:ACK 1:NAK) **************************************/ void ADXL345_SendACK(uchar ack) { SCL_OUT(); SDA_OUT(); if(ack==0)//SDA = ack; //写应答信号 { CLE_SDA(); } else { SET_SDA(); } SET_SCL();//SCL = 1; //拉高时钟线 delay_us(2);//Delay5us(); //延时 CLE_SCL();//SCL = 0; //拉低时钟线 delay_us(5);//Delay5us(); //延时 } /************************************** 接收应答信号 **************************************/ uchar ADXL345_RecvACK(void) { SDA_INT(); SCL_OUT(); SET_SCL();//SCL = 1; //拉高时钟线 delay_us(2);// Delay5us(); //延时 SET_SCL(); if(SDA_VAL()== Bit_SET) //CY = SDA; //读应答信号 { err = 1; } else { err = 0; } CLE_SCL() ;//SCL = 0; //拉低时钟线 delay_us(5);// Delay5us(); //延时 SDA_OUT(); return err; } /************************************** 向IIC总线发送一个字节数据 **************************************/ void ADXL345_SendByte(unsigned char dat) { unsigned char i; SCL_OUT(); SDA_OUT(); for (i=0; i<8; i++) //8位计数器 { delay_us(5); //延时 if(dat&0x80) //SDA = CY; //送数据口 { SET_SDA();} else { CLE_SDA();} delay_us(5); //延时 SET_SCL();//SCL = 1; //拉高时钟线 delay_us(5); //延时 CLE_SCL();//SCL = 0; //拉低时钟线 dat <<= 1; //移出数据的最高位 } ADXL345_RecvACK(); } /************************************** 从IIC总线接收一个字节数据 **************************************/ unsigned char ADXL345_RecvByte(void) { unsigned char i; unsigned char Mid; unsigned char dat = 0; SDA_INT(); SCL_OUT(); for (i=0; i<8; i++) //8位计数器 { dat <<= 1; delay_us(5); //延时 SET_SCL(); if(SDA_VAL()== Bit_SET) //CY = SDA; //读应答信号 { Mid = 1; } else { Mid = 0; } if(Mid) dat++; delay_us(5); CLE_SCL();//SCL = 0; //拉低时钟线 } return dat; } //******单字节写入******************************************* void Single_Write_ADXL345(uchar REG_Address,uchar REG_data) { ADXL345_Start(); //起始信号 ADXL345_SendByte(SlaveAddress); //发送设备地址+写信号 ADXL345_SendByte(REG_Address); //内部寄存器地址,请参考中文pdf22页 ADXL345_SendByte(REG_data); //内部寄存器数据,请参考中文pdf22页 ADXL345_Stop(); //发送停止信号 } //********单字节读取***************************************** uchar Single_Read_ADXL345(uchar REG_Address) { uchar REG_data; ADXL345_Start(); //起始信号 ADXL345_SendByte(SlaveAddress); //发送设备地址+写信号 ADXL345_SendByte(REG_Address); //发送存储单元地址,从0开始 ADXL345_Start(); //起始信号 ADXL345_SendByte(SlaveAddress+1); //发送设备地址+读信号 REG_data=ADXL345_RecvByte(); //读出寄存器数据 ADXL345_SendACK(1); ADXL345_Stop(); //停止信号 return REG_data; } //********************************************************* // //连续读出ADXL345内部加速度数据,地址范围0x32~0x37 // //********************************************************* void Multiple_Read_ADXL345(void) { uchar i; ADXL345_Start(); //起始信号 ADXL345_SendByte(SlaveAddress); //发送设备地址+写信号 ADXL345_SendByte(0x32); //发送存储单元地址,从0x32开始 ADXL345_Start(); //起始信号 ADXL345_SendByte(SlaveAddress+1); //发送设备地址+读信号 for (i=0; i<6; i++) //连续读取6个地址数据,存储中BUF { BUF[i] = ADXL345_RecvByte(); //BUF[0]存储0x32地址中的数据 if (i == 5) { ADXL345_SendACK(1); //最后一个数据需要回NOACK } else { ADXL345_SendACK(0); //回应ACK } } ADXL345_Stop(); //停止信号 delay_us(5); } //***************************************************************** //初始化ADXL345,根据需要请参考pdf进行修改************************ void Init_ADXL345(void) { // Single_Write_ADXL345(0x31,0x0B); //测量范围,正负16g,13位模式 Single_Write_ADXL345(0x2C,0x08); //速率设定为25 参考pdf13页 Single_Write_ADXL345(0x2D,0x08); //选择电源模式 参考pdf24页 //参考14页表7进行修改 Single_Write_ADXL345(0x2E,0x80); //使能 DATA_READY 中断 Single_Write_ADXL345(0x38,0x00); Single_Write_ADXL345(0x2F,0x00); Single_Write_ADXL345(0x1E,0x00); //X 偏移量 根据测试
传感器的状态写入pdf29页 Single_Write_ADXL345(0x1F,0x00); //Y 偏移量 根据测试传感器的状态写入pdf29页 Single_Write_ADXL345(0x20,0x05); //Z 偏移量 根据测试传感器的状态写入pdf29页 } //*********************************************************************** //显示x轴 void ReadData_x(void) { int Acc_dis_data,dis_data,Acc_speed,Dis; //变量 Multiple_Read_ADXL345(); //连续读出数据,存储在BUF中 /*获取syz轴加速度*/ Acc_dis_data=(BUF[1]<<8)+BUF[0]; //合成数据 Acc_X=(float)Acc_dis_data*3.9/1000*9.8; //计算数据和显示,查考ADXL345快速入门第4页 Acc_dis_data=(BUF[3]<<8)+BUF[2]; //合成数据 Acc_Y=(float)Acc_dis_data*3.9/1000*9.8; //计算数据和显示,查考ADXL345快速入门第4页 Acc_dis_data=(BUF[5]<<8)+BUF[4]; //合成数据 Acc_Z=(float)Acc_dis_data*3.9/1000*9.8; //计算数据和显示,查考ADXL345快速入门第4页 /*获取syz轴坐标*/ dis_data=(BUF[1]<<8)+BUF[0]; //合成数据 temp_X=(float)dis_data*3.9; //计算数据和显示,查考ADXL345快速入门第4页 dis_data=(BUF[3]<<8)+BUF[2]; //合成数据 temp_Y=(float)dis_data*3.9; //计算数据和显示,查考ADXL345快速入门第4页 dis_data=(BUF[5]<<8)+BUF[4]; //合成数据 temp_Z=(float)dis_data*3.9; //计算数据和显示,查考ADXL345快速入门第4页 } int main(void) { #define ACC_X_FIL 500 #define TEMP_X_FIL 50 #define LINE_FIL_N 10 u8 time=0,j; u8 fil_count; uint16_t value_buf[LINE_FIL_N]; u8 i; u8 t=0; uint16_t Acc_X_hex, TEMP_X_hex, Acc_X_hex_last, TEMP_X_hex_last; uint32_t count_num = 0, fre = 0, fre_sum_fil = 0, fre_sum[10] = { 0}, fre_sum_num = 0, fil_sum = 0; uart_init(115200); //串口初始化为115200 delay_init(); //延时初始化 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级 LED_Init(); //初始化与LED连接的硬件接口 usart3_init(115200); //初始化串口3 KEY_Init(); BEEP_Init(); OLED_Clear(); TIM2_Int_Init(4999,7199); TIM6_Int_Init(2499,7199); OLED_Init(); //初始化OLED Init_ADXL345(); //adxl345初始化 DS18B20_Init(); //DS18B20初始化 printf("start !!!\r\n"); OLED_ShowString(0,0,"Electric machinery",12); OLED_ShowString(0,52,"ASCII:",12); OLED_ShowString(64,52,"CODE:",12); OLED_Refresh_Gram(); //更新显示到OLED u8 ret; ret=atk_8266_wifista_test(); delay_ms(1500); if(ret==2) { printf("wifi init ok !!!\r\n"); _mqtt.Init(rxbuf,0,txbuf,0);//MQTT初始化 //MQTT连接 ret=_mqtt.Connect("gl8dRlBcJhj.ESP8266|securemode=2,signmethod=hmacsha256,timestamp=2524608000000|", "ESP8266&gl8dRlBcJhj", "223d122ec212698603b5c2af5b73c9d0936e1c1e6327c566ea938089e56452ff"); delay_ms(1500); delay_ms(1500);//这两段延时可以适当减少,但删掉好像会出问题 } _mqtt.Init(rxbuf,0,txbuf,0);//MQTT初始化 ret=_mqtt.SubscribeTopic("/sys/a1e8HLT2lBT/test/thing/service/property/set",0,1); delay_ms(3000);//可以删掉试试 char * string=NULL; if(Single_Read_ADXL345(0X00)==0xe5) { delay_ms(5); } else { delay_ms(3); } j=' '; while(1) { count_num++; OLED_ShowChar(48,48,j,16,1);//显示ASCII字符 OLED_Refresh_Gram(); j++; if(j>'~')j=' '; OLED_ShowNum(103,48,j,3,16);//显示ASCII字符的码值 if(time%100==0){ temperature=DS18B20_Get_Temp(); ReadData_x(); //三轴检测函数 } //printf("\r\nTemp:%d.%d .C\n",temperature/10,temperature%10); // printf(" X=%4.3f m/s2 Y=%4.3f m/s2 Z=%4.3f m/s2\r\n",Acc_X,Acc_Y,Acc_Z); // printf("x轴的值:%.1f y轴的值:%.1f Z轴的值:%.1f\r\n",temp_X,temp_Y,temp_Z); // printf("%4.3f\r\n",Acc_X); Acc_X_hex = Acc_X * 1000; TEMP_X_hex = temp_X; if((abs(Acc_X_hex - Acc_X_hex_last) > ACC_X_FIL))//滤波 { fre++; } if((abs(TEMP_X_hex - TEMP_X_hex_last) > TEMP_X_FIL)) { fre++; } Acc_X_hex_last = Acc_X_hex; TEMP_X_hex_last = TEMP_X_hex; if(count_num % 100 == 0)//经校准此时为1s { fre_sum[(fre_sum_num++) % 10] = fre; for(i=0; i<10; i++) { fre_sum_fil += fre_sum[i]; } fre_sum_fil = fre_sum_fil/10; printf("\r\nTemp:%d.%d .C\n",temperature/10,temperature%10); printf("fre is: %d HZ\r\n",fre_sum_fil); Fre_sum_fil = fre_sum_fil; fre_sum_fil = 0; fre = 0