top of page
Writer's picture賴紀廷

血壓韌體

Updated: Dec 11, 2020

韌體

影片教學:

建立Keil專案加入lcd1602.c加入ADC.c量VR2加入DAC.c將DAC0固定輸出0VVR2調整DAC0輸出電壓VR2調整DAC1輸出電壓壓力與mmHg的校正加入UART0印Hello\nUART0輸出脈搏訊號安裝Jupyter讀取40s x 100筆脈搏訊號找峰值找谷底

建立Keil專案

建立一個Keil專案,勾選Core,Startup,SYS,UART,Timer,GPIO,DAC,ADC,CLK加入一個main.c檔,用何老師的doc網頁,把main的程式放入main.c中

#include "Nano100Series.h"
//-------------- HCLK  -------------
void init_HCLK(void){
  SYS_UnlockReg();
    CLK_EnableXtalRC(CLK_PWRCTL_HXT_EN_Msk);
    CLK_WaitClockReady( CLK_CLKSTATUS_HXT_STB_Msk);
    CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_HXT,CLK_HCLK_CLK_DIVIDER(1));
  SYS_LockReg();
}
//--------------- Systick ------------------
uint32_t tick=0;
void SysTick_Handler(void){
    tick++;
};
 
void delay_ms(uint32_t ms){
    ms += tick;
    while( ms != tick){}
}
 
//-------------- INIT  -------------
void init(void){
  init_HCLK();
    SysTick_Config( SystemCoreClock /1000);
}
 
//-------------- HCLK  -------------
int main(void){
  init();
 
  while(1){
 
  }  //while
}  //main

加入lcd1602.c

加入一個lcd1602.c檔,把lcd_1602的程式放入lcd1602.c中,并把公開的lcd_init()及lcd_print()函式copy到main.c,然後在main的init中加入

void init(void){
 init_HCLK();
 SysTick_Config(SystemCoreClock/1000);
 lcd_init();
 lcd_print(0x00,"    BPS DEMO    ");
}

Rebuild并燒錄到綠板📷

加入adc.c

在main.c檔,把ADC的程式放入,然後在main的init中加入init_ADC();在main()裡面加入

int main(void){
 init();
 while(1){
  delay_ms(100);
  ADC_START_COV();
 }
}

在ADC_IRQHandler(void)函式裡加入

void ADC_IRQHandler(void){
 char bf[32];
 uint16_t adl;
 float vr2;
 adl = ADC -> RESULT[1] & 0xFFF;
 sprintf(bf, "%4d", adl);
 lcd_print(0x40, bf);
 vr2 = adl *3.3 / 4095;
 sprintf(bf, "%.2f", vr2);
 lcd_print(0x48, bf);
 
 ADC_CLR_INT_FLAG(ADC, ADC_ADF_INT);
}

Rebuild并燒錄到綠板📷

加入dac.c

在main.c檔,把DAC0的程式放入,然後在main的init中加入init_DAC0(2048);在ADC_IRQHandler(void)函式裡加入DAC_WRITE_DATA(DAC,0,adl);Rebuild并燒錄到綠板將電表的紅線接到綠版的DAC0,黑線接GND,然後我們就可以看到DAC0傳出來的訊號📷

將DAC0固定輸出0V

在init(void)函式中修改init_DAC0(0);在ADC_IRQHandler(void)函式裡把DAC_WRITE_DATA(DAC,0,adl);這行拿掉Rebuild并燒錄到綠板

📷

VR2調整DAC0輸出電壓

📷

ARM DAC0調整壓力電壓準位可以由DAC0控制當DAC0控制時,R8R9可以不用上件調整準位到理想的位置,確保上下有盈餘度,然後取電壓(DAC0電壓為0V)

📷

VR2調整DAC1輸出電壓

📷

ARM DAC1調整壓力電壓準位可以由DAC1控制當DAC1控制時,R11R12可以不用上件調整準位到理想的位置,確保上下有盈餘度,然後取電壓(DAC1電壓為1V)

📷

📷

📷

所以我們確認DAC0的電壓是0V所以我們確認DAC1的電壓是1V

壓力與mmHg的校正

📷

對比血壓計的mmHg值跟LCD上的ADC的壓力讀數取3個樣本,例如:0mmHg,100mmHg,200mmHg時ADC的值各是多少用Python來劃出對應圖,每一個mmHg是多少ADC

📷

📷

📷

這次的結果是:1mmHg=12.985 ADC值或者是說1ADC = 0.077mmHg換算結果是:mmHg = ((ADC-503)*77+500)//1000

📷

加入UART0印Hello\n

UART0輸出脈搏訊號

📷

安裝Jupyter

官方網站去下載3.7版的Jupyter(不要下載最新版)安裝第一個畫面一定要打勾 Add Python3.7 to PATH安裝完成後,安裝Jupyterlab

pip install jupyterlab

安裝完成後,安裝Pyserial

pip install pyserial

安裝完成後,安裝Matplotlib

python -m pip install -U pip
python -m pip install -U matplotlib

用Jupyterlab讀取COMport的值

import serial
import matplotlib.pyplot as plt
plt.plot([0,100],[1000,2000])
plt.grid(True)

📷

讀取40s x 100筆脈搏訊號

ser.open()
ar=[]
for i in range(4000):
    b = ser.readline()
    ar += [b]
br = [int(e) for e in ar]
plt.plot(br)

📷

找峰值

📷

📷

📷

cr=[]
for i in range(900,2700):
  cr += [sum(br[i:i+16])//16]
plt.plot(cr)
plt.grid(True)  

plv, pdir = 100, 1
pmax, pmin = 0,5000
pt,maxn, minn = [], 0, 0
for px, py in enumerate(cr):
  pt += [py]
  if pdir ==1:
    if py > pmax:
   pmax = py
   maxn = px
 else:
   if(pmax - py) > plv:
     pdir = 0
  pmin = pmax
  else:
    if py < pmin:
   pmin = py
   minn = px
 else:
   if(py - pmin) > plv:
     pdir = 1
  break
plt.plot(pt)
plt.plot([maxn,minn], [cr[maxn],cr[minn]],'o' )
plt.grid(True)

找谷底

📷

可下載data.txt在Jupyterlab重新操作一次讀取data.txt方法可參考如下

📷

30 views0 comments

Comments


bottom of page