EEWORLD DIY——我的健康手环

交互设计

  两周时间又过去了,今天在这里记录一下这两周所做的事情。上上篇我们已经把硬件全部弄就绪,这两周主要是软件部分。软件部分主要是1、实现LCD的驱动2、实现心跳数据测量 3、实现体温的测量 4、时钟表的实现 我的健康手环显示部分使用Nokia5110,这比较老了,现在已经没有生产了,市面上能看到的基本上都是拆机的。不过使用起来挺简单了。它的主要特点是 1、单芯片 LCD 控制/驱动 2、48 行,84 列输出 3、显示数据 RAM 48*84 位,至于它的使用我这里也不多啰嗦了,有兴趣的朋友可以直接到网上搜索。我这里给出在stm32f103的驱动部分。 显示部份有了,接下来就是最重要的体温和心跳部分的数据显示了。 体温用的是DS18b20,这个网上的资料也是分析的很透彻。我就不再把其它地方的资料再搬上来了。只接用代码说话吧。 [C] 纯文本查看 复制代码 ? 001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 /** ****************************************************************************** * @file ds18b20.c * @author sun xiao wu * @version V1.0.0 * @date 2022/11/09 * @brief DS18B20温度传感器驱动文件 ****************************************************************************** */ #include "ds18b20.h" #include "delay.h" /** * @brief 复位DS18B20. * @note 单总线复位,总线主机拉低总线至少480us. 然后释放总线 * @param[in] none * @param[out] none. * @retval none * @par 标识符 * 保留 * @par 其它 * 无 * @par 修改日志 * sun xiao wu于2022-11-01创建 */ void DS18B20_Rst(void) { DS18B20_IO_OUT(); //SET PA11 OUTPUT DS18B20_DQ_OUT=0; //拉低DQ HAL_Delay_us(550); //拉低550us DS18B20_DQ_OUT=1; //DQ=1 HAL_Delay_us(15); //15US } /** * @brief 等待DS18B20的回应. * @note 在单总线复位后,检测总线上是否有60-240s 的低电平信号. * @param[in] none * @param[out] none. * @retval 返回1:未检测到DS18B20的存在 * 返回0:存在 * @par 标识符 * 保留 * @par 其它 * 无 * @par 修改日志 * sun xiao wu于2022-11-01创建 */ uint8_t DS18B20_Check(void) { //重试次数 u8 retry=0; DS18B20_IO_IN();//SET PA11 INPUT while (DS18B20_DQ_IN && retry<200) { retry++; HAL_Delay_us(1); }; if(retry>=200) return 1; else retry=0; while (!DS18B20_DQ_IN && retry<240) { retry++; HAL_Delay_us(1); }; if(retry>=240) return 1; return 0; } /** * @brief 从DS18B20读取一个bit位. * * @param[in] none * @param[out] none. * @retval 返回1,0 * @par 标识符 * 保留 * @par 其它 * 无 * @par 修改日志 * sun xiao wu于2022-11-01创建 */ uint8_t DS18B20_Read_Bit(void) // read one bit { u8 data; DS18B20_IO_OUT();//SET PA11 OUTPUT DS18B20_DQ_OUT=0; //r拉低总线 HAL_Delay_us(2); DS18B20_DQ_OUT=1; //释放总线 HAL_Delay_us(12); DS18B20_IO_IN();//SET PA11 INPUT if(DS18B20_DQ_IN) data=1; else data=0; HAL_Delay_us(50); //时隙持续时间的要求(至少60μs) return data; } /** * @brief 从DS18B20读取一个字节. * * @param[in] none * @param[out] none. * @retval 返回了个字节数据 * @par 标识符 * 保留 * @par 其它 * 无 * @par 修改日志 * sun xiao wu于2022-11-01创建 */ uint8_t DS18B20_Read_Byte(void) // read one byte { u8 i,j,dat; dat=0; for (i=1;i<=8;i++) { j=DS18B20_Read_Bit(); dat=(j<<7) (dat>>1); } return dat; } /** * @brief 写一个字节到DS18B20. * * @param[in] dat 要写入的字节 * @param[out] none. * @retval none * @par 标识符 * 保留 * @par 其它 * 无 * @par 修改日志 * sun xiao wu于2022-11-01创建 */ void DS18B20_Write_Byte(uint8_t dat) { u8 j; u8 testb; DS18B20_IO_OUT();//SET PA11 OUTPUT; for (j=1;j<=8;j++) { testb=dat&0x01; dat=dat>>1; if (testb) { DS18B20_DQ_OUT=0;// Write 1 HAL_Delay_us(2); DS18B20_DQ_OUT=1; HAL_Delay_us(60); } else { DS18B20_DQ_OUT=0;// Write 0 HAL_Delay_us(60); DS18B20_DQ_OUT=1; HAL_Delay_us(2); } } } /** * @brief 启动DS18B20进行温度转换. * * @param[in] none * @param[out] none. * @retval none * @par 标识符 * 保留 * @par 其它 * 无 * @par 修改日志 * sun xiao wu于2022-11-01创建 */ void DS18B20_Start(void)// ds1820 start convert { DS18B20_Rst(); DS18B20_Check(); DS18B20_Write_Byte(0xcc);// skip rom DS18B20_Write_Byte(0x44);// convert } /** * @brief 初始化DS18B20的IO口 DQ 同时检测DS的存在. * * @param[in] none * @param[out] none. * @retval 0:不存在 * 1:存在 * @par 标识符 * 保留 * @par 其它 * 无 * @par 修改日志 * sun xiao wu于2022-11-01创建 */ uint8_t DS18B20_Init(void) { GPIO_InitTypeDef gpio_1; //RCC->APB2ENR =1<<8; //使能PORTG口时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); // GPIOA->CRH&=0XFFFF0FFF;//PORTA.11 推挽输出 // GPIOA->CRH =0X00003000; // GPIOA->ODR =1<<11; //输出1 gpio_1.GPIO_Mode = GPIO_Mode_Out_PP; gpio_1.GPIO_Pin = GPIO_Pin_11; gpio_1.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOA,&gpio_1); GPIO_SetBits(GPIOA,GPIO_Pin_11); DS18B20_Rst(); return DS18B20_Check(); } /** * @brief 从ds18b20得到温度值. * @note 精度:0.1C * @param[in] none * @param[out] none. * @retval 温度值 (-550~1250) * @par 标识符 * 保留 * @par 其它 * 无 * @par 修改日志 * sun xiao wu于2022-11-01创建 */ float DS18B20_Get_Temp(void) { uint8_t temp; uint8_t TL,TH; short tem; float result; DS18B20_Start (); // ds1820 start convert DS18B20_Rst(); DS18B20_Check(); DS18B20_Write_Byte(0xcc);// skip rom DS18B20_Write_Byte(0xbe);// convert HAL_Delay_ms(750); TL=DS18B20_Read_Byte(); // LSB TH=DS18B20_Read_Byte(); // MSB if(TH>7) { TH=~TH; TL=~TL; temp=0;//温度为负 }else temp=1;//温度为正 tem=TH; //获得高八位 tem<<=8; tem+=TL;//获得底八位 result=(float)tem*0.0625;//转换 if(temp) return result; //返回温度值 else return -result; } /************************************************************************************** * 名 称: adjust_res * 功 能: 调整分辨率 * 参 数: 分辨率值 * 返 回 值: 无 **************************************************************************************/ void adjust_res(unsigned char res) ///res 分别等于 0x1f, 0x3f, 0x5f,0x7f温度读数分辨率分别对应 0.5, 0.25, 0.125,0.0625 { DS18B20_Rst(); //复位 DS18B20_Write_Byte(0xcc); //跳过Rom DS18B20_Write_Byte(0x4e); //写暂存器 DS18B20_Write_Byte(0x02); //写TH DS18B20_Write_Byte(0x01); //写TL DS18B20_Write_Byte(res); //写结构寄存器 DS18B20_Rst(); //复位 DS18B20_Write_Byte(0xcc); //跳过Rom DS18B20_Write_Byte(0x48); //把暂存器内容写到EPRam中 } 接下来的部分就是心率的测量了,这部分看了SON1303的资料,觉得可以用外部中断上升沿下降沿和定时器可以解决问题,可是以测试的时候发现外部中断很不稳定,心跳有抖动。没办法用外部中断,所以想了个笨的办法,直接测高低电平的时间,这样即便是在高电平上有点小的抖动,也能很好的去抖动。代码了做了详细的注释,大这看就能看明白。 [C] 纯文本查看 复制代码 ? 001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 /** ****************************************************************************** * @file son1303.c * @author sun xiao wu * @version V1.0.0 * @date 2022/11/16 * @brief 心率传感器son1303驱动文件 ****************************************************************************** */ #include "son1303.h" HEARTRATE Hreat; //心率 uint32_t risingTimes = 0; //高电平持续时间 ms uint32_t fallingTimes = 0; //低电平持续时间 ms /** @brief: SON1303的GPIO初始化,PB3开启心跳仪,PB4心跳输入 @param: None @return: None */ void SON1303_GPIO_init(void) { GPIO_InitTypeDef gpio_t; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); gpio_t.GPIO_Pin = GPIO_Pin_3; gpio_t.GPIO_Mode = GPIO_Mode_Out_PP; gpio_t.GPIO_Speed = GPIO_Speed_10MHz; GPIO_Init(GPIOB,&gpio_t); GPIO_ResetBits(GPIOB,GPIO_Pin_3); gpio_t.GPIO_Pin = GPIO_Pin_4; gpio_t.GPIO_Mode = GPIO_Mode_IN_FLOATING; gpio_t.GPIO_Speed = GPIO_Speed_10MHz; GPIO_Init(GPIOB,&gpio_t); } /** @brief: SON1303传感器初始化,PB4心跳输入 @param: None @return: None */ void SON1303_init(void) { NVIC_InitTypeDef nvic_1; TIM_TimeBaseInitTypeDef tim_t; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); /*心跳计时 TIM3 1000Hz 1ms*/ TIM_TimeBaseStructInit(&tim_t); tim_t.TIM_CounterMode = TIM_CounterMode_Up; tim_t.TIM_Period = 2000-1; tim_t.TIM_ClockDivision = TIM_CKD_DIV1; tim_t.TIM_Prescaler = 35; TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); TIM_TimeBaseInit(TIM3,&tim_t); nvic_1.NVIC_IRQChannel = TIM3_IRQn; nvic_1.NVIC_IRQChannelPreemptionPriority = 0; nvic_1.NVIC_IRQChannelSubPriority = 1; nvic_1.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&nvic_1); } /** @brief: 启动 SON1303传感器 @param: None @return: None */ void SON1303_start(void) { GPIO_SetBits(GPIOB,GPIO_Pin_3); TIM_Cmd(TIM3,ENABLE); } /** @brief: 停止 SON1303传感器 @param: None @return: None */ void SON1303_stop(void) { GPIO_ResetBits(GPIOB,GPIO_Pin_3); TIM_Cmd(TIM3,DISABLE); } /** @brief: 计算心率 @param: None @return: 心率 */ uint32_t CalcHeartRate(void) { uint32_t result = 0; uint32_t avg = 0; if(Hreat.TestStable) { avg = TESTCOUNT; int maxHeart = 0; int minHeart = 0; for(int i=0; i<avg; i++) { maxHeart = maxHeart > Hreat.HeartRate[i] ? maxHeart : Hreat.HeartRate;[/i] minHeart = minHeart < Hreat.HeartRate ? minHeart : Hreat.HeartRate; result += Hreat.HeartRate; } result = result - maxHeart - minHeart; avg = TESTCOUNT - 2; } else { avg = Hreat.TestTimes; for(int i=0; i<avg; i++) result += Hreat.HeartRate; } result = result / avg; return result; } /** @brief: 配置PA2为ADC,检测是否配带,PA2 @param: None @return: None */ void SON1303_ADC_init() { GPIO_InitTypeDef gpio_t; ADC_InitTypeDef adc_t; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA RCC_APB2Periph_ADC1,ENABLE); RCC_ADCCLKConfig(RCC_PCLK2_Div6); gpio_t.GPIO_Pin = GPIO_Pin_2; gpio_t.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(GPIOA,&gpio_t); ADC_DeInit(ADC1); adc_t.ADC_Mode = ADC_Mode_Indepent; adc_t.ADC_ScanConvMode = DISABLE; adc_t.ADC_ContinuousConvMode = DISABLE; adc_t.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; adc_t.ADC_DataAlign = ADC_DataAlign_Right; adc_t.ADC_NbrOfChannel = 1; ADC_Init(ADC1,&adc_t); ADC_Cmd(ADC1,ENABLE); ADC_RegularChannelConfig(ADC1,ADC_Channel_2,1,ADC_SampleTime_239Cycles5); ADC_ResetCalibration(ADC1); while(ADC_GetResetCalibrationStatus(ADC1)); ADC_StartCalibration(ADC1); while(ADC_GetCalibrationStatus(ADC1)); } /** @brief: 检测是否配带 @param: None @return: 配带返回true */ bool IsWeared(void) { ADC_SoftwareStartConvCmd(ADC1,ENABLE); while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)); uint32_t adValue = ADC_GetConversionValue(ADC1); return (adValue<0xD20); } void TIM3_IRQHandler(void) { /*PB4 心跳输入*/ static uint8_t last_status = 0; if(TIM_GetITStatus(TIM3,TIM_IT_Update) == SET) { if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_4) == Bit_SET) { /*上次状态是0,证明心跳了一次*/ if(last_status == 0) { uint32_t sumTimes = risingTimes + fallingTimes;//心跳一次的总时间 uint32_t tmp = 60000 / sumTimes; //一分钟是60000ms /**/ if(tmp > 50 && tmp < 200) { if(Hreat.TestTimes >=TESTCOUNT) { Hreat.TestTimes = 0; } Hreat.HeartRate[Hreat.TestTimes] = tmp; Hreat.TestTimes++; } risingTimes = 0; } last_status = 1; risingTimes++;//增加高电平的时间 } else { if(last_status == 1) fallingTimes = 0; last_status = 0; fallingTimes++;//增加低电平的时间 } TIM_ClearITPingBit(TIM3,TIM_IT_Update); } } 接下来就是主程序文件。这个逻辑就简单很多。 [C] 纯文本查看 复制代码 ? 001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 /** ****************************************************************************** * @file mainc.c * @author sun xiao wu * @version V1.0.0 * @date 2022/11/06 * @brief 穿戴数据终端主程序文件 ****************************************************************************** */ #include "stm32f10x.h" // Device header #include "LCD5110.h" #include "ds18b20.h" #include "son1303.h" #include "delay.h" #include "rtc.h" #include "key.h" #include <stdio.h> #include <time.h> void Clock_Init(void); char printBuffer[16]; extern LCD_Output_Number lcd_output_number; extern bool Key_Mode_Press; extern bool Key_Back_Press; extern bool Key_Up_Press; extern bool Key_Down_Press; extern enum KeySelect KeyValue; extern uint32_t LedDelay; extern bool bShowHeart; //显示心跳和体温标记 int ShowStatus=0; void GPIO_Configuration(void); void Show_time(void); void Show_Temperature(void); void Show_HeartRate(void); void Show_Logo(void); void Show_Power(void); int main() { //时钟初始化 Clock_Init(); GPIO_Configuration(); RTC_init(); //延时初始化 HAL_Delay_Init(); //DS18B20初始化 DS18B20_Init(); //心率传感器初始化 SON1303_init(); SON1303_ADC_init(); //Nokia5110初始化 LCD_init(); LCD_clear(); KEY_GPIO_init(); KEY_NVIC_init(); SON1303_start(); for(;;) { //交替显示心跳和体温 if(bShowHeart) { if(ShowStatus == 1) { /*如果是从显示体温界面转过来,则进行清屏,防止脱影*/ LCD_clear(); } Show_HeartRate(); ShowStatus = 0; } else { if(ShowStatus == 0) { /*如果是从显示心跳界面转过来,则进行清屏,防止脱影*/ LCD_clear(); } Show_Temperature(); ShowStatus = 1; } //显示EEWORLD DIY Show_Logo(); //显示电量 Show_Power(); //显示时间 Show_time(); HAL_Delay_ms(200); } } /** @brief: stm32芯片时钟初始化 @param: None @return: None */ void Clock_Init(void) { // RCC_DeInit(); // /* Enable HSE */ // RCC_HSEConfig(RCC_HSE_ON); // /* Wait till HSE is ready and if Time out is reached exit */ // while(!RCC_WaitForHSEStartUp()); // /* Configure HCLK such as HCLK = SYSCLK */ // RCC_HCLKConfig(RCC_SYSCLK_Div1); // /* Configure PCLK1 such as PCLK1 = HCLK/2 */ // RCC_PCLK1Config(RCC_HCLK_Div2); // /* Configure PCLK2 such as PCLK2 = HCLK */ // RCC_PCLK2Config(RCC_HCLK_Div1); // // FLASH_SetLatency(FLASH_Latency_2); // FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); // // /* Set PLL clock output to 72MHz using HSE (8MHz) as entry clock */ // RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9); // /* Enable the PLL */ // RCC_PLLCmd(ENABLE); // while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); // // /* Select the PLL as system clock source */ // RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); // while(RCC_GetSYSCLKSource() != 0x08); } /** @brief: GPIO初始化 @param: None @return: None */ void GPIO_Configuration(void) { LCD_GPIO_init(); SON1303_GPIO_init(); } /** @brief: 显示时间 @param: None @return: None */ void Show_time(void) { uint32_t t = RTC_GetCounter(); struct tm *ptm = localtime(&t); if(LedDelay>0) BkLED_On; else BkLED_Off; if(Key_Mode_Press) { switch(KeyValue) { case Hour: lcd_output_number = LCD_write_inverse_shu; lcd_output_number(2,4,ptm->tm_hour/10); lcd_output_number(3,4,ptm->tm_hour%10); lcd_output_number = LCD_write_shu; lcd_output_number(4,4,47); lcd_output_number(5,4,ptm->tm_min/10); lcd_output_number(6,4,ptm->tm_min%10); lcd_output_number(7,4,47); lcd_output_number(8,4,ptm->tm_sec/10); lcd_output_number(9,4,ptm->tm_sec%10); break; case Minute: lcd_output_number(2,4,ptm->tm_hour/10); lcd_output_number(3,4,ptm->tm_hour%10); lcd_output_number(4,4,47); lcd_output_number = LCD_write_inverse_shu; lcd_output_number(5,4,ptm->tm_min/10); lcd_output_number(6,4,ptm->tm_min%10); lcd_output_number = LCD_write_shu; lcd_output_number(7,4,47); lcd_output_number(8,4,ptm->tm_sec/10); lcd_output_number(9,4,ptm->tm_sec%10); break; case Second: lcd_output_number(2,4,ptm->tm_hour/10); lcd_output_number(3,4,ptm->tm_hour%10); lcd_output_number(4,4,47); lcd_output_number(5,4,ptm->tm_min/10); lcd_output_number(6,4,ptm->tm_min%10); lcd_output_number(7,4,47); lcd_output_number = LCD_write_inverse_shu; lcd_output_number(8,4,ptm->tm_sec/10); lcd_output_number(9,4,ptm->tm_sec%10); lcd_output_number = LCD_write_shu; break; } } else { LCD_write_shu(2,4,ptm->tm_hour/10); LCD_write_shu(3,4,ptm->tm_hour%10); LCD_write_shu(4,4,47); LCD_write_shu(5,4,ptm->tm_min/10); LCD_write_shu(6,4,ptm->tm_min%10); LCD_write_shu(7,4,47); LCD_write_shu(8,4,ptm->tm_sec/10); LCD_write_shu(9,4,ptm->tm_sec%10); } //LCD_write_hanzi(0,4,0); } /** @brief: 显示温度 @param: None @return: None */ void Show_Temperature(void) { int temperature = (int)DS18B20_Get_Temp(); LCD_write_hanzi(4,2,8); int x = temperature / 10; LCD_write_digital(2,2,x); x = temperature % 10; LCD_write_digital(3,2,x); } /** @brief: 显示心率 @param: None @return: None */ void Show_HeartRate(void) { uint32_t hr = CalcHeartRate(); LCD_write_hanzi(0,2,11); int x = hr / 100; LCD_write_digital(2,2,x); x = (hr % 100) / 10; LCD_write_digital(3,2,x); x = hr % 10; LCD_write_digital(4,2,x); } /** @brief: 显示LOGO @param: None @return: None */ void Show_Logo(void) { LCD_write_String(0,0,"EEWORLD DIY"); } /** @brief: 显示电量 @param: None @return: None */ void Show_Power(void) { //LCD_write_shu(0,1,48); } 按键部分,延时部分,RTC时间的代码我就不贴了,贴出来太多了。如果有人需要跟贴,我就把它们也贴出来。 还有一部分工作没有完成,就是电量显示,和低功耗部分。这部分在后面会慢慢实现。 先看下目前完成的情况。 操作视频: 这两天不知道怎么的,手上起了很多水泡,网上查了下是汗泡疹。大家有没有什么好的治疗办法分享一下,手上很多泡实在是很痒。

标签: 交互设计