项目介绍
- 项目介绍:该项目是一个小型的智能可穿戴手表,计划是将三个模块(电源模块,最小系统 模块,传感器模块)画在一个电路板上,但是为了调试方便最后画了3个电路板.最后我们实现的功能是可以进行简单的计步和计时.
- 软件介绍:我们这次使用keil进行编写代码,主要使用Max32660的库函数对传感器和屏幕进行通讯.
- 硬件介绍:AMS1117-3.3,MAX32660,ADXL362,12864OLED
项目用到的板卡、芯片、模块、仪器、设备
- MAX32660(使用该模块的iic通信与oled进行通信,spi通信与adxl362通讯)
MAX32660 是一款超低功耗、高性价比、高度集成的 32 位微控制器,专为电池供电设备和无线传感器而设计。 它结合了灵活的多功能电源管理单元和功能强大的 Arm® Cortex®-M4 处理器和浮点单元 (FPU),采用业界最小的外形,MAX32660 支持具有复杂传感器处理的设计,而不会影响电池寿命。 它还为传统设计提供了从 8 位或 16 位微控制器升级的简单且成本最优的途径。该器件支持 SPI、UART 和 I2C 通信,同时还集成了高达 256KB 的闪存和 96KB 的 RAM,以容纳应用程序和传感器代码。 可以使用通过 I2C、UART 或 SPI 的可选引导加载程序。
- ADXL362(用于测量加速度,进而用于计步算法)
ADXL362是一款超低功耗、3轴MEMS加速度计,输出数据 速率为100 Hz时功耗低于2 μA,在运动触发唤醒模式下功耗 为270 nA。与使用周期采样来实现低功耗的加速度计不同, ADXL362没有通过欠采样混叠输入信号;它采用全数据速 率对传感器的整个带宽进行采样。
- AMS1117-3.3(提供稳定的3v电压)
AMS1117 系列可调和固定电压调节器旨在提供 800mA 输出电流并在低至 1V 的输入至输出差分电压下工作。 器件的压差在最大输出电流时保证最大为 1.3V,在较低负载电流时降低。片上微调将参考电压调整为 1%。 还调整了电流限制,最大限度地减少了稳压器和电源电路在过载条件下的压力。
- 12864OLED(用于显示时间和步数)
OLED显示屏具有宽温(-40度到+80度的工作温度)、超薄的特点、自发光不需背光源、对比度高、视角广、反应速度快、可用于挠曲性面板等;由于上述优点,OLED显示屏适用于POS机、智能手机、移动终端、PDA、音响设备、数码相机、仪器仪表、GPS、飞机仪表、车载音响、导航、穿戴式设备。
- DAPLINK(用于下载程序)
DAPLink的原理和仿真器差不多,可以理解成通过一个MCU向另一个MCU烧写程序。 PC通过USB与烧写DAPLink的MCU连接上
关键性代码
void SpiFunction(unsigned char *OutputBuff,unsigned char *InputBuff, unsigned int NoOfBytes)//配置spi通信
{
spi_req_t req;
req.tx_data = OutputBuff ;
req.rx_data = InputBuff;
req.len = NoOfBytes;
req.bits = 8;
req.width = SPI17Y_WIDTH_1;
req.ssel = 0;
req.deass = 1;
req.tx_num = NoOfBytes;
req.rx_num = NoOfBytes;
req.callback = NULL;
SPI_MasterTrans(SPI0A, &req) ;
}
uint8_t ADXL362_Init(void)//adxl263初始化
{
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;
}
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;
}
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;
}
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;
}
功能演示:在视频中可以看见通过我们摇晃adxl362来模仿人走路的过程,oled中的steep在增加
心得体会:首先很感谢这次硬禾学堂和Digi-Key举办的这次活动,由于自己第一次参加这种项目活动,在很多地方都还欠缺经验和能力,既然是可穿戴模块我的电路板还应该设计更合理,没有将3个板子画在一起,供电模块原本采用MAX77655,由于该芯片是非常小的bga封装,自己画电路时没有画成功,所以现在采用的供电模块形状就十分大,软件部分由于算法没有做到十分完善,测量的步数不是十分精准.总体来说这次活动对我最大的意义就是对做项目有一个整体的认识.