///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
AVR Studio V4.19
// WinAVR 20050214
#include "main.h"
#include "localmath.h"
#ifdef ADC_BubbleSort_Enable
#define SWAP(a, b) { dword t; t=a; a=b; b=t; }
word BubbleSort(word *p, byte num){
byte i, j;
long k=0;
for(i=0; i<_AVERGE_NUMBER_-1; i++) {
for(j=1; j<_AVERGE_NUMBER_-i; j++) {
if(p[j-1] > p[j]) SWAP(p[j-1],p[j]);
}
}
for(i=_AVERGE_NUMBER_/3; i < (_AVERGE_NUMBER_/3)*2; i++) k += p[i];
return k/(_AVERGE_NUMBER_/3);
}
#endif
void Is_Rx(void){
while(g_RxTopCount != g_RxButtomCount){
if(g_RxEnd == 0){
if(g_RxRingBuffer[g_RxButtomCount] == _STX_) str = g_WorkBuf;
else if(g_RxRingBuffer[g_RxButtomCount] == _ETX_) g_RxEnd++;
*str++ = g_RxRingBuffer[g_RxButtomCount++];
*str = 0;
g_RxButtomCount %= _BufferLength_;
}
else{
if(g_RxEnd < 3){
g_RxEnd++;
*str++ = g_RxRingBuffer[g_RxButtomCount++];
*str = 0;
g_RxButtomCount %= _BufferLength_;
}
}
}
}
}
void Delay_xMs(word i){
CLEARBIT(TIMSK, TOIE0); // 타이머0 인터럽트 금지
g_DelayValue = i;
SETBIT(TIMSK, TOIE0); // 타이머0 인터럽트 허용
if((SREG & 0x80) == 0) sei(); // 인터럽터 활성화가 되어 있지 않다면 강제로 전체 인터럽터 활성화
while(g_DelayValue)
wdt_reset();
}
void SPI_WriteByte(unsigned char CMD){
SPDR = CMD;
while(!(SPSR & (1<
void Init_SPI_Clock_Devide(byte Devide){
if( Devide == 2) SPSR |= (1<
void Init_SPI(void){
Init_SPI_Clock_Devide(2);
SPDR = 0; // 초기화
SETBIT(SPCR, MSTR); // SPI 마스타로 동작
SETBIT(SPCR, SPE); // SPI 활성화
CLEARBIT(SPCR, CPOL); // SPI 모드 0으로 동작, 클럭 발생 상승 부터
CLEARBIT(SPCR, CPHA); // SPI ?
CLEARBIT(SPCR, DORD); // MSB를 먼저 출력
#ifdef _Is_Is_SPI_Interrupt__Proc_
SETBIT(SPCR, SPIE); // SPI 인터럽터 활성화
#endif
}
byte Write_SPI_One_byte(byte i){
while(g_Flag_SPI_TxStatus) wdt_disable();
SPDR = i;
return SPDR;
}
void Write_SPI_Several_byte(byte length, byte* pSend){
while(length--) Write_SPI_One_byte(*pSend++);
}
void Init_ADC(void){
// ADCSRA = 0; // 2분주
// ADCSRA = 1; // 2분주
// ADCSRA = 2; // 4분주
// ADCSRA = 3; // 8분주
// ADCSRA = 4; // 16분주
// ADCSRA = 5; // 32분주
// ADCSRA = 6; // 64분주
ADCSRA = 7; // 128분주
SETBIT(ADCSRA, ADEN); // AD 활성화
ADMUX = 0x02; // 입력 AIN2
#ifdef ADC_ISR_Load
CLEARBIT(ADMUX, REFS1); SETBIT(ADMUX, REFS0); // 기준 전압은 AVcc로 사용
// SETBIT(ADMUX, REFS1); SETBIT(ADMUX, REFS0); // 기준 전압은 내부 2.5V로 사용
// SETBIT(ADMUX, REFS1); SETBIT(ADMUX, REFS0);
SETBIT(ADCSRA, ADIE); // AD 변환 인터럽터 작동
SETBIT(ADCSRA, ADSC); // AD 변환 시작
#else
SETBIT(ADCSR, ADFR); // AD 자유 변환 시작
#endif
SETBIT(MCUCR, SM0); // AD Noise Reducation
}
word Read_ADC(void){
ADCSRA |= (1 << ADSC);
while(!(ADCSRA & (1 << ADIF)));
return ADC;
}
void Init_USART(unsigned long BaudRate){
UBRR0H = 0;
UBRR0L = (byte)((_FCPU_/(16 * BaudRate))-1);
// Enable receiver and transmitter, receiver Interrupt Enable
UCSR0B = (1<
// Set frame format: 8data, 1stop bit
UCSR0C = (3<
void Init_Ext_Int(void){
SETBIT(EICRB, ISC41); CLEARBIT(EICRB, ISC40);
SETBIT(EICRB, ISC51); CLEARBIT(EICRB, ISC50);
SETBIT(EICRB, ISC61); CLEARBIT(EICRB, ISC60);
SETBIT(EIMSK, INT4);
SETBIT(EIMSK, INT5);
SETBIT(EIMSK, INT6);
}
void Init_timer0(void){
#ifdef _FCPU_16MHz_
TCNT0 = _Timer0_16M_64Dived_1mSec_; // 16MHz 클럭 8분주 일때 1mSec 발생
#else
TCNT0 = _Timer0_8M_64Dived_1mSec_; // 8MHz 클럭 8분주 1mSec 발생
#endif
SETBIT(TCCR0, CS02); // 64분주
SETBIT(TIMSK, TOIE0); // 타이머0 인터럽트 허용
}
void Init_timer1(void){ // 카운터로 사용한다
TCCR1A = 0; // 자유증가 카운터 모드
SETBIT(TCCR1B, CS11); // 8 분주
TCNT1 = _TDELAY_;
SETBIT(TIMSK, TOIE1); // 타이머1 인터럽트 허용
}
void Init_timer2(void){
SETBIT(TCCR2, CS20);
TCNT2 = 0;
SETBIT(TIMSK, TOIE2); // 타이머2 인터럽트 허용
}
void Init_timer3(void){
TCCR3A = 0; // 자유증가 카운터 모드
SETBIT(TCCR3B, CS31); // 8 분주
TCNT3 = 0xff-50;
SETBIT(ETIMSK, TOIE3); // 타이머3 인터럽트 허용
}
byte Sum_Char_Return(byte i){
if(i > 9) return (i-10) + 'A';
else return i + '0';
}
byte BCC_Hi_Byte(byte i){
I >>= 4;
return Sum_Char_Return(i);
}
byte BCC_Low_Byte(byte i){
I &= 0x0f;
return Sum_Char_Return(i);
}
byte SUM_Check(void){
byte i = 0;
str = g_WorkBuf;
while(*str != _ETX_) i += *str++;
i += *str++;
if(BCC_Hi_Byte(i) != *str++) return 1;
if(BCC_Low_Byte(i) != *str++) return 2;
return 0;
}
SIGNAL(SIG_ADC){
CLEARBIT(ADCSRA, ADIF); // 인터럽터 플레그 클리어
#ifdef ADC_Convert_Enable
#ifdef ADC_BubbleSort_Enable
_g_AdcTempBuffer[_g_AdcTempBufCount++] = ADC;
_g_AdcTempBufCount %= _AVERGE_NUMBER_;
#endif
#endif
SETBIT(ADCSR, ADSC); // AD 변환 시작
}
SIGNAL(SIG_OVERFLOW0){
#ifdef _FCPU_16MHz_
TCNT0 = _Timer0_16M_64Dived_1mSec_; // 16MHz 클럭 64분주 일때 1mSec 발생
#else
TCNT0 = _Timer0_8M_64Dived_1mSec_; // 8MHz 클럭 64분주 1mSec 발생
#endif
if(g_DelayValue > 0) g_DelayValue--;
if(g_DelayRun > 0) g_DelayRun--;
else{
g_DelayRun = 500;
g_Run_Flag = ~g_Run_Flag;
if(g_Run_Flag) SETBIT(PORTD, _RUN_);
else CLEARBIT(PORTD, _RUN_);
}
#ifdef _Is_KeyPressDisp_test_Proc
if(TESTBIT(g_KeyStatus, 0)){
if(TESTBIT(PINE, 6)) CLEARBIT(g_KeyStatus, 0);
}
if(TESTBIT(g_KeyStatus, 1)){
if(TESTBIT(PINE, 5)) CLEARBIT(g_KeyStatus, 1);
}
if(TESTBIT(g_KeyStatus, 2)){
if(TESTBIT(PINE, 4)) CLEARBIT(g_KeyStatus, 2);
}
#endif
}
SIGNAL(SIG_OVERFLOW1){
CLEARBIT(TIMSK, TOIE1); // 타이머1 인터럽트 금지
_g_CommanSelect++;
_g_CommanSelect %= _FndCommMaxLength_;
#ifdef _Is_KeyPressDisp_test_Proc
PORTA = _ga_DispBUF[ _g_CommanSelect];
PORTC = _ga_FndComConst[_g_CommanSelect]; // FND Com 제어, 1개의 자리만 점등
#endif
TCNT1 = _TDELAY_;
SETBIT(TIMSK, TOIE1); // 타이머1 인터럽트 허용
}
SIGNAL(SIG_OVERFLOW3){
TCNT3 = 0xff-100; // 8MHz / 8 /100 = 20KHz
}
SIGNAL(SIG_USART0_RECV){
byte i = UDR0;
g_RxRingBuffer[g_RxTopCount++] = i; // 수신 링 버퍼
g_RxTopCount %= _BufferLength_;
}
SIGNAL(SIG_INTERRUPT4){
SETBIT(g_KeyStatus, 2);
}
SIGNAL(SIG_INTERRUPT5){
SETBIT(g_KeyStatus, 1);
}
SIGNAL(SIG_INTERRUPT6){
SETBIT(g_KeyStatus, 0);
}
void Init_Port(void){
// 1 일때 출력, 0 일때 입력으로 설정 된다
DDRA = 0xff; // 모두 출력, FND 데이터 출력
PORTA = 0xff; // 소등 데이터 출력
DDRB = (1<<_SS_)+(1<<_SCK_)+(1<<_MOSI_)+(1<<_PWM_A_)+(1<<_PWM_B_);
PORTB = (1<<_SS_)+(1<<_SCK_)+(1<<_MOSI_)+(1<<_PWM_A_)+(1<<_PWM_B_);
DDRC = 0xff; // 전체출력
PORTC = 0xff; // 세그먼트 공통 단자 끄기
DDRD = (1<<_Tx1_)+(1<<_START_)+(1<<_CHOICE_)+(1<<_RUN_)+(1<<_BUZZER_)+(1<<_BUZZER_)+(1<<_PowerEnable_);
PORTD = (1<<_Rx1_)+(1<<_Tx1_)+(1<<_START_)+ (1<<_RUN_)+(1<<_BUZZER_)+(1<<_BUZZER_)+(1<<_PowerEnable_);
DDRE = (1<<_Tx0_)+(1<<_Set_)+(1<<_Up_)+(1<<_Down_)+(1<<_RTS_);
PORTE = (1<<_Rx0_)+(1<<_Tx0_)+(1<<_Set_)+(1<<_Up_)+(1<<_Down_)+(1<<_RTS_);
DDRF = 0x00; // 전체입력
PORTF = 0x00;
}
void SystemInit(void){
Init_Port();
SETBIT(SFIOR, TSM); // 타이머 클럭 동기화 동작
Init_timer0(); // mSec Delay 함수사용
Init_timer1(); // FND 표시용
Init_ADC();
Init_SPI();
Init_USART(19200);
Init_Ext_Int();
CLEARBIT(MCUCSR, WDRF);
wdt_enable(WDTR_1S);
sei();
}
// 써미스터 부품 번호 : NTCALUGE2C90169
void Temp_Cal(void){
word Vo; // 써미스터와 직렬로 연결 된 분압저항 중간에서 읽은 전압
double R29 = 9729 // 써미스터와 직렬로 연결 되는 분압저항 값
double Rt;
double T, C;
double Ro = 10000; // 25도에서 NTC 저항 값
double To = 298.15; // 섭씨 25도 = 절대온도 298.15eh = 273.15 + C
double B = 3813; // 물질 상수, 오차율 +- 0.5% 이하
#ifdef ADC_ISR_Load
Vo = BubbleSort(_g_AdcTempBuffer, _AVERGE_NUMBER_); // 온도센서 저항 값
#else
Vo = Read_ADC();
#endif
Rt = R29 * ((1023.0/(double)Vo)-1.0); // 온도센서 저항 측정, 1023 이 5V
T = 1.0/((1.0/To)+(1/B)*log((Rt/Ro))); // B parameter를 이용한 온도 계산 방정식
C = T - 273.15;
g_temp_float = C;
g_temp_float = g_temp_float;
}
void Float_Str2FND(byte *ps){
byte i=0, *pd;
pd = _ga_DispBUF;
while(i < 6){
if(*ps >= '0' && *ps <= '9') *pd = _ga_FndFontConst[*ps - '0'];
else{
if(*ps == '.'){
if(i){
*pd--;
*pd &= _DIGITE_Dot_; // 소수점 생성
i--;
}
}
else{
if(*ps == '-') *pd = _DIGITE_Minus_; // - 생성
else *pd = 0;
}
}
i++;
*pd++;
*ps++;
}
*pd++ = 0;
}
void Temp_Display(void){
dtostrf(g_temp_float, 3 ,5, string);
Float_Str2FND(string);
}
void Task_Temp(void){
Temp_Cal();
Temp_Display();
}
void main(void){
SystemInit();
Task_Temp();
while(1){
Task_Temp();
Delay_xMs(250);
wdt_reset();
}
}
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define _FCPU_8MHz_ 8000000UL
//#define _FCPU_16MHz_ 16000000UL
#ifdef _FCPU_16MHz_
#define _FCPU_ _FCPU_16MHz_
#else
#define _FCPU_ _FCPU_8MHz_
#endif
#define WDTR_15MS 0
#define WDTR_30MS 1
#define WDTR_60MS 2
#define WDTR_120MS 3
#define WDTR_250MS 4
#define WDTR_500MS 5
#define WDTR_1S 6
#define WDTR_2S 7
#define _Timer0_16M_64Dived_1mSec_ 0xff-((_FCPU_/64)/1000) // 255-((16000000/64)/1000) = 5
#define _Timer0_8M_64Dived_1mSec_ 0xff-((_FCPU_/64)/1000) // 255-((8000000 /64)/1000) = 130
#define ADC_BubbleSort_Enable
#define ADC_Convert_Enable
#define ADC_ISR_Load
#define byte unsigned char
#define word unsigned int
#define dword int unsigned long
#define SETBIT( ADDRESS, BIT) (ADDRESS |= (1<
typedef union{
byte b_Value[2];
unsigned long W_Value;
}W2b;
W2b ConvWB;
typedef union{
byte b_Value[4];
unsigned long L_Value;
}L4b;
L4b ConvLB;
L4b integ;
typedef union{
byte b_Value[8];
unsigned long L_Value[2];
double d_Value;
}D8b;
D8b Double_64bit;
#define _Is_KeyPressDisp_test_Proc
#define _SegA_ 0x01
#define _SegB_ 0x02
#define _SegC_ 0x04
#define _SegD_ 0x08
#define _SegE_ 0x10
#define _SegF_ 0x20
#define _SegG_ 0x40
#define _SegDp_ 0x80
#define _DIGITE_0_ ~(_SegA_ + _SegB_ + _SegC_ + _SegD_ + _SegE_ + _SegF_)
#define _DIGITE_1_ ~(_SegB_ + _SegC_)
#define _DIGITE_2_ ~(_SegA_ + _SegB_ + _SegD_ + _SegE_ + _SegG_)
#define _DIGITE_3_ ~(_SegA_ + _SegB_ + _SegC_ + _SegD_ + _SegG_)
#define _DIGITE_4_ ~(_SegB_ + _SegC_ + _SegF_ + _SegG_)
#define _DIGITE_5_ ~(_SegA_ + _SegC_ + _SegD_ + _SegF_ + _SegG_)
#define _DIGITE_6_ ~(_SegA_ + _SegC_ + _SegD_ + _SegE_ + _SegF_ + _SegG_)
#define _DIGITE_7_ ~(_SegA_ + _SegB_ + _SegC_ + _SegF_)
#define _DIGITE_8_ ~(_SegA_ + _SegB_ + _SegC_ + _SegD_ + _SegE_ + _SegF_ + _SegG_)
#define _DIGITE_9_ ~(_SegA_ + _SegB_ + _SegC_ + _SegD_ + _SegF_ + _SegG_)
#define _SPACE_ ~0
#define _b_ ~(_SegC_ + _SegD_ + _SegE_ + _SegF_ + _SegG_)
#define _a_ ~(_SegA_ + _SegB_ + _SegC_ + _SegD_ + _SegE_ + _SegG_)
#define _A_ ~(_SegA_ + _SegB_ + _SegC_ + _SegE_ + _SegF_ + _SegG_)
#define _t_ ~(_SegD_ + _SegE_ + _SegF_ + _SegG_)
#define _E_ ~(_SegA_ + _SegD_ + _SegE_ + _SegF_ + _SegG_)
#define _R_ ~(_SegA_ + _SegB_ + _SegC_ + _SegE_ + _SegF_ + _SegG_)
#define _r_ ~(_SegE_ + _SegG_)
#define _S_ ~(_SegA_ + _SegC_ + _SegD_ + _SegF_ + _SegG_)
#define _y_ ~(_SegB_ + _SegC_ + _SegF_ + _SegG_)
#define _C_ ~(_SegA_ + _SegD_ + _SegE_ + _SegF_)
#define _h_ ~(_SegC_ + _SegE_ + _SegF_ + _SegG_)
#define _g_ ~(_SegA_ + _SegB_ + _SegC_ + _SegD_ + _SegF_ + _SegG_)
#define _DIGITE_Dot_ ~_SegDp_
#define _DIGITE_Minus_ ~_SegG_
#define _TDELAY_ 65535-4000
#define _FndCommMaxLength_ 6
static byte _g_CommanSelect = 0;
byte _ga_DispBUF[_FndCommMaxLength_ + 1]= {0, };
const byte _ga_FndFontConst[] = {_DIGITE_0_, _DIGITE_1_, _DIGITE_2_, _DIGITE_3_, _DIGITE_4_,
_DIGITE_5_, _DIGITE_6_, _DIGITE_7_, _DIGITE_8_, _DIGITE_9_, 0 };
const byte _ga_FndComConst[] = {~0x08, ~0x10, ~0x20, ~0x01, ~0x02, ~0x04, 0xff, 0};
// PORTA
#define _Sag_A_ 0
#define _Sag_B_ 1
#define _Sag_C_ 2
#define _Sag_D_ 3
#define _Sag_E_ 4
#define _Sag_F_ 5
#define _Sag_G_ 6
#define _Sag_P_ 7
// PORTB
#define _SS_ 0
#define _SCK_ 1
#define _MOSI_ 2
#define _MISO_ 3
#define _PWM_A_ 4
#define _PWM_B_ 5
#define _DSR_ 6
#define _DCD_ 7
// PORTC
#define _COM0_ 0
#define _COM1_ 1
#define _COM2_ 2
#define _COM3_ 3
#define _COM4_ 4
#define _COM5_ 5
#define _COM6_ 6
#define _COM7_ 7
// PORTD
#define _START_ 0
#define _CHOICE_ 1
#define _Rx1_ 2
#define _Tx1_ 3
#define _RUN_ 4
#define _BUZZER_ 5
#define _PowerEnable_ 6
#define _CTS_ 7
// PORTE
#define _Rx0_ 0
#define _Tx0_ 1
#define _Ain0_ 2
#define _Ain1_ 3
#define _Set_ 4
#define _Up_ 5
#define _Down_ 6
#define _RTS_ 7
// PORTF
#define _Adc0_ 0
#define _Adc1_ 1
#define _Adc2_ 2
#define _Adc3_ 3
#define _TCK_ 4
#define _TMS_ 5
#define _TDO_ 6
#define _TDI_ 7
#define _AVERGE_NUMBER_ 6
#ifdef ADC_BubbleSort_Enable
word _g_AdcTempBuffer[_AVERGE_NUMBER_+1] = {0, };
byte _g_AdcTempBufCount = 0;
#endif
byte g_Run_Flag = 0;
word g_DelayRun = 0;
word g_DelayValue = 0;
word gw_Delay_10uSec = 0;
//=========== 232 통신 관련 ===========================================================
#define _NUL_ 0x00
#define _BufferLength_ 100
#define _STX_ 0x02
#define _ETX_ 0x03
#define _ACK_ 0x06
#define _NAK_ 0x15
//=========== SPI 통신 관련 ===========================================================
byte g_Flag_SPI_TxStatus = 0;
byte g_RxRingBuffer[_BufferLength_+1] = {0, };
byte g_WorkBuf[20] = {0, };
byte g_TxBuf[20] = {0, };
byte g_RxEnd = 0;
byte g_RxTopCount = 0;
byte g_RxButtomCount = 0;
//=========== 공용 ===========================================================
#define _Err_OpenTempSenser_ 1
byte *str;
byte g_KeyStatus = 0;
byte string[20] = {0, };
double g_temp_float = 0;