# max32660_OLED **Repository Path**: root__locus/max32660_-oled ## Basic Information - **Project Name**: max32660_OLED - **Description**: 基于美信MAX32660的OLED智能手表设计 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 3 - **Forks**: 0 - **Created**: 2021-02-27 - **Last Updated**: 2024-07-04 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 说明文档 本代码主要实现了显示时间,以及对步数的记录。顺便加了个小的下位机,用来修改时间。 [toc] [**项目地址**](https://gitee.com/root__locus/max32660_-oled) ## 硬件连接 ~~~c #define SPI_CS_Pin PIN_12 #define SPI_CS_GPIO_Port PORT_0 #define SPI_DC_Pin PIN_13 #define SPI_DC_GPIO_Port PORT_0 #define SPI_RES_Pin PIN_4 #define SPI_RES_GPIO_Port PORT_0 #define SPI_DIN_Pin PIN_3 #define SPI_DIN_GPIO_Port PORT_0 #define SPI_CLK_Pin PIN_2 #define SPI_CLK_GPIO_Port PORT_0 ~~~ ![image-20210216221845791](https://gitee.com/root__locus/pic_cloud/raw/master/image-20210216221845791.png) ## 时间显示 这次还是用了OLED的文字库,用到了显示文字,和画图功能。 ~~~c DrawNum(0,0,step_cnt,5); SetFontSize(3); DrawChar(30,24,':'); DrawNum(0,24,hour,2); DrawNum(42,24,min,2); fresh_g(); RoundClock(hour,min,sec); ~~~ 其中画时钟的函数是我之前有用过,参照的是另外一个up主的内容,程序里有提到。具体的使用可以参照我之前的[**项目**](https://www.eetree.cn/project/detail/73) 下面源码,主要用了简单的画图函数。 ~~~c void RoundClock(int hours ,int minute ,int sec) { unsigned char i=0; TypeXY hourspoint,minutepoint,secpoint,tmp1,tmp2; center_pos.x = 104; center_pos.y = 39; //时针 SetRotateValue(center_pos.x,center_pos.y,hours*30+(minute*30)/60+clock_angle,1); //设定旋转中心,旋转角度,旋转方向 hourspoint=GetRotateXY(center_pos.x,center_pos.y-CLOCK_R+12); //给出一个不在中心的点,计算出其旋转后的坐标 DrawLine(center_pos.x,center_pos.y,hourspoint.x,hourspoint.y);//画线 //分针 SetRotateValue(center_pos.x,center_pos.y,minute*6+(sec*6)/60+clock_angle,1); minutepoint=GetRotateXY(center_pos.x,center_pos.y-CLOCK_R+6); DrawLine(center_pos.x,center_pos.y,minutepoint.x,minutepoint.y); //秒针 SetRotateValue(center_pos.x,center_pos.y,sec*6+clock_angle,1); secpoint=GetRotateXY(center_pos.x,center_pos.y-CLOCK_R+2); DrawLine(center_pos.x,center_pos.y,secpoint.x,secpoint.y); //表盘 for(i=0;i<12;i++) { SetRotateValue(center_pos.x,center_pos.y,i*30+clock_angle,1); tmp1=GetRotateXY(center_pos.x,center_pos.y-CLOCK_R+1); tmp2=GetRotateXY(center_pos.x,center_pos.y-CLOCK_R+1+CLOCK_LEN); DrawLine(tmp1.x,tmp1.y,tmp2.x,tmp2.y); } // /*表盘上的数字*/ // SetRotateValue(60,30,i*30+clock_angle,1); // if(i==0) // { // tmp3=GetRotateXY(center_pos.x,center_pos.y-num_pos); // SetFontSize(1); // DrawNum(tmp3.x,tmp3.y,12,2); // } // else if(i<7) // { // SetRotateValue(62,29,i*30+clock_angle,1); // tmp3=GetRotateXY(center_pos.x,center_pos.y-num_pos); // SetFontSize(1); // DrawNum(tmp3.x,tmp3.y,i,1); // } // else if(i<10) // { // tmp3=GetRotateXY(center_pos.x,center_pos.y-num_pos); // SetFontSize(1); // DrawNum(tmp3.x,tmp3.y,i,1); // } // else if(i<12) // { // tmp3=GetRotateXY(center_pos.x,center_pos.y-num_pos); // SetFontSize(1); // DrawNum(tmp3.x,tmp3.y,i,2); // } // } DrawFillCircle(center_pos.x,center_pos.y,2);//中心圆点 DrawCircle(center_pos.x,center_pos.y,CLOCK_R); UpdateScreen(); ClearScreen(); } ~~~ ## 步数记录 代码设计过程参考了CSDN上的一篇[**博客**](https://blog.csdn.net/Dancer__Sky/article/details/81504778) 前面是一些基本的滤波以及求峰值,后面才是计算是否走步。 ~~~c filter_acc(); peak_caculate(); slid_update(&temp_acc,&mpu); detect_step(&peak_acc,&temp_acc,&mpu); ~~~ 下面是判断是否走步的代码: ~~~c void detect_step(peak_info *peak, slid_reg_t *slid, axis_info *cur_sample) { char res = is_most_active(peak); switch (res) { case MOST_ACTIVE_NULL: { //fix break; } case MOST_ACTIVE_X: { short threshold_x = (peak->max_x + peak->min_x) / 2; if (slid->old_sample.acc_x > threshold_x && slid->new_sample.acc_x < threshold_x) { step_cnt ++; } break; } case MOST_ACTIVE_Y: { short threshold_y = (peak->max_y + peak->min_y) / 2; if (slid->old_sample.acc_y > threshold_y && slid->new_sample.acc_y < threshold_y) { step_cnt ++; } break; } case MOST_ACTIVE_Z: { short threshold_z = (peak->max_z + peak->min_z) / 2; if (slid->old_sample.acc_z > threshold_z && slid->new_sample.acc_z < threshold_z) { step_cnt ++; } break; } default: break; } } ~~~ ## 简易下位机 参照我之前的[**项目**](https://www.eetree.cn/project/detail/73),这次的下位机更加简单,没有头文件和结束语句,原因是max的串口我用的不是很明白,所以简化了 ~~~c void fresh_s_time(char *temp) { while(*temp != '\0') { switch(*temp++) { case 'h': hour = (*temp-'0')*10 + (*(temp+1)-'0'); temp+=2; break; case 'm': min = (*temp-'0')*10 + (*(temp+1)-'0'); temp+=2; break; case 's': sec = (*temp-'0')*10 + (*(temp+1)-'0'); temp+=2; break; } } } ~~~ ### 上位机 也是和之前一样用的python编写 ~~~python #-*- coding: UTF-8 -*- import serial # pyserial import datetime try: # 端口:CNU; Linux上的/dev /ttyUSB0等; windows上的COM3等 portx = "COM3" # 波特率,标准值有:50,75,110,134,150,200,300,600,1200,1800,2400,4800,9600,19200,38400,57600,115200 bps = 115200 # 超时设置,None:永远等待操作; # 0:立即返回请求结果; # 其他:等待超时时间(单位为秒) timex = 5 # 打开串口,并得到串口对象 ser = serial.Serial(portx, bps, timeout=timex) # 写数据 curr_time = datetime.datetime.now() result = ser.write(datetime.datetime.strftime(curr_time,'h%Hm%Ms%S').encode("gbk")) result = ser.write(datetime.datetime.strftime(curr_time,'s%S').encode("gbk")) ser.close() # 关闭串口 except Exception as e: print("error!", e) ~~~ ## 程序流图以及各个模块 ![流程图v1.1](https://gitee.com/root__locus/pic_cloud/raw/master/流程图v1.1.png) 模块关系图: ![逻辑关系系统框图](https://gitee.com/root__locus/pic_cloud/raw/master/%E9%80%BB%E8%BE%91%E5%85%B3%E7%B3%BB%E7%B3%BB%E7%BB%9F%E6%A1%86%E5%9B%BE.png)