BASIC4MCU | 질문게시판 | 타이머/UART 인터럽트부분 질문있습다.
페이지 정보
작성자 choi 작성일2020-11-27 16:16 조회4,258회 댓글1건본문
CTMS-03 시리즈 비접촉적외선센서 uart통신을 통해 센서값을 받아서 정상체온정도 나오면 LED점등하는식으로 확인하려합니다.
제가보기엔 인터럽트 2개 초기화부분이 잘못된거같은데 혹시 확인해주실수있나요? ㅠㅠ
#include<stdio.h> //빌드완료
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#define F_CPU 16000000UL
#define U_C unsigned char
#define U_I unsigned int
#define U_L unsigned long
volatile uint8_t Timer1_Flag = 0; // Timer1 flag
volatile uint8_t RX_CNT;
uint8_t TX_BUF[8], RX_BUF[13];
uint16_t crc16, au16regs[4];
float RawData, CompData, SensData;
const uint16_t TableCRC16[256] = { // CRC table
0x0, 0xC0C1, 0xC181, 0x140, 0xC301, 0x3C0, 0x280, 0xC241, 0xC601, 0x6C0, 0x780, 0xC741, 0x500, 0xC5C1, 0xC481, 0x440, 0xCC01, 0xCC0, 0xD80, 0xCD41,
0xF00, 0xCFC1, 0xCE81, 0xE40, 0xA00, 0xCAC1, 0xCB81, 0xB40, 0xC901, 0x9C0, 0x880, 0xC841, 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, 0xD201, 0x12C0, 0x1380, 0xD341,
0x1100, 0xD1C1, 0xD081, 0x1040, 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, 0x2800, 0xE8C1, 0xE981, 0x2940,
0xEB01, 0x2BC0, 0x2A80, 0xEA41, 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, 0x6600, 0xA6C1, 0xA781, 0x6740,
0xA501, 0x65C0, 0x6480, 0xA441, 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, 0xB401, 0x74C0, 0x7580, 0xB541,
0x7700, 0xB7C1, 0xB681, 0x7640, 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, 0x5A00, 0x9AC1, 0x9B81, 0x5B40,
0x9901, 0x59C0, 0x5880, 0x9841, 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
};
void TX1_CH(U_C ch) { while (!(UCSR1A & 0x20)); UDR1 = ch; } // 송신 1바이트
void TX1_STR(U_C* str) { while (*str)TX1_CH(*str++); } // 문자열 송신함수
//
ISR(USART1_RX_vect)
{
RX_BUF[RX_CNT++];
}
void USART1_Init(long baud)
{
unsigned int ubrr = F_CPU / 8 / baud - 1 + 0.5;
UBRR1H = (unsigned char)(ubrr >> 8);
UBRR1L = (unsigned char)ubrr;
UCSR1A |= (1 << U2X);
UCSR1C = 0b00000110;
UCSR1B = 0b11111000;
}
ISR(TIMER1_OVF_vect) { // interrupt service routine : interval 100ms
TCNT1 = 59286; // 65536-16MHz/256/10Hz = 65536 - 16000000/256/10Hz = 59286
Timer1_Flag = 1;
}
void Timer1_Init(void) { //레지스터 확인 필요
TCNT1 = 0;
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 59286; // preload timer 65536-16MHz/256/10Hz = 65536 - 16000000/256/10 = 59286
TCCR1B |= (1 << CS12); // 256 prescaler
TIMSK |= (1 << TOIE1); // enable timer overflow interrupt
}
uint16_t CalcCRC16(uint8_t * cdata, uint16_t ilen) {
uint16_t AccumCRC16 = 0xffff;
uint8_t i, j;
for (j = 0; j < ilen; j++) {
i = (AccumCRC16 ^ *(cdata++)) & 255;
AccumCRC16 = ((AccumCRC16 >> 8) ^ TableCRC16[i]) & 0xffff;
}
return AccumCRC16;
}
uint8_t highByte(uint16_t Data)
{
return (Data >> 8) & 0xFF;
}
uint8_t lowByte(uint16_t Data)
{
return Data & 0xFF;
}
int8_t query(void) {
uint8_t i;
TX_BUF[0] = 0x01;
TX_BUF[1] = 0x03;
TX_BUF[2] = 0x00;
TX_BUF[3] = 0x01;
TX_BUF[4] = 0x00;
TX_BUF[5] = 0x04;
crc16 = CalcCRC16(TX_BUF, 6);
TX_BUF[6] = lowByte(crc16);
TX_BUF[7] = highByte(crc16);
for (i = 0; i < 8; i++) {
TX1_CH(TX_BUF[i]);
_delay_ms(100);
}
}
int main()
{
DDRG = 0x03;
USART1_Init(9600);
Timer1_Init();
sei();
while (1) {
if (Timer1_Flag) {
Timer1_Flag = 0;
query(); // send query : 100ms cycle
RX_CNT = 0; //응답을 기다림 수신버퍼 비우기
}
if (RX_CNT == 13) // mySerial.available 역할?
{
if (RawData > 30 || CompData > 30) PORTG = 0x03; //체온측정시 LED 작동
//RX_BUF[RX_CNT] = mySerial.read(); 하나씩 이동
char ch = RX_BUF[RX_CNT++]; //헷갈림 serial.read역할?
//특정 RX_BUF위치 값으로 센서값 변환
switch (RX_CNT) {
case 0:
if (RX_BUF[0] == 0x01) { RX_CNT++; }
break;
case 1:
if (RX_BUF[1] == 0x03) { RX_CNT++; }
else { RX_CNT = 0; }
break;
case 2:
if (RX_BUF[2] == 0x08) { RX_CNT++; }
else { RX_CNT = 0; }
break;
case 3 ... 11:
RX_CNT++;
break;
case 12:
crc16 = CalcCRC16(RX_BUF, RX_CNT - 1); // CRC calculation.
if (crc16 == (RX_BUF[RX_CNT - 1] | RX_BUF[RX_CNT] << 8)) { // CRC verification.
au16regs[0] = (uint16_t)RX_BUF[3] << 8 | (uint16_t)RX_BUF[4];
au16regs[1] = (uint16_t)RX_BUF[5] << 8 | (uint16_t)RX_BUF[6];
au16regs[2] = (uint16_t)RX_BUF[7] << 8 | (uint16_t)RX_BUF[8];
au16regs[3] = (uint16_t)RX_BUF[9] << 8 | (uint16_t)RX_BUF[10];
RawData = (float)au16regs[0] * 0.02 - 273.15; // DataValue1 : Raw Temperature
CompData = (float)au16regs[1] * 0.02 - 273.15;// DataValue2 : Comp Temperature
//dummy = (float)au16regs[2]*0.02-273.15; // DataValue3 : reserved(not used)
SensData = (float)au16regs[3] * 0.02 - 273.15;// DataValue4 : Sensor package Temperature (Operating temperature)
}
RX_CNT = 0;
break;
default: RX_CNT = 0; break;
} // end switch(RX_CNT)
}
} //end loop()
return 0;
}
댓글 1
조회수 4,258master님의 댓글
master 작성일
void USART1_Init(long baud){
UBRR1L=8;
UCSR1A|=(1<<U2X);
UCSR1B = 0x98;
}