BASIC4MCU | 질문게시판 | atmega128 uart 질문입니다.
페이지 정보
작성자 bme12 작성일2023-06-05 01:03 조회593회 댓글1건본문
#define F_CPU 16000000UL
#include
#include
#include
#include
#include
#include
#include
#include
#define ADC_VREF_TYPE 0x40
#define moving_size 8
#define diff_size 5
#define lpf_size 5
#define threshold 300
volatile unsigned long filter_data = 0;
volatile unsigned short int ecg_data = 0;
volatile unsigned int heart_rate = 0;
volatile unsigned int filter_high, filter_low, moving_high, moving_low =0;
volatile bool timerflag = 0;
unsigned int read_adc(unsigned char adc_input)
{
ADMUX=adc_input | (ADC_VREF_TYPE & 0xff);
_delay_us(10);
ADCSRA|=0x40; //변환 시작(single conversion mode이기 떄문)
while ((ADCSRA & 0x10)==0); //ADC 변환 확인(값이 0일시 무한루프)
ADCSRA|=0x10; //ADC 변환 완료 flag실행
return ADCW; //ADCW = ADCH + ADCL 값 반환
}
//8-point moving average
unsigned long moving_avg[moving_size] = {0}; //연산 과정에서 오차를 줄이기 위해 실수 타입 사용
void moving_average(void)
{
int i=0;
int moving_sum=0; //MA filter result
moving_avg[0]=ecg_data; //refreshing data
for(i=0;i;i++){<>
moving_sum += moving_avg[i]; //data summing
}
for(i=moving_size-1;i>0;i--){
moving_avg[i]=moving_avg[i-1]; //data shift
}
moving_sum=moving_sum/moving_size; //averaging data
moving_high = moving_sum>>8; //Moving Average Filter 통과한 값 변수에 저장
moving_low = moving_sum;
}
signed long diff_filter[diff_size]= {0};
signed long lpf_filter[lpf_size]= {0};
void ecg_filter(void) //data digital filtering
{
int i;
diff_filter[0]=moving_high | moving_low;
lpf_filter[0]=diff_filter[0]-diff_filter[4]; //5SAMPLE HPF
filter_data=lpf_filter[0]+4*lpf_filter[1]+6*lpf_filter[2]+4*lpf_filter[3]+lpf_filter[4]; //FIR LPF
for(i=diff_size-1;i>0;i--){
diff_filter[i]=diff_filter[i-1]; //data spread
}
for(i=lpf_size-1;i>0;i--){
lpf_filter[i]=lpf_filter[i-1]; //data spread
}
filter_high=filter_data>>8;
filter_low=filter_data;
}
unsigned char delay = 0;
void peak_detection()
{
static int rr_interval = 0;
static int sampling_rate = 400;
if(filter_data>threshold && delay > 200){ //1CTC당 1ms
heart_rate=60*sampling_rate/rr_interval; //심박이 60~100의 주파수, 최대주파수 100의 4배
delay=0;
rr_interval=0;
}
else{
delay++;
rr_interval++;
}
}
ISR(TIMER0_COMP_vect)
{
peak_detection();
timerflag=1;
}
int main(void)
{
ADMUX=ADC_VREF_TYPE & 0xff; //외부 AVCC핀을 기준 전압(reference voltage)로 사용, data 오른쪽 정렬, ADC0 pin 사용
ADCSRA=0x84; //ADC enable, 16 prescaler = 1MHZ (1clock = 1us), single conversion mode
TCCR0=0x05; //분주비 128
OCR0=0x7D; //1ms
TIMSK=0x02; //compare-match interrupt enable
sei(); //global interrupt enable
DDRD=0xff; //portD output mode
UCSR0A=0x00; //8비트데이터, 패리티 없음, 1비트 정지모드
UCSR0B=0x08; //UART송신 기능 활성화
UCSR0C=0x06; //전송 비트수=8
UBRR0H=0x00; //115200 baud rate
UBRR0L=0x08; //for asynchronous mode baud rate
while (1)
{
if(timerflag==1){
OCR0=0x7D; //1ms
timerflag=0; //flag reset
}
ecg_data=read_adc(0); //ADCW값 입력
putchar(ecg_data); //raw data
putchar(moving_high<<8 | moving_low); //moving data
putchar(filter_high<<8 | filter_low); //filter data
putchar(heart_rate); //heart data
};
}
ECG는 리얼 데이터가 아니라 시뮬레이터 장비로 테스트를 했습니다.
80 bpm을 출력하도록 시뮬레이터 장비를 설정했습니다.
PORTF0 핀에 ecg신호를 입력했습니다.
amtega128에서 moving average filter, ecg filter, peak detector
등의 알고리즘을 참조했습니다.
MCU는 ATMEGA128를 사용했습니다.
시리얼 통신을 통하여 데이터를 전송했습니다.
위 코드가 맞는지 확인하기 위해서 EBTerminal이라는 프로그램을 사용하여 putchar로 보낸 데이터 값을 확인하려는 데 밑 사진에 open을 눌러도 아무것도 뜨질 않습니다.
코드가 어디가 잘못됐는지 chat gpt, 인터넷 등을 아무리 뒤져봐도 나오질 않았고 돌고 돌던 중, 이 사이트를 찾아 글을 써봅니다..
혹시 도움을 주실 분이 계실까요..?
댓글 1
조회수 593master님의 댓글
master 작성일
while (1){
putchar('1');
_delay_ms(1000);
}
}
통신 테스트는 간단한 코드로 하세요