久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费
標題:
基于stm32單片機的智能血壓計軟件硬件設計 程序原理圖PCB
[打印本頁]
作者:
liyonghua111
時間:
2024-8-28 14:51
標題:
基于stm32單片機的智能血壓計軟件硬件設計 程序原理圖PCB
自己diy的一個小項目,還有很多可以開發!
Altium Designer畫的原理圖和PCB圖如下:(51hei附件中可下載工程文件)
51hei.png
(71.97 KB, 下載次數: 13)
下載附件
2024-8-30 00:26 上傳
51hei.png
(36.39 KB, 下載次數: 5)
下載附件
2024-8-30 00:26 上傳
單片機源程序如下:
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "i2c.h"
#include "rtc.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "oled.h" // OLED顯示屏頭文件
#include "stdio.h" // 標準輸入輸出頭文件
#include "rtc.h" // 實時時鐘頭文件
#include "led.h" // LED控制頭文件
#include "key.h" // 按鍵控制頭文件
#include "ds18B20.h" // DS18B20溫度傳感器頭文件
#include "eeprom.h" // EEPROM存儲器頭文件
//#include "adc0832.h" // ADC0832模數轉換器頭文件
#include "string.h" // 字符串處理頭文件
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define SAMPLE_COUNT 20 // 采樣次數,調整此值以改變采樣率
uint8_t screen = 0; // 當前顯示的界面:0表示第一個界面,1表示第二個界面,2表示第三個界面
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
RTC_DateTypeDef GetData; // 獲取日期結構體
RTC_TimeTypeDef GetTime; // 獲取時間結構體
uint32_t key_Tick; // 按鍵時間標志
uint16_t adc_value; // ADC讀取值
uint8_t saveEEPROM = 0; // 保存EEPROM標志
uint8_t showEEPROM = 0; // 顯示EEPROM標志
uint8_t eepromDisplayed = 0; // 新增變量,用于標記EEPROM值是否已顯示
uint8_t measureInProgress = 0; // 測量進行中的標志
uint16_t highPressure = 0; // 高壓值
uint16_t lowPressure = 0; // 低壓值
uint16_t adc_values[SAMPLE_COUNT]; // ADC采集的值數組
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void KEY_Process() // 按鍵功能處理函數
{
if (uwTick - key_Tick < 20) return; // 防抖處理,避免誤觸發
key_Tick = uwTick; // 記錄當前時間
Key_Read(); // 讀取按鍵狀態
if (Trg & 0x01) // 按鍵1按下
{
HAL_UART_Transmit(&huart3, (uint8_t*)"B", 1, 50); // 通過串口發送字符'B',語音播報:測量中,不要移動和說話
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);
screen = 1; // 切換到第2個界面
measureInProgress = 1; // 開始測量
eepromDisplayed = 0; // 重置EEPROM顯示標記
}
if (Trg & 0x02) // 按鍵2按下
{
screen = 2; // 切換到第3個界面
HAL_UART_Transmit(&huart3, (uint8_t*)"C", 1, 50);
showEEPROM = 1; // 設置顯示EEPROM標志
eepromDisplayed = 0; // 重置EEPROM顯示標記
}
if (Trg & 0x04) // 按鍵3按下
{
OLED_Clear();
screen = 0; // 切換到第1個界面
HAL_UART_Transmit(&huart3, (uint8_t*)"A", 1, 50); // 通過串口發送字符'A',語音播報:歡迎使用便攜式電子血壓計
}
if (Trg & 0x08) // 按鍵4按下
{
OLED_Clear();
screen = 3; // 切換到第1個界面
HAL_UART_Transmit(&huart3, (uint8_t*)"F", 1, 50); // 通過串口發送字符'F',語音播報:時間播報
}
}
void ADC_Process(uint8_t is_high_pressure)
{
uint32_t adc_sum = 0;
uint16_t max_value = 0;
uint16_t min_value = 0xFFFF;
for (int i = 0; i < SAMPLE_COUNT; i++) // 采樣SAMPLE_COUNT次
{
HAL_ADC_Start(&hadc1); // 啟動ADC
HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY); // 等待轉換完成
uint16_t value = HAL_ADC_GetValue(&hadc1); // 獲取ADC值
adc_values[i] = value; // 存儲ADC值
adc_sum += value; // 累加ADC值
if (value > max_value) max_value = value; // 更新最大值
if (value < min_value) min_value = value; // 更新最小值
HAL_ADC_Stop(&hadc1); // 停止ADC
HAL_Delay(100); // 100ms延時
// Count++;
// if(Count >= 80)
// {
// HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_RESET);//氣閥開始放氣
// Count = 0;
// }
}
// 使用去掉最大值和最小值后的均值
adc_sum -= max_value + min_value;
uint16_t average_value = adc_sum / (SAMPLE_COUNT - 2);
// float voltage = average_value * 3.3 / 4095.0;
float voltage = average_value * 3.3 / 1150.0;
float pressure = ((voltage - 0.5) * 300.0) / 4.0;
if (is_high_pressure)
{
highPressure = (int)(pressure * 1.2); // 保存高壓值
// highPressure = average_value; // 保存高壓值
}
else
{
lowPressure = (int)(pressure * 0.8); // 保存低壓值
// lowPressure = average_value; // 保存低壓值
}
}
/*
void Measure_Pressure()
{
measureInProgress = 1; // 開始測量
if(measureInProgress == 1)
{
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_SET);//氣閥開始充氣
for (int i = 0; i < 5; i++) // 總共采集5次數據
{
if (i < 3) // 前3次采集低壓值
{
ADC_Process(0);
}
else // 后2次采集高壓值
{
ADC_Process(1);
}
}
measureInProgress = 0; // 測量完成
}
// HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_SET);//氣閥開始充氣
// for (int i = 0; i < 5; i++) // 總共采集5次數據
// {
// if (i < 3) // 前3次采集低壓值
// {
// ADC_Process(0);
// }
// else // 后2次采集高壓值
// {
//
// ADC_Process(1);
//
// }
// }
// measureInProgress = 0; // 測量完成
if(measureInProgress == 0)
{
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_RESET);//氣閥開始放氣
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET);
if((highPressure >= 85) && (highPressure <= 130) && (lowPressure >= 60) && (lowPressure <= 85))
{
HAL_UART_Transmit(&huart1, (uint8_t*)"D", 1, 50);
}
else
{
HAL_UART_Transmit(&huart1, (uint8_t*)"E", 1, 50);
}
}
}
*/
void Measure_Pressure()
{
measureInProgress = 1; // 開始測量
uint32_t startTick = HAL_GetTick(); // 記錄開始時間
int lowPressureSamples = 0; // 低壓樣本計數
int highPressureSamples = 0; // 高壓樣本計數
// 前6秒充氣
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_SET); // 開始充氣
while ((HAL_GetTick() - startTick) < 6000) // 在7秒內
{
if (lowPressureSamples < 3) // 前3次采集低壓值
{
ADC_Process(0);
lowPressureSamples++;
}
else if (highPressureSamples < 2) // 后2次采集高壓值
{
ADC_Process(1);
highPressureSamples++;
}
}
// 停止充氣
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_RESET);
// 如果6秒內沒有采集到足夠的數據,繼續采集直到滿足條件
while (lowPressureSamples < 3 || highPressureSamples < 2)
{
if (lowPressureSamples < 3) // 前3次采集低壓值
{
ADC_Process(0);
lowPressureSamples++;
}
else if (highPressureSamples < 2) // 后2次采集高壓值
{
ADC_Process(1);
highPressureSamples++;
}
}
// 等待最后2秒放氣
while ((HAL_GetTick() - startTick) < 7000) // 總共6秒
{
// 等待
}
// 最后2秒放氣
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET); // 開始放氣
// 等待測量完成
while ((HAL_GetTick() - startTick) < 10000) // 總共10秒
{
// 等待
}
measureInProgress = 0; // 測量完成
// 檢查血壓值并發送相應的串口消息
if((highPressure >= 85) && (highPressure <= 130) && (lowPressure >= 60) && (lowPressure <= 85))
{
HAL_UART_Transmit(&huart3, (uint8_t*)"D", 1, 50);
LED1_Off();
LED2_Off();
LED3_On();
}
else
{
HAL_UART_Transmit(&huart3, (uint8_t*)"E", 1, 50);
LED1_Off();
LED2_On();
LED3_Off();
}
}
void Save_Pressure_To_EEPROM()
{
uint8_t highPressureLow = highPressure & 0xFF;
uint8_t highPressureHigh = (highPressure >> 8) & 0xFF;
At24c02_Write_Byte(0x00, &highPressureLow);
At24c02_Write_Byte(0x01, &highPressureHigh);
uint8_t lowPressureLow = lowPressure & 0xFF;
uint8_t lowPressureHigh = (lowPressure >> 8) & 0xFF;
At24c02_Write_Byte(0x02, &lowPressureLow);
At24c02_Write_Byte(0x03, &lowPressureHigh);
saveEEPROM = 0;
}
void Show_EEPROM_On_OLED()
{
uint8_t highPressureLow = 0, highPressureHigh = 0;
uint8_t lowPressureLow = 0, lowPressureHigh = 0;
At24c02_Read_Byte(0x00, &highPressureLow);
At24c02_Read_Byte(0x01, &highPressureHigh);
uint16_t savedHighPressure = (highPressureHigh << 8) | highPressureLow;
At24c02_Read_Byte(0x02, &lowPressureLow);
At24c02_Read_Byte(0x03, &lowPressureHigh);
uint16_t savedLowPressure = (lowPressureHigh << 8) | lowPressureLow;
char highPressureString[20];
char lowPressureString[20];
snprintf(highPressureString, sizeof(highPressureString), "High: %u mmHg", savedHighPressure);
snprintf(lowPressureString, sizeof(lowPressureString), "Low : %u mmHg", savedLowPressure);
OLED_ShowString(2, 2, highPressureString, 16, 0);
OLED_ShowString(2, 4, lowPressureString, 16, 0);
showEEPROM = 0;
}
//串口重定義函數
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart3, (unsigned char*)ch, 1, 50); // 通過串口發送字符
return ch; // 返回字符
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_I2C1_Init();
MX_RTC_Init();
MX_TIM1_Init();
MX_TIM6_Init();
MX_USART3_UART_Init();
MX_ADC1_Init();
/* USER CODE BEGIN 2 */
OLED_Init(); // 初始化OLED顯示屏
LED_Init(); // 初始化LED
DS18B20_Init(); // 初始化DS18B20溫度傳感器
/* 設置RTC時間 */
RTC_set_time(24, 6, 15, 16, 22, 00, RTC_FORMAT_BIN);
HAL_UART_Transmit(&huart3, (uint8_t*)"A", 1, 50); // 通過串口發送字符'A',語音播報:歡迎使用便攜式電子血壓計
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
if (HAL_GetTick() % 300 == 0) // 每300ms執行一次
{
if (screen == 0) // 顯示時間和日期的界面
{
// HAL_RTC_GetDate(&hrtc, &GetData, RTC_FORMAT_BIN); // 獲取日期
// HAL_RTC_GetTime(&hrtc, &GetTime, RTC_FORMAT_BIN); // 獲取時間
// char timeString[20];
// snprintf(timeString, sizeof(timeString), "Time: %02d:%02d:%02d", GetTime.Hours, GetTime.Minutes, GetTime.Seconds); // 格式化時間字符串
// char dateString[20];
// snprintf(dateString, sizeof(dateString), "Date: %02d-%02d-%02d", GetData.Year, GetData.Month, GetData.Date); // 格式化日期字符串
// 第一行顯示12x12大小的漢字
OLED_ShowCHinese(2, 0, 0, 12, 0); // 顯示漢字"歡"
OLED_ShowCHinese(14, 0, 1, 12, 0); // 顯示漢字"迎"
OLED_ShowCHinese(26, 0, 2, 12, 0); // 顯示漢字"使"
OLED_ShowCHinese(38, 0, 3, 12, 0); // 顯示漢字"用"
OLED_ShowCHinese(50, 0, 4, 12, 0); // 顯示漢字"便"
OLED_ShowCHinese(62, 0, 5, 12, 0); // 顯示漢字"攜"
OLED_ShowCHinese(74, 0, 6, 12, 0); // 顯示漢字"式"
OLED_ShowCHinese(86, 0, 7, 12, 0); // 顯示漢字"血"
OLED_ShowCHinese(98, 0, 8, 12, 0); // 顯示漢字"壓"
OLED_ShowCHinese(110, 0, 9, 12, 0); // 顯示漢字"計"
// 第二行顯示16x16大小的漢字
OLED_ShowCHinese(2, 2, 0, 16, 0); // 顯示漢字"溫"
OLED_ShowCHinese(18, 2, 1, 16, 0); // 顯示漢字"度"
OLED_ShowCHinese(34, 2, 2, 16, 0); // 顯示漢字"值"
OLED_ShowCHinese(98, 2, 3, 16, 0); // 顯示漢字"℃"
float temperature = DS18B20_Get_Temperature(); // 獲取溫度
char tempString[20];
snprintf(tempString, sizeof(tempString), ":%.2f", temperature); // 格式化溫度字符串
OLED_ShowString(50, 2, tempString, 16, 0); // 顯示溫度
char pressureString[20];
snprintf(pressureString, sizeof(pressureString), "000mmHg");
OLED_ShowString(2, 4, pressureString, 16, 0); // 顯示默認的血壓值
}
else if (screen == 1) // 顯示測量血壓的界面
{
if (measureInProgress) // 測量進行中
{
LED1_On();
HAL_Delay(200);
LED1_Off();
HAL_Delay(200);
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_7);
OLED_Clear();
OLED_ShowCHinese(40, 2, 4, 16, 0); // 顯示"測量中"的中文字符
OLED_ShowCHinese(56, 2, 5, 16, 0);
OLED_ShowCHinese(72, 2, 6, 16, 0);
Measure_Pressure(); // 調用測量血壓函數,一直等待測量,測量完才進行下列代碼
OLED_Clear();
OLED_ShowCHinese(2, 2, 7, 16, 0); // 顯示高壓和低壓的中文字符
OLED_ShowCHinese(18, 2, 8, 16, 0);
OLED_ShowCHinese(2, 4, 9, 16, 0);
OLED_ShowCHinese(18, 4, 10, 16, 0);
char highPressureString[20];
snprintf(highPressureString, sizeof(highPressureString), ": %u mmHg", highPressure); // 格式化高壓字符串
OLED_ShowString(36, 2, highPressureString, 16, 0); // 顯示高壓
char lowPressureString[20];
snprintf(lowPressureString, sizeof(lowPressureString), ": %u mmHg", lowPressure); // 格式化低壓字符串
OLED_ShowString(36, 4, lowPressureString, 16, 0); // 顯示低壓
Save_Pressure_To_EEPROM(); // 保存血壓值到EEPROM
eepromDisplayed = 1; // 標記EEPROM已顯示
}
}
else if (screen == 2) // 顯示EEPROM數據的界面
{
if (!eepromDisplayed) // 如果EEPROM數據尚未顯示
{
OLED_Clear();
Show_EEPROM_On_OLED(); // 顯示EEPROM中的血壓數據
eepromDisplayed = 1; // 標記EEPROM已顯示
}
}
else if(screen == 3)
{
HAL_RTC_GetDate(&hrtc, &GetData, RTC_FORMAT_BIN); // 獲取當前日期
HAL_RTC_GetTime(&hrtc, &GetTime, RTC_FORMAT_BIN); // 獲取當前時間
char timeString[20];
snprintf(timeString, sizeof(timeString), "Time: %02d:%02d:%02d", GetTime.Hours, GetTime.Minutes, GetTime.Seconds); // 格式化時間字符串
char dateString[20];
snprintf(dateString, sizeof(dateString), "Date: %02d-%02d-%02d", GetData.Year, GetData.Month, GetData.Date); // 格式化日期字符串
/* 顯示界面 */
OLED_ShowCHinese(28, 0, 12, 16, 0); // 顯示“時”
OLED_ShowCHinese(44, 0, 13, 16, 0); // 顯示“間”
OLED_ShowCHinese(60, 0, 14, 16, 0); // 顯示“顯”
OLED_ShowCHinese(76, 0, 15, 16, 0); // 顯示“示”
OLED_ShowString(5, 4, timeString, 16, 0); // 顯示時間
OLED_ShowString(5, 2, dateString, 16, 0); // 顯示日期
}
}
KEY_Process(); // 按鍵處理
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE|RCC_OSCILLATORTYPE_LSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
……………………
…………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
資料51hei附件下載:
程序源碼.7z
(436.66 KB, 下載次數: 22)
2024-8-30 00:28 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
PCB Project.7z
(3.41 MB, 下載次數: 24)
2024-8-30 00:28 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
歡迎光臨 (http://m.zg4o1577.cn/bbs/)
Powered by Discuz! X3.1
主站蜘蛛池模板:
精品一区在线
|
国产精品国产成人国产三级
|
欧美成人h版在线观看
|
一本色道久久综合亚洲精品高清
|
日日淫
|
99国产精品99久久久久久
|
亚洲福利在线观看
|
日本精品久久久一区二区三区
|
一区二区三区四区在线视频
|
欧美成人精品一区二区男人看
|
男女网站视频
|
爱草视频
|
久久国产婷婷国产香蕉
|
一区二区三区四区电影
|
欧美日韩国产高清
|
久久综合一区
|
蜜桃在线视频
|
男女久久久
|
日韩欧美一区二区三区四区
|
中文字幕日韩专区
|
午夜手机在线视频
|
日韩一区在线观看视频
|
日韩欧美在线免费
|
久久精品国产免费看久久精品
|
就操在线
|
久国产视频
|
www国产亚洲精品久久网站
|
欧美精品一区二区三区蜜桃视频
|
亚洲精品欧美
|
久久综合婷婷
|
亚洲第一av
|
91欧美激情一区二区三区成人
|
成人精品一区亚洲午夜久久久
|
www.成人免费视频
|
在线观看电影av
|
亚洲毛片网站
|
日本一区二区三区免费观看
|
久久国产精品偷
|
国产二区精品视频
|
caoporn国产精品免费公开
|
国产一区欧美一区
|