FastBond主题一智能可穿戴之计步器
关于人在跑步时距离的测量,方便人对自己现有运动状态的一个认知。
标签
显示
PCB设计
电源变换及管理
杨不止
更新2021-11-30
943

根据ADI和美信提供的芯片,来实现一些特殊的功能。

一、项目介绍

此次,我参加的是Fastbond主题一,智能可穿戴系列,记录人们行走的里程。使用了美信的MAX32660、MAX1555、MAX887,和ADI的ADXL362,芯片MAX32660作为主控器,接受ADXL发送和处理的信号和在OLED屏幕上显示出对应的数据、芯片MAX1555是作为锂电池的充电器、芯片MAX887作为锂电池给MAX32660供电的降压模块。

二、项目用到的板卡、芯片、模块、仪器、设备等介绍

用到的板卡:MAX32660-EVSYS#、SEN-11446、

用到的芯片:MAX32660、ADXL362、MAX1555、MAX887

用到的模块:主控模块、加速度传感器模块、电源模块、降压模块

用到的仪器:示波器

用到的设备:Keil、AD

三、关键性代码及说明

unsigned int Max_3(unsigned int Number_1,unsigned int Number_2,unsigned int Number_3)
{
	unsigned int Max;
	if(Number_1>=Number_2&&Number_1>=Number_3)
		 Max=Number_1;
	 else if(Number_2>=Number_1&&Number_2>=Number_3)
		      Max=Number_2;
	      else
					Max=Number_3;
	return Max;
}

此函数用来比较三轴检测到的数值大小,并返回那个最大值。

 

int I2C_Init(mxc_i2c_regs_t *i2c, i2c_speed_t i2cspeed, const sys_cfg_i2c_t* sys_cfg)
{
    int err;
    int idx = MXC_I2C_GET_IDX(i2c);
    // Check the base pointer
    MXC_ASSERT(idx >= 0);

    // Set system level configurations
    if ((err = SYS_I2C_Init(i2c, sys_cfg)) != E_NO_ERROR) {
        return err;
    }

    // Always disable the HW autoflush on data NACK and let the SW handle the flushing.
    i2c->tx_ctrl0 |= 0x20;

    states[idx].num_wr = 0;

    i2c->ctrl = 0;   // clear configuration bits
    i2c->ctrl = MXC_F_I2C_CTRL_I2C_EN;       // Enable I2C
    i2c->master_ctrl = 0;  // clear master configuration bits
    i2c->status = 0;   // clear status bits

    /* If either SDA or SCL is already low, there is a problem.
     * Try reclaiming the bus by sending clocks until we have control of the SDA line.
     * Follow procedure defined in i2c spec.
     */
    if ((i2c->ctrl & (MXC_F_I2C_CTRL_SCL | MXC_F_I2C_CTRL_SDA)) !=
            (MXC_F_I2C_CTRL_SCL | MXC_F_I2C_CTRL_SDA)) {

        int i, have_control;

        // Set SCL/SDA as software controlled.
        i2c->ctrl |= MXC_F_I2C_CTRL_SW_OUT_EN;

        // Try to get control of SDA.
        for (i = 0; i < 16; i++) {
            have_control = 1;

            // Drive SCL low and check its state.
            i2c->ctrl &= ~(MXC_F_I2C_CTRL_SCL_OUT);
            mxc_delay(MXC_DELAY_USEC(5));
            if ((i2c->ctrl & MXC_F_I2C_CTRL_SCL) == MXC_F_I2C_CTRL_SCL) {
                have_control = 0;
            }

            // Drive SDA low and check its state.
            i2c->ctrl &= ~(MXC_F_I2C_CTRL_SDA_OUT);
            mxc_delay(MXC_DELAY_USEC(5));
            if ((i2c->ctrl & MXC_F_I2C_CTRL_SDA) == MXC_F_I2C_CTRL_SDA) {
                have_control = 0;
            }

            // Release SDA and check its state.
            i2c->ctrl |= (MXC_F_I2C_CTRL_SDA_OUT);
            mxc_delay(MXC_DELAY_USEC(5));
            if ((i2c->ctrl & MXC_F_I2C_CTRL_SDA) != MXC_F_I2C_CTRL_SDA) {
                have_control = 0;
            }

            // Release SCL and check its state.
            i2c->ctrl |= (MXC_F_I2C_CTRL_SCL_OUT);
            mxc_delay(MXC_DELAY_USEC(5));
            if ((i2c->ctrl & MXC_F_I2C_CTRL_SCL) != MXC_F_I2C_CTRL_SCL) {
                have_control = 0;
            }

            if (have_control) {
                // Issue stop
                // Drive SDA low.
                i2c->ctrl &= ~(MXC_F_I2C_CTRL_SDA_OUT);
                mxc_delay(MXC_DELAY_USEC(5));
                // Release SDA.
                i2c->ctrl |= (MXC_F_I2C_CTRL_SDA_OUT);
                mxc_delay(MXC_DELAY_USEC(5));
                break;
            }
        }

        if (!have_control) {
            return E_COMM_ERR;
        }
    }

    i2c->ctrl = 0;   // clear configuration bits
    i2c->ctrl = MXC_F_I2C_CTRL_I2C_EN;       // Enable I2C
    i2c->master_ctrl = 0;  // clear master configuration bits
    i2c->status= 0;   // clear status bits

    // Check for HS mode
    if (i2cspeed == I2C_HS_MODE) {
        i2c->ctrl |= MXC_F_I2C_CTRL_HS_MODE;    // Enable HS mode
    }

    // Disable and clear interrupts
    i2c->int_en0 = 0;
    i2c->int_en1 = 0;
    i2c->int_fl0 = i2c->int_fl0;
    i2c->int_fl1 = i2c->int_fl1;

    i2c->timeout = 0x0;   // set timeout
    i2c->rx_ctrl0 |= MXC_F_I2C_RX_CTRL0_RX_FLUSH; // clear the RX FIFO
    i2c->tx_ctrl0 |= MXC_F_I2C_TX_CTRL0_TX_FLUSH; // clear the TX FIFO

    return I2C_Setspeed(i2c, i2cspeed);
}

进行MAX32660与OLED屏幕的一个IIC同信初始化。

 

uint8_t ADXL362_Init(void)
{                 
    SPI_Init(SPI0A, 0 , 5000000);   	
	if(ADXL362RegisterRead(XL362_DEVID_AD)==0XAD)    
	{
	  ADXL362RegisterWrite(XL362_FILTER_CTL,0x93); 
	  ADXL362RegisterWrite(XL362_POWER_CTL,0x02);
		
		ADXL362RegisterWrite(XL362_ACT_INACT_CTL,0x3F);
		ADXL362RegisterWrite(XL362_INTMAP1,0x90);
		
		ADXL362RegisterWrite(XL362_THRESH_ACT_L,0xFA);
		ADXL362RegisterWrite(XL362_THRESH_ACT_H,0x00);
		ADXL362RegisterWrite(XL362_TIME_ACT,0x01);
		
		ADXL362RegisterWrite(XL362_THRESH_INACT_L,0x96);
		ADXL362RegisterWrite(XL362_THRESH_INACT_H,0x00);
		ADXL362RegisterWrite(XL362_TIME_INACT_L,0x1E);
		ADXL362RegisterWrite(XL362_TIME_INACT_H,0x00);
	
		return 0;
	}
	 return 1;

                           
} 

对ADXL362的一个初始化。

 

void SysTick_Handler(void)    

{
unsigned int i;
num++;
if(num==5)
{
num=0;
for(i=0;i<50;i++)
{
ADXL362_RD_Avval((xf+i),(yf+i),(zf+i));

}
data_pros();
}
}

中断。

 

 

void ADXL362_RD_Avval(unsigned int *x,unsigned int *y,unsigned int *z)
{
   
    uint8_t i; 
    *x=0;
    *y=0;
    *z=0;	
    for(i=0;i<9;i++)
	  {
			  *(tx+i)=*(tx+i+1);
			  *(ty+i)=*(ty+i+1);
			  *(tz+i)=*(tz+i+1);
		}
		ADXL362RegisterRead6(XL362_XDATA_L,6,(tx+9),(ty+9),(tz+9));
		for(i=0;i<10;i++)
		{
			*x+=tx[i];
			*y+=ty[i];
			*z+=tz[i];
		}
	   *x=*x/10;
		 *y=*y/10;
		 *z=*z/10;
    
  
}  

读取ADXL362的值。

 

 

unsigned int data_pros()    //Êý¾Ý´¦Àíº¯Êý
	{
		 
		 unsigned int i,j,t;
		unsigned int p,m,n;
		 unsigned char thread_old_1,thread_old_2,thread_new_1,thread_new_2;
		 unsigned int  thread_old,thread_new=0,thread_x,thread_y,thread_z;

			 
			thread_old_1=ADXL362RegisterRead(XL362_THRESH_ACT_L);                //¶ÁÈ¡ãÐÖµ
			thread_old_2=ADXL362RegisterRead(XL362_THRESH_ACT_H);
			thread_old=((uint16_t)thread_old_2<<8)|thread_old_1;
			for(i=0;i<50;i++)
			{
				 ADXL362_RD_Avval((xf+i),(yf+i),(zf+i));
	//			 p=*(xf+i);
	//			 m=*(yf+i);
	//			 n=*(zf+i);
	////			 printf("%d\n" ,xf[i]);
	//			

			}
			 for(i=0;i<50;i++)
		{
			
				 if((*(Huge+i)<=thread_old)&&((*(Huge+i-2)>thread_old)||(*(Huge+i-1)>thread_old)))
					 step+=1;
				 
		}
		
			for( i=0;i<50;i++)                  //ðÅÝ·¨ÅÅÐòµÃµ½ÐµÄ×î´óãÐÖµ
				for(j=0;j<50-i;j++)
			 {
				 if(*(xf+j)>*(xf+j+1))
				 {
					 t=*(xf+j);
					 *(xf+j)=*(xf+j+1);
					 *(xf+j+1)=t;
				 }
			 }	
			thread_x=(*(xf+49)-*xf)/2;	
					 
			 for( i=0;i<50;i++)
				for(j=0;j<50-i;j++)
			 {
				 if(*(yf+j)>*(yf+j+1))
				 {
					 t=*(yf+j);
					 *(yf+j)=*(yf+j+1);
					 *(yf+j+1)=t;
				 }
			 }
			thread_y=(*(yf+49)-*yf)/2;	
				 
			 for( i=0;i<50;i++)
				for(j=0;j<50-i;j++)
			 {
				 if(*(zf+j)>*(zf+j+1))
				 {
					 t=*(zf+j);
					 *(zf+j)=*(zf+j+1);
					 *(zf+j+1)=t;
				 }
			 }	
			thread_z=(*(zf+49)-*zf)/2;	
			
			
			thread_new=Max_3(thread_x,thread_y,thread_z);
			if(thread_new==thread_x)
				Huge=xf;
			 else if(thread_new==thread_y)
				 Huge=yf;
			 else 
				 Huge=zf;                           //ÅжÏãÐÖµÄĸöÖá×î´ó
			 
			 
		
			thread_new_2=(unsigned char)(thread_new>>8);
			thread_new_1=(unsigned char)(thread_new&0x00ff);
					
			ADXL362RegisterWrite(XL362_THRESH_ACT_L,thread_new_1);   //¸üÐÂãÐÖµ
			ADXL362RegisterWrite(XL362_THRESH_ACT_H,thread_new_2);
					
			return thread_new;
	}

进行函数的处理。

 

 

     //ÏÔʾ2¸öÊý×Ö
    //x,y :Æðµã×ø±ê
    //len :Êý×ÖµÄλÊý
    //size:×ÖÌå´óС
    //mode:ģʽ	0,Ìî³äģʽ;1,µþ¼Óģʽ
    //num:ÊýÖµ(0~4294967295);
    void OLED_ShowNum(uint8_t x,uint8_t y,unsigned int num,uint8_t len,uint8_t size2)
    {
    	uint8_t t,temp;
    	uint8_t enshow=0;
    	for(t=0;t<len;t++)
    	{
    		temp=(num/oled_pow(10,len-t-1))%10;
    		if(enshow==0&&t<(len-1))
    		{
    			if(temp==0)
    			{
    				OLED_ShowChar(x+(size2/2)*t,y,' ',size2);
    				continue;
    			}else enshow=1;

    		}
    	 	OLED_ShowChar(x+(size2/2)*t,y,temp+'0',size2);
    	}
    }

在屏幕上显示数字。

 

//ÏÔʾһ¸ö×Ö·ûºÅ´®
    void OLED_ShowString(uint8_t x,uint8_t y,uint8_t *chr,uint8_t Char_Size)
    {
    	unsigned char j=0;
    	while (chr[j]!='\0')
    	{		OLED_ShowChar(x,y,chr[j],Char_Size);
    			x+=8;
    		if(x>120){x=0;y+=2;}
    			j++;
    	}
    }

在OLED上显示字符。

 

四、功能演示结果及说明

点亮屏幕

FoYjaJkYnbECcEzhtyyq9YTkFR4k

正常显示时间,距离

Fm8vpY017D0bLuRkcbaWeHtJvm9K

模拟人走路

Fg6IVQkS_zSNueCQyKCLSmqsXnaZ

验证功能完毕,基本正确。能够很好的显示功能和模拟人在走路时功能。

 

五、对本活动的心得体会

作为一名在校大学生,非常荣幸参加贵公司由硬禾学堂联合Digi-Key共同发布的为期三个半月的“你创意,我买单” 的Fadtbond活动,这次活动让我有了一个很好的成长,也对AD软件,Keil软件更加熟悉了。“千里之行,始于足下”,这次充实的设计锻炼,丰富我们的学识,拓展我们的视野,是人生的一段重要的经历,也是一个重要步骤,对将来走上工作岗位也有着很大帮助。增强了认识问题,分析问题,解决问题的能力。原本以为自己已经学会了一些基础的知识就够用了,可到了设计电路和程序的时候才知道原来自己要学的东西还有很多,以后自己要走的路还很长,不能只安于现状,一定要奋勇直前。人是在不断前进中成长起来的,虽然会有很多坎坷,但总是会有办法解决的。最后,引用一句古诗结束“纸上得来终觉浅,绝知此事要躬行”。最后,由衷的感谢贵公司为我们提供如此宝贵的学习创造机会,谢谢!

软硬件
电路图
附件下载
max32660.zip
代码
原理图.zip
原理图
团队介绍
杨武
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号