两周时间又过去了,今天在这里记录一下这两周所做的事情。上上篇我们已经把硬件全部弄就绪,这两周主要是软件部分。软件部分主要是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时间的代码我就不贴了,贴出来太多了。如果有人需要跟贴,我就把它们也贴出来。
还有一部分工作没有完成,就是电量显示,和低功耗部分。这部分在后面会慢慢实现。
先看下目前完成的情况。
操作视频:
这两天不知道怎么的,手上起了很多水泡,网上查了下是汗泡疹。大家有没有什么好的治疗办法分享一下,手上很多泡实在是很痒。
EEWORLD DIY——我的健康手环
上一篇:「首席架构师推荐」数值计算库精选
下一篇:返回列表